OpenAgentID documentation
Source referencesRust module referenceoas-attestation

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:

  • holder is a valid did:oas identifier
  • 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:

  1. Validates the presentation structure
  2. Constructs the proof with the supplied challenge and domain
  3. Sets proof.proofValue to empty string
  4. JCS-canonicalizes the entire presentation
  5. Signs the canonical bytes with the holder's Ed25519 key
  6. 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:

  1. Validates the presentation structure
  2. Checks the proof exists and uses Ed25519Signature2020
  3. Checks the challenge matches the verifier's expected nonce
  4. Checks the domain matches the verifier's expected audience
  5. Reconstructs the canonical bytes (with proofValue set to empty)
  6. 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 (CapabilityVerification and 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.

On this page