Files
buzz/docs/nips/NIP-FI-DELEG.md
Tyler d97780b477 docs(nips): comprehensive NIP-FI — core + claimable profiles (EDGE/LIFECYCLE/DELEG/CONF) (#5946)
## What

Comprehensive NIP-FI against `main`: one normative core plus four
separately
claimable profiles, replacing the single-document structure of #3726
(which was
based on #1485's branch, not `main`). Six documents, 1,975 lines, docs
only.

- **`NIP-FI.md` (core, 632 lines)** — issuer-qualified identity `(iss,
sub)`,
independent Nostr proof, client-attached assertion, partial bijection
with
durable tombstones, atomic final admission, bounded leases, private
denials
  with a closed response vocabulary, retire/revoke/rotate, two contract
identities (`assertion_policy_id`, `transport_contract_id`), per-policy
  `skew` / `maximum_assertion_age` / `maximum_status_age` with missing
configuration denying, a closed token-class rule (`at+jwt`,
`nip-fi+jwt`,
  named compatibility; ID tokens always deny), declared freshness class
  (`offline-jwt` | `current-status`), server-declared body authorization
  relevance (NIP-98 payload-binding fix, including a `payload` tag on an
irrelevant-body operation), BCP 14, "equivalent" defined over identity /
bounds / provenance classes, a compact non-normative worked wire
example,
  and a non-normative comparison with DPoP, mTLS-bound tokens, and HTTP
  Message Signatures. FI-INV-01..16 are normative core text. The
behavioral-oracle table lists exactly 30 oracle IDs, one per row, with
no
  shorthand.
- **`NIP-FI-EDGE.md`** — trusted-edge surface: the
`trusted-proxy-hmac-v2`
envelope + canonicalization, or a private authenticated-edge adapter
under a
reviewed contract; `authorization_domain_id` derivation (exact 16 RFC
9562
UUID bytes); `proof_transport_code` registry (0x01 NIP-42, 0x02 NIP-98;
  0x03 Git smart-HTTP and 0x04 Blossom reserved pending their transport
contracts; 0x05–0x7f unassigned pending published stable specifications)
  + extension procedure; body-acquisition bounds; three normative test
vectors. An independent Nostr proof (the NIP-98 event in
`Authorization`,
  which reaches the verifier byte-identical, or the NIP-42 event after
connect) is the only decision input outside the MAC; absent or
incomplete
  provenance on an edge-required route is `missing_evidence`,
  present-but-failing provenance is `evidence_rejected`.
  Header-trust-without-provenance is nonconformant.
- **`NIP-FI-LIFECYCLE.md`** — provision / disable / re-enable /
administrative
expiry (`binding_not_after`) / pending-replacement lineage, one
conformance
trace per privileged transition; every binding-creating transition
declares
whether it continues or establishes a grant; a private-condition table
for
  CONF enumeration agreement.
- **`NIP-FI-DELEG.md`** — delegated agents; explicit temporal boundaries
matching core's inclusive-`nbf`/exclusive-`exp` idiom, with the
delegated
`skew` configured by this profile; lease deadline anchored to the lease
  issue instant; strict path separation — a delegated request carries no
assertion or provenance field, so it cannot traverse an edge-provenance
  route and uses ingress on which NIP-FI-EDGE is not required.
- **`NIP-FI-CONF.md`** — conformance evidence: an immutable claim tuple
  including the governing document revision and exit fixture digest; the
  complete 16-row denial-fixture enumeration with three mechanical
  enumeration-agreement checks; mutation adequacy with a countable
  denominator — one retained killed mutant per literal oracle-table row
(30 core + 6 EDGE + 11 LIFECYCLE + 7 DELEG + 4 CONF = 58), rows selected
structurally by their first cell, never by section title, with the
release
gate and CONF's own oracle rows stated in the same listed-oracle terms
and
  a mutant defined for CONF's own report- and suite-subject oracles; an
  interoperability exit test compared over signing inputs (per-transport
NIP-01 serialization for the NIP-98 and NIP-42 proofs; decoded protected
header and claims as JSON values for the assertion), with a shared exit
  fixture pinning complete pre-signature header/claim JSON and complete
unsigned event fields for both transports, and mandatory negative
controls.
  `FI-CONF-INTEROP-EXIT` is `deferred` with reason
`no-independent-implementation` until a second independent
implementation
  exists; the canonical fixture is editor-authored at
`docs/nips/fixtures/nip-fi-conf-exit.json` and is **not in this PR** —
until
it is published a claim records `pending-canonical-fixture`, valid only
  while the exit test is deferred. Explicit not-applicable dispositions,
including `offline-jwt` deployments for the two current-status oracles
and
  absence of a revocation-bounded external capability projection for
  `FI-TRACE-CAPABILITY-REVOCATION`.
- **`NIP-FI-MODEL.md`** — non-normative companion; defines no
requirement or
  conformance claim and is not claimable.

## Why

The prior draft rated 9 (soundness) / 6 (minimalness) / 7 (elegance) /
7 (correctness) in adversarial + comparative review. This restructure
keeps the
two-invariant spine untouched, makes everything else a claimable
profile, and
collapses five stacked versioning mechanisms into two contract
identities.

Mutation adequacy counts one mutant per literal oracle-table row — a set
two
implementers enumerate identically — instead of "each normative
requirement,"
which had four defensible readings.

Resolved product calls (owner-approved):
1. Enrollment/denial posture is private — boolean enrollment discovery,
TOFU
extension claim not self-advertised, `key_mismatch →
authorization_denied`
   joins the denial anonymity set, and replayed evidence is classed
   `authorization_denied` so resubmission reveals nothing about commit.
2. Revocation honesty — only `current-status` deployments may advertise
an
   unconditional residual-revocation bound; `offline-jwt` advertises
unbounded/unknown. Access tokens keep RFC 9068 `at+jwt`; `nip-fi+jwt` is
   reserved for a separately minted Buzz assertion.

## Acceptance bar

- Nothing in core is deletable without losing a stated core guarantee.
- From the core document plus the CONF exit fixture, a second
implementer can
produce a valid request equal over the request compared object (signing
  inputs), and a byte-exact public denial per class — no reference
  implementation.
- Every oracle-table row ships a retained killed mutant satisfying only
the
  entry it was selected for.
- Both deployment profiles (trusted proxy = EDGE, client-held OIDC =
core
  client-attached) pass the same lifecycle conformance suite.

## Status

Ready at head e720a5cda. Every revision below is on this branch: the
2026-08-17 and 2026-08-18 review laps (Wren, Dawn, Perci, Sami, Mari,
Quinn)
closed at 513e03b06, 17d455a9b, and 4f913a813; the 2026-08-20 external
line-by-line review (R1–R10, R12) closed across 56e74141e..772ba7a72;
the
2026-08-20/21 adversarial lap (#6437) squash-merged as b8db13d88; the
round-3
external review (R13, R14), the DELEG×EDGE composition note, and three
terminology nits closed at e720a5cda; R11 is this description. Oracle
census: 58 (30 core, 6 EDGE, 11 LIFECYCLE, 7 DELEG, 4 CONF).

Known follow-ups, filed after merge and out of scope here: adapter-only
edge
deployments and FI-EDGE claimability; an EDGE private-condition table
for
CONF's enumeration-agreement check; an enumerable definition of the
positive/negative oracle sets used by the global mutation controls;
NIP-OA's clock-free verification versus NIP-FI-DELEG's wall-clock
expiry.

Supersedes #3726 as the spec vehicle; #1485 remains the design-history
anchor.

---------

Signed-off-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Signed-off-by: Max <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@buzz.block.builderlab.xyz>
Signed-off-by: Perci <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@buzz.block.builderlab.xyz>
Signed-off-by: Wren <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz>
Signed-off-by: Dawn <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@buzz.block.builderlab.xyz>
Signed-off-by: Tyler Longwell <tlongwell@squareup.com>
Signed-off-by: Meli <5aaa86bce934fc3445fc254aab560a40923f10252f92107e665073dede0e04d3@buzz.block.builderlab.xyz>
Co-authored-by: Eva <011987e296fd5006292d2f930b574be47c7801048d1983c46c425d3c95f0cffd@buzz.block.builderlab.xyz>
Co-authored-by: Max <d8473ee32b973aa31a21a65adddcc4b69cc2a8a4dee8121ecd51926e0cddbc02@buzz.block.builderlab.xyz>
Co-authored-by: Perci <5a968df9a7494b4e019b9ecf739e088ba61097b4312124e9a88ae5b42e3f5f3e@buzz.block.builderlab.xyz>
Co-authored-by: Wren <5217c5c2f7bfb4333e46d17c98a9255a52dadee18dcd43a43536b95e6776dfa0@buzz.block.builderlab.xyz>
Co-authored-by: Dawn <c6237ef84fa537c78dcee78efd2d4e59f728859c7f194da42ac51ededfa0be05@buzz.block.builderlab.xyz>
Co-authored-by: Meli <5aaa86bce934fc3445fc254aab560a40923f10252f92107e665073dede0e04d3@buzz.block.builderlab.xyz>
2026-08-21 17:18:24 -04:00

8.4 KiB

NIP-FI-DELEG

Delegated agent authorization profile

draft optional relay

Protocol dependency: NIP-FI core.

The key words "MUST", "MUST NOT", "REQUIRED", "SHOULD", "SHOULD NOT", and "MAY" in this document are to be interpreted as described in BCP 14 (RFC 2119 and RFC 8174) when, and only when, they appear in all capitals.

Scope

This profile authorizes a delegate key from separately validated delegation evidence rooted in a currently eligible NIP-FI owner binding. The delegate proves its own key. It does not present a federated assertion and never receives or inherits the owner's binding. Because a trusted edge inserts assertion and provenance fields on every request it forwards, and FI-DELEG-PATH-SEPARATION denies any such field on a delegated request, delegated requests cannot traverse a route that requires edge provenance; they use ingress on which NIP-FI-EDGE is not required.

This profile defines the normalized delegation result and its additional preparation, final-admission, and lease witnesses. It does not define a wire format for creating delegation relationships; NIP-OA or another protocol may supply the evidence if it satisfies this contract.

Delegation evidence

A validator returns this closed result:

DelegationEvidence = (
  domain,
  owner_key,
  delegate_key,
  relationship_id,
  relationship_revision,
  audience,
  operations,
  conditions,
  resource_or_target,
  not_before?,
  mandatory_expiry
)

relationship_id and relationship_revision are deployment-local dependency identifiers. All other fields are interoperability-critical in meaning even when their concrete encoding belongs to the supplying delegation protocol.

The evidence authenticates every field, has one unambiguous owner and delegate, matches the server-owned domain and exact request or target, and has a finite expiry satisfying now < mandatory_expiry; equality at an expiry is expired. Optional not_before satisfies not_before <= now + skew, using the configured delegated skew; arithmetic is overflow-safe. A missing configured skew denies. The proven actor equals delegate_key. [FI-DELEG-EVIDENCE-CLOSED]

A delegated request carries fresh request-appropriate Nostr proof and no Nostr-Federated-Identity or profile provenance field. Mixed direct and delegated evidence denies rather than selecting a path. [FI-DELEG-PATH-SEPARATION]

Private denial conditions

This profile defines exactly this private condition identifier and owning public class for NIP-FI-CONF enumeration agreement:

Private condition identifier Public class
delegation_not_current authorization_denied

The identifier is a fixture name, not a wire value. Adding, removing, renaming, or reclassifying it requires the same change in NIP-FI-CONF's denial-fixture table.

Preparation

Preparation resolves the exact server-owned domain, target context, operation, resource, and proven delegate actor before validating delegation evidence. It then atomically reads:

  • the active owner binding and exact binding version;
  • every owner tombstone, key-revocation, administrative, and profile lifecycle gate applicable to that binding;
  • the exact relationship identifier and revision;
  • current local policy and resource versions; and
  • every invalidation dependency and deadline.

The owner binding is current and authorization-eligible at preparation. A cached owner lease is not authority. The requested capability is the intersection of the delegation's operation, audience, conditions, and target with current local policy; an unsupported operation or empty intersection denies. [FI-DELEG-OWNER-CURRENT]

Preparation remains read-only under FI-INV-08. It cannot create or change an owner or delegate binding, identity, provenance, lifecycle fact, relationship, last-seen value, replay claim, receipt, lease, or application effect. [FI-DELEG-NO-BINDING]

Final admission

Core final admission additionally requires:

  1. the exact delegation evidence and delegate proof remain live;
  2. domain, actor, target, audience, operation, resource, and relationship match the prepared value;
  3. the exact current owner binding and binding version remain eligible;
  4. relationship identity and revision remain current;
  5. current capability intersection equals the prepared intersection; and
  6. changed dependencies are reread and the complete delegated decision is recomputed before atomic commit.

Any mismatch, expiry, owner retirement, owner key revocation, owner binding version change, relationship change, unreadable dependency, or unsupported capability denies. Rotation makes the former owner key non-current; its relationships do not transfer to the new key. [FI-DELEG-OWNER-CURRENT]

The delegated path creates no owner or delegate binding and cannot consume an enrollment opportunity. Its receipt identifies the delegate actor and exact owner-binding and relationship dependencies without publishing identity material. [FI-DELEG-NO-BINDING]

Delegated leases

A deployment configures a positive finite delegated maximum and a non-negative finite delegated skew. The lease deadline is no later than the minimum of:

  • delegation expiry;
  • delegate proof or connection bound;
  • owner binding administrative bound, when applicable;
  • current relationship bound;
  • local policy bound;
  • the lease issue instant plus the configured delegated maximum; and
  • any stronger owner-assertion bound the deployment requires.

Missing finite configuration denies. Equality is expired and arithmetic is overflow-safe. [FI-DELEG-LEASE-BOUND]

Before each protected use, the service checks the delegate actor, owner binding and version, relationship and revision, capability intersection, target, resource, local policy, deadline, and invalidation state. It closes or rejects the lease within the deployment's tested revocation-detection bound after any owner or relationship dependency becomes ineligible. The claimed bound is no smaller than measured worst-case detection plus enforcement delay. [FI-DELEG-INVALIDATION-BOUND]

Owner retirement, revocation, rotation, disablement under NIP-FI-LIFECYCLE, or binding replacement invalidates dependent delegates on the same effective schedule as owner authority. A delegate lease never authorizes another delegate or owner key on the same connection. [FI-DELEG-OWNER-CURRENT]

Discovery

A relay claiming this profile MAY add "delegation": true to the NIP-11 federated_identity object only when owner-current resolution, the positive finite maximum, uniform final admission, and all profile oracles are active. It does not advertise relationship IDs, owner keys, private delegation protocol names, or policy detail. [FI-DELEG-DISCOVERY]

Behavioral oracles

ID Required outcome
FI-DELEG-EVIDENCE-CLOSED Valid closed evidence passes; unauthenticated, ambiguous, wrong-domain/actor/target/audience, not-yet-valid, and expiry-equality variants deny.
FI-DELEG-PATH-SEPARATION Delegation plus any direct assertion/provenance field denies; neither path falls back to the other.
FI-DELEG-OWNER-CURRENT Exact current owner succeeds; retirement, revocation, rotation, replacement, stale owner version, stale relationship, and unreadable owner state deny without inheritance.
FI-DELEG-NO-BINDING Successful, denied, and concurrent delegated requests create or change no owner/delegate binding or lifecycle state.
FI-DELEG-LEASE-BOUND Every authority bound and equality boundary closes the lease; absent finite maximum denies.
FI-DELEG-INVALIDATION-BOUND Measured owner/relationship revocation closes prepared evidence and live leases within the claimed detection bound.
FI-DELEG-DISCOVERY Discovery is false/absent until the complete active profile passes; public output contains no relationship or owner detail.

NIP-FI-CONF defines evidence packaging and mutation adequacy. Each uppercase requirement above names the oracle that detects its violation.

Security considerations

Delegation expands authority only by intersection and never by copying owner capabilities. A stolen delegation still requires the delegate key. A stolen delegate key is bounded by the relationship and finite lease. Owner rotation cannot silently transfer delegation because the exact owner key and binding version are dependencies. Implementations should invalidate by dependency index rather than wait for incidental delegate traffic.