| Internet-Draft | VAP-LAP | February 2026 |
| Yamakawa | Expires 28 August 2026 | [Page] |
This document specifies the Verifiable AI Provenance (VAP) Framework, a cross-domain upper framework for cryptographically verifiable decision audit trails in high-risk AI systems, along with the Legal AI Profile (LAP), a domain-specific instantiation for legal AI and LegalTech systems.¶
VAP defines common infrastructure including hash chain integrity, digital signatures, unified conformance levels (Bronze/Silver/Gold), external anchoring via RFC 3161 Time-Stamp Protocol and compatible transparency services (including IETF SCITT), a Completeness Invariant pattern guaranteeing no selective logging, standardized Evidence Pack format for regulatory submission, and privacy-preserving verification protocols.¶
LAP extends VAP for the judicial AI domain, addressing unique requirements including attorney oversight verification (Human Override Coverage), three-pipeline completeness invariants for legal consultation, document generation, and fact-checking, tiered content retention with legal hold protocols for judicial discovery compliance, graduated override enforcement mechanisms, and privacy- preserving fields designed to maintain attorney-client privilege while enabling third-party auditability.¶
This Internet-Draft is submitted in full conformance with the provisions of BCP 78 and BCP 79.¶
Internet-Drafts are working documents of the Internet Engineering Task Force (IETF). Note that other groups may also distribute working documents as Internet-Drafts. The list of current Internet-Drafts is at https://datatracker.ietf.org/drafts/current/.¶
Internet-Drafts are draft documents valid for a maximum of six months and may be updated, replaced, or obsoleted by other documents at any time. It is inappropriate to use Internet-Drafts as reference material or to cite them other than as "work in progress."¶
This Internet-Draft will expire on 28 August 2026.¶
Copyright (c) 2026 IETF Trust and the persons identified as the document authors. All rights reserved.¶
This document is subject to BCP 78 and the IETF Trust's Legal Provisions Relating to IETF Documents (https://trustee.ietf.org/license-info) in effect on the date of publication of this document. Please review these documents carefully, as they describe your rights and restrictions with respect to this document.¶
The deployment of AI systems in high-risk domains -- including finance, healthcare, transportation, and the administration of justice -- creates a structural accountability gap. AI decisions that affect fundamental rights and societal infrastructure lack standardized, cryptographically verifiable audit trails that independent third parties can inspect.¶
Current approaches rely on trust-based governance: AI providers assert that their systems are safe and well-logged, but no independent party can cryptographically verify these claims. The Verifiable AI Provenance (VAP) Framework addresses this gap by defining a "Verify, Don't Trust" architecture for AI decision provenance.¶
This document defines two complementary specifications:¶
VAP targets AI systems where "system failure could cause significant and irreversible harm to human life, societal infrastructure, or democratic institutions." This intentionally strict scope distinguishes VAP from general-purpose logging frameworks.¶
LAP specifically addresses legal AI systems that provide AI-powered legal consultation, document generation, and fact-checking services to licensed attorneys.¶
The core principle is "Verify, Don't Trust." Rather than relying on AI providers' claims about the safety and integrity of their systems, VAP enables independent, cryptographic verification of every AI decision's provenance, completeness, and human oversight.¶
NOTE: This Internet-Draft is the authoritative specification for the VAP Framework and LAP Profile. Where differences exist between this document and other published descriptions of the VAP Framework (e.g., companion white papers or implementation guides), this Internet-Draft takes precedence.¶
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 [RFC2119] [RFC8174] when, and only when, they appear in all capitals, as shown here.¶
VAP is organized into four core layers, a common infrastructure layer, and a domain profile layer:¶
VAP supports multiple domain profiles. Each profile MUST define:¶
Registered profiles include VCP (Finance), CAP (Content/Creative AI), and LAP (Legal AI, defined in Part II of this document). Additional profiles for automotive (DVP), medical (MAP), and public administration (PAP) domains are under development.¶
All VAP-conformant implementations MUST support the primary algorithms listed below. Implementations SHOULD support at least one alternative algorithm in each category for migration purposes. Post-quantum algorithms are listed for future migration readiness and are currently OPTIONAL.¶
| Category | Primary (MTI) | Alternative | Post-Quantum (Future MTI) |
|---|---|---|---|
| Hash | SHA-256 | SHA-384, SHA-512 | SHA3-256 |
| Signature | Ed25519 ([RFC8032]) | ECDSA P-256 ([RFC6979]) | ML-DSA-65 ([FIPS204]) |
| Encryption | AES-256-GCM | ChaCha20-Poly1305 | N/A (see KEM row) |
| KEM | N/A (classical key exchange) | N/A | ML-KEM-1024 ([FIPS203]) |
Note: The Post-Quantum signature algorithm ML-DSA-65 (formerly known as CRYSTALS-Dilithium, renamed upon FIPS 204 standardization in August 2024) provides security equivalent to AES-192. This parameter set was selected as a balance between signature size (3,309 bytes) and security margin for legal audit trails requiring multi-decade retention. ML-DSA-44 (AES-128 equivalent) was considered insufficient for the intended retention periods; ML-DSA-87 (AES-256 equivalent) imposes significantly larger signatures (4,627 bytes) with marginal practical benefit for this use case.¶
Note: ML-KEM-1024 (formerly known as CRYSTALS-Kyber, renamed upon FIPS 203 standardization in August 2024) is a key encapsulation mechanism (KEM), not an encryption algorithm. It is listed separately from symmetric encryption because KEM and symmetric encryption serve different roles: KEM establishes shared secrets for key agreement, while AES-256-GCM provides authenticated encryption of content.¶
Implementations MUST include algorithm identifiers in all cryptographic fields. The following table defines the canonical algorithm identifiers used in field values and wire-format prefixes:¶
| Algorithm | Field Value (hash_algo / sign_algo) | Wire Prefix (in encoded strings) | Reference |
|---|---|---|---|
| SHA-256 | "sha-256" | "sha-256:" | NIST FIPS 180-4 |
| SHA-384 | "sha-384" | "sha-384:" | NIST FIPS 180-4 |
| SHA-512 | "sha-512" | "sha-512:" | NIST FIPS 180-4 |
| SHA3-256 | "sha3-256" | "sha3-256:" | NIST FIPS 202 |
| Ed25519 | "ed25519" | "ed25519:" | [RFC8032] |
| ECDSA P-256 | "ecdsa-p256" | "ecdsa-p256:" | [RFC6979] |
| ML-DSA-65 | "ml-dsa-65" | "ml-dsa-65:" | [FIPS204] |
All algorithm identifiers MUST be lowercase ASCII strings with hyphens as separators. The field value and wire prefix use the same string (the wire prefix appends a colon as delimiter). Implementations MUST perform case-insensitive comparison when validating algorithm identifiers but MUST produce lowercase output. These identifiers enable crypto agility and algorithm migration as specified in Section 4.4.¶
Events MUST be linked in a hash chain where each event's hash includes the hash of the preceding event.¶
The Hash Input is computed by removing the following fields from the event before canonicalization:¶
The remaining fields (including security.hash_algo, security.sign_algo, and security.signer_id) are retained in the hash input. This explicit exclusion list prevents circular references (event_hash cannot be included in its own computation) and ensures that implementations agree on the hash input.¶
The computation proceeds as follows:¶
HashInput[n] = Event[n] with {security.event_hash,
security.signature} removed
EventHash[n] = HashAlgo(JCS-Canonicalize(HashInput[n]))
where:
Event[n].header.prev_hash = EventHash[n-1]
Event[0].header.prev_hash = null (genesis event)
HashAlgo is the algorithm specified in security.hash_algo
JCS-Canonicalize follows RFC 8785
¶
Canonicalization MUST follow [RFC8785] (JSON Canonicalization Scheme).¶
Chain integrity verification MUST confirm:¶
Every event MUST be signed. The signature MUST be computed over the EventHash bytes (not over the raw event):¶
Signature = SignAlgo.Sign(PrivateKey, EventHash_bytes)¶
The signature MUST be encoded as follows:¶
security.signature = sign_algo_id ":" Base64url(Signature_bytes)¶
where sign_algo_id is the canonical algorithm identifier from Table 2 matching the security.sign_algo field (e.g., "ed25519", "ecdsa-p256"), and Base64url encoding follows [RFC4648] Section 5 (URL-safe alphabet, no padding).¶
The primary mandatory-to-implement (MTI) signature algorithm is Ed25519 [RFC8032]. Implementations MUST support Ed25519 and SHOULD support at least one additional algorithm from Table 1 for migration purposes.¶
VAP is designed for crypto agility per BCP 201 [RFC7696]. Algorithm migration proceeds as follows:¶
During migration, the hash chain MAY contain events signed with different algorithms. Verifiers MUST support all algorithms that appear in the chain being verified.¶
Audit trails with multi-decade retention periods (up to 10 years at Gold level) face exposure to "harvest now, decrypt later" attacks. NIST has announced timelines for deprecating RSA and ECC algorithms (targeted deprecation by 2030, disallowance by 2035).¶
Implementations with Gold-level retention requirements SHOULD prepare for post-quantum transition by:¶
All VAP-conformant events MUST include the following fields:¶
{
"vap_version": "1.3",
"profile": {
"id": "string (VCP|CAP|LAP|DVP|MAP|PAP)",
"version": "semver string"
},
"header": {
"event_id": "UUIDv7 (RFC 9562)",
"chain_id": "UUIDv7",
"prev_hash": "sha-256:<64 lowercase hex chars> | null",
"timestamp": "RFC 3339 datetime with timezone",
"event_type": "string (profile-specific)",
"causal_link": {
"target_event_id": "UUIDv7 | null",
"link_type": "string (OUTCOME_OF|OVERRIDE_OF|HOLD_ON|
RECOVERY_OF|TIER_CHANGE_OF|null)"
}
},
"provenance": {
"actor": {
"actor_id": "string",
"actor_hash": "sha-256:<64 lowercase hex chars>",
"role": "string"
},
"input": { },
"context": { },
"action": { },
"outcome": { }
},
"accountability": {
"operator_id": "string",
"last_approval_by": "string",
"approval_timestamp": "RFC 3339"
},
"domain_payload": { },
"security": {
"event_hash": "sha-256:<64 lowercase hex chars>",
"hash_algo": "sha-256",
"signature": "ed25519:base64url...",
"sign_algo": "ed25519",
"signer_id": "string"
}
}
¶
Event identifiers MUST use UUIDv7 ([RFC9562]) to ensure time-ordered sortability. JSON canonicalization MUST follow [RFC8785].¶
The profile.id field MUST be 1-4 uppercase ASCII characters matching a registered profile identifier (see Section 21.2). Note that profile identifiers use uppercase (e.g., "LAP") while algorithm identifiers use lowercase (e.g., "sha-256") per Table 2; this distinction is intentional and reflects their different registries.¶
Timestamps MUST conform to [RFC3339] (a profile of ISO 8601) and MUST include a timezone offset or "Z" for UTC. Implementations SHOULD use UTC for all timestamps.¶
The header.causal_link field provides a standardized location for referential integrity across all profiles. Outcome events MUST set target_event_id to the originating attempt event's identifier and link_type to "OUTCOME_OF". HUMAN_OVERRIDE events MUST set target_event_id to the target output event and link_type to "OVERRIDE_OF". Events with no causal link MUST set both fields to null.¶
Hash values MUST be encoded as lowercase hexadecimal strings, prefixed with the canonical algorithm identifier (from Table 2) followed by a colon (e.g., "sha-256:a1b2c3..."). The hexadecimal string MUST be the exact length corresponding to the hash output (64 characters for sha-256, 96 for sha-384, 128 for sha-512).¶
All text fields MUST be encoded as UTF-8 ([RFC3629]).¶
Fields representing monetary amounts, cryptographic values, or high-precision measurements SHOULD be encoded as JSON strings rather than JSON numbers. This recommendation is motivated by:¶
Fields where exact precision is not critical (e.g., event_count, token_count) MAY use JSON numbers. Implementations MUST document which fields use string encoding. Implementations that use JSON numbers for counters MUST ensure that any numeric-to-string conversion performed during canonicalization is deterministic and documented, to avoid signature verification ambiguity across languages and libraries.¶
VAP defines three conformance levels applicable to all domain profiles. Each level inherits all requirements of lower levels (Gold is a superset of Silver, which is a superset of Bronze).¶
Target: SMEs, early adopters. Core capabilities:¶
Note: Formal JSON Schema definitions for validation are provided in Appendix "Appendix B. Validation Requirements". Bronze implementations MUST validate the presence and type of all REQUIRED fields defined in Section 5.¶
Target: Enterprise, regulated industries. Additional requirements beyond Bronze:¶
Target: Highly regulated industries. Additional requirements beyond Silver:¶
External anchoring proves that events existed at a specific point in time, preventing backdating, forward-dating, and log forking.¶
VAP defines an abstract anchoring interface that can be realized by multiple service types. The baseline anchoring service is [RFC3161] Time-Stamp Authority (TSA), with [RFC5816] support for ESSCertIDv2 (enabling SHA-256 certificate identification instead of SHA-1). Additional service types include transparency logs and public blockchains.¶
Gold Level implementations MUST use at least one transparency log service (such as SCITT) or equivalent, in addition to or instead of RFC 3161 TSA. Implementations SHOULD use multiple independent anchoring services for critical deployments.¶
{
"anchor_id": "UUIDv7",
"anchor_type": "RFC3161 | TRANSPARENCY_LOG | BLOCKCHAIN",
"merkle_root": "sha-256:<64 lowercase hex chars>",
"event_count": 1000,
"first_event_id": "UUIDv7",
"last_event_id": "UUIDv7",
"first_event_timestamp": "RFC 3339",
"last_event_timestamp": "RFC 3339",
"anchor_timestamp": "RFC 3339",
"anchor_proof": { },
"service_endpoint": "https://tsa.example.com"
}
¶
The anchor_proof field is an object whose structure depends on the anchor_type:¶
Events MUST be batched into a binary Merkle hash tree for efficient anchoring and selective disclosure. The tree construction follows [RFC9162] (Certificate Transparency Version 2.0) Section 2, which obsoletes [RFC6962]:¶
MTH({}) = SHA-256() (empty hash for zero inputs)
MTH({d(0)}) = SHA-256(0x00 || d(0))
MTH(D[n]) = SHA-256(0x01 || MTH(D[0:k]) || MTH(D[k:n]))
where:
D[n] is the list of n event hashes
k is the largest power of 2 less than n
0x00 is the leaf node prefix
0x01 is the interior node prefix
|| denotes concatenation
¶
This construction uses domain separation prefixes (0x00 for leaves, 0x01 for interior nodes) to prevent second-preimage attacks, and handles non-power-of-two leaf counts without duplicating leaves, consistent with [RFC9162].¶
The resulting Merkle root is submitted to the external anchoring service. Merkle inclusion proofs enable selective disclosure: a verifier can confirm that a specific event is included in an anchored batch without accessing other events in the batch.¶
The Completeness Invariant is a mathematical guarantee that every "attempt" event has exactly one corresponding "outcome" event. This prevents selective logging -- the omission of inconvenient records.¶
General form:¶
For each pipeline P:
Count(P_ATTEMPT) = Count(P_SUCCESS)
+ Count(P_DENY)
+ Count(P_ERROR)
¶
The invariant enforces three properties:¶
Domain profiles MUST specify which event types constitute attempts and outcomes for the invariant. Each outcome event MUST set header.causal_link.target_event_id to the originating attempt event's event_id and header.causal_link.link_type to "OUTCOME_OF".¶
Verification SHOULD account for a configurable grace period for in-flight operations. The grace period MUST NOT exceed 300 seconds (RECOMMENDED default: 60 seconds). If an ATTEMPT event has no corresponding outcome event after the grace period has elapsed, a verification implementation SHOULD treat this as a completeness violation. Implementations MAY emit a synthetic TIMEOUT_ERROR outcome event when the grace period expires, to maintain the invariant.¶
An Evidence Pack is a self-contained, signed package of provenance events suitable for regulatory submission and third-party audit.¶
An Evidence Pack MUST contain:¶
The Evidence Pack SHOULD be packaged as a ZIP archive with the media type application/vap-evidence-pack+zip (see Section 21.1). The manifest MUST use the media type application/vap-manifest+json.¶
The manifest MUST include the following fields:¶