Product Specifications
Browse technical specifications and schemas
2 directories
File Tree
spec
conformance
cases
data.export.v1
passports
payments.refunds.v1
passports
integrations
oap
examples
vc
docs
Open Agent Passport Verifiable Credential Mapping
Overview
This document defines how Open Agent Passport (OAP) objects can be exported and imported as W3C Verifiable Credentials (VCs) for interoperability with existing VC ecosystems.
Design Principles
- Optional VC Support: VCs are optional for OAP v1 - native OAP JSON remains the source of truth
- Deterministic Mapping: Export/import mappings are deterministic and reversible
- Minimal VC Dependencies: Avoid forcing VC adoption in OAP v1 implementations
- Future Compatibility: Design for future VC integration without breaking changes
Passport to VC Mapping
OAP Passport Credential
An OAP passport can be exported as a Verifiable Credential with the following structure:
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://raw.githubusercontent.com/aporthq/aport-spec/refs/heads/main/oap/vc/context-oap-v1.jsonld"
],
"type": ["VerifiableCredential", "OAPPassportCredential"],
"credentialSubject": {
"agent_id": "550e8400-e29b-41d4-a716-446655440000",
"kind": "template",
"spec_version": "oap/1.0",
"owner_id": "org_12345678",
"owner_type": "org",
"assurance_level": "L2",
"status": "active",
"capabilities": ["finance.payment.refund", "data.export"],
"limits": {
"finance.payment.refund": {
"currency_limits": {
"USD": {
"max_per_tx": 5000,
"daily_cap": 50000
}
},
"reason_codes": ["customer_request", "defective_product"],
"idempotency_required": true
}
},
"regions": ["US", "CA"],
"metadata": {
"name": "Customer Support AI",
"description": "AI agent for customer support operations"
},
"created_at": "2024-01-01T00:00:00Z",
"updated_at": "2024-01-15T10:30:00Z",
"version": "1.0.0"
},
"issuer": "https://aport.io",
"issuanceDate": "2024-01-01T00:00:00Z",
"expirationDate": "2025-01-01T00:00:00Z",
"proof": {
"type": "Ed25519Signature2020",
"created": "2024-01-01T00:00:00Z",
"verificationMethod": "https://aport.io/.well-known/oap/jwks.json#key-2025-01",
"proofPurpose": "assertionMethod",
"jws": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}
Mapping Rules
- Context: Include OAP context and W3C VC context
- Type: Use
["VerifiableCredential", "OAPPassportCredential"] - Credential Subject: Map all OAP passport fields directly
- Issuer: Use registry URL or owner domain
- Dates: Map
created_attoissuanceDate, setexpirationDatebased on policy - Proof: Use Ed25519Signature2020 over JCS-canonicalized credential subject
Decision to VC Mapping
OAP Decision Receipt
An OAP decision can be exported as a Verifiable Credential receipt:
{
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://raw.githubusercontent.com/aporthq/aport-spec/refs/heads/main/oap/vc/context-oap-v1.jsonld"
],
"type": ["VerifiableCredential", "OAPDecisionReceipt"],
"credentialSubject": {
"decision_id": "550e8400-e29b-41d4-a716-446655440002",
"policy_id": "finance.payment.refund.v1",
"agent_id": "550e8400-e29b-41d4-a716-446655440000",
"owner_id": "org_12345678",
"assurance_level": "L2",
"allow": true,
"reasons": [
{
"code": "oap.allowed",
"message": "Transaction within limits"
}
],
"created_at": "2024-01-15T10:30:00Z",
"expires_in": 3600,
"passport_digest": "sha256:abcd1234efgh5678ijkl9012mnop3456qrst7890uvwx1234yzab5678cdef"
},
"issuer": "https://aport.io",
"issuanceDate": "2024-01-15T10:30:00Z",
"expirationDate": "2024-01-15T11:30:00Z",
"proof": {
"type": "Ed25519Signature2020",
"created": "2024-01-15T10:30:00Z",
"verificationMethod": "https://aport.io/.well-known/oap/jwks.json#key-2025-01",
"proofPurpose": "assertionMethod",
"jws": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9..."
}
}
Decision Mapping Rules
- Context: Include OAP context and W3C VC context
- Type: Use
["VerifiableCredential", "OAPDecisionReceipt"] - Credential Subject: Map all OAP decision fields directly
- Issuer: Use registry URL
- Dates: Map
created_attoissuanceDate, computeexpirationDatefromexpires_in - Proof: Use Ed25519Signature2020 over JCS-canonicalized credential subject
Import/Export Rules
Export Rules
Requirements
- Deterministic: Same OAP object always produces same VC
- Complete: All OAP fields are included in VC
- Valid: Generated VCs are valid according to VC specification
- Signed: VCs include proper Ed25519 signatures
- Context: Include proper JSON-LD context
Import Rules
Import Requirements
- Advisory Only: VC import is advisory, not authoritative
- Validation: Validate VC structure and signatures
- Mapping: Map VC fields back to OAP format
- Source of Truth: Native OAP JSON remains authoritative
- Error Handling: Handle invalid or malformed VCs gracefully
Implementation Example
Code
// Export OAP passport to VC
function exportPassportToVC(passport, registryKey) {
const vc = {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://raw.githubusercontent.com/aporthq/aport-spec/refs/heads/main/oap/vc/context-oap-v1.jsonld"
],
"type": ["VerifiableCredential", "OAPPassportCredential"],
"credentialSubject": passport,
"issuer": "https://aport.io",
"issuanceDate": passport.created_at,
"expirationDate": computeExpirationDate(passport),
"proof": {
"type": "Ed25519Signature2020",
"created": passport.created_at,
"verificationMethod": `${registryKey.issuer}#${registryKey.kid}`,
"proofPurpose": "assertionMethod",
"jws": signCredential(passport, registryKey)
}
};
return vc;
}
// Import VC to OAP passport
function importVCToPassport(vc) {
// Validate VC structure
if (!isValidVC(vc)) {
throw new Error("Invalid VC structure");
}
// Verify signature
if (!verifyCredentialSignature(vc)) {
throw new Error("Invalid VC signature");
}
// Extract passport from credential subject
const passport = vc.credentialSubject;
// Validate OAP passport structure
if (!isValidOAPPassport(passport)) {
throw new Error("Invalid OAP passport structure");
}
return passport;
}
Interoperability Considerations
VC Ecosystem Integration
- Wallet Support: OAP VCs can be stored in standard VC wallets
- Presentation: OAP VCs can be presented using standard VC presentation protocols
- Verification: OAP VCs can be verified using standard VC verification libraries
- Storage: OAP VCs can be stored in standard VC repositories
OAP Ecosystem Integration
- Native Support: OAP implementations work with native JSON format
- VC Optional: VC support is optional for OAP compliance
- Performance: Native OAP format is optimized for performance
- Simplicity: Native OAP format is simpler for basic use cases
Future Considerations
VC v2.0 Support
Future versions may include:
- BBS+ Signatures: Support for selective disclosure
- ZKP Integration: Zero-knowledge proof support
- Multi-Signature: Support for multiple signers
- Revocation: Standard VC revocation mechanisms
OAP v2.0 Integration
Future OAP versions may:
- Native VC Support: Make VCs a first-class citizen
- DID Integration: Support for Decentralized Identifiers
- Credential Exchange: Standard credential exchange protocols
- Privacy Enhancements: Enhanced privacy and selective disclosure
Implementation Guide
Export OAP Passport to VC
function exportPassportToVC(passport, registryKey) {
// Validate passport structure
if (!isValidOAPPassport(passport)) {
throw new Error("Invalid OAP passport structure");
}
// Create VC structure
const vc = {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://raw.githubusercontent.com/aporthq/aport-spec/refs/heads/main/oap/vc/context-oap-v1.jsonld"
],
"type": ["VerifiableCredential", "OAPPassportCredential"],
"credentialSubject": {
// Map all OAP passport fields
"agent_id": passport.agent_id,
"kind": passport.kind,
"spec_version": passport.spec_version,
"parent_agent_id": passport.parent_agent_id,
"owner_id": passport.owner_id,
"owner_type": passport.owner_type,
"assurance_level": passport.assurance_level,
"status": passport.status,
"capabilities": passport.capabilities,
"limits": passport.limits,
"regions": passport.regions,
"metadata": passport.metadata,
"created_at": passport.created_at,
"updated_at": passport.updated_at,
"version": passport.version
},
"issuer": registryKey.issuer,
"issuanceDate": passport.created_at,
"expirationDate": computeExpirationDate(passport),
"proof": {
"type": "Ed25519Signature2020",
"created": passport.created_at,
"verificationMethod": `${registryKey.issuer}/.well-known/oap/jwks.json#${registryKey.kid}`,
"proofPurpose": "assertionMethod",
"jws": signCredential(passport, registryKey)
}
};
return vc;
}
Export OAP Decision to VC
function exportDecisionToVC(decision, registryKey) {
// Validate decision structure
if (!isValidOAPDecision(decision)) {
throw new Error("Invalid OAP decision structure");
}
// Create VC structure
const vc = {
"@context": [
"https://www.w3.org/2018/credentials/v1",
"https://raw.githubusercontent.com/aporthq/aport-spec/refs/heads/main/oap/vc/context-oap-v1.jsonld"
],
"type": ["VerifiableCredential", "OAPDecisionReceipt"],
"credentialSubject": {
// Map all OAP decision fields
"decision_id": decision.decision_id,
"policy_id": decision.policy_id,
"agent_id": decision.agent_id,
"owner_id": decision.owner_id,
"assurance_level": decision.assurance_level,
"allow": decision.allow,
"reasons": decision.reasons,
"created_at": decision.created_at,
"expires_in": decision.expires_in,
"passport_digest": decision.passport_digest,
"signature": decision.signature,
"kid": decision.kid,
"decision_token": decision.decision_token,
"remaining_daily_cap": decision.remaining_daily_cap
},
"issuer": registryKey.issuer,
"issuanceDate": decision.created_at,
"expirationDate": new Date(new Date(decision.created_at).getTime() + decision.expires_in * 1000).toISOString(),
"proof": {
"type": "Ed25519Signature2020",
"created": decision.created_at,
"verificationMethod": `${registryKey.issuer}/.well-known/oap/jwks.json#${registryKey.kid}`,
"proofPurpose": "assertionMethod",
"jws": signCredential(decision, registryKey)
}
};
return vc;
}
Import VC to OAP Objects
function importVCToPassport(vc) {
// Validate VC structure
if (!isValidVC(vc)) {
throw new Error("Invalid VC structure");
}
// Verify signature
if (!verifyCredentialSignature(vc)) {
throw new Error("Invalid VC signature");
}
// Extract passport from credential subject
const passport = vc.credentialSubject;
// Validate OAP passport structure
if (!isValidOAPPassport(passport)) {
throw new Error("Invalid OAP passport structure");
}
return passport;
}
function importVCToDecision(vc) {
// Validate VC structure
if (!isValidVC(vc)) {
throw new Error("Invalid VC structure");
}
// Verify signature
if (!verifyCredentialSignature(vc)) {
throw new Error("Invalid VC signature");
}
// Extract decision from credential subject
const decision = vc.credentialSubject;
// Validate OAP decision structure
if (!isValidOAPDecision(decision)) {
throw new Error("Invalid OAP decision structure");
}
return decision;
}
Validation Functions
function isValidVC(vc) {
return vc &&
vc["@context"] &&
vc.type &&
vc.credentialSubject &&
vc.issuer &&
vc.issuanceDate &&
vc.proof;
}
function isValidOAPPassport(passport) {
return passport &&
passport.agent_id &&
passport.kind &&
passport.spec_version &&
passport.owner_id &&
passport.owner_type &&
passport.assurance_level &&
passport.status &&
passport.capabilities &&
passport.limits &&
passport.regions &&
passport.created_at &&
passport.updated_at &&
passport.version;
}
function isValidOAPDecision(decision) {
return decision &&
decision.decision_id &&
decision.policy_id &&
decision.agent_id &&
decision.owner_id &&
decision.assurance_level &&
typeof decision.allow === 'boolean' &&
decision.reasons &&
decision.created_at &&
decision.expires_in &&
decision.passport_digest &&
decision.signature &&
decision.kid;
}