niko_trust/docs/DELEGATION.md
Niko Marmeladkov 20cc52c3a5 feat: network layer — PoW, checkpoint chain, gossip, light node, WS, delegation, rotation, BFT
- 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.
2026-08-25 20:38:40 +03:00

66 lines
2.8 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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.