Key the events store by addressable coordinate (kind:pubkey:dtag), not bare d-tag #121

Closed
opened 2026-06-18 11:20:49 +00:00 by padreug · 0 comments
Owner

From the nostr-patterns review against NDK + welshman.

Problem

src/modules/events/stores/events.ts keys events by event.id = the bare d-tag, and upsertEvent replaces on createdAt >= existing.createdAt ignoring pubkey. NIP-52 calendar events (31922/31923) are addressable (parameterized-replaceable) and their d-tags are author-scoped. So a different author publishing the same d-tag with a newer created_at would overwrite the legit event in the store (cross-author hijack). Both NDK (events/index.ts coordinate()) and welshman (eventsByAddress) key addressable events by kind:pubkey:dtag.

Proposed fix (client-side only — no DB/relay change)

  • Key the store Map by the full coordinate ${kind}:${pubkey}:${dtag}; replace only within the same coordinate (and newer created_at). Different authors → stored separately, no hijack.
  • Keep the d-tag as the route identifier: getEventById(dtag) resolves by scanning/secondary-index (unambiguous for our single-publisher calendar events). Add getByCoordinate(coord) for precise lookups.

No demo-DB surgery: the store is rebuilt from the relay each session.

Testing

Unit tests (vitest): same-coordinate-newer-wins, same-coordinate-older-ignored, same-d-tag-different-pubkey → both kept (no overwrite), getEventById resolves by d-tag.

To be done as a PR (gap #1 of the review).

From the nostr-patterns review against NDK + welshman. ## Problem `src/modules/events/stores/events.ts` keys events by `event.id` = the **bare d-tag**, and `upsertEvent` replaces on `createdAt >= existing.createdAt` **ignoring pubkey**. NIP-52 calendar events (31922/31923) are *addressable* (parameterized-replaceable) and their d-tags are **author-scoped**. So a different author publishing the same d-tag with a newer `created_at` would **overwrite** the legit event in the store (cross-author hijack). Both NDK (`events/index.ts coordinate()`) and welshman (`eventsByAddress`) key addressable events by `kind:pubkey:dtag`. ## Proposed fix (client-side only — no DB/relay change) - Key the store Map by the full coordinate `${kind}:${pubkey}:${dtag}`; replace only within the same coordinate (and newer `created_at`). Different authors → stored separately, no hijack. - Keep the d-tag as the route identifier: `getEventById(dtag)` resolves by scanning/secondary-index (unambiguous for our single-publisher calendar events). Add `getByCoordinate(coord)` for precise lookups. No demo-DB surgery: the store is rebuilt from the relay each session. ## Testing Unit tests (vitest): same-coordinate-newer-wins, same-coordinate-older-ignored, **same-d-tag-different-pubkey → both kept (no overwrite)**, `getEventById` resolves by d-tag. _To be done as a PR (gap #1 of the review)._
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
aiolabs/webapp#121
No description provided.