Files
buzz/docs/nips
Tyler b8db13d884 docs(nip-fi): state, don't argue — CONF −29%, rationale section, four pins (alt to #5946) (#6437)
## What this is

An alternative shape for the NIP-FI document family, built on top of
#5946 at its current head `772ba7a72` (so it carries R1–R12 and diffs
cleanly against it). Thesis: the current text *argues* where a standard
should *state*, and is silent where a reader needs one paragraph of
*why*. This PR makes every section either a rule or labeled as not one,
and fixes four correctness items found in review.

Base: `772ba7a72` (= `eva/nip-fi-comprehensive`). Eight FF commits, no
rebase. Three files. Oracle census unchanged at **58** (30/6/4/11/7).

**Review lap (Wren, Dawn, Eva) folded in as FF commits
`be72f0a5d`…`db35013c1`** — see "Review findings applied" below.

## Changes

### NIP-FI-CONF — 4,325 → 3,088 words (−29%), no obligation lost
- Denial fixtures 1,516 → ~740 words. Same 16-row table.
Enumeration-agreement checks 4 → 3 (checks 1 and 2 quantified over the
same set). Design history ("Two of these checks shipped red…", the
`Www-Authenticate` canonicalization paragraph, "one layer down", "a slow
way to discover…") removed from normative text.
- Interoperability exit test 934 → ~620 words. Same fixture contents,
same compared objects, same deferral rule, same negative control.
- Release gate restructured as a list; identical conjuncts.
- **BCP 14 keyword census 37 → 36.** Every `MUST`/`MUST
NOT`/`MAY`/`REQUIRED` sentence in the old text was fuzzy-matched to the
new text; the two that don't map are (a) "Their public responses MUST
compare byte-identical to each other, not merely equal in prefix or
status" — fully subsumed by the anonymity comparison one paragraph
later, and (b) the standalone "The suite MUST include a negative
control:" whose obligation is retained in the **Negative control**
paragraph. Reviewers: please try to find a third.

### NIP-FI core
- **New non-normative section "Relationship to other work"** (~190
words): DPoP / mTLS `cnf` with the NIP-42/98 event as the proof; durable
binding vs per-token claim; why 1:1 vs WebAuthn's N credentials; why two
contract IDs plus dependency versions; RFC 6750 error codes; RFC 9421 /
SigV4 family for the edge MAC. The "Thus two contract identities…"
argument paragraph moved here from the normative snapshot section. Three
source links added.
- **Pin:** `skew`, `maximum_assertion_age`, `maximum_status_age`
declared as configured finite values (missing → deny). Previously used
at :177-178/:266/:278 and never declared; EDGE already did this for its
own.
- **Pin:** NIP-98 `payload` hashes one defined referent — "body bytes:
the complete content after transfer decoding and before any content
decoding" — the same stage EDGE MACs as `payload_octets`. Previously
:315 said "bytes consumed by the application" and :320 said "body bytes
received", which differ under `Content-Encoding`. **This is a semantic
shift, not a clarification** (Eva's A3): under the old "consumed"
reading a `Content-Encoding` flip in flight was caught by hash mismatch;
under this pin the same octets hash equal, so the defense moves onto the
server-resolved-body-semantics rule (core:305-308, EDGE:176-178) and the
EDGE Metadata negative row (:367), which are now load-bearing for it.
All four body-wording sites say "substitution of the protected octets",
not "transformation", so content decoding after validation is permitted.
- **Pin:** a denial decided on a WebSocket upgrade, before any NIP-42
proof exists, is the HTTP table row sent instead of `101`; post-connect
denials are the Nostr text. `FI-TRACE-DENIAL-ORACLE` requires each row
"on every surface where its condition can be decided" (a private-state
row needing the proof is not decidable at upgrade — Wren). CONF exit
list aligned.

### NIP-FI-EDGE
- **R12 exception class-scoped** (Dawn's finding): "except an
independent Nostr proof validated on its own signature, such as the
NIP-98 event in `Authorization` or the NIP-42 event after connect"
instead of naming the field. Members are illustrative ("such as") so
`0x03`/`0x04` can conform once their contracts publish. Prohibition
widened to "request or connection component" — Dawn's model shows this
closes 6144 unprotected-connection derivations to 0. Requirement 3 gets
the matching carve-out.
- **`Authorization` byte-identity gains an oracle — as a two-point
witness, not a denial.** EDGE:62-65 makes altering it nonconformant; no
oracle named it. First attempt said "altered … denies"; Eva (A1) and
Dawn's `a1_oracle.py` showed that's false as a universal — an edge
substituting a fresh, valid NIP-98 event from the same actor *admits*,
because `Authorization` is outside the MAC by R12's design.
`FI-TRACE-PROXY-CROSS-REQUEST` now requires the bytes at final admission
to equal the client-sent bytes, witnessed at both points, and names the
mutant that must fail it (valid-proof substitution). The Request matrix
row no longer claims a denial for it.

## Review findings applied (all FF commits on `dcd0b2ff2`)
| # | Finder | Finding | Fix |
|---|---|---|---|
| W1 | Wren | Denial oracle demanded every private row on all three
surfaces; undecidable pre-proof | core:586 "on every surface where its
condition can be decided"; CONF:235-237 aligned |
| W2 | Wren | EDGE:168 and :372 still forbade any post-snapshot
"transformation" | "substitution of the protected octets denies" at all
four sites (core:315, :573; EDGE:168, :372) |
| W3/A2 | Wren, Eva | CONF dropped exit-evidence obligation (old :393) |
CONF:287 "Exit evidence includes the exchanged artifacts and each
implementation's statement of independence." |
| W4/A6 | Wren | Two-device sentence prescribed custody outside the
standard | core:605 "additional devices do not create additional active
bindings." |
| D1/A4 | Dawn, Eva | Em-dash members read exhaustive; `0x03` couldn't
conform | "such as" |
| D2 | Dawn | "a missing value denies" had no detecting oracle |
`FI-TRACE-ASSERTION-VALIDATION` gains "missing-configuration" negative |
| A1 | Eva, Dawn | `Authorization` oracle asserted a false denial
universal | two-point byte witness + valid-substitution mutant (above) |
| A5/W5 | Eva, Wren | Promotion guard retargeted by 4→3 collapse, now
inert | sentence deleted; check 2's disjointness already fails promotion
until the allowlist entry is removed, check 1 validates the class. CONF
MUST NOT 9→8, deliberate |
| D3 | Dawn | Replacement sentence said "only check 2's disjointness
fails" — false in 2/4 promotion cases (check 1 fails too when classes
disagree); "then" implied an ordering the independent conjuncts don't
have | both words dropped (`624429bd8`) |

Not taken this lap (predate this PR): EDGE:180 `maximum_provenance_age`
missing-config oracle; `0x04` Blossom row says "authorization event" not
"Nostr", so the class exception can't reach it until its contract is
written.

## Not changed
LIFECYCLE, DELEG, MODEL: zero bytes. Oracle tables, HMAC vectors,
negative matrix, denial table: zero bytes beyond the two cells named
above.

## Verification
- `git rev-parse HEAD` == `624429bd8` in the shell that produced the
census/keyword numbers below; section word counts above are from
`dcd0b2ff2` (CONF now 3,1k).
- Oracle census: `rg -c '^\| \`FI-[A-Z0-9-]+\` \|'` per file →
30/6/4/11/7.
- Distribution markers: 0 hits across all six docs and the commit
message.
- Keyword census and sentence mapping: script in the PR thread on
request.

## Open questions
1. ~~Two-device sentence~~ — closed by Wren's wording.
2. ~~R12 widening~~ — Dawn's model: net stricter than `772ba7a72`.
3. ~~CONF floor~~ — Eva measured Evidence rules at 317 words, every
sentence an obligation. Floor reached.
4. ~~A3 body-referent shift~~ — accepted by Wren and Eva at `db35013c1`:
the defense is a listed oracle row, hence inside the mutation regime.

## Verdicts
At `624429bd8`: Wren 9/9/9/9 · Eva 9/9/9/9 · Meli 9/9/9/9, each
re-pinned at this exact head. Dawn's three instruments (conf/a1/r12)
rc=0 at this head. CI 14 pass / 0 fail / 9 skipped. Zero known
falsehoods in the text.

Census partition note (Dawn): "58" is unique oracle IDs per document
across FI-TRACE/CONF/LC/DELEG prefixes; partitioned per prefix across
all docs including FI-INV the same corpus totals 75. Quote the partition
with the number.

---------

Signed-off-by: Meli <5aaa86bce934fc3445fc254aab560a40923f10252f92107e665073dede0e04d3@buzz.block.builderlab.xyz>
Co-authored-by: Meli <5aaa86bce934fc3445fc254aab560a40923f10252f92107e665073dede0e04d3@buzz.block.builderlab.xyz>
2026-08-21 09:22:40 -04:00
..
…
…