mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-11 16:57:39 +00:00
A high-effort audit of the branch found that the durability guarantees the
previous commits claimed were not the guarantees the code provided. Three of
these are in the code written to close the last review, and they defeat
exactly what those commits set out to fix.
`INostrClient.publish` returns Unit — it queues an event and never reports
acceptance; `publishAndConfirm` is the confirming variant. So every
`runCatching { publish(...); true }` was true whenever local signing worked.
That made minting's "record the link before handing out the URL" gate
decorative, and made revoke worse than decorative: it reported success for a
tombstone no relay stored, then recorded the kind-13303 tombstone, whose
merge drops the entry — destroying the only `signer_sk` that could ever
retire the link while the link stayed live. Both paths, and the Refounding
re-mint, now confirm.
`fetchAll` returns an empty list on cannot-connect / CLOSED / idle-timeout,
so "a relay served us and had nothing" and "nobody answered" were the same
observation. Reading the second as "no list yet" reintroduced, one layer
below, the wipe the null-vs-empty work existed to prevent. `fetchAllWithHooks`
gains a `doneOut` of per-relay terminal reasons plus `anyRelayServed()`, and
both clients now only treat an empty read as an empty list when a relay
actually reached EOSE.
The rest:
- `drainConcordRekeys` discarded the entry `adoptConcordRoot` now returns, so
only the account that *launched* a rotation re-minted its links. An admin
who was merely re-keyed left every link they had handed out on the dead
root, and anyone stranded behind one could never recover — which is the
branch's headline goal, holding only for the rotator.
- The join-time ban gate fetched the Control Plane from `bundle.relays`
alone (stale metadata refuses a community we can plainly reach) with a
single un-paged REQ (truncated at the relay's filter cap, so a missing
older ban edition fails the gate OPEN, re-admitting the account it exists
to refuse). Now unions in the relays that just served the bundle, and pages.
- `decodeOrNull` failed the whole document for one structurally incompatible
entry. Since null now means "refuse to write", that converted the old
silent data loss into a permanent write lock on a coordinate that never
ages out. Unreadable entries are carried verbatim instead, so they neither
block the account nor get dropped on re-encode.
- The list read took the newest event of any kind and then cast, so one stray
event at the coordinate read as "unreadable" forever. Filters by kind first.
- The Refounding refresh did one full round trip per link, serially, inside a
user-visible rotation. One pooled REQ over every link signer, then
concurrent confirmed re-mints, classified per coordinate so one link's
tombstone cannot decide another's status.
Verified on a tablet: mint, list, revoke and the cross-client refusal still
work end to end — and with the community relay killed, revoke now reports
"The link couldn't be revoked" and leaves the entry intact, where before it
would have claimed success and destroyed the key.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>