oas-attestation · presentation
Declared module signatures, types, configuration, and source documentation.
Source: oas/oas/oas-attestation/src/presentation.rs. SHA-256: b987664d14728ebd7f56f3d60db3ab60cc953031fa55d7a29ba0f0d2a8af7a7e.
This source reference follows declared modules and preserves feature attributes. It includes public declarations and implementation methods in those modules. Private-module exports and trait resolution still require the compiler; not every declaration is a crate-root import. Function bodies and constant values are omitted. Source comments describe their implementation context and are not a production deployment claim.
presentation::PRESENTATION_TYPE
The credential / presentation type literal "VerifiablePresentation".
pub const PRESENTATION_TYPE: &str;Source line: 108.
presentation::OAS_PRESENTATION_TYPE
The credential / presentation type literal "OasPresentation".
pub const OAS_PRESENTATION_TYPE: &str;Source line: 111.
presentation::AUTHENTICATION_PURPOSE
The fixed proof purpose for presentation proofs (per W3C VP spec).
pub const AUTHENTICATION_PURPOSE: &str;Source line: 114.
presentation::OasPresentation
An OAS Verifiable Presentation per Spec §14.5.
Wraps one or more [OasCredential]s for transmission from a holder to a
verifier. The presentation carries its own [PresentationProof] (separate
from the per-credential proofs) that binds the holder's signing key, the
verifier-supplied challenge, and the verifier's domain — providing replay
protection across sessions and verifiers.
Examples
use oas_attestation::credential::OasCredential;
use oas_attestation::presentation::OasPresentation;
use oas_attestation::types::AttestationType;
let cred = OasCredential::builder()
.issuer("did:oas:test:hmr:auditor")
.subject_id("did:oas:test:agent:bot")
.attestation_type(AttestationType::SecurityAudit)
.issuance_date("2026-04-06T00:00:00Z")
.subject_claim("auditType", serde_json::json!("codeAudit"))
.subject_claim("result", serde_json::json!("pass"))
.subject_claim("severityFindings", serde_json::json!({"critical": 0}))
.subject_claim("toolOrMethodology", serde_json::json!("OWASP"))
.subject_claim("auditDate", serde_json::json!("2026-04-06T00:00:00Z"))
.build()
.unwrap();
let vp = OasPresentation::builder()
.holder("did:oas:test:agent:bot")
.add_credential(cred)
.build()
.unwrap();
assert_eq!(vp.holder, "did:oas:test:agent:bot");
assert_eq!(vp.verifiable_credential.len(), 1);#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct OasPresentation {
/// JSON-LD context array.
#[serde(rename = "@context")]
pub context: Vec<String>,
/// VP type array (always includes `"VerifiablePresentation"` and
/// `"OasPresentation"`).
#[serde(rename = "type")]
pub presentation_type: Vec<String>,
/// The holder's `did:oas` identifier — the entity presenting this VP.
pub holder: String,
/// One or more verifiable credentials wrapped by this presentation.
pub verifiable_credential: Vec<OasCredential>,
/// The presentation proof (populated by [`sign_presentation`]).
#[serde(skip_serializing_if = "Option::is_none")]
pub proof: Option<PresentationProof>
}Source line: 159.
presentation::PresentationProof
An Ed25519Signature2020 proof on a [OasPresentation].
Per Spec §14.5, the proof structure includes a challenge (verifier
nonce) and domain (verifier audience identifier), both of which are
part of the signed payload. Tampering with either invalidates the
signature.
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct PresentationProof {
/// Fixed: `"Ed25519Signature2020"` (the OAS baseline format).
#[serde(rename = "type")]
pub proof_type: String,
/// ISO 8601 timestamp when the proof was created.
pub created: String,
/// Reference to the verification method used by the holder.
pub verification_method: String,
/// Fixed: `"authentication"` (W3C VP convention for VP proofs).
pub proof_purpose: String,
/// Verifier-supplied nonce — bound into the signature for replay
/// protection across sessions.
pub challenge: String,
/// Verifier audience identifier — bound into the signature for replay
/// protection across verifiers.
pub domain: String,
/// Multibase base58btc-encoded Ed25519 signature.
pub proof_value: String
}Source line: 188.
presentation::OasPresentation::builder
Creates a new [PresentationBuilder] with sensible defaults.
pub fn builder() -> PresentationBuilder;Source line: 216.
presentation::OasPresentation::validate
Validates the presentation's structural invariants per Spec §14.5.
Checks:
holderis a validdid:oasidentifier- At least one credential is present
- Every contained credential individually validates per §14.1
Errors
Returns [AttestationError] on the first failure.
pub fn validate(&self) -> Result<(), AttestationError>;Source line: 230.
presentation::PresentationBuilder
Builder for [OasPresentation].
#[derive(Debug, Default)]
pub struct PresentationBuilder {
}Source line: 260.
presentation::PresentationBuilder::holder
Sets the holder DID — the did:oas identifier of the presenting entity.
pub fn holder(mut self, holder: &str) -> Self;Source line: 267.
presentation::PresentationBuilder::add_credential
Adds a credential to the presentation. Multiple credentials may be included; all are covered by the single presentation proof.
pub fn add_credential(mut self, credential: OasCredential) -> Self;Source line: 274.
presentation::PresentationBuilder::add_credentials
Adds multiple credentials at once.
pub fn add_credentials(mut self, credentials: impl IntoIterator<Item = OasCredential>) -> Self;Source line: 280.
presentation::PresentationBuilder::build
Builds an unsigned [OasPresentation].
Errors
Returns [AttestationError] if the holder is missing or invalid, or
if no credentials were added.
pub fn build(self) -> Result<OasPresentation, AttestationError>;Source line: 291.
presentation::sign_presentation
Signs an [OasPresentation], producing a new presentation with an
attached [PresentationProof].
Per OAS Spec §14.5:
- Validates the presentation structure
- Constructs the proof with the supplied challenge and domain
- Sets
proof.proofValueto empty string - JCS-canonicalizes the entire presentation
- Signs the canonical bytes with the holder's Ed25519 key
- Encodes the signature as multibase base58btc and stores it in
proof.proofValue
Arguments
presentation- The unsigned presentation.holder_keypair- The holder's signing keypair.verification_method_id- Full verification method ID (e.g.,"did:oas:test:agent:bot#key-1").created- ISO 8601 timestamp for the proof.challenge- Verifier-supplied nonce (Spec §14.5 replay protection).domain- Verifier audience identifier (Spec §14.5 replay protection).
Returns
A new [OasPresentation] with the proof field populated.
Errors
Returns [AttestationError] if validation, canonicalization, or signing
fails.
pub fn sign_presentation(
mut presentation: OasPresentation,
holder_keypair: &OasKeyPair,
verification_method_id: &str,
created: &str,
challenge: &str,
domain: &str,
) -> Result<OasPresentation, AttestationError>;Source line: 373.
presentation::verify_presentation
Verifies an [OasPresentation] against a holder public key, with
challenge and domain replay protection.
Per OAS Spec §14.5:
- Validates the presentation structure
- Checks the proof exists and uses Ed25519Signature2020
- Checks the challenge matches the verifier's expected nonce
- Checks the domain matches the verifier's expected audience
- Reconstructs the canonical bytes (with proofValue set to empty)
- Verifies the Ed25519 signature against the holder's public key
This function does NOT enforce the §14.5.1 Holder Binding Rule. Use
[verify_presentation_holder_binding] for that check, or call this
function followed by the binding check.
Arguments
presentation- The signed presentation to verify.holder_public_key- The holder's 32-byte Ed25519 public key.expected_challenge- The nonce the verifier originally issued.expected_domain- The verifier's audience identifier.
Errors
- [
AttestationError::MissingProof] if the presentation has no proof. - [
AttestationError::PresentationChallengeMismatch] on nonce mismatch. - [
AttestationError::PresentationDomainMismatch] on audience mismatch. - [
AttestationError::InvalidProofSignature] on signature failure.
pub fn verify_presentation(
presentation: &OasPresentation,
holder_public_key: &[u8],
expected_challenge: &str,
expected_domain: &str,
) -> Result<(), AttestationError>;Source line: 435.
presentation::is_authority_bearing
Returns true if the given attestation type is authority-bearing per
Spec §14.5.1, meaning the strict-equality holder binding rule applies.
Per Spec §14.5.1, only CapabilityVerification is authority-bearing among
the standard types. Custom attestation types may opt in to authority-
bearing classification via their registered schema; this function does
not currently consult an external schema registry, so all Custom types
default to factual. Callers needing custom-schema-aware classification
should wrap this function and override for their custom types.
pub fn is_authority_bearing(attestation_type: &AttestationType) -> bool;Source line: 508.
presentation::verify_presentation_holder_binding
Enforces the §14.5.1 Holder Binding Rule (strict-equality form) on a presentation.
Per Spec §14.5.1:
- Authority-bearing attestations (
CapabilityVerificationand any custom type marked authority-bearing): the holder MUST be the credential subject, OR a lineage descendant of the subject. - Factual attestations (
SecurityAudit,BehaviorAttestation,ComplianceAttestation,ExpertEndorsement,CommunityReview,LineageAttestation): any holder MAY present.
This function enforces only the strict-equality branch
(holder == subject). For the descendant branch, use
[verify_presentation_holder_binding_with_lineage], which accepts a
holder lineage chain and accepts the binding when the credential subject
is any ancestor of the holder.
Arguments
presentation- The presentation to check.
Returns
Ok(()) if the rule is satisfied for every contained credential.
Errors
Returns [AttestationError::HolderBindingViolation] on the first
authority-bearing credential whose subject DID does not match the holder.
pub fn verify_presentation_holder_binding(
presentation: &OasPresentation,
) -> Result<(), AttestationError>;Source line: 541.
presentation::verify_presentation_holder_binding_with_lineage
Legacy raw-proof entry point for the §14.5.1 Holder Binding Rule.
Non-empty raw proof chains fail closed because they do not carry validated
parent documents or verifier root policy. Use
[verify_presentation_holder_binding_with_resolved_lineage] for
descendant-aware authorization.
Arguments
presentation- The signed presentation to check.holder_lineage_chain- Legacy raw proofs. Only an empty slice is accepted, yielding strict-equality semantics.
Errors
- [
AttestationError::LineageChainInvalid] if any raw proof is supplied. - [
AttestationError::HolderBindingViolation] if any authority-bearing credential's subject is neither the holder nor any ancestor proven by the chain.
Examples
use oas_attestation::credential::OasCredential;
use oas_attestation::presentation::{
verify_presentation_holder_binding_with_lineage, OasPresentation,
};
use oas_attestation::sign::sign_credential;
use oas_attestation::types::AttestationType;
use oas_crypto::keypair::OasKeyPair;
use oas_crypto::proof::AgentLineageProof;
// Parent issues a CapabilityVerification credential about itself.
let parent_kp = OasKeyPair::generate();
let cred = OasCredential::builder()
.issuer("did:oas:test:hmr:parent")
.subject_id("did:oas:test:hmr:parent")
.attestation_type(AttestationType::CapabilityVerification)
.issuance_date("2026-04-06T00:00:00Z")
.subject_claim("capabilities", serde_json::json!(["data-extraction"]))
.subject_claim("verificationMethod", serde_json::json!("benchmark"))
.subject_claim("verificationDate", serde_json::json!("2026-04-06T00:00:00Z"))
.build()
.unwrap();
let signed = sign_credential(
&cred, &parent_kp,
"did:oas:test:hmr:parent#key-1",
"2026-04-06T00:00:00Z",
).unwrap();
// Parent derives a child agent and the child holds the proof of descent.
let lineage = AgentLineageProof::generate(
&parent_kp,
"did:oas:test:hmr:parent",
"did:oas:test:agent:child",
"/agent-child",
).unwrap();
// Child holds a presentation containing the parent's capability — this is
// legitimate because the child is a lineage descendant of the parent.
let vp = OasPresentation::builder()
.holder("did:oas:test:agent:child")
.add_credential(signed)
.build()
.unwrap();
// Raw proofs cannot select their own verification authority.
assert!(verify_presentation_holder_binding_with_lineage(&vp, &[lineage]).is_err());pub fn verify_presentation_holder_binding_with_lineage(
presentation: &OasPresentation,
holder_lineage_chain: &[oas_crypto::proof::AgentLineageProof],
) -> Result<(), AttestationError>;Source line: 668.
presentation::verify_presentation_holder_binding_with_resolved_lineage
Verifies descendant holder binding through the strict lineage verifier.
This is the authorizing descendant-aware API. It resolves and validates the complete holder lineage, including parent document keys, signed bindings, chain continuity, current status, and verifier-controlled root anchors, before considering any ancestor credential subject covered.
Errors
Returns [AttestationError::LineageChainInvalid] if the holder document
does not match the presentation or strict lineage verification fails.
Returns [AttestationError::HolderBindingViolation] when an
authority-bearing credential subject is outside the verified chain.
pub fn verify_presentation_holder_binding_with_resolved_lineage(
presentation: &OasPresentation,
holder_document: &oas_document::OasDocument,
provider: &dyn oas_lineage::provider::DocumentProvider,
config: &oas_lineage::config::VerifyConfig,
) -> Result<(), AttestationError>;Source line: 689.