Causal Snapshot Sync Range
draft
Summary
This draft reserves a dedicated event kind range for causal snapshot sync events and defines the relay-visible sync metadata shared by that range.
This document does not define any application-specific inner payload format. It only defines:
- protocol identification by event kind
- sync metadata tags
- document identity rules
- relay validation and indexing expectations
Goals
- Let relays identify sync protocol events by kind alone
- Give causal snapshot sync a clean protocol namespace instead of overloading unrelated kinds
- Make document identity explicit
- Support local-first current-state sync, tombstones, bounded history, and causal conflict detection
- Keep causal sync metadata reusable across future causal snapshot sync kinds
Non-Goals
- Defining any application-specific inner payload schema
- Defining application-specific conflict-resolution policy
- Defining bootstrap, replay, or live tail transport
- Defining conflict winner semantics
- Reusing generic gift-wrap kinds as the protocol identifier
Why A Dedicated Range
Causal snapshot sync events should be recognizable as sync protocol events before inspecting arbitrary tag sets.
If sync reused a generic kind such as kind:1059, a relay would first need to parse and validate tags on every event of that kind to determine whether it was actually a causal snapshot sync event. That is a poor protocol boundary for a local-first sync extension.
A dedicated kind range gives causal snapshot sync events:
- kind-based protocol identity
- a clean home for sync-specific validation rules
- a clean home for sync-specific metadata tags
- room for future sync event families without changing sync metadata again
This draft uses a dedicated range above the currently standardized event-class ranges so sync kinds do not inherit unrelated replaceable, ephemeral, or addressable semantics.
Kind Range
This draft reserves:
40000 <= kind < 50000for causal snapshot sync events.
Rules:
- Any event in this range is a causal snapshot sync protocol event.
- Any event in this range must validate against the sync metadata defined below.
- Kinds in this range that are not explicitly defined remain reserved for future sync event families.
Event Model
The event author pubkey defines the top-level sync namespace.
This means:
- full document identity is
(pubkey, d)
This draft defines the causal metadata required for this snapshot sync family.
Events in this range determine supersedence and conflict using relay-visible vector clocks plus any additional decrypted profile state needed by clients during local apply.
The Nostr created_at field remains the event timestamp, but relay-visible vc metadata is the causal ordering metadata for this range.
Sync Metadata
Events in the causal snapshot sync range must include the following sync metadata tags.
Required Tags
["d", <document_coord>]["o", "put" | "del"]["vc", <device_id>, <counter>]vc is repeatable: one entry per vector-clock component.
Optional Tags
["c", <collection_name>]vc Normalization Rules
vc tags are the wire source of truth for vector-clock state in this range.
Each vc tag must have the exact shape:
["vc", <device_id>, <counter>]Normalization and validation rules:
device_idmust be a stable opaque identifier, not a human-readable device labeldevice_idshould be randomly generated by the clientdevice_idmatching is exact and case-sensitivecountermust be a base-10 positive integer stringcounter = 0is invalid because a missing vector-clock entry already implies0countermust be within the safe integer range1..9007199254740991- an event must contain at most
32vcentries - the same
device_idmust not appear more than once in one event - repeated
vctags must be emitted in ascending lexicographic order bydevice_id - relays and clients should reject malformed or non-canonical
vcsets rather than silently rewriting them
Important encoding rule:
- tag order is part of the signed Nostr event encoding
- clients must emit
vctags in canonical order before signing - relays must preserve the original tag order and must not rewrite
vctags in transit - vector-clock semantics are order-independent after successful parse because comparison operates on the normalized
(device_id -> counter)mapping
Vector-clock comparison rules:
- missing device entries are treated as
0 - a snapshot dominates another only if every component is greater than or equal and at least one component is greater
- incomparable
vcsets indicate concurrent snapshots
Tag Meanings
d: logical document coordinate tokeno: snapshot operationvc: causal vector-clock entry encoded as device id plus counterc: top-level collection classification such asnotes,notebooks, orfiles
Important identity rules:
dis not globally unique by itselfcis not part of document identity or snapshot identity
Validation Rules
A relay receiving an event in the causal snapshot sync range should validate at least the following:
dmust be present and non-emptyomust be present and equal toputordel- at least one
vctag must be present - each
vctag must satisfy the normalization rules above - a given
device_idmust appear at most once in thevcset
If a sync-range event is missing required tags or contains malformed values, the relay should reject it as invalid sync protocol data.
Snapshot Rules
Snapshot events
Each sync event in this range represents one immutable sync snapshot.
The relay-visible vc set is the causal metadata for determining whether one snapshot dominates, is dominated by, or is concurrent with another snapshot of the same (pubkey, d).
Tombstones
Logical deletion is represented as a normal sync event with:
["o", "del"]Profiles may define how deletion snapshots participate in supersedence and conflict resolution.
Conflict Semantics
This draft does not define a built-in winner among multiple snapshots for the same (pubkey, d).
That is intentional:
- sync metadata defines document scope and operation
- this range defines relay-visible causal ordering metadata
- application profiles define additional encrypted payload semantics
- conflict detection and resolution policy belong to the profile or application layer
Relay Expectations
To support snapshot sync, the relay should:
- classify sync events by kind range before inspecting application payloads
- retain fetchable sync events for the configured retention window
- maintain relay-local replay order
- allow filtering by the sync metadata tags
- use
vcmetadata when determining nondominated current snapshots for bootstrap and compaction
Recommended first-class query surface:
- author pubkey namespace
#d#o- optional
#c
This draft does not require the relay to decrypt payloads or derive content-level conflict winners.
Clients should treat:
das the document coordinate tokeno=delas a logical deletion markervcas the wire causal metadata for supersedence and conflict detection- decrypted payload data as the profile-defined note/application state
The client should not assume that one conflicting snapshot is automatically canonical.
Relationship To Local-First Applications
This model is designed to support local-first applications where:
- the canonical local object may remain a normal document record
- sync transmits encrypted snapshots of that record
- bounded recent history is acceptable
- full snapshot ancestry is not required forever