mirror of
https://github.com/block/buzz.git
synced 2026-08-18 06:50:31 +02:00
Draft wraps (kind:31234) now require exactly one `h` UUID tag binding them to a specific Buzz channel or DM. The relay enforces: - Exactly one valid UUID `h` tag on every kind:31234 event - Channel existence: the `h` UUID must resolve to a live channel - Membership: author must be a member of that channel at write time - Immutable binding: once a (author, d_tag) draft is written to channel A, replacement events must carry the same h=A; rebinding to a different channel is rejected at the ingest layer The previous channel-less/global-state design is removed. Draft fan-out already applied the author-only gate (AUTHOR_ONLY_KINDS); with channel_id now non-NULL for kind:31234, the existing channel visibility/membership filter in fan-out applies naturally with no additional changes. E2E test suite rewritten for the channel-bound contract: - h-tag validation: missing, duplicate, non-UUID, nonexistent channel - Non-member author rejection + removed-member regression - Immutable binding: rebind rejected, same-channel replacement accepted - Author-only reads: WS REQ/COUNT, HTTP /query, /count, live fan-out - known-#d privacy tripwires (exclusive and kindless) - Tombstone head queryable by author, tombstone replaces live draft - NIP-01 same-second tie-break (distinct candidates enforced) - Stale write cannot supersede current head - Workflow / channel kindless query exclusion - Tenant confinement (alien channel rejected) - FTS exclusion (NULL search_tsv confirmed) - NIP-11 advertises NIP-37, not NIP-40 Co-authored-by: Will Pfleger <pfleger.will@gmail.com> Signed-off-by: Will Pfleger <pfleger.will@gmail.com>