clasp-caps
Delegatable capability tokens with Ed25519 signatures for CLASP.
Features
- Ed25519 Signatures - Tokens are cryptographically signed, no shared secrets needed
- Delegation Chains - Delegate tokens with attenuated scopes (UCAN-style)
- Scope Attenuation - Child tokens can only narrow permissions, never widen them
- Expiration Clamping - Child tokens cannot outlive their parent
- Chain Depth Limits - Configurable maximum delegation depth
- ValidatorChain Integration - Works alongside CPSK and Entity validators
Installation
[]
= "3.5"
Usage
Create a Root Token
use CapabilityToken;
use SigningKey;
use OsRng;
// Generate a root keypair
let root_key = generate;
// Create a root token with admin access, valid for 24 hours
let expires = now
.duration_since
.unwrap
.as_secs + 86400;
let root_token = create_root?;
// Encode for transmission
let wire = root_token.encode?; // "cap_<base64url(msgpack)>"
Delegate a Token
// Generate a child keypair
let child_key = generate;
// Delegate with narrower scopes -- child can only write to /lights/**
let child_token = root_token.delegate?;
// Delegate again with even narrower scopes
let grandchild_key = generate;
let grandchild_token = child_token.delegate?;
Decode and Inspect
let decoded = decode?;
assert_eq!; // root token
assert!;
decoded.verify_signature?;
Validate with Trust Anchors
use CapabilityValidator;
let root_pubkey = root_key.verifying_key.to_bytes.to_vec;
let validator = new;
// Implements clasp_core::security::TokenValidator
use TokenValidator;
match validator.validate
Token Wire Format
Tokens use the cap_ prefix followed by URL-safe base64-encoded MessagePack:
cap_<base64url(msgpack(CapabilityToken))>
Delegation Chain
Root Token (issuer: KeyA, scopes: admin:/**)
│
│ delegate() -- scope attenuation enforced
▼
Child Token (issuer: KeyB, scopes: write:/lights/**)
│ proofs: [ProofLink{issuer: KeyA, scopes, sig}]
│
│ delegate() -- expiration clamped to parent
▼
Grandchild (issuer: KeyC, scopes: read:/lights/room1/**)
proofs: [ProofLink{KeyA,...}, ProofLink{KeyB,...}]
Each delegation step enforces:
- Scope subset -- child scopes must be a subset of parent scopes
- Action hierarchy --
admin > write > read(custom actions require exact match) - Pattern subset -- child patterns must be covered by parent patterns
- Expiration clamping --
child_expires = min(child_expires, parent.expires_at)
Configuration Reference
CapabilityToken
| Field | Type | Description |
|---|---|---|
version |
u8 |
Token version (currently 1) |
issuer |
Vec<u8> |
Issuer's Ed25519 public key (32 bytes) |
audience |
Option<Vec<u8>> |
Audience public key (None = bearer token) |
scopes |
Vec<String> |
Scopes in action:pattern format |
expires_at |
u64 |
Expiration as Unix timestamp (seconds) |
nonce |
String |
UUID v4 nonce for replay prevention |
proofs |
Vec<ProofLink> |
Delegation chain (empty for root tokens) |
signature |
Vec<u8> |
Ed25519 signature (64 bytes) |
CapabilityValidator
| Parameter | Type | Description |
|---|---|---|
trust_anchors |
Vec<Vec<u8>> |
Trusted root issuer public keys (32 bytes each) |
max_depth |
usize |
Maximum allowed delegation chain depth |
Action Hierarchy
| Parent Action | Allowed Child Actions |
|---|---|
admin |
admin, write, read, any custom |
write |
write, read |
read |
read only |
| custom | exact match only |
License
Licensed under either of Apache License, Version 2.0 or MIT license at your option.
Maintained by LumenCanvas