Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions src/constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/**
* @veritasacta/verify: Single-source-of-truth constants
*
* Strings and identifiers that MUST stay byte-identical across the CLI,
* the test-vectors generator, and any future conformance-test runner.
* Importing from one place prevents docs/code drift from silently
* desynchronizing rejection-path semantics.
*
* Add a new constant here when:
* - a fixture's `expected_result.error` should match the CLI's output
* verbatim, AND
* - the string is normatively pinned to a spec section (cite the
* normative reference in the JSDoc comment).
*/

/**
* Rejection error: APS verification key transported inside the receipt
* envelope without an independent anchor (sidecar JWKS, DID resolution,
* or other independently anchored key reference).
*
* Pinned to draft-farley-acta-signed-receipts-02 Security Considerations.
*
* Used by:
* - test-vectors/generate.mjs → cross-verify-embedded-key-bundle.json
* `expected_result.error` and `expected_verification.error`
* - src/verifier.js (forthcoming v0.7+ enforcement landing) → emitted
* when a bundle declares `external_receipts.aps.signing_key` without
* an accompanying `verification_key_ref`.
*/
export const REJECTION_ERROR_EMBEDDED_KEY =
'verification key transported inside receipt without independent anchor';
20 changes: 18 additions & 2 deletions test-vectors/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ Shipped to support the cross-verify work tracked in
| File | Purpose |
|------|---------|
| [`jcs-test-vectors.json`](jcs-test-vectors.json) | JCS canonicalization conformance. 9 cases. Feed each `input` to your canonicalizer and compare the output string and SHA-256 to the expected values. Includes the AIP-0001 ASCII-only key restriction case. |
| [`cross-verify-bundle.json`](cross-verify-bundle.json) | One complete Knowledge Unit: 4 models × 2 rounds + 1 synthesis + 1 aggregate = 10 Ed25519-signed receipts, hash-chained via `payload.previousReceiptHash`. Includes an `external_receipts.aps` slot for an APS `DecisionLineageReceipt` to drop in. |
| [`cross-verify-bundle.json`](cross-verify-bundle.json) | MUST accept. One complete Knowledge Unit: 4 models × 2 rounds + 1 synthesis + 1 aggregate = 10 Ed25519-signed receipts, hash-chained via `payload.previousReceiptHash`. Includes an APS `DecisionLineageReceipt` whose verification key is independently anchored via [`keys/aps-ku-cross-verify.jwks`](keys/aps-ku-cross-verify.jwks). |
| [`cross-verify-embedded-key-bundle.json`](cross-verify-embedded-key-bundle.json) | MUST reject in `@veritasacta/verify` v0.7+ once draft-02 enforcement ships. Deliberately preserves the embedded-key anti-pattern so verifiers can prove they reject verification keys transported inside a receipt or bundle without an independent anchor. **Note for current 0.6.0 consumers:** the verifier does not yet enforce this rejection path; running the suite against 0.6.0 will accept this fixture, which is expected. The fixture's purpose is as a regression target for the v0.7+ enforcement landing, not a test of current behavior. |
| [`keys/aps-ku-cross-verify.jwks`](keys/aps-ku-cross-verify.jwks) | Sidecar JWKS for the APS cross-verification fixture. Referenced by `external_receipts.aps.verification_key_ref`. |
| [`selective-disclosure-salted-commit.json`](selective-disclosure-salted-commit.json) | AIP-0002 salted SHA-256 commitment reference. The Grok-4.20 round-1 dissenting response is published with `response.position` and `response.confidence` replaced by commitments. The unsigned `witness` block carries salts + plaintext to unlock them. |
| [`generate.mjs`](generate.mjs) | The generator. Deterministic: same seed produces byte-identical output. Run `node generate.mjs <outdir>` from a workspace with `@veritasacta/artifacts` installed. |

Expand All @@ -23,6 +25,15 @@ npx @veritasacta/verify test-vectors/cross-verify-bundle.json --bundle
# → Bundle: VALID
# Total: 10 Passed: 10 Failed: 0

# Positive APS cross-layer fixture with sidecar-anchored key
npx @veritasacta/verify test-vectors/cross-verify-bundle.json \
--bundle --jwks test-vectors/keys/aps-ku-cross-verify.jwks

# Negative embedded-key fixture
npx @veritasacta/verify test-vectors/cross-verify-embedded-key-bundle.json --bundle
# → MUST fail non-zero:
# verification key transported inside receipt without independent anchor

# Selective-disclosure receipt (redacted shape, signature over redacted payload)
npx @veritasacta/verify test-vectors/selective-disclosure-salted-commit.json
# Note: CLI input shape here is the `redacted_receipt` field; pass it directly
Expand All @@ -37,7 +48,12 @@ For a third-party canonicalizer + verifier to pass:
2. For the ASCII-only case, the canonicalizer MUST throw when a key contains non-ASCII.
3. For `cross-verify-bundle.json`, every receipt individually verifies under the
`verification.signing_keys[].kid` that matches its `kid` field.
4. For `selective-disclosure-salted-commit.json`, the redacted receipt verifies
4. For `cross-verify-bundle.json`, the APS receipt verifier MUST resolve
`external_receipts.aps.verification_key_ref` to the sidecar JWKS and MUST NOT
rely on a verification key transported inside the receipt or bundle.
5. For `cross-verify-embedded-key-bundle.json`, a verifier MUST reject with
`verification key transported inside receipt without independent anchor`.
6. For `selective-disclosure-salted-commit.json`, the redacted receipt verifies
without the witness, and for each entry in `witness.disclosures`:
`sha256(salt + ":" + JSON.stringify(plaintext))` equals `expected_commitment`.

Expand Down
130 changes: 129 additions & 1 deletion test-vectors/cross-verify-bundle.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,135 @@
"signature"
],
"receipt_uri": null,
"receipt": null
"receipt": {
"receiptId": "dlr_va_ku_4b3f7c2a9d8e1f05",
"timestamp": "2026-04-18T00:00:00Z",
"decisionArtifactId": "veritasacta:ku:ku_4b3f7c2a9d8e1f05",
"decisionType": "knowledge_unit_deliberation",
"contributingSources": [
{
"sourceId": "ku:model:claude-opus-4.6",
"accessReceiptId": "sha256:2b06eb3385bcfa7bf29d59ae693c28124062fdb9b548a9710c1ee44f2eeae192",
"derivationDepth": 1,
"transformPath": [
"aggregation"
],
"termsVersionAtAccess": "veritasacta:knowledge-unit-bundle:v1",
"lineageConfidence": "complete",
"compensationStatus": "settled"
},
{
"sourceId": "ku:model:gpt-5",
"accessReceiptId": "sha256:a54dde3a9dd2501476b0e9613990333371a29b2b669c9da02e348a86e6b2ff83",
"derivationDepth": 2,
"transformPath": [
"aggregation"
],
"termsVersionAtAccess": "veritasacta:knowledge-unit-bundle:v1",
"lineageConfidence": "complete",
"compensationStatus": "settled"
},
{
"sourceId": "ku:model:gemini-2.5-pro",
"accessReceiptId": "sha256:76cce8f734ae646b56f4df333a15a400f254dcacece06e7b2bf26c97438b8bbc",
"derivationDepth": 3,
"transformPath": [
"aggregation"
],
"termsVersionAtAccess": "veritasacta:knowledge-unit-bundle:v1",
"lineageConfidence": "complete",
"compensationStatus": "settled"
},
{
"sourceId": "ku:model:grok-4.20",
"accessReceiptId": "sha256:653a70f396a16d2114b42996305f514b35d5ba59e6b37527b6311aa4d9e79aeb",
"derivationDepth": 4,
"transformPath": [
"aggregation"
],
"termsVersionAtAccess": "veritasacta:knowledge-unit-bundle:v1",
"lineageConfidence": "complete",
"compensationStatus": "settled"
},
{
"sourceId": "ku:model:claude-opus-4.6",
"accessReceiptId": "sha256:69eaa88bb7b4d0c66e9649096dae4aad20b84f7d9862b404f46a37e0a96e8240",
"derivationDepth": 5,
"transformPath": [
"aggregation"
],
"termsVersionAtAccess": "veritasacta:knowledge-unit-bundle:v1",
"lineageConfidence": "complete",
"compensationStatus": "settled"
},
{
"sourceId": "ku:model:gpt-5",
"accessReceiptId": "sha256:18ac3cef4d85205ebe2886b8b94b368ae8d28585088762e91df80ab3031a42d6",
"derivationDepth": 6,
"transformPath": [
"aggregation"
],
"termsVersionAtAccess": "veritasacta:knowledge-unit-bundle:v1",
"lineageConfidence": "complete",
"compensationStatus": "settled"
},
{
"sourceId": "ku:model:gemini-2.5-pro",
"accessReceiptId": "sha256:b69cef75b1f0eeb36ece82755df449ccea4dde04915268c254fef33508ce016f",
"derivationDepth": 7,
"transformPath": [
"aggregation"
],
"termsVersionAtAccess": "veritasacta:knowledge-unit-bundle:v1",
"lineageConfidence": "complete",
"compensationStatus": "settled"
},
{
"sourceId": "ku:model:grok-4.20",
"accessReceiptId": "sha256:b744f32a94d8f1f7727e9020308a8b1db87aef8c80b53c7644398ae0078317bc",
"derivationDepth": 8,
"transformPath": [
"aggregation"
],
"termsVersionAtAccess": "veritasacta:knowledge-unit-bundle:v1",
"lineageConfidence": "complete",
"compensationStatus": "settled"
},
{
"sourceId": "ku:arbiter:scopeblind-reference",
"accessReceiptId": "sha256:b0b54512737617227b1ac7569c06e71fbe8dd944011050c3ceaeac5e79526122",
"derivationDepth": 9,
"transformPath": [
"aggregation"
],
"termsVersionAtAccess": "veritasacta:knowledge-unit-bundle:v1",
"lineageConfidence": "complete",
"compensationStatus": "settled"
},
{
"sourceId": "ku:arbiter:scopeblind-reference",
"accessReceiptId": "sha256:a630e18f8a394f5b8f3488b6d6ffa1ce2193380b3ae35de8b7477b640fdacb6b",
"derivationDepth": 10,
"transformPath": [
"aggregation"
],
"termsVersionAtAccess": "veritasacta:knowledge-unit-bundle:v1",
"lineageConfidence": "complete",
"compensationStatus": "settled"
}
],
"lineageCompleteness": "complete",
"externalHopsPresent": true,
"transformChain": [
"aggregation"
],
"governingPurpose": "research:academic",
"jurisdictionContext": "veritasacta:knowledge-unit-bundle:v1",
"explanation": "APS DecisionLineageReceipt attesting to VeritasActa Knowledge Unit ku_4b3f7c2a9d8e1f05. Bundle terminal aggregate sha256: a630e18f8a394f5b8f3488b6d6ffa1ce2193380b3ae35de8b7477b640fdacb6b. Each entry in contributingSources commits to the JCS-canonical sha256 of one KU receipt; tampering any byte of any KU receipt invalidates the recorded accessReceiptId, breaking cross-layer integrity even though APS's Ed25519 signature over this DecisionLineageReceipt remains cryptographically valid.",
"signature": "c4ff9a5142ddf133294ccbbbed55facf077df11e3b067627fd041277832a0e5865d74d32845aac6486242aca2b8d52142699bc6c3fe8b4f0bf987e2b56001001"
},
"verifier_hint": "Verify APS DecisionLineageReceipt using the independently anchored key referenced by external_receipts.aps.verification_key_ref. Cross-layer integrity: each contributingSources[].accessReceiptId is the JCS-canonical sha256 of the corresponding entry in bundle.receipts.",
"verification_key_ref": "test-vectors/keys/aps-ku-cross-verify.jwks#aps-ku-cross-verify-v1"
}
},
"receipts": [
Expand Down
Loading