Repository navigation
previous-Zeitreferenzen in Revisionen schreiben #26
Copy link
Copy link
Open
Description
Activity
**** commented:
Technical refinement
Status: ready. A small, self-contained change to the publish helpers plus one derived list in the store. The reading side is best-effort, because
groups_relaydoes not verify the tag.What exists today
TAGS.PREVIOUS = 'previous'is defined (src/nostr/kinds.ts:100), docs/02 describes the tag and NOSTR.md lists it as not written. No code reads or writes it.- Publish helpers build their tags themselves:
publishRevision(src/nostr/publish-page.ts),publishPlacement(src/nostr/publish-placement.ts),publish-comment.ts, andpublishModerationinsrc/nostr/moderation.ts. Each starts from['h', groupId]. SpaceStore(src/nostr/space-store.ts) sees every event of the group through its four subscriptions (group state by#d, revisions/comments/placements by#h) but keeps no 'recently seen ids' list;apply*only store the parsed objects.- docs/08 records that
groups_relaydoes not implement or verify timeline references, so writing them changes nothing on this relay — the value is portability and future gap detection, not enforcement.
Approach
- Track the recent group events. In
SpaceStore, maintain a bounded list of the ids of every group event seen (all four subscriptions), newest first bycreated_at, ties by id, capped (50 is the usual NIP-29 order of magnitude). Expose it as a method (recentEventIds()), not as part ofSpaceSnapshot, so publishing can read it without a React prop drilling exercise.- Include revisions, placements and comments. Group state (
39000-39002) is relay-generated and changes on its own; include it only if it proves useful — recommend leaving it out in the first iteration so the list is stable and about author-visible content. - Update on every incoming event, including duplicates (dedupe by id); do not clear it on
dropCollected()within the same identity if a publish may happen right after a resubscribe — decide explicitly and test it.
- Include revisions, placements and comments. Group state (
- A shared tag builder. Add one helper (e.g.
timelineTags(recentIds: string[]): string[][]) in a small module, so all publishers produce the same shape: one['previous', ...ids]tag, or one tag per id if that proves better against the relay — measure. Wire it intopublishRevision,publishPlacement,publishCommentandpublishModeration. The publish functions take the ids as an input field (previous?: string[]), so they stay network-free and testable; callers read the store. - Callers.
PageEditor/NewPageView/HistoryView.restore/useMovePage/Comments/MemberAdmineach call a publish helper; each can obtaingetSpaceStore(relayUrl, groupId).recentEventIds()at publish time. Prefer a tinywithTimeline(relayUrl, groupId)wrapper over touching every call site's signature. - Reading side (best effort). Parse
previousinparseRevisionand keep it on the revision (and on comments/placements if cheap). Then a light diagnostic: if apreviousid is not among the events the client has seen, the relay may have withheld something. Surface it only as a subtle 'history may be incomplete' hint, never as a hard error — false positives are expected, because the union of 'recently seen' differs per client and per session. - Measure against the relay first. Confirm that
groups_relayaccepts a1818carryingprevious(it should, since it does not verify it) and that the event is stored and served back intact. If the relay strips it, the write side is still worth doing for foreign relays; the reading side then simply never sees it locally.
Subtasks
-
SpaceStore.recentEventIds()with cap, ordering and lifecycle rules -
timelineTagshelper +previousinput onpublishRevision,publishPlacement,publishComment,publishModeration - Callers read the store at publish time (thin wrapper preferred)
- Parse and retain
previous; optional gap hint - Relay measurement (accepted, stored, served back intact)
- Tests: list ordering/cap/dedupe, every publisher emits the tag, parse round-trip
- Docs: docs/02 ('not implemented yet' -> written), docs/09 completeness note, NOSTR.md tag table, docs/10 doc-gap row
Acceptance criteria
- Every
1818,31818,1111and moderation event the app publishes carries aprevioustag listing the most recent group events the client had seen. - The list is bounded and deterministic; it never grows without limit and never contains duplicates.
- The app still publishes (with an empty or absent tag) when the store has seen nothing yet — a publish must not be blocked by this feature.
- Incoming
previousvalues are parsed and do not break anything when absent or malformed.
Risks / open decisions
groups_relayignores the tag, so this is groundwork, not a security fix. Do not present it as making withholding detectable on the current relay.- Gap detection is heuristic (docs/09 already says so): different clients have different 'recently seen' sets, so a missing id is not proof of censorship. Keep it a hint.
- Event size: 50 ids per event is a few KB; consider a smaller cap if it shows up in relay limits or storage.
- Ordering by
created_atis manipulable (docs/09); the tag is informational, andparent-revremains the real order. - A stale list after a reconnect is acceptable for a reference tag, but must not be presented as exhaustive.
Depends on / relates to
CON-8 (cache may make the seen-set larger and more useful), CON-10/11 (deletion/tombstone events also belong in the timeline), docs/09 (completeness), docs/08 (relay ignores the tag).
Das Datenmodell sieht
previous-Tags vor (NIP-29-Zeitreferenzen auf kürzlich gesehene Events der Gruppe, als Schutz gegen ein Relay, das Ereignisse unterschlägt oder umschreibt). Beim Veröffentlichen einer Revision werden sie nicht gesetzt.Aufgabe: Beim Signieren die letzten bekannten Event-IDs der Gruppe als
previousmitgeben (src/nostr/publish-page.ts), Quelle ist der Space-Store. Beim Lesen zumindest auswerten können.Quelle: docs/02-data-model-events.md, docs/10-roadmap.md (Doc-Lücken)
Task: uhoz07pa3889p3ndh8fnj5py