tidaldb/tidal-server/src/cluster
jordan a6f663f002
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
harden: validate embeddings before the WAL, fix the reseed-latch leak, run every test suite
Fixes the two defects a malformed probe exposed on the live cluster, plus the
coverage gap that let a stale assertion survive the same day it was falsified.

TASK 17 — validate before the WAL append. A 128-dim vector against a 1536-dim
slot was appended to the WAL FIRST, then validated, then answered 500 — so an
already-durable, unapplicable record shipped to both followers, halted both
receivers, and put shard 1 into a quorum-write outage. Validation now runs before
the append and returns 400 via invalid_input; nothing enters the log.
`storage::vector::validate_dimensions` is now the single comparison, replacing an
inline duplicate of the same rule in lifecycle/ops.rs:57-62 — two copies of a
dimension check drift, and the apply-path copy is the one that halts replication
when it disagrees.

The receiver's halt-vs-skip decision is now explicit instead of "halt on
anything". A record whose failure is deterministic and node-independent (schema
width) is skipped, counted on blobs_apply_failed_total and ERROR-logged, so the
frontier advances; a record that could become applicable after a binary upgrade
(unknown batch kind, capability skew) still halts, because skipping那 would
silently drop replicated data. Both branches are proven reachable by tests.

TASK 18 — the reseed latch outlived its discharge. A node hosting 3 shard groups
latched a marker per group but discharged on a single seqno, so two latches meant
permanent 503 on a node whose every shard read lag 0 — it hit all three pods
during the roll and each needed a manual delete. Gaps are now tracked per group
in a ReseedGapSet and cleared on evidence about themselves; a REFUSED
reseed_self_restart re-evaluates every 15s instead of waiting for a latch that
never arrives. /health's cause ladder was also lying: it printed "joiner boot not
yet converged" for a node whose groups had all converged, because the fallback
asserted a state it never tested. It now names the outstanding gaps, gained the
decommissioned-by-signal arm that is_ready checked but the ladder did not, and
its terminal arm says "reason unavailable" rather than inventing one.

COVERAGE — 14 of 23 integration suites were run by NO pipeline. Not theoretical:
cluster_routes still asserted the wire fabrication removed hours earlier
(applied_events == 0 with a lag derived from it) and nothing caught it because
nothing ran it. cluster_sharding (dense-rank, /sharded/* opt-in), vector_search
(distance contract) and cluster_poison_embedding (task 17's own gate) were in the
same position, so those guards would have rotted identically. Every suite now has
a runner: 8 in-process ones in a new `fast-suites` push step (measured 71s, runs
FIRST so a cheap failure precedes the 6.5-min gate), 6 multiproc ones in the
nightly. All 23 scheduled; all 4 never-before-run heavy suites verified passing
before being scheduled.

Also fixes cluster_chaos.rs:329, which the nightly's FIRST EVER run caught 13
minutes in — it demanded an unreachable peer report worst-case lag, i.e. it
required the fabrication task 04a deleted.

Verified: fmt clean; clippy 72 vs 73 baseline (one FEWER, zero added, measured on
touched trees at 431340f); lib 2115 passed; all 8 fast suites green;
cluster_chaos 5, cluster_sharding 5, cluster_poison_embedding 1,
cluster_cross_shard_reads 2, cluster_graph_persistence 1, cluster_multiproc 5,
cluster_e2e 2; doc-guard OK.
2026-08-31 00:46:00 -06:00
..
audit.rs fix(m11): review remediation + tidal-stress perf sweep + perf wave 2 2026-06-13 12:28:04 -06:00
election_driver.rs fix(cluster): anchor the reseed-marker clear to the marker, not the leader tail 2026-08-20 22:23:35 -06:00
forward.rs feat(m12p6): persist HNSW graph + bounded SIGTERM drain — boot loads, no rebuild 2026-06-15 13:09:20 -06:00
http_tls.rs fix(m11): review remediation + tidal-stress perf sweep + perf wave 2 2026-06-13 12:28:04 -06:00
join_boot.rs feat(cluster): separate operator authority from data-plane access 2026-08-22 00:57:01 -06:00
membership.rs feat(m11): data-plane sharding × replication (m11p6 L0-L2) 2026-06-12 23:06:41 -06:00
mod.rs docs: withdraw the pre-release "not ready for production" disclaimer 2026-07-30 19:03:34 -06:00
node_reseed_gap_tests.rs harden: validate embeddings before the WAL, fix the reseed-latch leak, run every test suite 2026-08-31 00:46:00 -06:00
node.rs harden: validate embeddings before the WAL, fix the reseed-latch leak, run every test suite 2026-08-31 00:46:00 -06:00
reseed_restart.rs fix(m12): break the post-reseed false-ReseedRequired loop (durable term marker + readiness gating + restart coordinator) 2026-06-18 21:06:18 -06:00
reseed.rs feat(cluster): separate operator authority from data-plane access 2026-08-22 00:57:01 -06:00
routes.rs harden: restore CI verification, remove four wire-level fabrications, instrument the 401 path 2026-08-30 20:55:58 -06:00
security.rs feat(cluster): separate operator authority from data-plane access 2026-08-22 00:57:01 -06:00
snapshot.rs feat(m11): membership, snapshot install, and reseed (m11p5) 2026-06-12 19:55:54 -06:00
state.rs docs: withdraw the pre-release "not ready for production" disclaimer 2026-07-30 19:03:34 -06:00
topology.rs feat(m11): observability+ops (m11p8) + perf-sweep wave 2 T2 2026-06-13 09:17:49 -06:00
transport.rs feat(m11): membership, snapshot install, and reseed (m11p5) 2026-06-12 19:55:54 -06:00