TRACE profile: TAP egress sessions
TAP issues each ended sandbox session as a TRACE v0.2 Trust Record (agentrust-io/trace-spec, spec/trace-v0.2.md), so existing TRACE tooling can read TAP's evidence. This page says how TAP fills each field, how to verify a record, and what the record does not claim.
Written against trace-spec revision dcca4e0 (October 2026), a pre-1.0 draft.
Getting a record
node sdk/cli.ts trace --url https://<tap-host> --owner-key ~/.tap/owner.pem --session <id> --out record.json
Or GET /v1/sessions/<id>/trace?nonce=<challenge> with the owner's read signature (see the HTTP API). The session must have ended. Each request issues a fresh record: iat is the issue time and runtime.nonce echoes the challenge, so a verifier gets a fresh, nonce-bound record whenever it asks.
Field mapping
| TRACE field | TAP value | Assurance |
|---|---|---|
eat_profile |
tag:agentrust-io.com,2026:trace-v0.2 |
|
iat |
Issue time of the record (Unix seconds) | |
subject |
spiffe://<trust domain>/tap/sandbox/<sandbox id> (--trust-domain) |
A name in SPIFFE form; TAP does not run SPIRE and no SVID is issued |
model |
{provider, model_id, version?} as the platform states it when opening the session |
Platform-stated. TAP cannot see which model the agent uses; unknown when not stated |
runtime.platform |
amd-sev-snp, or software-only without hardware |
|
runtime.measurement |
sha384: + the SEV-SNP launch measurement; sha256: and zeros without hardware |
See Limitations |
runtime.rim_uri |
AMD KDS certificate chain for the chip's product | |
runtime.nonce |
The verifier's challenge, when given | |
policy.bundle_hash |
sha256: + SHA-256 of the policy text the session ran under |
Same hash as in TAP's attestation statement and session claim |
policy.enforcement_mode |
enforce |
TAP refuses what the policy does not allow |
policy.version |
The policy's version, as a string | |
data_class |
The policy's data_class (default unclassified) |
Owner-declared. TAP does not classify requests |
tool_transcript.hash |
sha256: + the session's hash-chain head |
The preimage is TAP's records: h0 = SHA-256("tap/1" ‖ session id), hn = SHA-256(hn-1 ‖ record n) |
tool_transcript.call_count |
Number of records (requests TAP saw) | |
build_provenance.digest |
sha256: over TAP's src/*.ts (name, NUL, contents, NUL, in name order) |
Self-computed; see Limitations |
build_provenance.slsa_level |
0 |
No SLSA provenance yet |
appraisal |
affirming if TAP checked its own SEV-SNP report against AMD's chain at start, else none; verifier is TAP's attestation endpoint |
Producer's report (the spec's own wording): a relying party checks the attestation itself |
cnf.jwk |
TAP's Ed25519 key (OKP) |
The key TAP's attestation statement binds to the hardware report |
signature |
Embedded: Ed25519 over the RFC 8785 form of the record without signature, canonical unpadded base64url |
|
transparency, origin, references, delegation, reproducibility |
Not set | No SCITT anchoring yet; absent origin means self |
Verifying
- Attest TAP with a fresh nonce (
POST /v1/attest): check the SEV-SNP report up to AMD's root and that it binds TAP's statement, whosesign_keyis TAP's Ed25519 key. (sdk/cli.ts provisionand the console do this.) - Check the record with that key:
cnf.jwkis that key, and the embedded signature verifies over the RFC 8785 form of the record withoutsignature. Checkruntime.nonceagainst your challenge. - Check the transcript: fetch the session's records (
GET /v1/sessions/<id>), recompute the hash chain and compare its head and length withtool_transcript.
sdk/cli.ts trace runs all three. Any TRACE v0.2 verifier can run step 2 given TAP's key as the trusted key; the records of step 3 are TAP's own format, which TRACE v0.2 leaves to the producer.
The records' shape is tested against the official schema/trace-claim.json (TRACE_SPEC_DIR=<trace-spec checkout> npm test). Schema validity is not conformance.
Conformance
| Level | TAP | Why |
|---|---|---|
| 0 | software backend | software-only, signed, policy, appraisal present |
| 1 | SEV-SNP backend | hardware platform and measurement, build_provenance present, appraisal affirming |
| 2 | not yet | needs a SCITT receipt for each record (transparency) |
This is our reading of the conformance levels; we have not yet run the official conformance suite against TAP's records.
What a record does not claim
- TAP's code is not in the measurement yet. On GCP the launch measurement covers the VM firmware; TAP is installed after boot. Until TAP ships as a measured image,
runtime.measurementdoes not tie the record to a TAP build, andbuild_provenance.digestis TAP's own report of its code. modelis the platform's statement anddata_classthe owner's, not something TAP observed.- Per-request records are TAP's format. TRACE v0.2 has no normative per-call schema (the MCP profile is planned for v0.3); TAP's records are what
tool_transcript.hashcommits to. - No transparency anchoring. Without a SCITT receipt, revocation of TAP's key is all-or-nothing (spec section 3.2.3); TAP's keys are new at every start anyway.