Skip to content

fix: keep reserved sentinels virtual#197

Open
marcus-pousette wants to merge 1 commit into
fix/order-key-hardeningfrom
fix/reserved-sentinel-targets
Open

fix: keep reserved sentinels virtual#197
marcus-pousette wants to merge 1 commit into
fix/order-key-hardeningfrom
fix/reserved-sentinel-targets

Conversation

@marcus-pousette

@marcus-pousette marcus-pousette commented Jul 12, 2026

Copy link
Copy Markdown
Collaborator

Problem

ROOT and TRASH are protocol sentinels, but materialization could treat them like application nodes before rejecting an operation. That could create physical sentinel rows, lose former-parent metadata, suppress the first move-to-Trash event, or emit false replay moves.

Fix

  • Canonical operations targeting TRASH are deterministic no-ops.
  • Canonical structural inserts, moves, deletes, and tombstones targeting ROOT are deterministic no-ops.
  • Payload(ROOT, ...) remains the supported document-level payload.
  • Normal nodes may attach to virtual TRASH without creating a TRASH row.
  • First/repeated moves and former-parent opRefs remain correct through canonical replay.
  • Invariant validation rejects a physical TRASH row or parented ROOT.
  • Empty SQLite order-key BLOBs round-trip as empty bytes.

Strict input contract

Reserved targets do not bypass #218's structural-key validation. Malformed ROOT/TRASH operations are rejected before no-op handling; only canonical operations reach the sentinel fast path.

There is no old-log exception, schema version, migration marker, row scan, backfill, or upgrade replay. Development databases containing the earlier shape must be recreated.

Fast paths

  • Schema initialization performs no sentinel scan or replay scheduling.
  • Ordinary application-node operations add only reserved-ID comparisons.
  • Canonical reserved-target operations return before snapshotting or touching node/payload stores.
  • A node attached to virtual TRASH stores no sibling order key and creates no sentinel parent row.

Size

11 files, +234/-31 relative to #186. Removing the prior compatibility/migration design cut the PR by more than 400 lines.

Verification

  • cargo test --workspace
  • strict workspace Clippy
  • Rust and TypeScript formatting
  • interface and engine-conformance TypeScript builds
  • malformed ROOT/TRASH rejection and canonical no-op coverage
  • git diff --check

Stack

Stacked on #186.

@marcus-pousette marcus-pousette added bug Something isn't working area:core CRDT semantics, canonical log, ordering, operation identity, and core Rust area:materialization Derived tree state, replay, outcomes, events, and materialization cursors labels Jul 12, 2026
@marcus-pousette
marcus-pousette force-pushed the fix/order-key-hardening branch from b7024f8 to 1485ca1 Compare July 12, 2026 11:11
@marcus-pousette
marcus-pousette force-pushed the fix/reserved-sentinel-targets branch from ae24474 to 9f0225b Compare July 12, 2026 11:11
@marcus-pousette
marcus-pousette force-pushed the fix/order-key-hardening branch from 1485ca1 to 0c7480f Compare July 13, 2026 13:21
@marcus-pousette
marcus-pousette force-pushed the fix/reserved-sentinel-targets branch from 9f0225b to 87389a6 Compare July 13, 2026 13:21
@marcus-pousette
marcus-pousette force-pushed the fix/order-key-hardening branch from 0c7480f to 7e2c90f Compare July 13, 2026 15:04
@marcus-pousette
marcus-pousette force-pushed the fix/reserved-sentinel-targets branch from 87389a6 to 4ab15c1 Compare July 13, 2026 15:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area:core CRDT semantics, canonical log, ordering, operation identity, and core Rust area:materialization Derived tree state, replay, outcomes, events, and materialization cursors bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant