195 lines
9.0 KiB
Python
195 lines
9.0 KiB
Python
"""Compatibility adapters from existing runtimes into the canonical contract."""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import Any, Mapping
|
|
|
|
from .contracts import CONTRACT_VERSION, actor, evidence_digest, outcome, utc_now
|
|
from .policy import evaluate_risk
|
|
|
|
|
|
class NativeHarnessAdapter:
|
|
runtime_type = "casan-native-harness"
|
|
|
|
def map_execution(self, event: Mapping[str, Any]) -> dict[str, Any]:
|
|
run_id = str(event.get("run_id") or event.get("trace_id") or "")
|
|
actor_id = str(event.get("actor") or "unidentified")
|
|
action_name = str(event.get("action") or "agent_step")
|
|
mode = str(event.get("mode") or "enforce")
|
|
risk = evaluate_risk(
|
|
action=action_name,
|
|
tool=str(event.get("tool") or action_name),
|
|
resource=str(event.get("resource") or ""),
|
|
command=str(event.get("command") or ""),
|
|
actor=actor_id if actor_id != "unidentified" else "",
|
|
environment=str(event.get("environment") or "development"),
|
|
)
|
|
execution_status = str(event.get("execution_status") or "unknown")
|
|
assurance_status = str(event.get("assurance_status") or "unknown")
|
|
certification = str(event.get("certification_status") or "non_certified")
|
|
return _bundle(
|
|
run_id=run_id,
|
|
runtime_type=self.runtime_type,
|
|
runtime_version=str(event.get("runtime_version") or "legacy-compatible"),
|
|
mode=mode,
|
|
actor_id=actor_id,
|
|
action_name=action_name,
|
|
risk=risk,
|
|
execution_status=execution_status,
|
|
assurance_status=assurance_status,
|
|
certification=certification,
|
|
event=event,
|
|
)
|
|
|
|
|
|
class AgenticBridgeAdapter:
|
|
runtime_type = "agentic-bridge"
|
|
|
|
def map_execution(self, event: Mapping[str, Any]) -> dict[str, Any]:
|
|
run_id = str(event.get("trace_id") or event.get("run_id") or "")
|
|
actor_id = str(event.get("actor") or "unidentified")
|
|
action_name = str(event.get("action") or event.get("last_action") or "agent_step")
|
|
mode = str(event.get("mode") or event.get("hook_trust_mode") or "observe")
|
|
risk = evaluate_risk(
|
|
action=action_name,
|
|
tool=str(event.get("tool") or event.get("last_tool") or action_name),
|
|
resource=str(event.get("resource") or ""),
|
|
command=str(event.get("command") or ""),
|
|
actor=actor_id if actor_id != "unidentified" else "",
|
|
environment=str(event.get("environment") or "development"),
|
|
)
|
|
execution_status = str(event.get("execution_status") or "unknown")
|
|
assurance_status = str(event.get("assurance_status") or "unknown")
|
|
certification = "certified" if event.get("certified") else "non_certified"
|
|
return _bundle(
|
|
run_id=run_id,
|
|
runtime_type=self.runtime_type,
|
|
runtime_version=str(event.get("adapter_version") or "legacy-compatible"),
|
|
mode=mode,
|
|
actor_id=actor_id,
|
|
action_name=action_name,
|
|
risk=risk,
|
|
execution_status=execution_status,
|
|
assurance_status=assurance_status,
|
|
certification=certification,
|
|
event=event,
|
|
)
|
|
|
|
|
|
def _bundle(
|
|
*,
|
|
run_id: str,
|
|
runtime_type: str,
|
|
runtime_version: str,
|
|
mode: str,
|
|
actor_id: str,
|
|
action_name: str,
|
|
risk: Mapping[str, Any],
|
|
execution_status: str,
|
|
assurance_status: str,
|
|
certification: str,
|
|
event: Mapping[str, Any],
|
|
) -> dict[str, Any]:
|
|
step_id = str(event.get("step_id") or f"{run_id}:1")
|
|
correlation_id = str(event.get("correlation_id") or run_id)
|
|
raw_evidence = list(event.get("evidence") or [])
|
|
claim_id = f"{run_id}:assurance-claim"
|
|
evidence = []
|
|
for index, item in enumerate(raw_evidence, 1):
|
|
raw = item if isinstance(item, Mapping) else {"detail": str(item)}
|
|
canonical_evidence = {
|
|
"evidence_id": str(raw.get("evidence_id") or f"{run_id}:evidence:{index}"),
|
|
"claim_refs": [claim_id],
|
|
"producer_identity": runtime_type,
|
|
"timestamp": raw.get("at") or raw.get("timestamp") or utc_now(),
|
|
"artifact_ref": str(raw.get("artifact_ref") or f"inline:{run_id}:{index}"),
|
|
"validation_status": "valid" if raw.get("decision") in {"allow", "pass", "passed", "certified"} else "unverified",
|
|
"retention_class": str(raw.get("retention_class") or "runtime_assurance"),
|
|
"category": str(raw.get("category") or "runtime_control"),
|
|
}
|
|
canonical_evidence["integrity"] = {
|
|
"algorithm": "sha256",
|
|
"digest": evidence_digest(canonical_evidence),
|
|
"source_content_hash": raw.get("content_hash"),
|
|
}
|
|
evidence.append(canonical_evidence)
|
|
policy_decisions = []
|
|
for item in list(event.get("policy_decisions") or []):
|
|
if not isinstance(item, Mapping):
|
|
continue
|
|
decision = str(item.get("decision") or "observe_only")
|
|
if decision not in {"allow", "deny", "quarantine", "require_approval", "transform", "observe_only"}:
|
|
decision = "observe_only"
|
|
policy_decisions.append({
|
|
"policy_id": str(item.get("policy_id") or "casan.compatibility.policy"),
|
|
"policy_version": str(item.get("policy_version") or item.get("schema_version") or CONTRACT_VERSION),
|
|
"decision": decision,
|
|
"reason_codes": list(item.get("reason_codes") or [item.get("reason_code") or "compatibility_mapping"]),
|
|
"effective_risk": str(item.get("effective_risk") or "high"),
|
|
"input_facts": dict(item),
|
|
"enforcement_point": str(item.get("enforcement_path") or runtime_type),
|
|
"timestamp": str(item.get("timestamp") or utc_now()),
|
|
"decision_engine_identity": "casan-assurance-kernel",
|
|
"evidence_ref": evidence[0]["evidence_id"] if evidence else None,
|
|
})
|
|
result = outcome(execution_status, assurance_status, certification)
|
|
return {
|
|
"schema_version": CONTRACT_VERSION,
|
|
"extension_namespace": f"casan.runtime.{runtime_type}",
|
|
"run": {
|
|
"run_id": run_id,
|
|
"parent_run_id": event.get("parent_run_id"),
|
|
"tenant": str(event.get("tenant") or "default"),
|
|
"project": str(event.get("project") or event.get("project_id") or "default"),
|
|
"environment": str(event.get("environment") or "development"),
|
|
"runtime": {"type": runtime_type, "version": runtime_version},
|
|
"mode": mode,
|
|
"requested_goal": str(event.get("requested_goal") or ""),
|
|
"started_at": event.get("started_at") or event.get("timestamp") or utc_now(),
|
|
"completed_at": event.get("completed_at") or utc_now(),
|
|
"status": execution_status,
|
|
"risk_summary": dict(risk),
|
|
"evidence_manifest_ref": event.get("evidence_manifest_ref"),
|
|
"correlation_id": correlation_id,
|
|
"outcome": result,
|
|
},
|
|
"actors": [actor(actor_id, "agent" if runtime_type == "casan-native-harness" else "runtime", runtime_type, "verified" if actor_id != "unidentified" else "unverified", event.get("authentication_evidence_ref"))],
|
|
"steps": [{
|
|
"step_id": step_id,
|
|
"run_id": run_id,
|
|
"parent_step_id": event.get("parent_step_id"),
|
|
"sequence": int(event.get("sequence") or 1),
|
|
"actor_ref": actor_id,
|
|
"action": {"class": risk["action_class"], "name": action_name, "tool": event.get("tool"), "side_effect_level": risk["side_effect_level"]},
|
|
"resource": event.get("resource"),
|
|
"input_context_refs": list(event.get("input_context_refs") or []),
|
|
"policy_decisions": policy_decisions,
|
|
"tool_invocation": event.get("tool_invocation"),
|
|
"verification_results": list(event.get("verification_results") or []),
|
|
"evidence_refs": [item["evidence_id"] for item in evidence],
|
|
"outcome": result,
|
|
"started_at": event.get("started_at") or event.get("timestamp") or utc_now(),
|
|
"completed_at": event.get("completed_at") or utc_now(),
|
|
}],
|
|
"runtime_capabilities": {
|
|
"canCancel": False, "canPause": False, "canResume": False,
|
|
"canRollback": False, "canReduceAuthority": False,
|
|
"canQuarantine": runtime_type == "agentic-bridge",
|
|
},
|
|
"claims": [{
|
|
"claim_id": claim_id,
|
|
"statement": "CASAN evaluated the runtime assurance outcome",
|
|
"evidence_refs": [item["evidence_id"] for item in evidence],
|
|
"validation_status": "validated" if assurance_status == "passed" else "insufficient",
|
|
}],
|
|
"evidence": evidence,
|
|
"trace_links": [
|
|
{"type": "parent_to_child_execution", "from": run_id, "to": step_id},
|
|
*[
|
|
{"type": "evidence_to_outcome", "from": item["evidence_id"], "to": claim_id}
|
|
for item in evidence
|
|
],
|
|
],
|
|
"extensions": {f"casan.runtime.{runtime_type}": dict(event.get("extensions") or {})},
|
|
}
|