- BLAKE3 keyed proof-of-work on object storage and auth challenges, with frozen vectors cross-checked against an independent Python reference implementing the single-block hash it needs. - Sparse Merkle trie over object IDs: order-independent roots, inclusion and absence proofs (internal/smt). - Signed checkpoint chain per relay: transport key amendment to INV-1, /v1/checkpoint/* and inclusion/absence proof endpoints, restart-safe epoch continuity (internal/checkpoint). - Head gossip with TOFU pinning and equivocation detection; light node (cmd/lightnode) that stores no history: quorum of pinned relays, every served object proven against the agreed root, LRU disk cache. - WebSocket streaming on relay and light node (coder/websocket): scoped channels mirroring REST, raw envelopes verified client-side; light node marks streamed objects unproven until checkpoint coverage. - Protocol v1 additions: DelegationClaim tag 0x07 with deterministic chain resolution in verify.Graph, KeyRotationRequest/Confirm tags 0x08/0x09 with hash-bound two-sided consent and Policy.RotationMaxAge; spec sections, frozen vectors appended byte-identically, Python reference extended. - Optional permissioned BFT finality over gossip (internal/bft): prevote/precommit with quorum certificates verifiable offline. - Quick wins: Policy.TrustedIssuers, per-type stored metrics, batch fetch, lexicographic lists with stable cursor pagination. - Security review of the network layer (docs/SECURITY-REVIEW.md) with findings F-01..F-09; hub send/close race and unstable pagination fixed under review. 12 packages green, vet/gofmt clean, protocol fuzzing stable.
66 lines
2.8 KiB
Markdown
66 lines
2.8 KiB
Markdown
# Delegation
|
||
|
||
How one identity lends its voice to another, and how a verifier decides
|
||
whether a claim made by someone it does not know is backed by someone it
|
||
does.
|
||
|
||
The wire object is `DelegationClaim` (PROTOCOL.md §8.7, tag `0x07`). This
|
||
document is about what it means and how chains are resolved.
|
||
|
||
---
|
||
|
||
## 1. The statement
|
||
|
||
```
|
||
granter says: grantee may issue claims covering these exact predicates,
|
||
re-delegating at most max_depth further times.
|
||
```
|
||
|
||
- **Exact predicates only.** `{minecraft.op: true}` covers the key
|
||
`minecraft.op` and nothing else. There are no prefixes and no wildcards:
|
||
a grant of `user.` that silently covered `users.admin` would turn an
|
||
administrative convenience into an escalation primitive.
|
||
- **Every predicate value is the boolean `true`**, enforced at decode time.
|
||
Coverage is membership, not interpretation (INV-5).
|
||
- **`max_depth` counts hops below the grant.** `0` means the grantee speaks
|
||
for itself only; `2` allows the grantee to delegate onward once, and that
|
||
sub-grantee once more.
|
||
- **Revocation mirrors claims**: the granter signs a `Revocation` targeting
|
||
the delegation's object ID. Expired grants die on their own; supersession
|
||
(`serial`) replaces terms without revoking history.
|
||
|
||
## 2. Chain resolution
|
||
|
||
A consumer anchors trust in roots — issuers it already decided to believe
|
||
(`Policy.TrustedIssuers`). When a claim's issuer is not a root, the verifier
|
||
searches for a path:
|
||
|
||
```
|
||
trusted root ──grant──▶ … ──grant──▶ claim issuer ──claim──▶ subject
|
||
```
|
||
|
||
Rules, implemented deterministically in `verify.Graph`:
|
||
|
||
1. Every link must be signature-valid, current at the evaluation instant,
|
||
unrevoked by its granter, and cover the claim's exact predicate.
|
||
2. Where several grants could serve, the highest `serial` wins, ties broken
|
||
by lowest content ID — map order never leaks into a decision.
|
||
3. Total hops are bounded by `Policy.MaxDepth` (default 3), and each link's
|
||
own `max_depth` must fit the hops below it: link *i* of *k* needs
|
||
`max_depth ≥ k−1−i`.
|
||
4. Cycles cannot loop: depth bounds terminate every walk.
|
||
5. The accepted result reports the full path in `Result.Chain`
|
||
(`issuer → … → root`) as audit evidence.
|
||
|
||
An empty `TrustedIssuers` keeps the original model exactly: any issuer the
|
||
consumer fed into the graph may satisfy the policy directly. Delegation only
|
||
activates when roots are named.
|
||
|
||
## 3. What delegation does not mean
|
||
|
||
- It is not identity merging: the claim still names its real issuer, and the
|
||
chain names everyone who lent authority.
|
||
- It is not transitive by default: a root that grants with `max_depth: 0`
|
||
creates exactly one hop and nothing more.
|
||
- A hostile link can stop forwarding, but cannot forge: every hop is signed
|
||
by its own granter, and the root sees only grants it signed itself.
|