| Internet-Draft | RVP | September 2026 |
| van de Meent & AI | Expires 2 April 2027 | [Page] |
This document defines RVP, a protocol for asking a bounded verification question, carrying that question through one of several possible verification mechanisms, and producing evidence that is bound to the exact question. RVP separates five concerns that are often collapsed: the consumer policy that decides whether evidence is needed, the frozen evidence requirement, the lifecycle of the question, the carrier that obtains a response, and the later act of consuming the evidence.¶
RVP does not grant authority, establish admission, or replace account authentication and session policy. A successful result means only that the presented evidence satisfied the referenced requirement for the referenced question. The consumer and target system remain responsible for deciding what, if anything, may happen next.¶
The protocol supports local biometric checks, signed companion-device responses, WebAuthn, authenticated-session evidence, recovery standing, and future carriers without assigning ceremony semantics or authority to those carriers. It is transport-independent and can operate locally without a central identity provider.¶
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 2 April 2027.¶
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. Code Components extracted from this document must include Revised BSD License text as described in Section 4.e of the Trust Legal Provisions and are provided without warranty as described in the Revised BSD License.¶
Security systems frequently use one word, such as "verification" or "presence", for several different facts. An account may be authenticated, a session may still be valid, a human may be freshly present, a device may be enrolled, and a recovery key may permit repair. These facts can all be useful, but they are not interchangeable.¶
RVP represents verification as a question with a bounded lifecycle. A consumer freezes the evidence requirement, opens a request, and selects or offers one or more carriers. A carrier obtains a response. RVP verifies whether that response satisfies the frozen requirement. A consumer binds the result only when it actually uses the evidence. Policy and admission remain outside RVP.¶
This separation permits both high-friction and low-friction policies. One deployment can accept an OAuth-authenticated session with MFA for a workday, require fresh human presence after a pause, and require a stronger device-bound method for a sensitive transition. Another deployment can require fresh evidence for every transition. RVP carries the evidence for either policy; it does not choose between them.¶
Existing verification integrations commonly fail in one or more of the following ways:¶
This document defines:¶
This document does not define:¶
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.¶
consumer policy
| decides WHETHER evidence is required
v
frozen evidence requirement
| states WHAT evidence satisfies this purpose
v
verification lane
| owns request, lifetime, and terminal outcome
v
carrier
| presents the exact question and returns evidence
v
RVP evaluator
| verifies the response against the frozen requirement
v
consumer bind
| records actual consumption
v
target policy / admission
decides what may happen next
¶
An implementation MAY combine these components in one process, but it MUST preserve their semantic boundaries. In particular, a carrier success MUST NOT directly produce admission, and a lane MUST NOT infer a terminal outcome from an unmapped carrier-specific result.¶
The following facts are independent and MUST be represented separately:¶
A policy MAY require any conjunction or disjunction of these facts. For example, a policy can require a valid workday session and fresh presence after a pause. The policy MUST state that composition; RVP MUST NOT infer it from method strength or a scalar score.¶
A carrier window MUST carry exactly one request. Attaching the same window to a second request, including a request in another lane, MUST fail. A responder and verifier MUST reject a response if the window or challenge resolves to zero or more than one request.¶
Multiple carriers MAY be offered for one request. Their responses still terminate the same lane, and a terminal lane MUST reject later responses as stale.¶
RVP records are JSON objects as defined by [RFC8259]. Deployments MAY use another serialization if it preserves every field and defines an equivalent canonical representation. The examples in this section omit deployment-specific signatures and provenance fields for readability. The kind identifiers and assurance labels in these examples are illustrative; an interoperable profile MUST define the meaning of any assurance labels it uses. Draft revision -03 and record version 2 identify different version spaces.¶
An evidence requirement is immutable after publication. A reference MUST contain all of:¶
evidence_requirement_id: a stable local or globally
scoped identifier;¶
evidence_requirement_version: an immutable revision;¶
evidence_requirement_digest: a digest of the canonical
requirement bytes.¶
A requirement body SHOULD state its purpose, evidence class, accepted method or assurance constraints, freshness rule, and an explicit statement that satisfying the requirement grants nothing.¶
{
"kind": "org.example.rvp.evidence-requirement.v1",
"evidence_requirement_id": "admin_ctx_entry_presence",
"evidence_requirement_version": 1,
"purpose": "admin.enter",
"evidence_class": "fresh_human_presence",
"accepted_assurance": ["H1", "H2"],
"freshness": {"type": "inside_request_window"},
"grants": "nothing"
}
A bare identifier that can silently resolve to a newer version MUST NOT be used in a request. A digest mismatch makes the requirement unresolved and the request unanswerable.¶
A request MUST contain:¶
request_id and scoped lane_ref.¶
window_ref and challenge_ref.¶
{
"protocol": "RVP",
"version": 2,
"kind": "org.example.rvp.request.v2",
"request_id": "pr-8a41b7c2",
"lane_ref": "presence:admin-entry:17",
"window_ref": "win-f04ac811",
"challenge_ref": "cid-ef86b3d0",
"op": "admin.enter",
"target": "box:raint-a46acdf5",
"subject": "jasper.aint",
"actor": "jasper-admin.aint",
"on_behalf_of": "jasper.aint",
"consumer": "iab-admin",
"purpose": "admin.enter",
"evidence_requirement": {
"evidence_requirement_id": "admin_ctx_entry_presence",
"evidence_requirement_version": 1,
"evidence_requirement_digest": "sha256:..."
},
"created_at": "2026-09-25T10:00:00Z",
"deadline": "2026-09-25T10:00:45Z",
"question_commitment": {
"version": 2,
"algorithm": "sha-256",
"digest": "sha256:..."
}
}
The on_behalf_of field, when present, names the principal on
whose behalf the actor operates. It MUST NOT be used in the reverse
direction. Absent optional identity fields MUST be represented as
explicit null values in the question commitment.¶
A successful response MUST identify the request, lane, window, challenge, evidence method and class, subject or presenter, issue time, expiry or freshness boundary, requirement digest, and question commitment. It MUST contain or reference cryptographic evidence that covers these fields.¶
{
"protocol": "RVP",
"version": 2,
"kind": "org.example.rvp.evidence-response.v2",
"response_id": "re-19d1e4c7",
"request_id": "pr-8a41b7c2",
"lane_ref": "presence:admin-entry:17",
"window_ref": "win-f04ac811",
"challenge_ref": "cid-ef86b3d0",
"subject": "jasper.aint",
"presenter": "device:phone-7",
"evidence_class": "fresh_human_presence",
"method": "passkey-smartphone",
"assurance": "H2",
"issued_at": "2026-09-25T10:00:12Z",
"expires_at": "2026-09-25T10:00:45Z",
"evidence_requirement_digest": "sha256:...",
"question_commitment": {
"version": 2,
"digest": "sha256:..."
},
"signature": {
"key_ref": "jis:phone-7.aint#ed25519",
"suite": "ed25519",
"value": "base64url:..."
},
"grants": "nothing"
}
A local biometric carrier MAY use a locally attested result instead of a portable signature, but it MUST bind the result to the same request and question commitment. A claim that a biometric check occurred is not equivalent to a measured biometric result.¶
A matching response does not mean that any consumer used it. When a consumer uses a successful response, it MUST write or return a separate binding containing:¶
A response MUST NOT be bound more than once unless the requirement explicitly permits multiple named consumers. Such a requirement MUST list those consumers and each consumption MUST produce its own binding. The permitted purposes and target scopes for each consumer MUST also be frozen in the requirement; consumers MUST NOT add a new purpose after the response. Consumption MUST be serialized or otherwise made atomic so concurrent consumers cannot bypass these limits.¶
Before binding, the consumer MUST check that the evidence remains usable under the frozen freshness rule and that the referenced target transition is still current. Expiry, revocation, or replacement of the target state MUST NOT be hidden by a historical match. A profile MUST define how these checks are coordinated with consumption and how a retry identifies an existing binding without consuming again.¶
JSON-based profiles of RVP SHOULD use the JSON Canonicalization Scheme [RFC8785] before hashing or signing. A profile that uses another canonicalization MUST identify it in the signed data. Digest and signature algorithm identifiers MUST be explicit.¶
A transport challenge proves freshness only for that challenge. It does not prove what operation or target was shown to the responder. RVP therefore requires a question commitment for every signed response.¶
Question commitment version 2 covers at least:¶
request_id, lane_ref, window_ref, and
challenge_ref.¶
op, target, subject, actor,
and on_behalf_of, including explicit null values.¶
The window and challenge references MUST be allocated before the commitment is frozen. Multiple carriers offered for that request MUST bind to this same question; carrier-specific challenges, if any, MUST be verifiably bound to it by the carrier profile. A profile MUST define the exact commitment object, its canonical bytes, domain separator, and digest construction. The commitment digest itself and response signature are not inputs to that commitment.¶
For human approval, the responder MUST derive both the commitment and an unambiguous rendering from the same frozen question fields. An automated evidence carrier MUST bind to those same fields without claiming that human approval occurred. The verifier MUST recompute it from its own request record. A mismatch MUST terminate the lane without binding.¶
A verifier that requires question commitment version 2 MUST NOT silently accept a version 1 response that signs only a challenge. Version negotiation MUST happen before the question is presented, and a downgrade MUST be visible to the consumer.¶
An implementation MAY arm a scoped lane before a request arrives. Arming states that a verification path is prepared; it does not state that a human is present, that a request has been made, or that a carrier is reachable.¶
The canonical lifecycle event name for this phase is
presence.arm when the evidence class is human presence. Other
evidence classes SHOULD use an equally scoped event name rather than
overloading presence.¶
The consumer creates a request after freezing the requirement and
question commitment. The request enters the proposed state. The
canonical human-presence event name is presence.request.¶
Creating or persisting a request does not prove that any carrier is serving it. A system that tells a human that a question is answerable SHOULD measure that at least one selected carrier is serving the same window and request.¶
A lane reaches exactly one of the following terminal outcomes:¶
Carrier-specific outcomes MUST be mapped explicitly into this set.
An unknown carrier or unmapped carrier outcome MUST fail closed. Only
match is eligible for binding. The canonical human-presence
response event is presence.response, and it records the typed
terminal outcome.¶
A lane terminal outcome is immutable. Implementations MUST arbitrate competing responses and deadline events so only one terminal outcome is committed. Rejected late responses MAY be recorded separately but MUST NOT replace an earlier match, refusal, or other terminal result.¶
A consumer binds a matched response only when it actually applies
the evidence to its named purpose. The canonical human-presence event
is presence.bind. A lane closure with any other outcome MUST
NOT emit a bind.¶
A bind does not imply admission. For example, fresh human presence can satisfy the evidence requirement for entering a read context. Access to protected information still requires the applicable read authorization; the evidence does not create that authorization.¶
Interactive and headless operation MAY share one request and one carrier window. An interactive caller can wait for the terminal result; a headless caller can return while the same request remains pending. These are caller behaviors, not different ceremonies.¶
A persisted window is not proof that its carrier service survived a process or system restart. An implementation that resumes a persisted request MUST re-establish and measure the carrier for the same window, or report the carrier as unreachable. It MUST NOT create a second question merely to restart transport.¶
RVP separates the following time domains:¶
These durations answer different questions and MUST NOT be derived from one another without an explicit profile rule. RVP defines no universal default duration. A process timeout such as the time spent waiting for a fingerprint reader is not, by itself, an evidence-freshness policy.¶
Implementations SHOULD use a monotonic clock for local waiting and an authenticated or causally ordered record for protocol events. Wall-clock timestamps are useful for interchange but MUST NOT be the only replay defense.¶
Evidence class describes what a result means. Method describes how the result was obtained. Assurance and anchoring describe additional properties. These fields MUST remain separate.¶
Fresh human-presence evidence states that a qualifying measurement associated a human with this request inside the required window. Local fingerprint matching, a hardware-backed authenticator with user verification, and a signed companion-device approval can be methods for this class when the frozen requirement accepts their measured properties. A device signature alone MUST NOT be treated as evidence that a human acted during the request window.¶
Being root, holding a process position, setting an environment variable, or possessing an unsigned record is not a human-presence method.¶
An authenticated session can be evidence that an account completed a login ceremony and remains inside a policy-defined session. OAuth, MFA, SSH, and local login systems can establish such standing. This evidence MAY satisfy requirements designed for session standing. It MUST NOT be relabelled as fresh human presence.¶
A recovery key or recovery procedure can establish the right to address an unresolved binding or restore state. It does not prove fresh presence and does not necessarily grant ordinary operation. A consumer MAY require recovery standing together with fresh presence or session evidence.¶
An implementation MAY use numeric scores to select or evaluate local methods. Such scores are method- and deployment-specific metadata. They MUST NOT be added across unrelated evidence classes, interpreted as portable admission decisions, or compared between deployments unless a profile defines the complete calibration and semantics.¶
A requirement SHOULD prefer explicit accepted methods, assurance classes, anchoring properties, and freshness rules over an unqualified scalar threshold.¶
A carrier MUST:¶
A carrier MUST NOT:¶
RVP lifecycle events can be recorded in a provenance system such as TIBET [TIBET]. A typical sequence is:¶
presence.arm presence.request presence.response outcome=match|refused|timed_out|... presence.bind only after successful consumer consumption¶
The provenance writer can serialize, hash-chain, sign, and durably append these records. That mechanical inscription does not decide the evidence result or grant authority. A chain hash proves record integrity and ordering; it is not a substitute for the responder's signature or the target's admission decision.¶
Missing history MUST NOT be rewritten as a successful history. A deployment that imports a pending request created before lifecycle recording existed can describe its opening as unrecorded and still record an honest later closure.¶
Two implementations conform to this document for a profile only if they agree on:¶
A conformance suite SHOULD include at least the following hostile cases:¶
Test reporting MUST distinguish a verified measurement harness from protocol conformance. A harness can operate correctly while exposing a contract gap; this is not full conformance.¶
RVP does not require a central verifier. Requirements, request records, enrolled device keys, local biometric results, and consumer bindings can all remain under the target operator's control.¶
Offline operation does not mean weakening an unresolved requirement. If the required carrier or validation material is unavailable, the lane terminates as unreachable or remains pending according to policy. It MUST NOT silently become a match.¶
Raw biometric data SHOULD be processed on the measuring device and SHOULD NOT appear in an RVP response. The response should contain the minimum method, assurance, anchoring, and result data needed to verify the requirement.¶
RVP is transport-independent. Records can be carried over local IPC, HTTP, QR-mediated companion-device exchanges, message queues, removable media, or other transports. The transport MUST preserve the bytes covered by question commitments and signatures.¶
Transport reachability is not evidence. TLS authenticates and protects a channel, but it does not by itself satisfy an RVP evidence requirement. Likewise, an HTTP success response does not imply that the lane bound the result.¶
Continuous collection can become continuous surveillance. RVP does not require continuous telemetry. A deployment SHOULD request evidence only at policy-defined transitions and SHOULD disclose the purpose before the responder acts.¶
Implementations MUST minimize evidence records. Raw fingerprints, facial images, voice recordings, keystrokes, and behavioral traces MUST NOT be included merely to make a response independently auditable. Local verifiers should instead attest the result and retain only what the requirement and incident policy need.¶
Stable subject, device, lane, and key identifiers enable correlation. Profiles SHOULD support scoped or pairwise identifiers where global linkage is unnecessary. Retention periods for requests, failed outcomes, and bindings SHOULD be independently configurable.¶
A strong method does not make every evidence class true. A passkey can establish a signed device response and user verification, but it does not prove a local fingerprint was measured. A recovery key can permit repair, but it does not become fresh presence. Verifiers MUST compare the evidence class and requirement, not only an assurance label.¶
If a responder signs only a challenge, a compromised or buggy server can show one operation and apply the signature to another. The complete question commitment in Section 5 is REQUIRED to prevent this attack.¶
Challenges MUST be one-time, windows MUST carry one question, and a terminal lane MUST reject later responses. Expiry is necessary but not sufficient: replay protection also requires durable consumption or closure state.¶
Binding at response time creates authority leakage: evidence can be recorded as used even when the consumer rejected or never observed it. Implementations MUST keep match and bind as separate state transitions.¶
A persisted carrier window can outlive the process serving it. Implementations SHOULD probe the service against the same request or otherwise prove that it serves that exact window. Starting a process and recording its process identifier is not sufficient proof that it successfully bound a socket or can verify the request.¶
Key rotation SHOULD preserve a relationship only when a verifiable continuity link connects the old and new keys, as described by JIS [JIS]. A new key without such a link is a new or forked identity, not a silent rotation. Even a valid rotation can trigger a policy requirement for fresh evidence; RVP carries that evidence but does not mandate the policy.¶
This document requests registration of the
application/rvp+json media type in the Standards Tree using the
procedure in [RFC6838]. This is a registration request;
publication of this Internet-Draft does not itself register the media
type.¶
RVP version 1 tokens can contain a method, scalar confidence, threshold, resolution, and transport challenge without committing to the complete question. Such a token MUST NOT be accepted where a version 2 requirement demands operation and target binding.¶
A deployment can retain version 1 records as historical evidence. It SHOULD label them as not carrying question commitment version 2. A version 2 verifier MUST NOT manufacture missing fields from its local state and then claim that the signer approved them.¶
The authors thank Codex (codex.aint) for the implementation crosswalk, hostile protocol analysis, and architecture rewrite that informed this revision. The separation between policy, requirements, lanes, carriers, evidence, and binding was refined through implementation and testing in AInternet-in-a-box.¶