Files
amethyst/commons
Vitor PamplonaandClaude Opus 5 fc3f181184 feat(cli): add amy concord revoke — retire an invite link (CORD-05)
The reading half of revocation already existed: `classify` has always
resolved a `vsk=9` tombstone to `Revoked`, and Amethyst's join honours it.
Nothing anywhere could *produce* one, so a leaked link could only be
outrun by a Refounding — rotating the whole community to retire one URL.

`ConcordInviteBundle.buildRevocation` emits the grave the spec describes
and Armada's `buildRevocationEvent` already publishes: kind 33301 at the
link's own `["d",""]` coordinate, empty content, `["vsk","9"]`, signed by
the `link_signer` secret. Empty content is the interop contract, not an
omission — there is nothing to encrypt when the point is that no bundle
key opens anything.

`amy concord revoke COMMUNITY TOKEN|URL` takes either the shareable URL a
creator actually has to hand or the bare token. It publishes the wire
tombstone FIRST and records the kind-13303 tombstone second, which is the
inverse of minting and deliberate: the list entry holds the only copy of
the `signer_sk` the publish needs, and a merge drops a tombstoned token's
entry terminally. Recording first and then failing to publish would leave
the link live with its signer gone and no way left to retire it. A failed
list write is recoverable by comparison and is reported rather than
swallowed.

Also fixes a revocation bypass in amy's own `join`, found while testing
this: it opened the first wrap that decrypted instead of classifying the
coordinate, so a relay still serving a stale copy alongside the grave
would have handed out a revoked link. It now resolves per CORD-05 §2 like
Amethyst does, and can say which of revoked/expired/unreadable/absent it
hit instead of reporting everything as `not_found`.

Verified end to end against a local relay: revoking flips the coordinate
to vsk=9 with empty content, the link is refused from that moment on, a
second revoke reports `already_revoked`, and a Refounding afterwards moves
the surviving link while leaving the grave alone — the first real proof of
the tombstone-skip in the refresh path, which until now had only unit
coverage.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 00:30:09 -04:00
..