VAL-RF — Receipt Format Specification
Version: 0.1 Status: Draft License: Apache License 2.0 Editor: Open VAL Foundation (pending donation; currently VAL Inc.)
1. Abstract
This specification defines the VAL Receipt Format (RF) — a cryptographically signed record of an agent action decision and its outcome, bound to a VAL-AM manifest and a VAL-CPL policy set hash, chained to a tamper-evident ledger, and verifiable by any third party without trusting the issuer.
2. Goals
A VAL-RF receipt MUST:
- Bind to a specific Action Manifest by hash.
- Bind to a specific Conduct Policy Set by hash.
- Bind to the immediately prior receipt by hash (tamper-evident chain).
- Be signed by a key controlled by the operator (NOT by VAL Inc.).
- Include an independent RFC 3161 timestamp.
- Be verifiable offline given (a) the receipt, (b) the operator's public key, (c) the spec.
3. Threat Model
VAL-RF is designed to resist:
- Issuer tampering. An operator (or VAL Inc.) cannot alter a past receipt without breaking the hash chain and invalidating every subsequent receipt's chain.
- Retroactive policy denial. An operator cannot claim "we had a stricter policy at the time" because the policy_set_hash in the receipt is independently verifiable against the operator's archived policies.
- Timestamp manipulation. The RFC 3161 timestamp from an independent TSA establishes an upper bound on issuance time.
- Receipt forgery by VAL Inc. Because the operator owns the signing key, VAL Inc. cannot manufacture a receipt that appears to be from an operator.
VAL-RF is NOT designed to resist:
- Operator collusion with TSA. If both the operator and the timestamping authority are adversarial, timestamps cannot be independently verified.
- Pre-issuance policy fraud. A policy that was never actually enforced (only logged after the fact) cannot be distinguished from one that was enforced. This is mitigated by the policy archive practices in Section 11, not by the receipt format itself.
4. Receipt Structure
A receipt is a CBOR-encoded object (RFC 8949) wrapped in a COSE_Sign1 structure (RFC 9052) for the operator signature. Top-level CBOR map (decoded into JSON for human readability below):
4.1 The signed payload
{
"receipt_id": "<UUIDv7 string>",
"spec_version": "0.1",
"issued_at": "<RFC 3339 UTC timestamp>",
"issuer": "<operator URN>",
"agent": {
"id": "<agent id from manifest>",
"substrate": {
"vendor": "<vendor>",
"model": "<model id>",
"version": "<version>"
}
},
"manifest_hash": "<SHA-256 hex digest of canonicalized VAL-AM manifest>",
"policy": {
"policy_set_hash": "<SHA-256 hex>",
"decision": {
"effect": "ALLOW" | "DENY" | "ESCALATE" | "REFUSE" | "PAUSE",
"matched_rules": [
{ "name": "<rule>", "policy_name": "<policy>" },
...
],
"external_signals_used": ["<signal path>", ...]
}
},
"approval": {
"required": <boolean>,
"approver_urn": "<URN of approver, or null>",
"approver_method": "human" | "policy_attached" | "none",
"approved_at": "<RFC 3339 UTC timestamp, or null>"
},
"outcome": {
"executed": <boolean>,
"status": "success" | "failure" | "blocked" | "timeout",
"error_class": "<short error class, or null>",
"executed_at": "<RFC 3339 UTC timestamp, or null>",
"duration_ms": <integer, or null>
},
"chain": {
"prev_receipt_hash": "<SHA-256 hex of prior receipt's signed payload, or null for genesis>",
"sequence_number": <integer, monotonic per operator>
},
"timestamp": {
"tsa_url": "<URL of TSA>",
"tsa_token": "<base64-encoded RFC 3161 TimeStampToken>"
},
"extensions": {
"<namespace>": { ... }
}
}
4.2 The COSE_Sign1 envelope
The payload above is RFC 8785 JCS canonicalized → CBOR-encoded → wrapped in a COSE_Sign1 structure with the operator's signing key. The signature algorithm SHALL be one of:
| Algorithm | COSE identifier | Notes |
|---|---|---|
ES256 | -7 | ECDSA over P-256 with SHA-256. RECOMMENDED default. |
ES384 | -35 | ECDSA over P-384. |
EdDSA | -8 | Ed25519. RECOMMENDED for long-term archival. |
RS256 | -257 | RSASSA-PKCS1-v1_5 with SHA-256. Permitted for compatibility. |
5. Hash Chain
Each receipt's chain.prev_receipt_hash is the SHA-256 of the prior receipt's signed payload (the COSE_Sign1 protected bytes, not the inner CBOR alone). The chain starts at a genesis receipt with prev_receipt_hash = null and sequence_number = 0.
The hash chain provides tamper evidence: alteration of any past receipt invalidates every subsequent receipt's chain. An auditor verifies the chain by walking from genesis forward (or from the most recent receipt backward).
Operators MAY publish periodic chain checkpoints — a signed root hash of the chain at a given height — to anchor the chain externally (e.g., to a public blockchain, a notary, or a third-party transparency log). Checkpoint format is defined in a separate VAL-RF Extensions document.
6. Signing Key Management
The operator's signing key SHALL be controlled by the operator, NOT by VAL Inc. or any reference implementation provider.
Recommended key management practices:
- Keys SHOULD be backed by a hardware security module (HSM), cloud KMS, or equivalent.
- Keys SHOULD be rotated annually. Rotated keys SHOULD remain available for receipt verification indefinitely.
- The operator's public key SHOULD be published at a well-known URL (e.g.,
https://acme.example/.well-known/val-pubkey.jwks). - Operators MAY publish a key history with rotation timestamps for receipt verification across rotations.
7. RFC 3161 Timestamping
Each receipt SHALL include a timestamp.tsa_token field containing an RFC 3161 TimeStampToken issued by an independent TSA. The TSA SHOULD be one that maintains its own audit trail and root-anchored CA chain (e.g., DigiCert, GlobalSign, or a national TSA).
The TSA's timestamp covers the signed payload hash (not the receipt's signature). This independently bounds the receipt's existence time. A receipt issued at sequence number N with TSA timestamp T proves the operator knew the payload no later than T.
Operators in jurisdictions without easy TSA access MAY use a publicly auditable alternative (e.g., publishing the receipt hash to a blockchain). Such alternatives MUST be declared in extensions["org.openval.alt_timestamp"].
8. Verification Procedure
A third-party verifier (regulator, auditor, insurer, court) verifies a receipt as follows:
- Parse the COSE_Sign1 envelope; extract protected header, signed payload, signature.
- Fetch the operator's public key from the URL referenced in the protected header's
kid(key identifier). - Verify the signature with the public key.
- Validate the RFC 3161 TimeStampToken against the operator-archived TSA chain.
- Verify the hash chain — for each receipt in the verification window, compute SHA-256 of the prior receipt's signed payload and compare to
chain.prev_receipt_hash. - Verify the manifest binding — if the original manifest is available, canonicalize via JCS, hash via SHA-256, and compare to
manifest_hash. - Verify the policy binding — if the original policy set is available, compute the set hash per VAL-CPL Section 8 and compare to
policy_set_hash.
A receipt that passes all six checks is cryptographically authentic. Authenticity does not imply correctness of the policy decision — only that the decision was emitted by the operator-controlled key at the time claimed.
9. Worked Example
Genesis receipt for operator acme.example:
{
"receipt_id": "01963d2a-2e4f-7d6a-9c01-b3a7f8e9c2d1",
"spec_version": "0.1",
"issued_at": "2026-06-07T14:23:51.490Z",
"issuer": "urn:val:operator:acme.example",
"agent": {
"id": "support-fleet/refund-handler-v3",
"substrate": {
"vendor": "anthropic",
"model": "claude-opus-4-7",
"version": "claude-opus-4-7"
}
},
"manifest_hash": "a3f5b8c7d9e2f1a4b6c5d8e7f0a3b2c1d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9",
"policy": {
"policy_set_hash": "b4e6c9d8e3f2b1a5c7d6e9f8a1b4c3d2e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0",
"decision": {
"effect": "ESCALATE",
"matched_rules": [
{ "name": "refund-cap", "policy_name": "acme-support-agent-conduct" }
],
"external_signals_used": ["approver.role"]
}
},
"approval": {
"required": true,
"approver_urn": "urn:val:user:acme.example:support-lead:lpark",
"approver_method": "human",
"approved_at": "2026-06-07T14:25:09.103Z"
},
"outcome": {
"executed": true,
"status": "success",
"error_class": null,
"executed_at": "2026-06-07T14:25:11.522Z",
"duration_ms": 819
},
"chain": {
"prev_receipt_hash": null,
"sequence_number": 0
},
"timestamp": {
"tsa_url": "https://timestamp.digicert.com",
"tsa_token": "<base64-encoded RFC 3161 TimeStampToken>"
}
}
The above payload is JCS-canonicalized, CBOR-encoded, signed via ES256 with the operator's key, and wrapped in COSE_Sign1.
10. Receipt Storage and Retention
The receipt format does not mandate a storage backend. Operators choose:
- Operator-hosted ledger. Receipts stored in the operator's own database (Postgres, S3, etc.). Required for operators that will not route receipts through third parties.
- VAL Inc. hosted ledger. Operators MAY use the VAL Inc. reference hosted service for storage and indexing. The hosted service NEVER holds the operator's signing key.
- Hybrid. Receipts replicated to both for redundancy and analytics.
Retention SHOULD match the longest applicable regulatory window (e.g., 7 years for most financial regimes, indefinite for healthcare in some jurisdictions). The receipt format imposes no upper bound.
11. Policy Archive Practices
Receipt verification depends on the operator's ability to produce the policy text whose hash matches policy_set_hash. Operators SHOULD:
- Archive every policy version that has ever been deployed, indefinitely.
- Sign policy archive entries with the same or related key as receipts.
- Publish archived policies on an internal verification endpoint accessible to auditors.
A receipt whose policy_set_hash cannot be matched to an archived policy version is verifiable as authentic, but its policy decision becomes unauditable. Operators that fail to retain policies effectively weaken their own audit posture.
12. Conformance
An implementation conforms to VAL-RF v0.1 if:
- It emits receipts with all REQUIRED fields per Section 4.
- It uses one of the signature algorithms in Section 4.2.
- It includes a valid RFC 3161 TimeStampToken (or declared alternative).
- It correctly chains receipts per Section 5.
- It supports the verification procedure in Section 8.
- It passes the VAL-RF Conformance Test Suite (published separately).
13. Security Considerations
- Signing key compromise. If the operator's signing key is compromised, all receipts after the compromise date are suspect. Operators SHOULD implement key rotation and SHOULD support key revocation lists (CRLs) in the verifier procedure.
- TSA compromise. If the TSA is compromised, timestamps become unreliable. Operators in high-trust regimes SHOULD timestamp against multiple independent TSAs.
- Side-channel via receipt metadata. Extensions in the
extensionsfield appear in signed payloads and are publicly verifiable. Operators SHOULD NOT include secrets in extensions. - Replay. A receipt is uniquely identified by
receipt_idand bound to a specific manifest hash. Replay protection at the application layer is the agent runtime's responsibility, not VAL-RF's.
14. Privacy Considerations
- Receipts contain agent IDs, approver URNs, and manifest hashes. They do NOT contain raw manifest payloads. Operators choose what target identifiers to use in manifests, controlling indirect PII exposure (see VAL-AM Section 14).
- Receipts retained for regulatory windows MAY exceed PII retention requirements for the underlying business data. Operators SHOULD plan accordingly (e.g., by using opaque pseudonyms in
agent.context.originating_humanURNs).
15. Change Log
- v0.1 (2026): Initial publication.
16. References
- [RFC 2119] Key Words for Use in RFCs
- [RFC 3161] PKIX Time-Stamp Protocol
- [RFC 8949] Concise Binary Object Representation (CBOR)
- [RFC 9052] CBOR Object Signing and Encryption (COSE)
- [RFC 8785] JSON Canonicalization Scheme (JCS)
- [RFC 9562] UUIDs — UUIDv7
- VAL-AM — Action Manifest (this repository)
- VAL-CPL — Conduct Policy Language (this repository)
End of VAL-RF v0.1.