exo-avc — Autonomous Volition Credential
AVC is a portable, signed, machine-verifiable credential that
defines what an autonomous actor is authorized to pursue under a
human or organizational principal.
Identity proves who an actor is. Authority proves who delegated
power. Consent proves what posture applies. AVC proves what
autonomous intent is allowed before action occurs.
In this crate, volition strictly means delegated operational
intent. It does not denote consciousness, sentience, emotion, or
human-like free will.
Determinism contract
- All collections in signed payloads are sorted and deduplicated.
- All hashing is BLAKE3 over canonical CBOR — only ordered maps and
sets (
BTreeMap, BTreeSet), no platform-dependent integer widths,
and no floating-point arithmetic.
- Validation never reads system time; the caller passes
now.
- Validation is fail-closed: any unresolved key, missing required
reference, malformed structural value, scope violation, expiration,
or revocation produces an explicit
Deny decision with reason
codes describing why.
High-level API
use exo_avc::{
AutonomyLevel, AuthorityScope, AvcConstraints, AvcDraft, AvcSubjectKind,
DelegatedIntent, InMemoryAvcRegistry, AvcRegistryWrite, AvcValidationRequest,
AvcDecision, issue_avc, validate_avc, AVC_SCHEMA_VERSION,
};
use exo_authority::permission::Permission;
use exo_core::{Did, Hash256, Timestamp};
use exo_core::crypto::KeyPair;
let issuer_keypair = KeyPair::from_secret_bytes([0x11; 32]).unwrap();
let issuer_did = Did::new("did:exo:issuer").unwrap();
let mut registry = InMemoryAvcRegistry::new();
registry.put_public_key(issuer_did.clone(), issuer_keypair.public);
let draft = AvcDraft {
schema_version: AVC_SCHEMA_VERSION,
issuer_did: issuer_did.clone(),
principal_did: issuer_did.clone(),
subject_did: Did::new("did:exo:agent").unwrap(),
holder_did: None,
subject_kind: AvcSubjectKind::AiAgent {
model_id: "alpha".into(),
agent_version: None,
},
created_at: Timestamp::new(1_000, 0),
expires_at: Some(Timestamp::new(2_000, 0)),
delegated_intent: DelegatedIntent {
intent_id: Hash256::from_bytes([0xAA; 32]),
purpose: "research".into(),
allowed_objectives: vec!["primary".into()],
prohibited_objectives: vec![],
autonomy_level: AutonomyLevel::Draft,
delegation_allowed: false,
},
authority_scope: AuthorityScope {
permissions: vec![Permission::Read],
tools: vec![],
data_classes: vec![],
counterparties: vec![],
jurisdictions: vec!["US".into()],
},
constraints: AvcConstraints::permissive(),
authority_chain: None,
consent_refs: vec![],
policy_refs: vec![],
parent_avc_id: None,
};
let credential = issue_avc(draft, |bytes| issuer_keypair.sign(bytes)).unwrap();
let request = AvcValidationRequest {
credential,
action: None,
now: Timestamp::new(1_500, 0),
};
let result = validate_avc(&request, ®istry).unwrap();
assert_eq!(result.decision, AvcDecision::Allow);