Skip to content
zit Timeline
Login

Timeline

Parents and children of check-in [ba805e5913]

2026-07-20
04:13
Compose storage and network faults in the sync DST

The sync sweep and the storage sweep ran in disjoint PRNG streams off the same seed and never intersected: no exchange ever ran over a client store that could tear. A partial pull could leave torn frames that recovery accepts but a resumed session never converges past.

runCrashResume backs the client store with a real LogStore over a tearable FaultyFile instead of the pure MemStore, seeded healthy then armed to tear. Between phase-1 rounds, on a seeded coin, it power-cuts the store mid-persist, reopens it, reloads the recovered prefix, and resumes with a fresh Client over the same durable store, mirroring cmd/sync's loadContentStore for wire-name to log-digest identity.

The oracle keeps every existing sync invariant and adds the crash bite: post-recovery contents are a subset of the pre-crash held set, no corrupt frame crosses the boundary, and phase-2 liveness heals both domains before a fresh session converges in the bounded window (sync 3.7). One seeded PRNG stream drives the whole run, so a failure replays from the shared reproduce line.

The composed-fault and liveness-under-faults discipline follows TigerBeetle's VOPR. closed check-in: d2b5f729ef user: dmestas tags: h3-crashsync

03:41
Merge h1-soak: the out-of-band deep soak the harnesses assume exists

The fuzz and simulation harnesses defer real depth to a nightly runner that was never written; the gate only ever ran a shallow smoke. scripts/ soak.sh is that runner. In a ReleaseSafe build it runs the deterministic simulation over many seeds and long step counts, then every fuzz target -- enumerated from the runner's own usage so the list cannot drift -- under an equal wall-clock budget per target, so a cheap target reaches far more rounds than an expensive one with no second cost table to maintain. A failure appends a runnable reproduce line to a dated log, drops a flag file, and exits nonzero; it never files or fixes anything, and its logs live outside the checkout. Proven to catch both a seeded simulation regression and a seeded fuzz regression, each replaying from the logged line. Installing the schedule and the first full nightly are operator steps, documented in the script and its README. check-in: 1b447f8b47 user: dmestas tags: trunk

03:34
Merge h8-readrot: simulate latent read rot, prove the read path detects it

The fault simulator only ever corrupted at crash and restart boundaries. It could not model a latent sector error: bit rot that surfaces during a read of a store that opened clean. A new read_rot_pct knob does that -- a read returns payload-derived, never-self-healing corruption for a frame that is intact on disk -- and a sweep reopens a healthy store, arms it, and reads every held hash. The oracle: each read returns exactly the stored bytes or a declared corruption error, never wrong bytes as success. The append open path re-runs the whole-frame checksum per read, so it catches the rot; the sweep is green and a companion test proves the sweep can fail by reading through the checksum-skipping read-only open. The knob is inert at zero, so every existing seed keeps its byte stream. The crash-point fault technique follows TigerBeetle's storage fault model. check-in: ba805e5913 user: dmestas tags: trunk

03:29
Add online read-fault injection to the storage DST sweep

FaultyFile injected corruption only at crash/restart boundaries. Add a read_rot_pct knob: a read of an intact byte interns one offset in its span as permanently corrupt (payload-derived mask, never self-heals) -- a latent sector error surfacing at content() time on a store that opened clean, independent of any crash. A healthy disk draws nothing, so existing sweeps keep a byte-identical PRNG stream.

New storage_sweep.readRotSweep joins the dst gate: after a healthy open, every content-bearing hash reads back either its exact bytes or a declared corruption error -- wrong bytes presented as success is SilentCorruption. The append open path re-runs each frame's whole-frame CRC per read, so latent rot is detected and the gate stays green. The verified-on-open read path (openReadOnly) trusts the scan-time CRC on an immutable-length assumption that bit rot violates; a test drives that path to prove the oracle fires SilentCorruption.

Read-fault model follows TigerBeetle's storage-fault-injection lineage. closed check-in: fde61b03b2 user: dmestas tags: h8-readrot

03:27
Merge h5a-asserts: TigerStyle assert pass on update, serve, transport

Assert density was collapsing exactly where the working tree and the wire are touched: update.zig held 2 asserts across 2127 lines, serve.zig 3, transport.zig 2 -- against the hundreds in the artifact and sync cores. This pass adds 17 asserts stating invariants that already hold: the checkout-state transitions in update (managed-set, record and rollback image agreement around each applyCheckin stage), the request/response postconditions in serve (media, arity and body-ceiling), and the frame, redirect and body-cap postconditions in transport. Asserts only, no behaviour change; where a result had to be named to assert on it the error mapping is preserved exactly. All survive the deterministic simulation sweeps, which is the point of landing them before the checkout crash-recovery sweep that will hammer update. check-in: 9654d06838 user: dmestas tags: trunk