diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..1cc5f1a --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,15 @@ +# TriTRPC transport and agent-sandbox control-plane ownership. +# This file protects workflow, transport-profile, schema, fixture, and verifier surfaces. + +.github/workflows/* @mdheller +.github/CODEOWNERS @mdheller +.github/copilot-instructions.md @mdheller + +README.md @mdheller +Makefile @mdheller + +docs/CAPABILITY_FABRIC_SEMANTIC_SOURCE.md @mdheller +docs/AGENT_SANDBOX_TRANSPORT_PROFILE.md @mdheller +schemas/jsonschema/agent-sandbox-transport.v0.schema.json @mdheller +fixtures/agent_sandbox_transport/* @mdheller +tools/verify_agent_sandbox_transport.py @mdheller diff --git a/.github/copilot-instructions.md b/.github/copilot-instructions.md new file mode 100644 index 0000000..6e43e39 --- /dev/null +++ b/.github/copilot-instructions.md @@ -0,0 +1,17 @@ +# Copilot instructions for TriTRPC + +TriTRPC is the transport authority for deterministic ternary-native RPC framing, fixtures, canonical byte encoding, envelope ordering, AEAD/AAD boundaries, and transport-level verifier behavior. + +Do not redefine Capability Fabric semantic objects in this repository. Canonical semantics live in `SocioProphet/socioprophet-standards-knowledge`. + +When working on agent sandbox lifecycle artifacts: + +1. Treat this repository as the transport and fixture layer only. +2. Reference the standards objects instead of redefining them. +3. Preserve no-push failure invariants for infrastructure/model/tool failures. +4. Do not modify `.github/workflows/**`, `.github/CODEOWNERS`, or transport verifier scripts without explicit maintainer review. +5. Do not convert rate-limit, MCP, model, tool, attestation, or runner-bootstrap failures into successful writes. +6. Prefer deterministic fixtures, canonical JSON, digest binding, and cross-language verifier behavior. +7. Keep runtime implementation concerns in AgentPlane, Prophet Platform, or workspace-controller repositories rather than in TriTRPC transport docs. + +For ordinary code changes, keep `make verify` passing. diff --git a/.github/workflows/agent-sandbox-transport.yml b/.github/workflows/agent-sandbox-transport.yml new file mode 100644 index 0000000..3c3363e --- /dev/null +++ b/.github/workflows/agent-sandbox-transport.yml @@ -0,0 +1,23 @@ +name: agent-sandbox-transport + +on: + pull_request: + paths: + - 'docs/AGENT_SANDBOX_TRANSPORT_PROFILE.md' + - 'schemas/jsonschema/agent-sandbox-transport.v0.schema.json' + - 'fixtures/agent_sandbox_transport/**' + - 'tools/verify_agent_sandbox_transport.py' + - '.github/workflows/agent-sandbox-transport.yml' + workflow_dispatch: + +permissions: + contents: read + +jobs: + verify-agent-sandbox-transport: + runs-on: ubuntu-latest + steps: + - name: Check out repository + uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 + - name: Verify agent sandbox transport fixtures + run: python tools/verify_agent_sandbox_transport.py diff --git a/docs/AGENT_SANDBOX_TRANSPORT_PROFILE.md b/docs/AGENT_SANDBOX_TRANSPORT_PROFILE.md new file mode 100644 index 0000000..83ab318 --- /dev/null +++ b/docs/AGENT_SANDBOX_TRANSPORT_PROFILE.md @@ -0,0 +1,145 @@ +# Agent Sandbox Transport Profile for TriTRPC (v0.1 draft) + +## Status + +Draft transport profile. This document is intentionally scoped to TriTRPC carriage, serialization, digest binding, fixture behavior, and verifier behavior. + +Canonical lifecycle semantics live in `SocioProphet/socioprophet-standards-knowledge`: + +- `docs/standards/044-agent-sandbox-lifecycle.md` +- `schemas/jsonschema/capability-fabric/agent-sandbox-lifecycle.v0.schema.json` + +TriTRPC MUST NOT redefine the semantic meaning of `AgentSandboxSpec`, `AgentGenesisManifest`, `AgentFailureBundle`, or `AgentSandboxReceipt`. + +## Purpose + +This profile defines how agent sandbox lifecycle artifacts are carried over deterministic TriTRPC-style transport surfaces. + +It covers: +- typed artifact carriage; +- canonical JSON serialization for examples and fixtures; +- digest and reference binding; +- failure-bundle transport invariants; +- deterministic verification expectations. + +It does not define: +- actor trust semantics; +- controllability class semantics; +- proof-strength semantics; +- admission policy meaning; +- runtime placement policy. + +Those belong to the Capability Fabric standards source. + +## Transport object classes + +TriTRPC MAY carry the following lifecycle object classes as typed payloads or typed attachments: + +- `application/vnd.socioprophet.agent-sandbox-spec+json;v=0` +- `application/vnd.socioprophet.agent-genesis-manifest+json;v=0` +- `application/vnd.socioprophet.agent-failure-bundle+json;v=0` +- `application/vnd.socioprophet.agent-sandbox-receipt+json;v=0` + +A TriTRPC frame carrying one of these objects SHOULD bind: +- object media type; +- canonical payload digest; +- semantic schema reference; +- producer identity or attestation reference; +- parent sandbox or phase reference. + +## Canonical JSON profile + +For JSON fixtures and transport examples, canonicalization MUST use: +- UTF-8 encoding; +- sorted object keys; +- no insignificant whitespace; +- exact string values for enum-like fields; +- SHA-256 digest over the canonical byte string. + +Digest strings use: + +```text +sha256: +``` + +## Typed blob envelope + +A transport-facing lifecycle blob SHOULD use this shape: + +```json +{ + "schema_version": "tritrpc-agent-sandbox-transport.v0", + "blob_id": "blob_agent_sandbox_spec_0001", + "media_type": "application/vnd.socioprophet.agent-sandbox-spec+json;v=0", + "semantic_schema_ref": "capability-fabric:agent-sandbox-lifecycle.v0#/AgentSandboxSpec", + "payload_digest": "sha256:...", + "payload": { "...": "..." }, + "attestation_ref": "github-attestation://..." +} +``` + +TriTRPC implementations MAY carry `payload` inline for fixtures and small objects, or replace it with a `payload_ref` for large artifacts. + +## Failure-bundle no-push invariant + +A transport profile MUST preserve the failure-policy invariant from the canonical standard: + +- infrastructure/model/tool failures MUST NOT be represented as write-authorized outcomes; +- `allow_partial_push` MUST be false for infrastructure failure bundles; +- `allow_push_after_infra_failure` MUST be false for infrastructure failure bundles; +- failure bundles SHOULD be sealed as artifacts or receipts, not converted into branch mutations. + +This is specifically intended to prevent the observed coding-agent failure mode where a model quota error enters a commit/push path during teardown. + +## Inception and genesis carriage + +An inception phase SHOULD emit an `AgentSandboxSpec` typed blob. + +A genesis phase SHOULD emit an `AgentGenesisManifest` typed blob. + +The genesis manifest SHOULD reference: +- the exact control-plane revision; +- the target workspace revision; +- tool policy; +- egress policy; +- credential policy; +- failure policy; +- receipt policy. + +TriTRPC transport fixtures SHOULD prove that these references and digests are stable under canonical serialization. + +## Receipt carriage + +Every phase receipt carried by TriTRPC SHOULD include: +- phase; +- outcome; +- payload digest; +- signature or attestation reference; +- parent sandbox identifier. + +Receipts MAY be carried as standalone typed blobs or bundled with the corresponding object. + +## Verification expectations + +A TriTRPC transport verifier SHOULD check: +1. media type is recognized; +2. semantic schema reference points to the standards source; +3. canonical JSON digest matches payload; +4. failure bundles preserve no-push invariants; +5. phase receipt digest references are internally consistent; +6. protected-path or write-policy semantics are referenced, not redefined. + +## Repository placement + +This repository owns: +- this transport profile; +- example typed lifecycle blobs; +- transport verifier scripts; +- deterministic fixtures proving digest/reference behavior. + +The standards repository owns: +- lifecycle object semantics; +- field meaning; +- controllability classes; +- proof-strength constraints; +- receipt obligations. diff --git a/fixtures/agent_sandbox_transport/failure_bundle.transport.example.json b/fixtures/agent_sandbox_transport/failure_bundle.transport.example.json new file mode 100644 index 0000000..96e8703 --- /dev/null +++ b/fixtures/agent_sandbox_transport/failure_bundle.transport.example.json @@ -0,0 +1,22 @@ +{ + "schema_version": "tritrpc-agent-sandbox-transport.v0", + "blob_id": "blob_agent_failure_bundle_0001", + "media_type": "application/vnd.socioprophet.agent-failure-bundle+json;v=0", + "semantic_schema_ref": "capability-fabric:agent-sandbox-lifecycle.v0#/AgentFailureBundle", + "payload_digest": "sha256:bc7bf0ac87b530c1c64543511fd07ede7509684a0cc2fb18cda9c64e2c72351b", + "payload": { + "schema_version": "agent-sandbox-lifecycle.v0", + "sandbox_id": "sandbox_tritrpc_pr_comment_0001", + "failure_kind": "model_rate_limited", + "failure_class": "INFRASTRUCTURE", + "retry_after_seconds": 1094, + "allow_partial_push": false, + "allow_push_after_infra_failure": false, + "evidence_refs": [ + "github-actions-log://SocioProphet/TriTRPC/actions/runs/copilot-example#user_model_rate_limited" + ], + "sealed_at": "2026-05-04T00:00:00Z" + }, + "attestation_ref": "github-attestation://example/failure-bundle/0001", + "parent_ref": "sandbox_tritrpc_pr_comment_0001" +} diff --git a/rust/tritrpc_v1/src/lib.rs b/rust/tritrpc_v1/src/lib.rs index 4abbfc1..d578ace 100644 --- a/rust/tritrpc_v1/src/lib.rs +++ b/rust/tritrpc_v1/src/lib.rs @@ -434,7 +434,7 @@ pub mod avroenc { out.extend(enc_string(comp)); out } - pub fn enc_Error(code: i32, msg: &str, details: Option<&[u8]>) -> Vec { + pub fn enc_error(code: i32, msg: &str, details: Option<&[u8]>) -> Vec { let mut out = Vec::new(); out.extend(enc_int(code)); out.extend(enc_string(msg)); diff --git a/schemas/jsonschema/agent-sandbox-transport.v0.schema.json b/schemas/jsonschema/agent-sandbox-transport.v0.schema.json new file mode 100644 index 0000000..8ea7428 --- /dev/null +++ b/schemas/jsonschema/agent-sandbox-transport.v0.schema.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://schemas.socioprophet.example/tritrpc/agent-sandbox-transport.v0.schema.json", + "title": "TriTRPC Agent Sandbox Transport Blob v0", + "type": "object", + "additionalProperties": false, + "required": [ + "schema_version", + "blob_id", + "media_type", + "semantic_schema_ref", + "payload_digest" + ], + "properties": { + "schema_version": { "type": "string", "const": "tritrpc-agent-sandbox-transport.v0" }, + "blob_id": { "type": "string", "minLength": 1 }, + "media_type": { + "type": "string", + "enum": [ + "application/vnd.socioprophet.agent-sandbox-spec+json;v=0", + "application/vnd.socioprophet.agent-genesis-manifest+json;v=0", + "application/vnd.socioprophet.agent-failure-bundle+json;v=0", + "application/vnd.socioprophet.agent-sandbox-receipt+json;v=0" + ] + }, + "semantic_schema_ref": { "type": "string", "pattern": "^capability-fabric:agent-sandbox-lifecycle\\.v0#/.+" }, + "payload_digest": { "type": "string", "pattern": "^sha256:[0-9a-f]{64}$" }, + "payload": { "type": "object" }, + "payload_ref": { "type": "string" }, + "attestation_ref": { "type": "string" }, + "parent_ref": { "type": "string" } + }, + "oneOf": [ + { "required": ["payload"] }, + { "required": ["payload_ref"] } + ] +} diff --git a/spec/drafts/path_h_semantic_wire/README.md b/spec/drafts/path_h_semantic_wire/README.md new file mode 100644 index 0000000..4cbf64a --- /dev/null +++ b/spec/drafts/path_h_semantic_wire/README.md @@ -0,0 +1,95 @@ +# Path-H Semantic Wire Fixtures + +Status: draft fixture slice +Scope: TritRPC Path-H hot-path control frames bound to Semantic SerDes projections + +## Purpose + +This slice adds executable fixture coverage for the Path-H semantic-wire contract. +It complements the Path-H qutrit / hybrid control annex by binding the hot +control frame to Semantic SerDes objects without placing full semantic payloads +or quantum states on the hot path. + +The contract is: + +```text +SemanticCell / SHIR assertion + -> SemanticControlCodebook + -> WireSemanticProjection + -> RouteProjectionBundle + -> Path-H hot frame + -> receipt / replay / projection-loss report +``` + +## Hot-path rule + +Path-H semantic frames carry only compact handles and ternary coordinates: + +- `CTRL243` +- `route_h` +- `projection_id` +- `sem243_ref` +- `state243_ref` +- `schema_h` +- `context_h` +- `bundle_h` +- replay epoch and sequence coordinates + +They must not carry: + +- full semantic payloads +- sensitive policy objects +- n-ary assertion graphs +- trainable semantic tensors +- quantum states + +## Required invariants + +The validator in `tools/verify_path_h_semantic_wire.py` enforces these draft +invariants: + +1. `CTRL243.profile` must be `2` for Path-H. +2. Path-H semantic control must use quantum or hybrid lane, never classical. +3. Every semantic frame must include `route_h` and `projection_id`. +4. Every semantic frame must include `sem243_ref` and `state243_ref`. +5. Sensitive or full semantic payloads must remain off the hot path. +6. Strict codebook epoch fixtures must not drift from the frame epoch. +7. Lossy semantic lowering must cite a projection-loss report. +8. BSM3 frames must use one of the nine canonical qutrit BSM3 codes. + +## Fixtures + +Positive fixtures live under: + +```text +spec/drafts/path_h_semantic_wire/fixtures/valid/ +``` + +Negative fixtures live under: + +```text +spec/drafts/path_h_semantic_wire/fixtures/invalid/ +``` + +Negative fixtures include `expected_error` so they act as regression tests for +specific failure modes, not only generic failure. + +## Validation + +Run: + +```bash +python tools/verify_path_h_semantic_wire.py +``` + +or through the repository verification surface: + +```bash +make path-h-semantic-wire +``` + +## Boundary with Semantic SerDes + +Semantic SerDes owns the source meaning, codebook, projection, route bundle, +receipts, and projection-loss reports. This repository owns the Path-H hot-frame +invariants that make those handles safe to move over TritRPC. diff --git a/spec/drafts/path_h_semantic_wire/fixtures/valid/bsm3_semantic_witness_frame.json b/spec/drafts/path_h_semantic_wire/fixtures/valid/bsm3_semantic_witness_frame.json new file mode 100644 index 0000000..6a2fbff --- /dev/null +++ b/spec/drafts/path_h_semantic_wire/fixtures/valid/bsm3_semantic_witness_frame.json @@ -0,0 +1,38 @@ +{ + "fixture_name": "valid_path_h_bsm3_semantic_witness_frame", + "kind": "TELEPORT.BSM3", + "epoch_id": "epoch:path-h-semantic-wire:2026-05-12T00:00:00Z", + "codebook_version": "sem243-control-path-h-v0.1.0", + "ctrl243": { + "profile": 2, + "lane": 1, + "evidence": 1, + "fallback": 1, + "routefmt": 1 + }, + "route_h": "handle:route-path-h-bsm3-semantic-witness-v1", + "payload": { + "seq": 1843, + "ttl_ms": 1000, + "ts_ns": 1778709000100000000, + "pair_id": "pair:path-h-qutrit-001", + "basis_id": 3, + "bsm3_code": "12", + "projection_id": "wire-projection-path-h-bsm3-witness-001", + "sem243_ref": "sem243:qutrit.teleport.witness", + "state243_ref": "state243:qutrit-bsm3:v0.1", + "schema_h": "handle:schema-path-h-bsm3-v0.1", + "context_h": "handle:context-qutrit-link-001", + "bundle_h": "handle:bundle-bsm3-witness-001", + "semantic_projection_mode": "OPAQUE_HANDLE_ONLY", + "truth_class": "OBSERVED", + "control_evidence": "sampled", + "sensitive_off_hot_path": true, + "defer_ok": true + }, + "receipt": { + "semantic_receipt_h": "handle:receipt-path-h-bsm3-witness-001", + "replay_required": true, + "projection_loss_report_ref": null + } +} diff --git a/spec/drafts/path_h_semantic_wire/fixtures/valid/permission_claim_frame.json b/spec/drafts/path_h_semantic_wire/fixtures/valid/permission_claim_frame.json new file mode 100644 index 0000000..954d1a4 --- /dev/null +++ b/spec/drafts/path_h_semantic_wire/fixtures/valid/permission_claim_frame.json @@ -0,0 +1,35 @@ +{ + "fixture_name": "valid_path_h_permission_claim_frame", + "kind": "SEMANTIC.CONTROL", + "epoch_id": "epoch:path-h-semantic-wire:2026-05-12T00:00:00Z", + "codebook_version": "sem243-control-path-h-v0.1.0", + "ctrl243": { + "profile": 2, + "lane": 2, + "evidence": 2, + "fallback": 1, + "routefmt": 1 + }, + "route_h": "handle:route-path-h-permission-claim-v1", + "payload": { + "seq": 1842, + "ttl_ms": 5000, + "ts_ns": 1778709000000000000, + "basis_id": 7, + "projection_id": "wire-projection-path-h-permission-claim-001", + "sem243_ref": "sem243:policy.permission.claim", + "state243_ref": "state243:allow-mid-deny:v0.1", + "schema_h": "handle:schema-shir-assertion-v0.1", + "context_h": "handle:context-actor-action-resource-condition", + "bundle_h": "handle:bundle-permission-claim-001", + "semantic_projection_mode": "OPAQUE_HANDLE_ONLY", + "truth_class": "ASSERTED", + "control_evidence": "verified", + "sensitive_off_hot_path": true + }, + "receipt": { + "semantic_receipt_h": "handle:receipt-path-h-permission-claim-001", + "replay_required": true, + "projection_loss_report_ref": null + } +} diff --git a/spec/slices/scoped_disclosure_v0/README.md b/spec/slices/scoped_disclosure_v0/README.md new file mode 100644 index 0000000..932b607 --- /dev/null +++ b/spec/slices/scoped_disclosure_v0/README.md @@ -0,0 +1,59 @@ +# Scoped Disclosure Slice v0 + +## Purpose + +This slice defines the first transport-facing method pack for governed disclosure rooms. + +It does **not** attempt to make TriTRPC the canonical home of social doctrine. The doctrine layer belongs in the shared governance standards repository. This slice instead freezes the method surface that a deterministic transport layer needs in order to carry room creation, disclosure append, relay governance, moderation, reveal, and replay materialization. + +## Status + +This slice is a **composition-level design pack** for TriTRPC. + +It is not yet part of the stable TritRPC v1 normative wire canon. It is a reviewable slice pack that can later be bound to deterministic fixtures and cross-language pack/unpack tests. + +## Slice goals + +The slice exists to prove that disclosure governance can travel over the same deterministic transport discipline already used for policy, evidence, and replay flows. + +Minimum goals: + +- typed room-open request and response shapes +- typed disclosure append request and response shapes +- explicit relay authorization and denial flows +- explicit moderation decision flows +- explicit reveal request and reveal decision flows +- first-class evidence append and room materialization + +## Method catalog + +1. `room.v1.Room/Open` +2. `room.v1.Disclosure/Append` +3. `room.v1.Relay/Authorize` +4. `room.v1.Moderation/Decide` +5. `room.v1.Reveal/Request` +6. `room.v1.Reveal/Decide` +7. `room.v1.Room/Materialize` + +See `methods.md` for request/response requirements. + +## Cross-repo relationship + +- `identity-is-prime-reference` owns root actor and projection semantics. +- `sociosphere` owns local-first room realization and local relay/storage precedence. +- `agentplane` owns tenant-side adjudication and evidence-bearing remote moderation or reveal execution. +- `cairnpath-mesh` owns replay lineage and cairn materialization schemas. +- `socioprophet-standards-storage` owns the canonical governance doctrine. +- `TriTRPC` owns the typed transport-facing slice and its eventual deterministic fixtures. + +## Constraints + +- no viral default fan-out semantics +- no implicit reveal by transport operator +- no unconstrained public-provider egress by default +- no mutation without evidence-bearing follow-up +- no room materialization without versioned room-contract reference + +## Immediate next step + +Bind this slice to deterministic fixture vectors once the initial payload schemas stabilize across the standards, identity, and cairn repositories. diff --git a/spec/slices/scoped_disclosure_v0/methods.md b/spec/slices/scoped_disclosure_v0/methods.md new file mode 100644 index 0000000..5749568 --- /dev/null +++ b/spec/slices/scoped_disclosure_v0/methods.md @@ -0,0 +1,160 @@ +# Scoped Disclosure Slice v0 — Method Catalog + +This document defines the transport-facing methods for governed disclosure rooms. + +The request and response fields below are conceptual v0 shapes meant to guide shared schema work. They are not yet declared as stable TritRPC v1 canonical payload contracts. + +## 1. `room.v1.Room/Open` + +### Request + +- `room_contract_ref` — versioned reference to the governing room contract +- `room_id` — deterministic room identifier or proposed identifier +- `membership_snapshot_ref` — reference to the opening membership set +- `projection_policy` — attributable / scoped pseudonymous / masked rules +- `minimum_anonymity_set` +- `retention_policy_ref` + +### Response + +- `room_id` +- `room_contract_version` +- `room_state_ref` +- `decision` — accepted / rejected +- `reason_code` + +## 2. `room.v1.Disclosure/Append` + +### Request + +- `room_id` +- `event_id` +- `actor_projection_ref` +- `discourse_class` +- `payload_ref` or `payload_inline` +- `attachment_refs[]` +- `requested_relay_mode` +- `client_risk_flags[]` + +### Response + +- `event_id` +- `accepted_projection_mode` +- `accepted_relay_mode` +- `moderation_state` +- `evidence_append_ref` +- `reason_code` + +## 3. `room.v1.Relay/Authorize` + +### Request + +- `room_id` +- `event_id` +- `requested_relay_mode` +- `target_scope_ref` +- `policy_basis_ref` +- `requester_role` + +### Response + +- `event_id` +- `relay_decision` — allow / deny / escalate +- `granted_scope_ref` +- `relay_receipt_ref` +- `reason_code` + +## 4. `room.v1.Moderation/Decide` + +### Request + +- `room_id` +- `event_id` +- `moderation_action` +- `policy_basis_ref` +- `evidence_refs[]` +- `requester_role` + +### Response + +- `event_id` +- `moderation_decision_ref` +- `effective_visibility` +- `effective_relay_mode` +- `appeal_path_ref` +- `reason_code` + +## 5. `room.v1.Reveal/Request` + +### Request + +- `room_id` +- `target_event_id` +- `requester_identity_ref` +- `requester_role` +- `reason_code` +- `policy_basis_ref` +- `requested_reveal_scope` + +### Response + +- `reveal_request_ref` +- `submission_state` — accepted / rejected / requires_quorum +- `reason_code` + +## 6. `room.v1.Reveal/Decide` + +### Request + +- `reveal_request_ref` +- `deciding_authority_ref` or `quorum_ref` +- `decision` +- `authorized_scope` +- `rationale_ref` + +### Response + +- `reveal_decision_ref` +- `decision` +- `effective_scope` +- `evidence_append_ref` +- `reason_code` + +## 7. `room.v1.Room/Materialize` + +### Request + +- `room_id` +- `materialization_point` — latest / as_of_event / as_of_time +- `include_withdrawn` +- `include_moderation_history` +- `include_reveal_history` + +### Response + +- `room_state_ref` +- `cairnline_ref` +- `room_contract_version` +- `membership_snapshot_ref` +- `event_sequence_refs[]` + +## Deterministic fixture priorities + +The first fixture pass SHOULD prioritize: + +1. room open with contract version binding +2. masked confessional append accepted under minimum anonymity set +3. allegation append forced into moderator-only relay +4. reveal request denied without sufficient authority +5. reveal request approved with explicit decision artifact +6. room materialization including moderation and reveal lineage + +## Invariants + +A conforming implementation of this slice MUST preserve these invariants: + +- no disclosure append without room-contract reference +- no reveal decision without reveal request lineage +- no relay widening without explicit relay receipt +- no room materialization that hides contract version +- no mutation of visibility or relay posture without evidence-bearing artifact emission diff --git a/tools/verify_agent_sandbox_transport.py b/tools/verify_agent_sandbox_transport.py new file mode 100644 index 0000000..2fd103d --- /dev/null +++ b/tools/verify_agent_sandbox_transport.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python3 +from __future__ import annotations + +import hashlib +import json +import pathlib +import sys + +ROOT = pathlib.Path(__file__).resolve().parents[1] +FIXTURE_DIR = ROOT / "fixtures" / "agent_sandbox_transport" + +KNOWN_MEDIA_TYPES = { + "application/vnd.socioprophet.agent-sandbox-spec+json;v=0", + "application/vnd.socioprophet.agent-genesis-manifest+json;v=0", + "application/vnd.socioprophet.agent-failure-bundle+json;v=0", + "application/vnd.socioprophet.agent-sandbox-receipt+json;v=0", +} + + +def canonical_digest(payload: object) -> str: + data = json.dumps(payload, sort_keys=True, separators=(",", ":"), ensure_ascii=False).encode("utf-8") + return "sha256:" + hashlib.sha256(data).hexdigest() + + +def verify_blob(path: pathlib.Path) -> None: + blob = json.loads(path.read_text(encoding="utf-8")) + assert blob["schema_version"] == "tritrpc-agent-sandbox-transport.v0", path + assert blob["media_type"] in KNOWN_MEDIA_TYPES, path + assert blob["semantic_schema_ref"].startswith("capability-fabric:agent-sandbox-lifecycle.v0#/"), path + assert "payload" in blob or "payload_ref" in blob, path + if "payload" in blob: + got = canonical_digest(blob["payload"]) + assert got == blob["payload_digest"], f"{path}: digest mismatch {got} != {blob['payload_digest']}" + payload = blob["payload"] + if blob["media_type"] == "application/vnd.socioprophet.agent-failure-bundle+json;v=0": + assert payload.get("failure_class") in {"INFRASTRUCTURE", "CONTROL_PLANE", "VALIDATION", "POLICY", "USER_INPUT", "REPOSITORY", "UNKNOWN"}, path + assert payload.get("allow_partial_push") is False, f"{path}: failure bundle must not allow partial push" + assert payload.get("allow_push_after_infra_failure") is False, f"{path}: infra failure must not allow push" + + +def main() -> int: + fixtures = sorted(FIXTURE_DIR.glob("*.json")) + if not fixtures: + raise SystemExit("no agent sandbox transport fixtures found") + for fixture in fixtures: + verify_blob(fixture) + print(f"verified {len(fixtures)} agent sandbox transport fixture(s)") + return 0 + + +if __name__ == "__main__": + raise SystemExit(main())