mirror of
https://github.com/turnstonelabs/turnstone.git
synced 2026-08-12 23:12:23 -06:00
fix(server): widen the boot epoch to 64 bits; docstring precision (#881)
token_hex(4) left the epoch equality check — the only thing between a prior-boot cursor and a silent replay_ok-empty alias — at 2^-32 per same-node restart-pair; 64 bits puts a fleet-lifetime of restarts engineered far below threshold (review round 4, classified design-margin). Docstring rounds from the same pass: the resume contract now notes reason=boot_epoch also covers the same-epoch empty-ring fail-safe (not exclusively foreign epochs), and the collector ruling says precisely that the staleness CHECK and envelope can never fire there — the epoch-tagged ids are on the wire, just never read.
This commit is contained in:
@@ -398,7 +398,7 @@ def test_epoch_is_hex_and_dashless_by_construction() -> None:
|
||||
import secrets
|
||||
|
||||
for _ in range(64):
|
||||
assert "-" not in secrets.token_hex(4)
|
||||
assert "-" not in secrets.token_hex(8)
|
||||
# And the production init uses token_hex — source-level pin.
|
||||
import inspect
|
||||
|
||||
|
||||
@@ -284,8 +284,9 @@ class ClusterCollector:
|
||||
``node_snapshot`` and the collector rebuilds wholesale. That is
|
||||
this consumer's recovery model (idempotent state-of-world, not
|
||||
append-only history), it side-steps cursor staleness across node
|
||||
restarts entirely, and it means the epoch-tagged ids and the
|
||||
``replay_truncated`` envelope on this stream can never fire here.
|
||||
restarts entirely, and it means the epoch staleness check and
|
||||
the ``replay_truncated`` envelope can never fire here — the
|
||||
epoch-tagged ids themselves are on the wire, just never read.
|
||||
If a cursor is ever adopted, present the SSE ``id:`` VERBATIM
|
||||
(opaque ``"{boot_epoch}-{counter}"`` — never parse it) and handle
|
||||
``replay_truncated`` explicitly; today an unknown event type
|
||||
|
||||
+11
-3
@@ -1029,7 +1029,10 @@ async def global_events_sse(request: Request) -> Response:
|
||||
from any other epoch — a prior boot, another node, a pre-#881
|
||||
bare-int client — gets ``replay_truncated`` with
|
||||
``reason="boot_epoch"`` followed by a fresh ``node_snapshot``, since
|
||||
the events it missed died with the process that minted it. Clients
|
||||
the events it missed died with the process that minted it.
|
||||
``boot_epoch`` is not exclusively a foreign-epoch signal: a
|
||||
same-epoch cursor over an EMPTY ring (impossible from our own ids —
|
||||
forged or a bug) also draws it via the fail-safe branch below. Clients
|
||||
treat the cursor as an opaque string; only this handler parses it.
|
||||
"""
|
||||
# -- Service-scope gate ---------------------------------------------------
|
||||
@@ -5172,8 +5175,13 @@ def create_app(
|
||||
# differs from the live process is stale by construction and draws
|
||||
# the ``replay_truncated`` + node_snapshot recovery floor in
|
||||
# :func:`global_events_sse`. Hex nonce (never contains ``-``), so
|
||||
# ``partition("-")`` splits the id unambiguously.
|
||||
app.state.global_boot_epoch = secrets.token_hex(4)
|
||||
# ``partition("-")`` splits the id unambiguously. 64 bits: the
|
||||
# equality check is the ONLY thing standing between a prior-boot
|
||||
# cursor and a silent ``replay_ok``-empty alias, and the collision
|
||||
# event is per same-node restart-pair — 2^-64 keeps a
|
||||
# fleet-lifetime of restarts engineered far below threshold where
|
||||
# 32 bits left it merely unlikely (review round 4).
|
||||
app.state.global_boot_epoch = secrets.token_hex(8)
|
||||
app.state.skip_permissions = skip_permissions
|
||||
app.state.jwt_secret = jwt_secret
|
||||
app.state.auth_storage = auth_storage
|
||||
|
||||
Reference in New Issue
Block a user