Follow-up to the event class renames: the names around those classes now
match too.
Quartz (published API, every old name kept as a @Deprecated alias/forwarder):
- nip51Lists packages moved: followList -> starterPack, hashtagList -> interestList,
peopleList -> followSet, labeledBookmarkList -> bookmarkSet. The old packages
keep a Deprecated.kt with typealiases and forwarding extension functions
(ReplaceWith points at the new package).
- LnZapPrivateEvent -> PrivateZapEvent, LnZapReceiptValidator -> ZapReceiptValidator,
ChannelListDiff -> PublicChatListDiff, HashtagListDiff -> InterestListDiff.
- Kind 30063 now indexes NIP-82 release notes for search (never NIP-51 content,
which can hold encrypted private items). searchable-events docs updated.
App code (amethyst, commons, desktopApp, cli; no aliases needed):
- model packages nip51Lists.{hashtagLists,peopleList,labeledBookmarkLists,relayFeeds}
-> {interestLists,followSets,bookmarkSets,favoriteRelays}.
- State/cache/UI names derived from the old event names: HashtagListState ->
InterestListState, PeopleListsState -> FollowSetsState, FollowListsState ->
StarterPacksState, LabeledBookmarkList -> BookmarkSet, RelayFeedListState ->
FavoriteRelayListState, ContactCardsState -> UserAssertionsState, NIP90* view
models/renderers -> Dvm*, LnZap* handlers -> Zap*, SealedRumor* -> Seal*, and
Account.peopleLists/followLists/hashtagList -> followSets/starterPacks/interestList.
- String literals were left untouched, so preference keys and @SerialName values
stored on disk are unchanged.
- The generic PeopleList UI model (shared by follow sets and starter packs) and the
EmojiPackSelection route (which shows a kind 30030 pack) keep their names.
Docs: plans, brainstorms, changelogs, skills and READMEs use the new names.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_015VvJ8XpeYqBe8bYT3bJ7UD
4.6 KiB
Concord event layer → per-kind Event classes (nip88Polls structure)
Why
The Concord quartz layer currently centralizes wire kinds in a single
concord/events/ConcordKinds.kt constant object and hand-rolls rumors with raw
string tags (see cord03Channels/ChannelChat.kt:
RumorAssembler.assembleRumor(kind = ConcordKinds.MESSAGE, tags = arrayOf(arrayOf("q", …)))).
Two problems:
- Duplicates standard Nostr kinds.
ConcordKinds.MESSAGE=9,REACTION=7,DELETE=5,COMMENT=1111,EDIT=3302shadowChatEvent.KIND,ReactionEvent.KIND,DeletionRequestEvent.KIND,CommentEvent.KIND. Concord chat rumors are those standard events (they already parse back asChatEventetc. on read) — the build side should reuse the classes, not re-derive by number. - No per-event structure. Every other protocol in quartz gives each event
kind a package:
XxxEvent.kt(theEventsubclass +build), plusTagArrayBuilderExt.kt/TagArrayExt.ktand atags/folder of typed tag classes (nip88Polls/poll/…is the reference). Concord instead has loose builders (ChannelChat,ControlEditionBuilder) and stringly-typed tags.
Target: match the nip88Polls shape. Reuse standard events where the protocol
uses standard kinds; give each genuinely-Concord kind its own package.
Reuse standard events (chat plane, CORD-03)
A Concord chat rumor is a standard event + a ["channel", id] + ["epoch", n]
binding. Introduce a binding-tag package and reuse the standard builders:
cord03Channels/tags/ChannelTag.kt,tags/EpochTag.kt— typed tags.cord03Channels/TagArrayBuilderExt.kt—channel(id),epoch(n)on the DSL.cord03Channels/TagArrayExt.kt—channelId(),epoch(),isBoundTo(...).
| rumor | reuse | binding |
|---|---|---|
| message (9) | ChatEvent.build |
channel + epoch |
| reply (9 + q) | ChatEvent.build + q/p |
channel + epoch |
| reaction (7) | ReactionEvent.build |
channel + epoch |
| delete (5) | DeletionRequestEvent.build |
channel + epoch |
ChannelChat keeps its public API (returns unsigned rumors via RumorAssembler)
but builds tags from the standard event's DSL + the binding ext. Delete
ConcordKinds.MESSAGE/REACTION/DELETE/COMMENT/EDIT.
Interop guard: the exact on-wire tags must stay byte-identical to today's
output (Armada compat). Keep ["q", parentId] + ["p", parentAuthor] for
replies and ["e"/"p"/"k"] for reactions — do not switch to QEventTag's
3-element form. Verify with ConcordPlaneRegistryTest + an amy↔Armada round-trip.
New per-kind Event classes (genuinely Concord)
Each gets concord/<cordXX>/<name>/XxxEvent.kt + TagArrayBuilderExt +
TagArrayExt + tags/:
| kind | event | CORD |
|---|---|---|
| 3308 | ControlEditionEvent (from ControlEdition/ControlEditionBuilder) |
02/04/06 |
| 3303 | RekeyEvent |
06 |
| 3306 / 3309 / 3312 | GuestbookJoinLeaveEvent / KickEvent / SnapshotEvent |
02 |
| 3313 | DirectInviteEvent |
05 |
| 23311 / 23313 | TypingEvent / VoicePresenceEvent |
03/07 |
| 3310 | WebxdcEvent |
03 |
| 33301 | InviteBundleEvent (from ConcordInviteBundle) |
05 |
| 13303 | InviteListEvent |
05 |
| 20013 / 20014 / 1059 / 21059 | envelope seals + inverted wrap | 01 |
ConcordCommunityListEvent (13302) is already an Event class (now a
BaseReplaceableEvent) — keep, just move under a per-kind package if desired.
After the move, ConcordKinds retains only the truly-Concord kinds (envelope,
control, rekey, guestbook, invites, voice), not the standard-Nostr aliases.
Sequencing (incremental, compile + interop-test each)
- ✅ Chat plane reuse —
ChatEvent/ReactionEvent+cord03Channels/tags+ ext; droppedMESSAGE/REACTION/DELETE/COMMENTaliases. (commitc2cbd602) - ✅ Control plane 3308 →
cord04Roles/control/ControlEditionEventpackage +tags/(vsk/eid/ev/ep/vac) + ext;EventFactoryregisters 3308. (commitdc2abc0e) - Invites: ✅ 33301 bundle →
cord05Invites/bundle/ConcordInviteBundleEvent(addressable, reusesDTag+VskTag; registered inEventFactory). Remaining: 3313 direct-invite →ConcordDirectInviteEvent(the rumor has empty tags; thep/kindex lives on the giftwrap). 13303 invite-list has no implementation yet (a bareConcordKindsconstant) — build it when the private-invite feature lands. - Guestbook (3306/3309/3312) + voice (23313/23311) + rekey (3303). ← next
- Envelope seals (20013/20014) / wrap (1059/21059).
- Shrink
ConcordKindsto only kinds without their own event class; auditEventFactorycoverage.