mirror of
https://github.com/block/buzz.git
synced 2026-10-27 12:40:30 +00:00
## 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>