# aegis-delegate
Delegation and authority model for AEGIS. Create and verify cryptographic delegation proofs, manage delegation trees with depth limits, issue time-limited session keys, validate scope anti-amplification, and track revocations with cascading.
## Delegation Proofs
Create Ed25519-signed delegation proofs using JCS canonicalization. The delegator signs a canonical JSON payload binding the delegate's DID to a specific scope.
```rust
use aegis_delegate::proof::{create_delegation_proof, verify_delegation_proof};
use aegis_core::DelegationScope;
use ed25519_dalek::SigningKey;
let scope = DelegationScope {
actions: vec!["transfer".into(), "approve".into()],
resources: vec!["0xtoken_contract".into()],
chains: vec!["ethereum".into()],
limits: None,
temporal: None,
};
let delegation = create_delegation_proof(
"did:oas:prod:hmr:alice", // delegator
"did:oas:prod:agent:bot1", // delegate
scope,
Some(Utc::now() + Duration::days(7)), // expires in 7 days
&signing_key,
"did:oas:prod:hmr:alice#delegation-key",
)?;
// Verify the proof
let valid = verify_delegation_proof(&delegation, &verifying_key)?;
assert!(valid);
```
### Functions
```rust
/// Create a signed delegation proof.
///
/// Signs a JCS-canonicalized JSON payload containing:
/// delegator DID, delegate DID, scope, and optional expiry.
/// Proof type: "AegisDelegationProof2025"
pub fn create_delegation_proof(
delegator_did: &str,
delegate_did: &str,
scope: DelegationScope,
expires: Option<DateTime<Utc>>,
signing_key: &SigningKey,
verification_method: &str,
) -> Result<Delegation, DelegationError>;
/// Verify a delegation proof against the delegator's public key.
///
/// Re-canonicalizes the payload and verifies the JWS signature.
pub fn verify_delegation_proof(
delegation: &Delegation,
delegator_public_key: &VerifyingKey,
) -> Result<bool, DelegationError>;
```
## Scope Validation
Prevent scope amplification: a delegate's scope must be a subset of (or equal to) the delegator's scope.
```rust
use aegis_delegate::scope::{check_scope_validity, amplify_scope};
// Ensure a scope is well-formed
check_scope_validity(&scope)?;
// Check that delegate scope does not exceed delegator scope
amplify_scope(&delegator_scope, &delegate_scope)?;
// Returns Ok(()) if valid, Err(ScopeAmplification) if delegate exceeds delegator
```
### Functions
```rust
/// Validate that a delegation scope is well-formed.
/// Checks: non-empty actions, valid chain names.
pub fn check_scope_validity(scope: &DelegationScope) -> Result<(), DelegationError>;
/// Check for scope amplification.
/// Returns Err(ScopeAmplification) if delegate_scope contains
/// actions, resources, or chains not present in delegator_scope.
pub fn amplify_scope(
delegator_scope: &DelegationScope,
delegate_scope: &DelegationScope,
) -> Result<(), DelegationError>;
```
## Delegation Tree
Track delegations as a directed tree. Enforces maximum depth, provides chain verification, and computes effective scopes by intersecting parent scopes.
```rust
use aegis_delegate::tree::DelegationTree;
let mut tree = DelegationTree::new(5); // max depth = 5
tree.add_delegation(&delegation)?;
// Verify the delegation chain for a delegate
let chain_valid = tree.verify_chain("did:oas:prod:agent:bot1")?;
// Get the effective scope (intersection of all parent scopes)
let effective = tree.get_effective_scope("did:oas:prod:agent:bot1")?;
// Get depth of a node in the tree
let depth = tree.get_depth("did:oas:prod:agent:bot1");
// Revoke a delegation (cascading to all children)
let revoked_ids = tree.revoke("delegation-id-123")?;
```
### DelegationTree
```rust
impl DelegationTree {
/// Create a new tree with a maximum delegation depth.
pub fn new(max_depth: u32) -> Self;
/// Add a delegation to the tree.
/// Returns Err(MaxDepthExceeded) if adding would exceed max_depth.
pub fn add_delegation(&mut self, delegation: &Delegation) -> Result<(), DelegationError>;
/// Verify the delegation chain from a delegate back to the root delegator.
pub fn verify_chain(&self, delegate_did: &str) -> Result<bool, DelegationError>;
/// Compute the effective scope for a delegate by intersecting all parent scopes.
pub fn get_effective_scope(
&self,
delegate_did: &str,
) -> Result<DelegationScope, DelegationError>;
/// Get the depth of a DID in the delegation tree.
pub fn get_depth(&self, did: &str) -> usize;
/// Revoke a delegation and cascade to all children.
/// Returns the list of all revoked delegation IDs.
pub fn revoke(&mut self, delegation_id: &str) -> Result<Vec<String>, DelegationError>;
}
```
## Session Keys
Issue time-limited session keys with constrained scope and optional transaction limits.
```rust
use aegis_delegate::session_key::SessionKeyIssuer;
let session_key = SessionKeyIssuer::issue_session_key(
"did:oas:prod:hmr:alice",
scope,
Some(100), // max 100 transactions
&signing_key,
"did:oas:prod:hmr:alice#session-key",
)?;
// Verify the session key
let valid = SessionKeyIssuer::verify_session_key(
&session_key,
&verifying_key,
)?;
assert!(valid);
```
### SessionKeyIssuer
```rust
impl SessionKeyIssuer {
/// Issue a new session key with scope and optional transaction limit.
pub fn issue_session_key(
principal_did: &str,
scope: DelegationScope,
max_transactions: Option<u64>,
signing_key: &SigningKey,
verification_method: &str,
) -> Result<SessionKey, DelegationError>;
/// Verify a session key's proof against the principal's public key.
pub fn verify_session_key(
session_key: &SessionKey,
principal_public_key: &VerifyingKey,
) -> Result<bool, DelegationError>;
}
```
## Storage Traits
### DelegationStore
```rust
#[async_trait]
pub trait DelegationStore: Send + Sync {
async fn store(&self, delegation: &Delegation) -> Result<(), DelegationError>;
async fn load(&self, delegation_id: &str) -> Result<Delegation, DelegationError>;
async fn list_by_delegator(&self, delegator_did: &str) -> Result<Vec<Delegation>, DelegationError>;
async fn list_by_delegate(&self, delegate_did: &str) -> Result<Vec<Delegation>, DelegationError>;
async fn delete(&self, delegation_id: &str) -> Result<(), DelegationError>;
}
```
### RevocationStore
```rust
#[async_trait]
pub trait RevocationStore: Send + Sync {
async fn revoke(&self, delegation_id: &str) -> Result<(), DelegationError>;
async fn is_revoked(&self, delegation_id: &str) -> Result<bool, DelegationError>;
async fn list_revoked(&self) -> Result<Vec<String>, DelegationError>;
}
```
Both have in-memory implementations (`InMemoryDelegationStore`, `InMemoryRevocationStore`).
## License
Copyright © 2026 [L1fe Labs, Inc.](https://l1fe.ai)
Licensed under either of [Apache License 2.0](../LICENSE-APACHE) or [MIT license](../LICENSE-MIT), at your option.