Module 6: Verification, attestation, and revocation

Understand exactly what verification proves, what it does not prove, and how to handle revocation failure.

DEV, PROVIDER, GOVERNANCE 25 min

Learning objectives

By the end of this module, you will be able to:

  • Run the maintained Python verification API and handle all 18 outcomes
  • Distinguish signature integrity, configured trust, and attestation claim quality
  • Configure online or revocation-list (CRL) checking and handle its failure safely
  • Describe the additional evidence required for audit or compliance claims

6.1 — Verification in practice

Verification takes the bundle and a description of where you intend to use it: which model, for what purpose, in which environment, for which audience and region. The orchestrator checks the bundle's declared scope against that description, along with its signatures, trust anchors, time window and revocation status, and returns one outcome.

from vcp import Orchestrator, VerificationContext, VerificationResult

verification_context = VerificationContext(
    trust_config=trust,
    model_family="example-model-*",
    purpose="customer-support",
    environment="production",
    audience="adult",
    region="GB",
)

result = Orchestrator(trust).verify(
    bundle,
    context=verification_context,
)

if result is not VerificationResult.VALID:
    raise PermissionError("VCP verification failed: " + result.name)

The SDK does not promise that verification finishes within any fixed time, and no outcome means "timed out". Fetching bundles and checking revocation both go over the network, so put your own timeout around that work at the application boundary, and decide and document what your application does when it fires.

6.2 — The 18 verification outcomes

OutcomeSDK categoryMeaning
VALIDSuccessAll configured verification checks passed
SIZE_EXCEEDEDSecurityManifest or content exceeded the accepted byte bound
INVALID_SCHEMAConfigurationBundle shape or types were malformed
UNTRUSTED_ISSUERConfigurationNo valid issuer trust anchor matched
INVALID_SIGNATURESecurityIssuer signature did not verify
UNTRUSTED_AUDITORConfigurationNo valid auditor trust anchor matched
INVALID_ATTESTATIONSecurityAttestation signature or claim structure was invalid, or the claim type was not INJECTION_SAFE or FULL_AUDIT
HASH_MISMATCHSecurityCanonical content did not match the manifest hash
NOT_YET_VALIDTemporalCurrent time is earlier than the bundle's not-before time (nbf)
EXPIREDTemporalCurrent time is past the bundle's expiry time (exp)
FUTURE_TIMESTAMPSecurityThe issued-at time (iat) is later than now by more than the allowed clock skew
REPLAY_DETECTEDSecurityThis bundle's unique ID (jti) was already in the bounded replay cache, so this exact bundle has been seen before
TOKEN_MISMATCHSecurityDeclared token information did not match
BUDGET_EXCEEDEDConfigurationBundle budget exceeded the configured context allowance
SCOPE_MISMATCHConfigurationModel, purpose, environment, audience, or region did not match scope
REVOKEDSecurityConfigured revocation evidence marks the bundle revoked
FETCH_FAILEDTransientA required bounded network retrieval failed. Reserved; SDK 4.2.0 does not return it
REVOCATION_UNAVAILABLETransientNo configured revocation source could establish a status, so the bundle was rejected (fail closed)

Only VALID lets the application continue to local enforcement. The category tells you what a failure means. A transient failure, such as an unreachable revocation service, may pass on a later attempt. A temporal failure means the bundle is outside its valid time window. A configuration failure means the bundle's shape, issuer, auditor, scope or budget does not match what your deployment accepts. A security failure, such as a bad signature, altered content, a replayed bundle or a revocation, will not fix itself, so never retry it as if it were transient.

6.3 — Safety attestation

The issuer signature binds bundle bytes to an issuer key. Every bundle must also carry a safety-attestation claim signed by a separately trusted auditor. VCP-SDK 4.2.0 recognizes the four claim types below, but only INJECTION_SAFE and FULL_AUDIT pass verification, because only they cover the risk of placing the bundle in a model's prompt. A bundle attested as CONTENT_SAFE or COMPETENCE_CALIBRATION fails with INVALID_ATTESTATION:

TypeClaim
INJECTION_SAFEThe auditor asserts the defined injection-safety review was completed
CONTENT_SAFEThe auditor asserts the defined content-safety review was completed
FULL_AUDITThe auditor asserts the organization's defined full-audit evidence exists
COMPETENCE_CALIBRATIONThe auditor asserts the defined competence-calibration review was completed

A valid signature shows that the bytes have not changed since signing (integrity) and that a key you configured as trusted signed them (provenance). On its own, it does not establish that the review method was adequate, lawful, complete, or correctly described. Your governance process must define the evidence required for each claim.

6.4 — Revocation

A manifest may name an HTTPS endpoint (check_uri) that answers in real time whether this one bundle has been withdrawn, and a certificate revocation list, or CRL (crl_uri), a published list of every withdrawn bundle ID. The SDK tries the endpoint first and falls back to the list. It validates schemes, ports, credentials, fragments, DNS results, resolved addresses, response size, JSON shape, issuer binding, and freshness before accepting network evidence. Those checks keep a hostile manifest from steering the checker toward addresses inside your own network or feeding it a stale answer.

"revocation": {
  "check_uri": "https://status.example.org/vcp/revocation",
  "crl_uri": "https://status.example.org/vcp/crl.json"
}

If a manifest declares no revocation URI, both SDKs treat the bundle as not revoked; the Python SDK also logs a warning. High-assurance deployments that require revocation must add that rule themselves, in application policy or a custom enforcement plugin, and reject any bundle that names no approved revocation mechanism.

If no configured endpoint can establish a status, the orchestrator returns REVOCATION_UNAVAILABLE and rejects the bundle. A confirmed revocation returns REVOKED. An unavailable status may clear on a retry within your deadline. Decide in advance, for each kind of action your application takes, whether to block or to continue in a constrained mode that does not use this bundle.

6.5 — What verification proves

  • The accepted bytes matched their declared canonical hash
  • The signatures verified under the configured algorithms and keys
  • The issuer and auditor matched current trust anchors
  • Configured temporal, replay, budget, scope, and revocation checks passed

Verification does not prove that a model followed the content, a tool action was safe, a reviewer exercised sound judgment, the system complied with law, or downstream logs are complete. Those need separate runtime, human, legal, and operational evidence.

Exercise

Run examples/python/02_verify_bundle.py. Then test hash mismatch, missing audience, future timestamp, revoked jti, and unreachable CRL behavior. Confirm that no failure path formats or injects the bundle.

See it in action

The Marta demo shows how declared personal state changes a pre-scripted reply. It verifies no bundles, so treat it as an explanatory scenario, not cryptographic verification evidence.