JOLT REQUEST FOR COMMENTS · 0008

Device Writer Tombstones, Causal Heads, and Delta Sync

Jolt Project                                                JOLT-RFC-0008
Request for Comments: 0008                                  August 2026
Category: Experimental
Status: Experimental Draft
Updates: JOLT-RFC-0003
Obsoletes: none

Status of This Memo

This document specifies implemented extensions to Jolt's experimental multi-writer protocol. It is not an IETF publication. Distribution of this memo is unlimited.

The Tombstone operation, causal-head encoding, operation-level negotiation, and bounded delta synchronization described here are implemented. The memo remains a draft with JOLT-RFC-0003 because the wider device-writer protocol is still experimental.

Abstract

This document extends JOLT-RFC-0003 with three generic protocol behaviors: signed logical deletion through Tombstones, causal supersession of observed singleton heads, and bounded cursor-based synchronization of device-writer histories.

The extensions are negotiated independently. Operation level 2 introduces Tombstones, operation level 3 introduces signed observed heads, and sync level 2 introduces delta pages. A provider never removes newer operations to make a history appear compatible with an older requester.

1. Introduction

JOLT-RFC-0003 defines independent device hash chains containing SetPath operations. That v1 model can publish and deterministically select values, but it cannot represent deletion, distinguish a causal successor from a concurrent branch, or refresh a large retained history without repeatedly transferring the complete logs.

This memo adds those behaviors without teaching the protocol about documents, posts, feeds, or application schemas. The protocol still handles only signed identity paths, content identifiers, operation state, and device-log history.

2. Conventions and Requirements Language

The key words MUST, MUST NOT, REQUIRED, SHOULD, SHOULD NOT, and MAY are interpreted as BCP 14 [RFC2119] [RFC8174]. Primitive encodings, entry hashes, authority validation, and device-log validation use JOLT-RFC-0002 and JOLT-RFC-0003.

3. Scope

This memo defines:

This memo does not define:

4. Terminology

Operation level
The highest device-writer entry behavior a peer can interpret. It is independent of the sync level and transport protocol name.
Sync level
The highest device-writer history exchange behavior a peer can interpret.
Tombstone
A signed generic operation making a singleton path's current protocol state Deleted without carrying application content.
Observed head
The entry hash of a singleton branch that the writer had incorporated when producing a successor.
Cursor
A device identifier, device sequence, and exact entry hash naming a verified point in one device log.

5. Compatibility Levels

Device-writer operation levels are cumulative:

Level Contract
1 JOLT-RFC-0003 SetPath entries without observed heads.
2 Level 1 plus TombstonePath.
3 Level 2 plus non-empty signed observed_heads.

Device-writer sync levels are cumulative:

Level Contract
1 Complete authority and device-log response.
2 Level 1 plus validated cursors, bounded delta pages, heads, and continuation.

The required operation level of a history is the greatest level required by any entry in the complete history. Once a history contains a Tombstone or non-empty observed-head set, later SetPath entries do not lower that requirement.

6. Tombstone Operation

TombstonePath has this logical shape:

TombstonePath {
  path: string
}

Its operation discriminator is 0x01, followed by the canonical string(path) encoding. The existing SetPath discriminator remains 0x00.

The enclosing entry retains JOLT-RFC-0003's record type, record version 1, signature domain, device sequence, previous-entry hash, and signature rules. The canonical path MUST pass the same identity/path validation as SetPath. Changing the path after signing MUST invalidate the signature.

A valid Tombstone participates as a singleton candidate whose state is Tombstone rather than Present. It contains no content identifier and does not erase immutable content bytes or append records.

7. Causal Observed Heads

The device-writer entry body gains one additive field:

observed_heads: [DeviceWriterLogEntryHash]

The list MUST be sorted in ascending raw-byte order and MUST contain no duplicates. A receiver MUST reject a non-canonical list. Each hash is exactly 32 bytes.

When the list is empty, it is omitted from serialized representations and the canonical signed bytes remain exactly those of JOLT-RFC-0003 v1. When it is non-empty, the canonical bytes append the following after created_at:

0x00 || "jolt:observed-singleton-heads:v1" || 0x00
uint64be(number_of_heads)
head_0[32] || ... || head_n[32]

The complete extension is signature-covered and therefore also contributes to the entry hash. Changing, reordering, adding, or removing an observed head MUST invalidate the signature.

Observed heads apply to singleton merge only. Append records continue to coexist and do not become superseded through this field.

8. Singleton Merge

After the authority and per-device checks from JOLT-RFC-0003, a resolver groups singleton SetPath and TombstonePath entries by path.

For each path, the resolver marks as superseded:

  1. the previous singleton entry for that path in the same verified device log; and
  2. every entry hash named by a candidate's observed_heads.

Candidates not marked as superseded are active heads. More than one active head means the writes are concurrent. The resolver retains the losing active heads as conflict history and selects a deterministic current head using the greatest tuple:

(device_sequence, device_id, entry_hash)

device_id is compared by UTF-8 byte order and entry_hash as 32 raw bytes. Device wall-clock created_at MUST NOT choose a singleton winner. It remains presentation metadata for append-record ordering.

9. Resolution and Restoration

Resolving a path whose current head is Present returns its content identifier. Resolving a path whose current head is a Tombstone returns the distinct path_tombstoned outcome. A Tombstoned path MUST NOT fall back to a stale legacy path binding or fetch the formerly referenced content as its current value.

Restoration is not a special protocol operation. An authorized writer restores a path by appending a singleton SetPath entry that observes the current Tombstone head. The logical path remains stable and the new immutable content identifier becomes Present. The Tombstone remains in signed history.

10. Sync Negotiation

The device-writer request adds fields that default to the legacy level when absent:

DeviceWriterSyncRequest {
  identity: IdentityId,
  max_operation_version: uint16 = 1,
  max_sync_version: uint16 = 1,
  cursors: [DeviceWriterCursor] = [],
  authority_records: [DeviceAuthorizationRecord] = [],
  device_logs: [[DeviceWriterLogEntry]] = []
}

The response adds:

DeviceWriterSyncResponse {
  required_operation_version: uint16 = 1,
  sync_version: uint16 = 1,
  heads: [DeviceWriterCursor] = [],
  continuation: optional DeviceWriterSyncContinuation,
  authority_records: [DeviceAuthorizationRecord],
  device_logs: [[DeviceWriterLogEntry]]
}

If the complete history requires an operation level greater than the requester's maximum, the provider MUST return the required level and MUST return no authority records or device logs. It MUST NOT strip Tombstones, observed heads, or their entries to fabricate a compatible history.

Current transports advertise /jolt/device-writer/4.0.0, 3.0.0, 2.0.0, and 1.0.0 in newest-first order. The explicit operation and sync fields are the semantic negotiation boundary; the older stream names remain available for peer compatibility.

11. Delta Synchronization

A sync-level-2 cursor has this shape:

DeviceWriterCursor {
  device_id: string,
  device_sequence: uint64,
  entry_hash: bytes[32]
}

For every supplied cursor, the responder MUST find the named device log and MUST verify that the entry at that sequence has the exact supplied hash. Duplicate device cursors, an unknown device, an unavailable sequence, or a hash mismatch invalidates the delta assumption and causes a complete sync-level-1 response.

For valid cursors, the responder returns entries after each cursor and complete logs for devices without a cursor. Device logs and cursor sets use stable device-ID ordering. heads names the responder's complete current head for each non-empty device log, independently of page truncation.

A response page is bounded by both entry count and encoded response bytes. The implemented default limits are 256 entries and 1 MiB. If more entries remain, continuation contains the last transferred cursor for each progressed device and preserves the request cursor for the others. The requester submits those cursors for the next page. If even the first entry cannot fit, the responder falls back to a complete response so the exchange does not report false progress.

Every received authority record and device-log entry remains untrusted. The requester MUST perform the normal authority, chain, signature, operation, and merge verification before retaining or applying it.

12. Error Conditions

Implementations SHOULD distinguish:

An incompatible operation level is not permission to apply a partial history. A divergent cursor is a synchronization fallback condition, not proof that the remote history is invalid.

13. Compatibility and Versioning

New readers consume level-1 histories unchanged. Empty observed_heads retain the exact legacy canonical bytes and hashes. Missing request and response negotiation fields decode to level 1.

Old readers cannot correctly materialize a history after it adopts a higher operation level. Supporting providers therefore fail closed with an empty history payload rather than presenting false Missing or resurrecting a deleted value.

Operation levels describe entry semantics. Sync levels describe transfer semantics. A future extension MUST increase the relevant level and preserve the same no-downgrade rule when removing the extension would change materialized state.

14. Security Considerations

Tombstones and observed heads have authority only as signed entries from a currently eligible device sequence. A provider cannot create, alter, reorder, or remove their signed fields without detection, although it can still withhold an entire valid history.

An authorized writer that observes a head is allowed to supersede it. This is the same identity-write authority that allows it to publish a replacement or Tombstone; causal metadata does not grant authority over another identity.

Cursor hashes prevent a sequence number alone from accepting a different same-device fork. Delta responses remain subject to complete local re-verification and MUST NOT be spliced into trusted state solely because a cursor matched.

15. Privacy Considerations

Tombstones reveal that a path was deleted and retain its timing, writer, and history metadata. Observed heads reveal which branch hashes a writer had seen. Delta cursors reveal the device logs and sequences already held by a requester. This memo does not hide those protocol metadata.

Logical deletion does not claw back content already cached, decrypted, or copied by another party.

16. IANA Considerations

This document requests no IANA actions. Record strings, separators, operation levels, sync levels, and stream protocol names are project-local experimental identifiers.

17. Implementation Status

Operation levels 2 and 3 and sync level 2 are implemented across jolt-core, jolt-network, jolt-store, and jolt-server. Verification covers signed Tombstones, tampering, persistence and restart, stale legacy resolution, restore, canonical observed heads, concurrent branches, deterministic convergence, operation-level refusal, cursor divergence, bounded pages, and complete-history fallback.

Application schemas and conflict policies remain above this protocol boundary in the Data SDK. Delivery and verification are recorded in cards 129, 130, 111, and 112.

18. References

18.1 Normative References

18.2 Informative References

Appendix A. Delete and Restore Example

An authorized device first publishes singleton SetPath("/notes/1", CID_A). Deleting the logical record appends TombstonePath("/notes/1") while observing the Present head. Resolution now returns path_tombstoned; CID_A remains an immutable historical object.

A later restore publishes SetPath("/notes/1", CID_B, singleton) while observing the Tombstone head. Resolution returns CID_B. A peer must support operation level 2 to receive the complete history, even though its current head is again a SetPath entry.