astrid-capabilities
The agent cannot forge the token. It cannot replay an old one. It cannot talk its way past the check.
In the OS model, capability tokens are the kernel's access control mechanism. An agent that wants to call mcp://filesystem:read_file needs a signed token granting Permission::Invoke on a matching resource pattern. No token, no access. The token is Ed25519-signed by the runtime key, linked to the approval audit entry that created it, optionally time-bounded, and scoped to session or persistent storage. The agent has no way to mint, modify, or extend them.
How tokens work
When a human approves an action with "Allow Always", the security interceptor (astrid-approval) calls into this crate to mint a CapabilityToken. The token is signed, stored, and returned as proof. On subsequent calls, the interceptor finds the token and skips the approval prompt.
ResourcePattern uses compiled glob matching via globset. Patterns like mcp://filesystem:* match any tool on that server. file:///home/user/** matches any file under that directory. Exact URIs skip glob compilation for speed. Path traversal (..) is rejected at pattern creation and again at match time. Defense in depth.
Dual-tier storage. Session tokens live in memory via RwLock<HashMap>. Persistent tokens survive restarts via SurrealKV. Both tiers share revocation and single-use tracking. Revocation persists to KV before updating in-memory state, so a crash between the two cannot resurrect a revoked token.
Replay protection. Single-use tokens are marked consumed atomically under a write lock. mark_used checks, persists, and inserts in one critical section to prevent TOCTOU races. State survives process restart via KV.
Tamper detection on read. Persistent tokens are re-validated (expiry + signature) on every get(), find_capability(), and has_capability() call. A token tampered on disk fails signature verification and is silently skipped. Session tokens skip this check because they were validated at add() time and live in trusted memory.
Clock-skew tolerance. Configurable window (default 30 seconds) via validate_with_skew. A token that expired 10 seconds ago still passes with the default tolerance.
Resource pattern examples
| Pattern | Matches |
|---|---|
mcp://filesystem:read_file |
Exactly that one tool |
mcp://filesystem:* |
Any tool on the filesystem server |
mcp://*:read_* |
Any read_ tool on any server |
file:///home/user/** |
Any file under /home/user |
Usage
[]
= { = true }
use ;
use Permission;
use KeyPair;
let runtime_key = generate;
let pattern = new.unwrap;
let token = create;
let store = in_memory;
store.add.unwrap;
assert!;
This crate also defines DirHandle and FileHandle, the opaque UUID-based handles used by astrid-vfs. You cannot construct a path to a directory you have not been granted.
Development
License
Dual MIT/Apache-2.0. See LICENSE-MIT and LICENSE-APACHE.