feat(cli): drop relays.json — kind:10002/10050/10051 in the store ARE the config

The local relay configuration was redundant once the event store
became the source of truth: every account already publishes signed
kind:10002 (NIP-65), kind:10050 (DM inbox), and kind:10051
(KeyPackage relays) events, and Context now reads each set straight
out of the local store.

Removed:
  - data class RelayConfig (nip65/inbox/keyPackage buckets)
  - DataDir.relaysFile / loadRelays() / saveRelays()
  - Context.relays parameter — Context.open() no longer reads JSON
  - CreateCommand.defaultRelayConfig() helper
  - CreateCommand's saveRelays() call (redundant: ctx.publish persists
    the bootstrap events into the store anyway)

Context now serves the four relay accessors from the store with sane
fallbacks:
  outboxRelays()      = relaysOf(self)?.writeRelaysNorm() ?: DefaultNIP65RelaySet
  inboxRelays()       = dmInboxOf(self)?.relays() ?: DefaultDMRelayList.toSet()
  keyPackageRelays()  = keyPackageRelaysOf(self)?.relays() ?: outboxRelays()
  anyRelays()         = union of the three
  bootstrapRelays()   = anyRelays() ∪ DefaultNIP65RelaySet ∪ DefaultDMRelayList

RelayCommands rewritten:
  - `relay add URL --type T` — read existing relay-list event from the
    store, append URL, build + sign + ingest a new event of the
    matching kind. The replaceable slot mechanism replaces the old
    winner atomically.
  - `relay list` — dump URLs from the latest event in each bucket.
  - `relay publish-lists` — broadcast whichever events are present in
    the store; errors out cleanly when none exist (suggests `relay add`
    or `create`).

No migration: existing data dirs that still have `relays.json` will
ignore it. Run `amy relay add` or `amy create` to repopulate. Per
discussion this is a clean break, not a backwards-compat shim.

README + DEVELOPMENT updated to reflect the new on-disk layout (no
more `relays.json`; events-store/ is the relay configuration).
This commit is contained in:
Claude
2026-04-25 03:45:12 +00:00
parent b2bf874c15
commit 37a4f89178
6 changed files with 177 additions and 134 deletions
+18 -5
View File
@@ -260,8 +260,13 @@ events.
```
<data-dir>/
├── identity.json # nsec/npub/hex — the account
├── relays.json # nip65 / inbox / key_package buckets
├── state.json # sync cursors (giftWrapSince, groupSince)
├── events-store/ # FsEventStore — every observed Nostr event
│ ├── events/<aa>/<bb>/… # canonical kind:0 / 3 / 10002 / 10050 / 10051 / 1 / 5 / 1059 / …
│ ├── replaceable/<k>/… # one slot per (kind, pubkey) for kind:0/3/10000-19999
│ ├── addressable/… # one slot per (kind, pubkey, d-tag) for kind:30000-39999
│ ├── idx/ # hardlink indexes (kind / author / owner / tag / fts / expires_at)
│ └── tombstones/ # NIP-09 / NIP-62 enforcement
└── marmot/
├── keypackages.bundle # MLS KeyPackage bundles (NostrSignerInternal)
└── groups/
@@ -272,6 +277,13 @@ events.
All files are plain JSON or framed binary — human-inspectable, easy to
diff across two data-dirs in a test run.
The local relay configuration (kind:10002 / 10050 / 10051) is **not** a
separate file — it lives in `events-store/` as signed events.
`amy relay add` builds + signs + ingests a new relay-list event;
`amy relay list` reads URLs straight out of the latest event for each
kind; `amy relay publish-lists` broadcasts those events to upstream
relays. There is no `relays.json`.
---
## Troubleshooting
@@ -281,9 +293,10 @@ diff across two data-dirs in a test run.
- **`not_member`** — the group GID is unknown to this data-dir. Run
`marmot group list` to confirm, or `marmot await group --name …` to
wait for an invite to arrive.
- **Hang on a network verb** — Amy connects to the relays in
`relays.json`; verify with `amy relay list`. Every network-bound
operation has a timeout — use `--timeout` for `await`, or wrap the
whole command in `timeout(1)` if you're scripting.
- **Hang on a network verb** — Amy connects to the relays advertised
in your local kind:10002 / 10050 / 10051 events; inspect with
`amy relay list`. Every network-bound operation has a timeout — use
`--timeout` for `await`, or wrap the whole command in `timeout(1)`
if you're scripting.
- **Nothing seems to publish** — inspect stderr; each publish prints
per-relay `OK` / `REJECT` via the `[cli] …` traces.