Skip to content

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 < 50000

for 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_id must be a stable opaque identifier, not a human-readable device label
  • device_id should be randomly generated by the client
  • device_id matching is exact and case-sensitive
  • counter must be a base-10 positive integer string
  • counter = 0 is invalid because a missing vector-clock entry already implies 0
  • counter must be within the safe integer range 1..9007199254740991
  • an event must contain at most 32 vc entries
  • the same device_id must not appear more than once in one event
  • repeated vc tags must be emitted in ascending lexicographic order by device_id
  • relays and clients should reject malformed or non-canonical vc sets rather than silently rewriting them

Important encoding rule:

  • tag order is part of the signed Nostr event encoding
  • clients must emit vc tags in canonical order before signing
  • relays must preserve the original tag order and must not rewrite vc tags 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 vc sets indicate concurrent snapshots

Tag Meanings

  • d: logical document coordinate token
  • o: snapshot operation
  • vc: causal vector-clock entry encoded as device id plus counter
  • c: top-level collection classification such as notes, notebooks, or files

Important identity rules:

  • d is not globally unique by itself
  • c is 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:

  • d must be present and non-empty
  • o must be present and equal to put or del
  • at least one vc tag must be present
  • each vc tag must satisfy the normalization rules above
  • a given device_id must appear at most once in the vc set

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 vc metadata 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:

  • d as the document coordinate token
  • o=del as a logical deletion marker
  • vc as 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