Skip to content

Commit ebd946b

Browse files
authored
docs: RFC-008 delegation chains, envelope APIs, and May 2026 updates (#43)
New pages: - concepts/delegation.md: Authority Envelopes & Delegation Chains concept - how-to/security/delegation-chains.md: Step-by-step delegation chain guide Updated references: - reference/grpc.md: Add 4 envelope RPCs (CreateEnvelope, DeriveEnvelope, BuildTransportHeaders, VerifyEnvelopeChain) and SimpleGuardService to service overview - reference/sdk-python/simple-guard.md: Add create_envelope(), derive_envelope(), make_delegation_headers() docs - reference/sdk-python/mcp.md: Add structured rejection fields (error_code, rejection_detail, requested/presented_capability) and scope_insufficient deny reason (RFC-008 B8) - reference/server/policy-enforcement.md: Add EnvelopeVerification config (CAPISCIO_MAX_CHAIN_DEPTH, CAPISCIO_ORG_TRUST_BOUNDARY), chain headers, chain verification error codes, PDP enrichment fields Updated guides: - identity/index.md: Show connect() zero-argument env var fallback - how-to/security/gateway-setup.md: Add chain verification config section - how-to/security/badge-keeper.md: Document automatic CA→PoP mode upgrade - mcp-guard/guides/evidence.md: Add GuardEventEmitter and policy_enforced event emission on deny Nav: - Add 'Delegation Chains' to Concepts and How-To > Security sections
1 parent b626e55 commit ebd946b

11 files changed

Lines changed: 790 additions & 4 deletions

File tree

docs/concepts/delegation.md

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
---
2+
title: Delegation Chains
3+
description: How authority envelopes enable scoped, verifiable delegation between agents
4+
---
5+
6+
# Delegation Chains
7+
8+
In multi-agent workflows, one agent often needs to act on behalf of another. Authority Envelopes provide a cryptographic mechanism for scoped, verifiable delegation.
9+
10+
---
11+
12+
## The Problem
13+
14+
Consider a workflow where Agent A asks Agent B to perform a database query, and Agent B delegates that to Agent C (a specialized database reader). Without delegation:
15+
16+
- Agent C has no proof that Agent A authorized this action
17+
- There's no way to scope what Agent C is allowed to do
18+
- The chain of authority is invisible to enforcement points
19+
20+
Trust badges prove **identity** ("I am Agent B"), but not **authority** ("Agent A authorized me to read from the database").
21+
22+
---
23+
24+
## Authority Envelopes
25+
26+
An **Authority Envelope** is a JWS-signed token (defined in [RFC-008](https://github.com/capiscio/capiscio-rfcs/blob/main/docs/008-delegated-authority-envelopes.md)) that grants scoped authority from one agent to another.
27+
28+
Key claims in an envelope:
29+
30+
| Claim | Description |
31+
|-------|-------------|
32+
| `iss` | DID of the agent granting authority |
33+
| `sub` | DID of the agent receiving authority |
34+
| `cap` | Capability class (e.g., `tools.database.read`) |
35+
| `depth` | Remaining delegation depth (decrements at each hop) |
36+
| `exp` | Expiration time |
37+
| `parent_hash` | SHA-256 hash of the parent envelope (for chain integrity) |
38+
| `constraints` | Optional restrictions (time windows, resource filters) |
39+
| `enforcement_mode_min` | Minimum enforcement mode for this delegation |
40+
41+
---
42+
43+
## Chain Structure
44+
45+
Envelopes form **hash-linked chains** where each child references its parent:
46+
47+
```
48+
┌──────────────────┐ ┌──────────────────┐ ┌──────────────────┐
49+
│ Root Envelope │────▶│ Child Envelope │────▶│ Leaf Envelope │
50+
│ │ │ │ │ │
51+
│ iss: Agent A │ │ iss: Agent B │ │ iss: Agent C │
52+
│ sub: Agent B │ │ sub: Agent C │ │ sub: Agent D │
53+
│ cap: tools.* │ │ cap: tools.db.* │ │ cap: tools.db.rd │
54+
│ depth: 2 │ │ depth: 1 │ │ depth: 0 │
55+
└──────────────────┘ └──────────────────┘ └──────────────────┘
56+
```
57+
58+
### Monotonic Narrowing
59+
60+
Each link in the chain must be **equal or narrower** than its parent:
61+
62+
- **Capability class** can only narrow (e.g., `tools.*``tools.db.*``tools.db.read`)
63+
- **Delegation depth** must decrease
64+
- **Constraints** can only become more restrictive
65+
- **Expiration** cannot exceed the parent's expiration
66+
67+
This ensures authority can never be escalated through delegation.
68+
69+
### Enforcement Mode Escalation
70+
71+
Envelopes can set a minimum enforcement mode via `enforcement_mode_min`. This mode can only **escalate** (become stricter) through the chain:
72+
73+
| Mode | Strictness | Behavior on DENY |
74+
|------|-----------|-------------------|
75+
| `EM-OBSERVE` | Lowest | Logged, request proceeds |
76+
| `EM-GUARD` | Medium | Request blocked |
77+
| `EM-STRICT` | Highest | Request blocked, unknown obligations denied |
78+
79+
If a parent sets `EM-GUARD`, no child can relax it to `EM-OBSERVE`.
80+
81+
---
82+
83+
## Chain Verification
84+
85+
When the gateway PEP receives a request with delegation headers, it verifies the entire chain (RFC-008 §9.2):
86+
87+
1. **Signature verification** — Each envelope is signed by its issuer
88+
2. **Hash chain integrity** — Each child's `parent_hash` matches the parent
89+
3. **Narrowing validation** — Capabilities, depth, and constraints narrow monotonically
90+
4. **Badge binding** — The leaf envelope's `sub` matches the caller's badge subject
91+
5. **Depth limits** — Chain length does not exceed `MaxChainDepth` (default: 10)
92+
6. **Expiration** — All envelopes in the chain are within their validity period
93+
7. **Enforcement mode** — The strictest mode across the chain is applied
94+
95+
---
96+
97+
## Trust Boundaries
98+
99+
Delegation chains can span organizational boundaries. The `OrgTrustBoundary` configuration controls whether cross-org chains are accepted:
100+
101+
- **Same-org chains**: All issuers share the same org DID prefix — always accepted
102+
- **Cross-org chains**: Issuers from different orgs — accepted only when `OrgTrustBoundary` is empty or matches
103+
104+
---
105+
106+
## Relationship to Badges
107+
108+
Envelopes and badges serve complementary roles:
109+
110+
| | Badge | Envelope |
111+
|-|-------|----------|
112+
| **Proves** | Identity ("I am Agent B") | Authority ("Agent A authorized me") |
113+
| **Issued by** | CA / Self-signed | Another agent |
114+
| **Scope** | Agent-level trust | Per-action capability |
115+
| **Lifetime** | Hours to days | Minutes to hours |
116+
| **Header** | `X-Capiscio-Badge` | `X-Capiscio-Authority` |
117+
118+
A delegated request carries both: the badge proves who the caller is, and the envelope chain proves they have authority to act.
119+
120+
---
121+
122+
## Transport Headers
123+
124+
Delegation chains are transmitted via HTTP headers:
125+
126+
| Header | Content |
127+
|--------|---------|
128+
| `X-Capiscio-Authority` | Leaf envelope JWS |
129+
| `X-Capiscio-Authority-Chain` | Base64url-encoded JSON array of the full chain |
130+
| `X-Capiscio-Badge-Map` | JSON object mapping intermediate agent DIDs to their badge JWS tokens |
131+
132+
---
133+
134+
## DID Resolution
135+
136+
Chain verification requires resolving issuer DIDs to their public keys. CapiscIO uses a **composite key resolver** that handles both DID methods:
137+
138+
| DID Method | Resolution | Example |
139+
|------------|-----------|---------|
140+
| `did:key` | Local decode (no network) | `did:key:z6Mk...` |
141+
| `did:web` | HTTPS fetch of DID document | `did:web:agent.example.com` |
142+
143+
### DID:web Security
144+
145+
The `did:web` resolver includes SSRF protections (RFC-008 §17.1):
146+
147+
- **HTTPS required** in production (HTTP only allowed in dev mode)
148+
- **Blocked destinations**: localhost, private IPs (10.x, 172.16.x, 192.168.x), link-local, cloud metadata endpoints
149+
- **No redirect following** (prevents SSRF via redirect chains)
150+
- **Response size limits**: 64 KB maximum
151+
- **Request timeouts**: 10 seconds
152+
- **Document caching**: 5-minute TTL (reduces network calls)
153+
154+
---
155+
156+
## Next Steps
157+
158+
- [Create and use delegation chains](../how-to/security/delegation-chains.md) — Step-by-step guide
159+
- [Gateway setup](../how-to/security/gateway-setup.md) — Configure the PEP to verify chains
160+
- [Policy enforcement config](../reference/server/policy-enforcement.md) — Chain verification settings
161+
- [RFC-008](https://github.com/capiscio/capiscio-rfcs/blob/main/docs/008-delegated-authority-envelopes.md) — Full specification

docs/how-to/security/badge-keeper.md

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,25 @@ Reduce check frequency:
280280

281281
---
282282

283+
## Automatic PoP Mode Upgrade
284+
285+
When badge keeper starts in CA mode, it automatically upgrades to **Proof of Possession (PoP) mode** if the agent's private key is available:
286+
287+
1. Loads the agent's private JWK from `~/.capiscio/keys/`
288+
2. Derives the agent's DID via `did:key`
289+
3. Uses the PoP endpoints (`/v1/sdk/agents/{did}/badge/challenge``/pop`)
290+
291+
This upgrade is transparent — no configuration change is needed. PoP badges (IAL-1) provide stronger identity assurance than CA-only badges because they cryptographically prove the agent possesses the private key corresponding to its DID.
292+
293+
!!! info "When does PoP upgrade happen?"
294+
The upgrade occurs automatically when:
295+
296+
- The agent's private key exists at `~/.capiscio/keys/`
297+
- The badge keeper is configured with `--key` pointing to the key
298+
- The CapiscIO Registry supports PoP (all current versions do)
299+
300+
---
301+
283302
## See Also
284303

285304
- [Issue and Verify Badges](./badges.md) - Manual badge workflow

0 commit comments

Comments
 (0)