At reviewed SHA 811d6a267b34f1eba2ed0969dd24ccdda565371b, malformed Lamport counters are accepted and make same-op-set projection depend on arrival order.
stamp[0] is coerced with Number(...), so a string such as "not-a-number" becomes NaN.
- the comparator then reports both
compare(NaN, 2) and compare(2, NaN) as newer (1), breaking antisymmetry.
- an independent two-order reproduction ended with different widget values while every op reported
applied.
Evidence and reproduction
Reviewed SHA: 811d6a267b34f1eba2ed0969dd24ccdda565371b.
Exact source locations:
Independent verification seeded two documents from one Yjs snapshot and applied the same malformed and valid set_widget ops in opposite orders:
- malformed then valid: final value
V, stored stamp counter 2
- valid then malformed: final value
M, stored malformed counter serialized as null
Both operations returned applied in both replicas. This violates deterministic convergence and the total-order premise of the LWW gate. Open issue #15 concerns stamp authority but does not cover malformed numeric coercion, NaN, comparator antisymmetry, or this arrival-order divergence.
Suggested root fix: validate the stamp tuple at the wire envelope before digesting or entering a transaction. Require a finite valid Lamport counter plus the contractually valid actor and reject malformed input without mutation. Add a two-arrival-order regression that asserts identical projection and rejection.
Draft-head check: open drafts #123 (38e6ec6fb02a68d676855dd64d271bea96edc3cd) and #138 (ca2a3ec25bcc0d6243a8346d1f8ed53f606cd243) do not address this path.
At reviewed SHA
811d6a267b34f1eba2ed0969dd24ccdda565371b, malformed Lamport counters are accepted and make same-op-set projection depend on arrival order.stamp[0]is coerced withNumber(...), so a string such as"not-a-number"becomesNaN.compare(NaN, 2)andcompare(2, NaN)as newer (1), breaking antisymmetry.applied.Evidence and reproduction
Reviewed SHA:
811d6a267b34f1eba2ed0969dd24ccdda565371b.Exact source locations:
op_id; it does not validatestamp,base_version, oractor:src/applier.ts:385-401stampKeyaccepts any array of length at least two and coerces the first member:src/stamps.ts:54-59compareStampKeysassumes the numeric member is orderable:src/stamps.ts:42-46set_widgetuses this result as its LWW gate:src/applier.ts:895-903Independent verification seeded two documents from one Yjs snapshot and applied the same malformed and valid
set_widgetops in opposite orders:V, stored stamp counter2M, stored malformed counter serialized asnullBoth operations returned
appliedin both replicas. This violates deterministic convergence and the total-order premise of the LWW gate. Open issue #15 concerns stamp authority but does not cover malformed numeric coercion,NaN, comparator antisymmetry, or this arrival-order divergence.Suggested root fix: validate the stamp tuple at the wire envelope before digesting or entering a transaction. Require a finite valid Lamport counter plus the contractually valid actor and reject malformed input without mutation. Add a two-arrival-order regression that asserts identical projection and rejection.
Draft-head check: open drafts #123 (
38e6ec6fb02a68d676855dd64d271bea96edc3cd) and #138 (ca2a3ec25bcc0d6243a8346d1f8ed53f606cd243) do not address this path.