feat(test-vectors): APS DecisionLineageReceipt for ku_4b3f7c2a9d8e1f05#7
feat(test-vectors): APS DecisionLineageReceipt for ku_4b3f7c2a9d8e1f05#7aeoess wants to merge 1 commit intoVeritasActa:feat/ku-test-vectorsfrom
Conversation
…eipts.aps.receipt slot for ku_4b3f7c2a9d8e1f05
tomjwxf
left a comment
There was a problem hiding this comment.
Thanks for populating the APS slot. Cross-verifying APS DecisionLineageReceipts against @veritasacta/verify is a meaningful first in the implementation matrix, and the cross-layer integrity demo (contributingSources[i].accessReceiptId binding APS receipts to the Ed25519 chain via hash) is the concrete shape the IETF draft has been asserting without fixtures to point at. Good work.
Want to hold on merging until the signing_key placement is adjusted though. Current structure inlines the public key at external_receipts.aps.signing_key, which is the exact pattern surfaced as a spec gap by @desiorac on GetBindu #459 recently. draft-02 (going out later this week) adds a normative "MUST NOT accept a verification key transported inside the receipt unless that key is independently anchored" requirement in Security Considerations, @veritasacta/verify 0.4.0 will enforce it, and a matching negative conformance vector lands in ScopeBlind/agent-governance-testvectors. The canonical verify repo shipping a fixture that relies on the embedded-key convenience would teach the wrong lesson right as the spec tightens.
Two restructure options that keep the educational value:
Option A (probably the one you want): Move the key to a sidecar JWKS at test-vectors/keys/aps-ku-cross-verify.jwks and reference via a verification_key_ref field in the bundle. Verifier invocation becomes:
npx @veritasacta/verify test-vectors/cross-verify-bundle.json \
--bundle --jwks test-vectors/keys/aps-ku-cross-verify.jwks
Single extra JSON file, establishes the pattern future fixtures copy.
Option B: Leave a SHA-256 fingerprint of the key in the receipt ("this receipt claims to be signed by the key with this fingerprint") but require the verifier to resolve the full key from a known location. Matches how SSH known_hosts works. More involved restructure.
Option A is the minimal change. Happy to push a suggested-change commit to this branch with the sidecar JWKS + verifier-invocation update if easier than doing it yourself. Let me know which option you prefer and I'll either draft it or wait for you.
Everything else in the PR is clean and ready to land the moment the key placement is resolved.
Summary
Drops a signed APS
DecisionLineageReceiptintoexternal_receipts.aps.receiptfor
ku_id=ku_4b3f7c2a9d8e1f05, completing the slot left open in #6.Refs #2 (cross-verify commitment) and #6 (KU test vectors).
The receipt commits to the bundle by recording, for each entry in
bundle.receipts, acontributingSources[i].accessReceiptIdof the formsha256:<jcs-canonical-sha256>. The 10 hashes match the bundle exactly,including the chain values your own
previousReceiptHashfields alreadypublish (e.g.
sha256:2b06eb3385bcfa…for receipt 1).The signing key is a deterministic test key (NOT an AEOESS production
issuer), derived as
sha256("aps:veritasacta:ku-cross-verify:v1"). Publickey + seed note are inlined in
external_receipts.aps.signing_keyso anyonecan re-derive and re-verify offline. Reference signer:
interop/scripts/sign-va-ku-receipt.tsin agent-passport-system.
Verification
APS-side independent check (Ed25519 sig + 10/10 cross-layer hashes match):
Tamper test
Flip a single field in receipt 9 (
payload.synthesis.synthesis_confidence0.68 → 0.99) and re-verify:
@veritasacta/verify:Receipt 9: invalid_signature— the round chaindetects the change exactly where it happened.
APS Ed25519 signature valid: true,Cross-layer integrity (9/10 hashes match bundle): false—contributingSources[8].accessReceiptIdno longer matches the recomputedhash. APS's signature stays valid (proving APS isn't the tamperer) while
the bundle is observably stale relative to APS's attestation.
This is the cross-layer integrity property promised in #2: tampering
invalidates both the VeritasActa Ed25519 chain and the APS attestation,
without requiring APS to re-sign anything per receipt.
Scope
test-vectors/cross-verify-bundle.json— populates thepre-existing
external_receipts.apsslot, leaves all 10 KU receipts andsigning keys byte-for-byte unchanged.
cc @tomjwxf — happy to adjust the receipt's shape if you'd prefer a
different commitment scheme (e.g. Merkle root over receipt hashes instead
of per-receipt entries).