Skip to content

feat(transport): live-call wiring (attestation handshake and A2A transport)#53

Merged
imran-siddique merged 5 commits into
mainfrom
live-call-wiring
Jul 20, 2026
Merged

feat(transport): live-call wiring (attestation handshake and A2A transport)#53
imran-siddique merged 5 commits into
mainfrom
live-call-wiring

Conversation

@imran-siddique

Copy link
Copy Markdown
Contributor

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

  • attestation.py: the handshake. offer_channel / attest_channel, verify_offer (software mode gives assurance="none"; hardware via an injected verifier), and seal_to_peer. A payload is sealed only to a verified peer key.
  • transport/a2a.py: A2A wire binding. Parses an A2A message's ca2a block into a PeerRequest; serializes result, error, and channel offer.
  • node.py: PeerNode holding the enclave channel key, policy, and provider; offer() and handle().
  • transport/server.py, transport/client.py: standard-library-only reference HTTP server and client, so the live call runs anywhere Python does, including a container platform.
  • tee/software.py: explicit, never-auto-selected software provider (no hardware guarantee).

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 the verifier seam in attestation.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

imran-siddique and others added 3 commits July 19, 2026 21:49
…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.

@carloshvp carloshvp left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requesting changes: the reference client currently permits an attestation downgrade before sealing the task payload.

  1. In verify_offer(), platform == "software-only" returns a VerifiedPeer(assurance="none") before the supplied hardware verifier is consulted. fetch_verified_peer(..., verifier=...) has no expected-platform or minimum-assurance policy, and send_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.

  2. 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.

imran-siddique and others added 2 commits July 20, 2026 09:39
#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>
@imran-siddique
imran-siddique merged commit 7d33445 into main Jul 20, 2026
11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants