docs(specs): gap re-validation 2026-06-24 (5 HA/raft specs)
/kiro-validate-gap gap-focused sweep. Per-spec gap analysis written to each spec's research.md (3 new, 2 appended), grounded in file:line evidence: - config-upgrade-snapshot (new): real open gap — transport + (term,lsn) marker + COW substrate exist, but the entity-bearing snapshot PAYLOAD does not (16-byte LSN sentinel). HARD-blocked on entity-bearing-snapshots. Closes bug-857. Effort L (XL incl. blocker) / Risk High. - raft-commit-safety (new): CLOSED — G4 Figure-8 commit (raft.c:733) + G6 vote freshness (raft.c:157) done, full sim coverage; the "(0,0) stopgap / broken build" concern is stale (build green, real vote tuple at cluster.c:435). - raft-sim-conformance (new): mostly open — raft.tla is reference-only; only 1 of 4 invariants (Log Matching) checked in code. Missing PRNG/replay, message-fault bag, scheduler, 3 invariant checkers, fault switches, scenarios. Effort L / Risk Medium. - ha-repl-hardening (append): RESCOPE/superseded — 31/33 EARS closed; Req 2.3 + Req 6 obsolete (CTRL_PRIMARY_COMMITTING removed). Residual: docs only. - ha-convergence-recovery (append): done bar Task 8 (live E2E); bug-1028 post-failover availability resolved 2026-06-23. Skipped ha-elect-ctx-lifecycle (no requirements.md). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01MSxwb2Xt5F84ATgiAZnH8V
This commit is contained in:
parent
50b976aedc
commit
05febbc9a7
5 changed files with 570 additions and 0 deletions
53
.kiro/specs/raft-commit-safety/research.md
Normal file
53
.kiro/specs/raft-commit-safety/research.md
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# Gap Analysis — raft-commit-safety (2026-06-24)
|
||||
|
||||
> Scope: the **commit-safety (G4 Figure-8 commit advance) + election-freshness (G6 `(lastLogTerm,lastLogIndex)` vote/PreVote)** half of `raft/raft.tla`, in `src/lib/raft` only. Boundary owns the library entry points + callbacks; the controller barrier/durability, config markers/snapshot, and conformance harness are owned elsewhere (`ha-term-safety`, `raft-sim-conformance`). HARD dep: `raft-log-replication`.
|
||||
|
||||
## Executive Summary
|
||||
|
||||
This spec is **DONE**. All tasks 1.1–8.1 are `[x]` in `tasks.md`, and the actual code confirms it: the library half (G4 commit-advance + G6 vote/PreVote freshness) is implemented in `src/lib/raft/{raft.h,raft.c,raft_sim.c}`, fully tested in `src/lib/testsuite/test_raft.c`, and **already consumed by the controller** via the `ha-term-safety` adapter. The historical "(0,0) stopgap disables G6 / build broken" state recorded in project memory is **stale** — it has been superseded: the controller build is green (later commits `bug-1060`/`bug-1067` build on top of it), the wire schema carries `last_log_term`/`last_log_index`, and `cluster.c` feeds the real candidate tuple into `raft_on_vote_request`. **No unsafe stopgap remains in this spec's surface.**
|
||||
|
||||
## Requirement-to-Asset Map
|
||||
|
||||
| Req | Asset (file:line) | Status |
|
||||
|-----|-------------------|--------|
|
||||
| **R1** Library-owned `commit_index` + current-term advance (G4) | `raft.h:62` (`commit_index`), `raft.h:199` (`initial_commit_index`), `raft.c:733` `raft_advance_commit` — leader-only `-EPERM` (`raft.c:738`), `Max(agreeIndexes)` scan (`raft.c:740`), current-term gate before advance, monotonic | **DONE** |
|
||||
| **R2** `on_commit_advanced` callback triggers barrier (no durability in lib) | `raft.h:169` decl (REQUIRED), `raft.c:58` NULL-check `-EINVAL` at init, `raft.c:780` fired once on strict advance; AE-reply does not advance (`test_ae_reply_does_not_advance_commit`) | **DONE** |
|
||||
| **R3** `(lastLogTerm,lastLogIndex)` binding-vote freshness (G6) | `raft.c:157` `raft_log_ok`, applied in `raft_on_vote_request` (`raft.c:234`) BEFORE `on_vote_eligible`; extended sig `raft.h:267` | **DONE** |
|
||||
| **R4** Same freshness on PreVote, side-effect-free | `raft_on_pre_vote_request` (`raft.c:291` `raft_log_ok`), no state mutation / no `on_persist`; sig `raft.h:329` | **DONE** |
|
||||
| **R5** Preserve sync commit barrier + durability as policy | Library returns status codes only; barrier remains in controller `commit.c`/`ha.c`; `on_commit_advanced` is trigger-only | **DONE** |
|
||||
| **R6** Deterministic Figure-8 + Leader Completeness + freshness sim | `test_raft.c`: `test_advance_commit_figure8_hold_previous_term` (2765), `test_sim_7_1_figure8_commit_refusal` (4095), `test_sim_7_2_leader_completeness_across_changes` (4161), `test_sim_7_3_freshness_gate_lexicographic` (4245), `test_sim_7_4_on_commit_advanced_trigger_semantics` (4345); all `RUN_TEST`-registered | **DONE** |
|
||||
|
||||
No gaps tagged Missing/Unknown within the spec boundary.
|
||||
|
||||
## Downstream Consumption (out-of-scope here, but verified present)
|
||||
|
||||
The controller integration that routes the WAL/commit barrier through the library is owned by **`ha-term-safety`**, and it is wired:
|
||||
|
||||
- **Wire schema**: `src/schema/controller.capnp:833-834` adds `lastLogTerm @4` / `lastLogIndex @5` to the RequestVote message.
|
||||
- **Vote path**: `src/controller/cluster.c:395-396,435-436` reads the candidate's `last_log_term`/`last_log_index` from the wire and passes the real tuple into `raft_on_vote_request(...)`. **No `(0,0)` stopgap** — the application freshness gate (`config_tag`/`durable_floor`) is layered IN ADDITION to the library `logOk`, not in place of it.
|
||||
- **PreVote path**: `cluster.c:489,533` plumbs the same tuple into `raft_on_pre_vote_request`.
|
||||
- **Commit source**: `src/controller/ha.c:1686` `ha_cb_commit_advanced_stub` (name is legacy — it is a real, wired callback) calls `commit_set_raft_commit_index(...)`, making the library's current-term-gated `commit_index` the steady-state commit SOURCE; the term-blind `ha_compute_safe_committed_lsn` is no longer the steady-state driver. Callback table at `ha.c:1741`.
|
||||
- **Build state**: green. Later commits `61e1391 fix bug-1060 bug-1067` and the `ha-term-safety` series build on top of the extended vote signature, confirming the earlier "vote-signature extension BROKE cluster.c" condition is resolved.
|
||||
|
||||
## Options (retrospective — for any follow-up only)
|
||||
|
||||
- **Option A — Extend existing (CHOSEN, complete).** The library log/election core already existed (`raft-library` + `raft-log-replication`); this spec extended `raft.{c,h}` with one new action, one callback, and two freshness args. Trade-off accepted: keeps everything in the pure library, no new TU. ✅ minimal surface, leverages existing callback contract.
|
||||
- **Option B — Library owns `logOk` (CHOSEN for freshness plumbing).** Vote/PreVote signatures gained `cand_last_log_term`/`cand_last_log_index` and the library now owns the `logOk` decision (formerly the caller/dispatcher's). This is the "freshness-decision locus move" called out in R5.4. ✅ single authoritative predicate (`raft_log_ok`) shared by both paths.
|
||||
- **Option C — Hybrid / new component.** Not needed; rejected implicitly. A separate commit module would have split the `commit_index` invariant away from the log model it depends on.
|
||||
|
||||
## Effort & Risk
|
||||
|
||||
- **Effort: S (already delivered).** Remaining work for *this spec* = none. Verification re-run only.
|
||||
- **Risk: Low.** Pure, synchronous, deterministic library code with full simulator coverage (Figure-8 hold/release, Leader Completeness across forced leader changes, lexicographic freshness, trigger-fire-count). No I/O, no threads; controller integration validated downstream by `ha-term-safety` live soak.
|
||||
|
||||
## Recommendations for design phase
|
||||
|
||||
- **No further design needed for raft-commit-safety.** Treat as closed; G4/G6 of bug-851 are addressed at the library layer.
|
||||
- **Carry-forward (owned elsewhere, not this spec):**
|
||||
- `ha-term-safety` owns the controller wiring already in place — keep the bug-828/854/991/1060/1067 follow-ups there.
|
||||
- `raft-sim-conformance` owns the full TLC trace-check harness (Leader Completeness oracle) — this spec only seeds the deterministic sim assertions it will consume.
|
||||
- **Stale-memory correction (research item closed):** the project-memory note "vote-signature extension BROKE the controller build (cluster.c); (0,0) stopgap unsafe—disables G6" is **no longer current**. Verified 2026-06-24: build green, real tuple wired, no stopgap. Update the memory entry accordingly.
|
||||
|
||||
## Research-Needed
|
||||
|
||||
- None within this spec's boundary. (Open HA items — bug-828 residual / bug-854 client discovery — are tracked under `ha-term-safety`, not here.)
|
||||
Loading…
Add table
Add a link
Reference in a new issue