mirror of
https://github.com/vitorpamplona/amethyst.git
synced 2026-08-12 01:07:46 +00:00
Closes the liveness half of A2. Recovery's whole premise is that the
community keeps re-minting its bundle at the SAME addressable coordinate, so
the link a stranded member already holds starts pointing at the new epoch.
Nothing did: `ConcordInviteBundle.mintLink` generates a fresh KeyPair and
token per call, and no client persisted `linkSignerPrivKey`. Every mint was a
new coordinate, so `recover` could only ever return `already_current` — the
mechanism was dead code, and an owner evicted by a rogue admin had no way
back.
The kind-33301 bundle is addressable and authored by the link signer, so
re-signing at that coordinate with the same token replaces what is there and
every holder of that link keeps working. Exposes that as
`ConcordActions.remintBundleAt`, persists the link signer + token in amy's
store at mint time, and has `concord refound` refresh every link it minted
for the new epoch.
Re-minting every live link is safe precisely because the security half is
already in: `refound` bans the removed members on the way out, and `recover`
reads the banlist of the epoch being LEFT, so a removed member's own recovery
is refused even though their link now resolves. That gate stops being
belt-and-braces here and becomes load-bearing — which is what the audit
predicted for any client that re-mints (Armada does).
Verified end to end against a loopback geode, both directions:
bob joins by link, holds no role, never posts (unfindable by a rotation)
alice refound --remove <stranger> → recipients=1, invites_refreshed=1
bob rekey → no_blob_for_us (genuinely stranded)
bob recover → recovered, epoch 0 → 1 ← first time this has ever fired
bob reads the community at the new epoch
alice refound --remove bob → epoch 1 → 2, invites_refreshed=1
bob recover → refused, reason "banned", still at epoch 1
Still open for the shipping client: Amethyst persists no link signer, so
A2 liveness remains open on Android. Doing it there means deciding where the
secret lives in the kind-13302 list, which Armada also reads — a wire-schema
call, not a code one.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>