# oas-document
W3C DID Document implementation with OAS extensions: builder pattern, conformance levels, lifecycle management, verification methods, service endpoints, lineage sections, and document proofs.
## Installation
```toml
[dependencies]
oas-document = "1.0"
```
## Quick Start
```rust
use oas_document::{DocumentBuilder, ConformanceLevel, LifecycleStatus, ServiceEndpoint};
use oas_crypto::OasKeyPair;
let keypair = OasKeyPair::generate();
let doc = DocumentBuilder::new("did:oas:example:agent:analyzer", "agent")
.controller("did:oas:example:hmr:alice")
.add_verification_method(&keypair)
.conformance_level(ConformanceLevel::L1)
.lifecycle_status(LifecycleStatus::Active)
.name("Analyzer Agent")
.description("An agent that analyzes data")
.add_service(ServiceEndpoint {
id: "did:oas:example:agent:analyzer#api".to_string(),
service_type: "AgentAPI".to_string(),
service_endpoint: "https://api.example.com/analyzer".to_string(),
})
.build_and_sign(&keypair, "2026-01-15T00:00:00Z")
.unwrap();
assert_eq!(doc.id, "did:oas:example:agent:analyzer");
assert!(doc.proof.is_some());
```
## API Reference
### `OasDocument`
```rust
pub struct OasDocument {
pub context: Vec<String>,
pub id: String,
pub controller: Option<String>,
pub verification_method: Vec<VerificationMethod>,
pub authentication: Vec<String>,
pub assertion_method: Vec<String>,
pub capability_invocation: Vec<String>,
pub capability_delegation: Vec<String>,
pub service: Vec<ServiceEndpoint>,
pub oas_version: String,
pub kind: String,
pub name: Option<String>,
pub description: Option<String>,
pub lineage: Option<LineageSection>,
pub conformance_level: Option<ConformanceLevel>,
pub lifecycle_status: Option<LifecycleStatus>,
pub sequence: Option<u64>,
pub metadata: Option<DocumentMetadata>,
pub proof: Option<DocumentProof>,
pub revoked: Option<bool>,
pub revoked_at: Option<String>,
}
impl OasDocument {
/// Returns the default context array for OAS documents.
pub fn default_context() -> Vec<String>
/// Whether this document represents a root entity (hmr, mhr, or enr).
pub fn is_root(&self) -> bool
/// Whether this document has been revoked.
pub fn is_revoked(&self) -> bool
/// The multibase-encoded public key of the first verification method.
pub fn primary_public_key_multibase(&self) -> Option<&str>
/// Find a verification method by full ID or fragment (e.g., "#key-1").
pub fn find_verification_method(&self, id_or_fragment: &str) -> Option<&VerificationMethod>
}
```
### `DocumentBuilder`
```rust
pub struct DocumentBuilder { /* private fields */ }
impl DocumentBuilder {
/// Create a new builder with the DID and entity kind.
pub fn new(id: &str, kind: &str) -> Self
/// Set the controller DID.
pub fn controller(self, controller: &str) -> Self
/// Add a verification method from a keypair.
/// Automatically registers it in authentication, assertionMethod,
/// capabilityInvocation, and capabilityDelegation arrays.
pub fn add_verification_method(self, keypair: &OasKeyPair) -> Self
/// Set the conformance level (L0, L1, L2).
pub fn conformance_level(self, level: ConformanceLevel) -> Self
/// Set a human-readable name.
pub fn name(self, name: &str) -> Self
/// Set a human-readable description.
pub fn description(self, description: &str) -> Self
/// Set the lineage section for non-root entities.
pub fn lineage(self, lineage: LineageSection) -> Self
/// Set the lifecycle status.
pub fn lifecycle_status(self, status: LifecycleStatus) -> Self
/// Set the document sequence number.
pub fn sequence(self, seq: u64) -> Self
/// Add a service endpoint.
pub fn add_service(self, service: ServiceEndpoint) -> Self
/// Build the document and sign it with the provided keypair.
/// Returns a fully constructed OasDocument with a valid proof.
pub fn build_and_sign(
self,
signing_keypair: &OasKeyPair,
created: &str,
) -> Result<OasDocument, DocumentError>
}
```
### `ConformanceLevel`
```rust
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum ConformanceLevel {
/// Basic: DID + verification method only.
L0,
/// Accountable: Adds lineage and controller.
L1,
/// Full: Adds attestations and service endpoints.
L2,
}
impl ConformanceLevel {
pub fn as_str(&self) -> &'static str // "L0", "L1", "L2"
}
```
### `LifecycleStatus`
```rust
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub enum LifecycleStatus {
Nascent, // Newly created, not yet active
Active, // Operational
Dormant, // Temporarily inactive
Suspended, // Administratively suspended
Terminated, // Permanently deactivated
Archived, // Read-only historical record
}
impl LifecycleStatus {
pub fn as_str(&self) -> &'static str
}
```
### `VerificationMethod`
```rust
pub const VERIFICATION_METHOD_TYPE: &str = "Ed25519VerificationKey2020";
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct VerificationMethod {
pub id: String,
pub method_type: String,
pub controller: String,
pub public_key_multibase: String,
}
impl VerificationMethod {
/// Create a new verification method.
/// The ID is formatted as `{did}#key-{key_num}`.
pub fn new(did: &str, key_num: u32, public_key_multibase: &str) -> Self
/// The key ID fragment (e.g., "key-1").
pub fn key_id(&self) -> &str
}
```
### `ServiceEndpoint`
```rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServiceEndpoint {
pub id: String,
pub service_type: String,
pub service_endpoint: String,
}
```
### `LineageSection`
```rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct LineageSection {
/// DID of the ultimate human root.
pub human_root_did: String,
/// DID of the immediate parent/creator.
pub creator_did: String,
/// Generation depth (0 = root, 1 = direct child, etc.).
pub generation: u32,
/// Cryptographic proof of derivation from parent.
pub derivation_proof: Option<AgentLineageProof>,
/// Chain of DIDs from this entity back to the human root.
pub human_root_chain: Vec<String>,
}
```
### `DocumentProof`
```rust
pub const DOCUMENT_PROOF_TYPE: &str = "Ed25519Signature2020";
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DocumentProof {
pub proof_type: String,
pub created: String,
pub verification_method: String,
pub proof_purpose: String,
pub proof_value: String,
}
impl DocumentProof {
/// Generate a proof by signing the document JSON with JCS canonicalization.
pub fn generate(
document_json: &serde_json::Value,
keypair: &OasKeyPair,
verification_method_id: &str,
created: &str,
) -> Result<Self, DocumentError>
/// Verify the proof against the document JSON and a public key.
pub fn verify(
&self,
document_json: &serde_json::Value,
public_key_bytes: &[u8],
) -> Result<(), DocumentError>
}
```
### `GovernanceSection` (ENR entities only)
```rust
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct GovernanceSection {
pub current_mhr: String, // Governing MHR DID
pub epoch: u64, // Monotonic epoch counter
pub transitions: Vec<GovernanceTransition>,
pub policy: GovernancePolicy,
}
pub struct GovernanceTransition {
pub from: Option<String>, // Outgoing MHR DID
pub to: String, // Incoming MHR DID
pub epoch: u64,
pub proof: GovernanceTransitionProof,
}
pub struct GovernanceTransitionProof {
pub proof_type: String, // "EnrGovernanceTransitionProof2025"
pub mhr_threshold_signature: String, // FROST threshold sig (base64url)
pub timestamp: String, // ISO 8601
}
pub struct GovernancePolicy {
pub transition_requires: String, // "mhr_threshold"
pub signing_key_rotation_requires: String, // "mhr_threshold"
pub max_transitions_per_day: u32, // Default: 1
pub timelock_hours: u32, // Default: 24
}
```
### `DocumentMetadata`
```rust
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DocumentMetadata {
pub created: String,
pub updated: String,
pub version: u64,
}
```
### Constants
```rust
pub const OAS_CONTEXT: &str = "https://openagent.id/ns/oas/v1";
pub const DID_CONTEXT: &str = "https://www.w3.org/ns/did/v1";
pub const ED25519_CONTEXT: &str = "https://w3id.org/security/suites/ed25519-2020/v1";
pub const OAS_VERSION: &str = "1.0.0";
```
### Error Type
```rust
#[derive(Debug, Error)]
pub enum DocumentError {
#[error("missing required field: {field}")]
MissingField { field: String },
#[error("invalid field value: {field}: {reason}")]
InvalidField { field: String, reason: String },
#[error("serialization error: {0}")]
Serialization(#[from] serde_json::Error),
#[error("crypto error: {0}")]
Crypto(#[from] oas_crypto::CryptoError),
#[error("DID error: {0}")]
Did(#[from] oas_did::DidError),
#[error("proof generation failed: {reason}")]
ProofGeneration { reason: String },
#[error("proof verification failed: {reason}")]
ProofVerification { reason: String },
#[error("invalid proof: {reason}")]
InvalidProof { reason: String },
#[error("invalid context: {reason}")]
InvalidContext { reason: String },
#[error("document error: {reason}")]
Other { reason: String },
}
```
## Dependencies
| `oas-crypto` | workspace | Signing, encoding, JCS |
| `oas-did` | workspace | DID parsing and validation |
| `serde` | 1.0 | Serialization with derive |
| `serde_json` | 1.0 | JSON support |
| `chrono` | 0.4 | Timestamp handling |
| `thiserror` | 2.0 | Error derive macros |
## License
Copyright © 2026 [L1fe Labs, Inc.](https://l1fe.ai)
Licensed under the [MIT license](../LICENSE).