feat(transport): live-call wiring (attestation handshake and A2A transport)#53
Conversation
…sport) Compose the landed decision core (peer.handle_peer_request), Cedar policy, sealed channel, and provenance DAG into a runnable live call, closing the two v0.2 "Remaining" items in ROADMAP: wire the decision core to a live A2A transport, and bind the seal to a verified attestation report on a live call. - attestation.py: handshake that gates the sealed channel on a verified channel key (offer, verify, seal). Software mode records assurance="none"; hardware plugs in via an injected verifier callable, so this module carries no hardware dependency. - transport/a2a.py: A2A wire binding. Parse an A2A message's ca2a block into a PeerRequest, build that message, and serialize result, error, and channel offer. - node.py: PeerNode holding the enclave channel key, policy, and provider. - transport/server.py, transport/client.py: standard-library-only reference HTTP server and client that run the full inbound pipeline over the wire. - tee/software.py: explicit, never-auto-selected software provider (no hardware guarantee), so the path runs off confidential hardware. - tests/unit/test_live_call.py: in-process pipeline, HTTP end-to-end, and fail-closed on over-scope, tampered payload, and stale nonce. Software mode runs off confidential hardware; the real-hardware quote path is the verifier seam. ruff, mypy --strict, and the full unit suite (136 tests) pass. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reconcile with main's A2A metadata adapter (transport.a2a_adapter and transport.constants), which landed while this PR was open. Drop the duplicate transport/a2a.py, rebase the peer node, HTTP server, and client onto a2a_adapter.parse_peer_request and attach_ca2a_metadata, and add transport/wire.py for the reference server's response and channel-offer JSON (which the adapter intentionally leaves out). ruff, mypy --strict, and 155 unit tests pass.
# Conflicts: # ROADMAP.md
carloshvp
left a comment
There was a problem hiding this comment.
Requesting changes: the reference client currently permits an attestation downgrade before sealing the task payload.
-
In
verify_offer(),platform == "software-only"returns aVerifiedPeer(assurance="none")before the supplied hardwareverifieris consulted.fetch_verified_peer(..., verifier=...)has no expected-platform or minimum-assurance policy, andsend_task()then seals to that key. An active peer or network intermediary can therefore replace a genuine hardware offer with an unsigned software-only offer and obtain a payload from a caller that intended to require hardware verification. This contradicts the PR's claim that the sealed channel is gated on a verified attestation report. Please make the caller select the expected platform/minimum assurance, reject software-only offers whenever hardware assurance is required, and add a negative test showing that a forged software offer cannot downgrade a hardware-configured call. -
The reference client also accepts arbitrary URL schemes at both
urlopen()sites. CI's Bandit gate is failing with B310 for these calls. Validate the scheme before I/O (and document whether hardware-assured calls require HTTPS) rather than suppressing the finding.
Validation: on head d4170206e653515138f4b13a34ec64393b41ca85, pytest tests/unit/test_live_call.py -q passed (7 tests) and ruff check src/ tests/ passed. bandit -c pyproject.toml -r src/ reproduced the two B310 failures; the GitHub test matrix is failing on the same security scan.
#48 added the A2A profile adapter; this branch adds a reference HTTP server/client, the attestation handshake, and PeerNode. The scope docs still said the A2A transport was flatly out of scope and that nothing served a live inbound call, which is now false in software mode. Reconcile honestly, keeping the transport in core (a reference, not the profile) and preserving the software-vs-hardware boundary: - LIMITATIONS: reference transport + handshake are built (software mode); the remaining gap is the hardware verifier seam, not live serving. Reframe the out-of-scope bullet: the profile mandates no transport, a non-normative reference one ships. - transport.md: status table and the overlay claim distinguish the profile (no new endpoint) from the reference transport (which does expose endpoints). - call-graph.md, concepts.md: the live path now runs in software mode; the hardware quote via the verifier seam is what remains. - CHANGELOG: record the reference transport under Unreleased. No code change: the transport already layers cleanly on #48's adapter after the merge. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…it B310) bandit flagged B310 on the reference client's two urllib.request.urlopen calls (file:/ and custom schemes). The existing `# noqa: S310` only silenced ruff, not bandit, so `bandit -r src/` failed CI. Validate the URL scheme against an http/https allowlist before opening, failing closed with TransportError, and annotate the calls for both tools. Add a test for the rejection. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
What
Wires cA2A's landed pieces (the peer decision core, Cedar policy, sealed channel, and provenance DAG) into a runnable live call, and gates the sealed channel on a verified attestation report. Closes the two v0.2 "Remaining" items in ROADMAP.
Changes
offer_channel/attest_channel,verify_offer(software mode givesassurance="none"; hardware via an injectedverifier), andseal_to_peer. A payload is sealed only to a verified peer key.ca2ablock into aPeerRequest; serializes result, error, and channel offer.PeerNodeholding the enclave channel key, policy, and provider;offer()andhandle().Testing
tests/unit/test_live_call.py: the in-process pipeline, a real HTTP end-to-end call, and fail-closed behavior on over-scope capability, tampered payload, and stale offer nonce. ruff clean, mypy --strict clean, 136/136 unit tests pass.Scope and honesty
Runs end to end in software mode only (
assurance="none"), which is why it works off confidential hardware. The real-hardware quote path is theverifierseam inattestation.py; end-to-end validation on a confidential VM (SEV-SNP, TDX, TPM) remains the pending hardware step and is unchanged by this PR.🤖 Generated with Claude Code