fix(events): key the events store by addressable coordinate (#121) #125
No reviewers
Labels
No labels
app:activities
app:chat
app:events
app:forum
app:libra
app:market
app:restaurant
app:tasks
app:wallet
app:webapp
bug
enhancement
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
aiolabs/webapp!125
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "fix/events-store-coordinate-key"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes the gap from the nostr-patterns review against NDK + welshman. Fixes #121.
Problem
NIP-52 calendar events (kinds 31922/31923) are addressable — their d-tag is author-scoped. The store keyed
eventsMapbyevent.id(bare d-tag) and replaced on newercreated_atignoring pubkey, so a different author republishing the same d-tag with a newer timestamp could overwrite a legit event in the store (cross-author hijack). NDK (event.coordinate()) and welshman (eventsByAddress) both key addressable events by the fullkind:pubkey:d-tagcoordinate.Fix (client-side only)
eventsMapbyeventCoordinate()=${kind}:${pubkey}:${dtag}; same-coordinate-newer-wins, different authors stored independently.getEventById(dtag)scans and returns the newest match (single-publisher in practice), so existing URLs/links are unchanged. AddgetByCoordinate()for precise, author-known lookups.removeEvent(dtag)deletes every coordinate sharing that d-tag.No demo-DB surgery — the store is rebuilt from relays each session.
Tests
src/modules/events/stores/events.spec.ts: same-coordinate newer-wins / older-ignored, same-d-tag different-pubkey → both kept (no overwrite),getEventByIdresolves by d-tag (and newest-wins across authors),removeEventby d-tag, coordinate/kind formatting. Run withpnpm test.Merge order
Branches off
chore/vitest-setup(the vitest PR) — merge that first; this PR's diff drops the vitest files once it lands.🤖 Generated with Claude Code
NIP-52 calendar events (kinds 31922/31923) are addressable: their d-tag is author-scoped, so the replacement key is kind:pubkey:d-tag, not the bare d-tag. The store keyed `eventsMap` by `event.id` (d-tag) and replaced on newer `created_at` ignoring pubkey, so a different author republishing the same d-tag could overwrite a legit event in the store (cross-author hijack). NDK (`event.coordinate()`) and welshman (`eventsByAddress`) both key addressable events by the full coordinate. - Key `eventsMap` by `eventCoordinate()` = `${kind}:${pubkey}:${dtag}`; same-coordinate-newer-wins replacement, different authors stored apart. - Keep the d-tag as the route identifier: `getEventById(dtag)` scans and returns the newest match (single-publisher in practice). Add `getByCoordinate()` for precise, author-known lookups. - `removeEvent(dtag)` deletes every coordinate sharing that d-tag. Client-side only — the store is rebuilt from relays each session, so no demo-DB surgery. Covered by vitest unit tests including the cross-author no-overwrite case. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>