Repository navigation
Description
Low priority. Inherited from the TypeScript capture, so leaving it open regresses nothing against the relay as it ships today; it needs a concurrency window (a publish passing the vanish check while a kind-62 completes) and the fix has an open design question, which is why it is a decision rather than a patch. Tracked in the Nostream 4.0 Rust Rewrite project as Todo.
A publish that has already passed the vanish check can store its event after a kind-62 request finishes, and nothing removes it afterwards.
The window
handlers/event.rs:462 checks is_vanished once per inbound event, before the strategy runs. Each message is handled in its own task (relay.rs's JoinSet), so this interleaving is possible:
- publish from author A passes
is_vanished→ false, - A's kind-62
vanishrunsdelete_by_pubkey_except_kinds(line 33), creates the request (37),set_vanished(A, true)(42), - the publish from step 1 stores its event.
Reads exclude deleted rows, not vanished authors, so the event from step 3 is readable indefinitely. set_vanished moving earlier would not close the window: the publish already passed the check.
Found by the static review of job 011-relay-strategies at 0dac5fe (crates/nostream-relay/src/strategies/vanish.rs:33-42).
Why it is not that job's defect
The capture has the same window, in the same order: vanish-event-strategy.ts deletes, creates, then calls setVanished, and event-message-handler.ts:385 checks isVanished once before dispatch. The port reproduces the capture exactly, which is what a parity job owes. Fixing it here would be a deviation that needs its own decision.
What a fix has to decide
- Whether to coordinate per pubkey (a write lock or a per-author queue) or to filter vanished authors at read time — the second is cheaper but changes query shape and index needs.
- Whether an in-flight event should fail with a policy refusal or be stored and then swept.
- What the capture's users experience today, since any real deployment of the TypeScript relay has this behaviour: a fix is an improvement, not a parity repair, and should be recorded as one.
Expected cost: $2.00 — a small concurrency fix plus tests, but the read-path alternative makes it a design decision first.
Activity
chappie-daemon commentedon Nov 3, 2026
Do not pick this up as a patch job. This issue opens by saying it "needs a concurrency window … and the fix has an open design question, which is why it is a decision rather than a patch" — and that is still true. A recon→spec→build run would have the factory settle an ADR question by accident, which is how a design decision gets made by whoever happened to be next in the queue.
First step is an ADR, in
docs/rewrite/decisions/, settling how a publish that has already passedis_vanishedis prevented from storing after a kind-62 completes — whether a second check at the write seam, a vanish generation counter, or an ordering guarantee in the store. Only after that lands does this become a buildable issue.It sits at the top of the Todo column by number, so it is the first thing a queue reader hits. That is why this is written here rather than in a review folder.