feat(log): log authority is the fleet default — adopt-at-open, oracle-gated; plus the power-cut throw-site cures and the loud torn-record contract
THE DEFAULT FLIP (ruled on proven evidence — at-ack survived 301/301 acked-writes-through-power-cut in block-layer fault injection; deferred tree authority demonstrably loses flush-covered acks): a brain with NO stored authority artifact now ADOPTS LOG AUTHORITY AT OPEN. The oracle gates the flip exactly as the guarded adoption path always did — curable divergences baseline-backfilled, the flip lands ONLY on a green verdict — and a brain that cannot verify STAYS tree-authoritative loudly, with the refusal recorded on the switch artifact so subsequent opens are cheap. config logAuthority: 'defer' is the explicit documented opt-out (no automatic adoption; declared flush-window loss; adoptLogAuthority() flips later). A stored artifact always wins. RELEASES.md carries the posture. Two standing .fails debt pins FLIP TO HOLDING under the default: the at-ack crash-survival gap and the ack-at-log durability target — both now permanent asserted truths, not aspirations. POWER-CUT THROW SITES (fault-injection findings, brainy-alone config): - A manifest-listed-but-unloadable column segment QUARANTINES at discovery (loud once, counted always, quarantinedSegments() exposed for the heal) and the field serves its remaining segments DEGRADED — never a raw throw killing every query on the field. Real storage faults still propagate untouched. - Torn generation artifacts (NaN/garbage in manifest or counter) DISCARD with narration at the store's open and recovery re-derives — plus a defensive finite-integer guard at the init consumer. Never a RangeError killing an open. THE LOUD TORN-RECORD CONTRACT: an existing-but-unparseable stored record now surfaces as a typed, counted TornRecordError on every entity-read surface (including fifteen previously-blind per-item batch catches); ENOENT stays clean-absent; artifact readers with designed absent-recovery keep null-tolerance behind the loud floor. Disk corruption can no longer read as silent data invisibility. Suite migration: the default's pins inverted deliberately, generation baselines made relative, quarantine-contract pins rewritten to the ruled behavior. Gates: tsc 0 · unit 2065/2065 (159 files) · integration 826 (93 files) · conformance 31/31 · kill-matrix 15/15 · torn-open guards 2/2.
This commit is contained in:
parent
67c606be69
commit
214c98b4d5
23 changed files with 833 additions and 154 deletions
|
|
@ -1,22 +1,34 @@
|
|||
/**
|
||||
* @module tests/integration/log-authority
|
||||
* @description The guarded log-authority core, end-to-end: the per-brain
|
||||
* authority switch (default 'tree', stored artifact, checked at open only),
|
||||
* the verification oracle (replay the fact log, diff latest per-id state
|
||||
* authority switch (stored artifact, checked at open only), the
|
||||
* verification oracle (replay the fact log, diff latest per-id state
|
||||
* against the canonical tree, NAME every divergence by class), the guarded
|
||||
* flip (refuses on red with the cure in the message; lands on green and
|
||||
* engages durable-at-ack immediately), and the switch surviving reopen.
|
||||
*
|
||||
* THE 10.0.0 FLEET DEFAULT is ADOPT-AT-OPEN (`logAuthority: 'adopt'`): a
|
||||
* fresh brain with no stored artifact runs the oracle at open, backfills
|
||||
* curable divergences, and flips to log authority on green — so a
|
||||
* default-config brain opens ALREADY log-authoritative and durable-at-ack.
|
||||
* The first two pins hold that default and its explicit opt-out
|
||||
* (`logAuthority: 'defer'`, the pre-10 tree behavior). Every test below
|
||||
* them that exercises the ORACLE or the EXPLICIT flip opens its brain with
|
||||
* `'defer'` — otherwise the open-time adoption would have pre-flipped the
|
||||
* brain and pre-cured the very divergences under test.
|
||||
*
|
||||
* KNOWN GAPS PINNED WITH `.fails` (real findings, not test bugs — see the
|
||||
* comments on each): a fresh brain is NOT log-complete by construction
|
||||
* today, because the VFS root is written at init as a baseline
|
||||
* (generation-less) write that never gets a fact, so the oracle reports it
|
||||
* as a `pre-log-record` and no fresh brain can flip without a manual
|
||||
* baseline backfill. The tests that need a green oracle perform that
|
||||
* backfill explicitly (an identity update of the root as the FINAL write —
|
||||
* final, because derived-index maintenance rewrites canonical noun records
|
||||
* outside generations, so an earlier fact's after-image goes stale; see the
|
||||
* module tail comment on `backfillBaseline`).
|
||||
* as a `pre-log-record`. The open-time adoption (and adoptLogAuthority())
|
||||
* CURES this by baseline backfill — a re-commit, not construction — so the
|
||||
* by-construction pin stays `.fails` on a deferred brain. Tests that need
|
||||
* a green oracle on a deferred brain perform that backfill explicitly (an
|
||||
* identity update of the root as the FINAL write — final, because
|
||||
* derived-index maintenance rewrites canonical noun records outside
|
||||
* generations, so an earlier fact's after-image goes stale; see the module
|
||||
* tail comment on `backfillBaseline`).
|
||||
*/
|
||||
import { describe, it, expect, afterEach } from 'vitest'
|
||||
import { mkdtempSync, rmSync } from 'node:fs'
|
||||
|
|
@ -88,14 +100,24 @@ describe('log authority — the switch, the oracle, the guarded flip', () => {
|
|||
const dirs: string[] = []
|
||||
const brains: Brainy[] = []
|
||||
|
||||
const openBrain = async (dir?: string): Promise<{ brain: Brainy; dir: string }> => {
|
||||
/**
|
||||
* Open a brain over `dir`. Omit `logAuthority` to exercise the FLEET
|
||||
* DEFAULT (adopt-at-open); pass `'defer'` for the tests that need a
|
||||
* tree-authoritative brain so the oracle/explicit-flip path is actually
|
||||
* the thing under test (the default would pre-flip and pre-backfill).
|
||||
*/
|
||||
const openBrain = async (
|
||||
dir?: string,
|
||||
logAuthority?: 'adopt' | 'defer'
|
||||
): Promise<{ brain: Brainy; dir: string }> => {
|
||||
const d = dir ?? mkdtempSync(join(tmpdir(), 'brainy-log-authority-'))
|
||||
if (!dir) dirs.push(d)
|
||||
const brain = new Brainy({
|
||||
storage: { type: 'filesystem', path: d },
|
||||
requireSubtype: false,
|
||||
silent: true,
|
||||
dimensions: 384
|
||||
dimensions: 384,
|
||||
...(logAuthority ? { logAuthority } : {})
|
||||
})
|
||||
brains.push(brain)
|
||||
await brain.init()
|
||||
|
|
@ -109,8 +131,37 @@ describe('log authority — the switch, the oracle, the guarded flip', () => {
|
|||
for (const d of dirs.splice(0)) rmSync(d, { recursive: true, force: true })
|
||||
})
|
||||
|
||||
it('DEFAULT IS TREE: a fresh brain reports tree authority, stores no artifact, and plain acks never await a log fsync', async () => {
|
||||
const { brain } = await openBrain()
|
||||
// THE RULED DEFAULT (10.0.0): with no config and no stored artifact, a
|
||||
// fresh brain ADOPTS log authority at open — oracle green (the open-time
|
||||
// baseline backfill cures the generation-0 VFS root), artifact on disk,
|
||||
// durable-at-ack live from the first write.
|
||||
it('DEFAULT IS ADOPT-AT-OPEN: a fresh brain opens already log-authoritative — artifact stored, plain acks await the covering log fsync', async () => {
|
||||
const { brain } = await openBrain() // no logAuthority config = the fleet default
|
||||
|
||||
const authority = brain.logAuthority()
|
||||
expect(authority.authority).toBe('log')
|
||||
expect(typeof authority.flippedAt).toBe('number')
|
||||
expect(authority.oracle, 'the open-time flip records its green oracle summary').toBeDefined()
|
||||
|
||||
const artifact = (await internals(brain)
|
||||
.storage.readRawObject(AUTHORITY_ARTIFACT)
|
||||
.catch(() => null)) as { authority?: string } | null
|
||||
expect(artifact, 'the adoption wrote the switch artifact').not.toBeNull()
|
||||
expect(artifact!.authority).toBe('log')
|
||||
|
||||
// The MODE assertion (not a timing one): in log authority a single-op
|
||||
// ack awaits the log's covering-fsync path.
|
||||
expect(internals(brain).generationStore.logDurability).toBe('at-ack')
|
||||
const spy = spyEnsureSynced(brain)
|
||||
await brain.add({ data: 'log mode write', type: 'document', metadata: { n: 1 } })
|
||||
expect(spy.calls(), 'adopted default: add() awaits the covering fsync').toBeGreaterThanOrEqual(1)
|
||||
})
|
||||
|
||||
// THE EXPLICIT OPT-OUT: `logAuthority: 'defer'` is the pre-10 behavior —
|
||||
// tree authority, NO artifact written (a deferred posture is config, not
|
||||
// stored state), and single-op acks never await a log fsync.
|
||||
it("OPT-OUT ('defer'): the brain stays tree-authoritative, stores no artifact, and plain acks never await a log fsync", async () => {
|
||||
const { brain } = await openBrain(undefined, 'defer')
|
||||
|
||||
expect(brain.logAuthority().authority).toBe('tree')
|
||||
expect(brain.logAuthority().flippedAt).toBeUndefined()
|
||||
|
|
@ -118,7 +169,7 @@ describe('log authority — the switch, the oracle, the guarded flip', () => {
|
|||
const artifact = await internals(brain)
|
||||
.storage.readRawObject(AUTHORITY_ARTIFACT)
|
||||
.catch(() => null)
|
||||
expect(artifact, 'no switch artifact exists before any flip').toBeNull()
|
||||
expect(artifact, "'defer' writes no switch artifact").toBeNull()
|
||||
|
||||
// The MODE assertion (not a timing one): in tree authority a single-op
|
||||
// ack must never call the log's covering-fsync path.
|
||||
|
|
@ -134,10 +185,12 @@ describe('log authority — the switch, the oracle, the guarded flip', () => {
|
|||
// (00000000-0000-0000-0000-000000000000) is created at init by a baseline
|
||||
// write with NO generation and NO fact, yet it is enumerated by the
|
||||
// canonical walk — so the oracle on a fresh brain is red with exactly one
|
||||
// `pre-log-record` mismatch on the root, and adoptLogAuthority() refuses
|
||||
// on every fresh brain. Verified empirically on this branch.
|
||||
// `pre-log-record` mismatch on the root. The adopt-at-open default (and
|
||||
// adoptLogAuthority()) CURES this by baseline backfill — a re-commit,
|
||||
// which is why this pin opens with 'defer': it holds the BY-CONSTRUCTION
|
||||
// intent, which the backfill masks but does not deliver.
|
||||
it.fails('ORACLE INTENT: a fresh brain is log-complete by construction — verdict green with zero mismatches', async () => {
|
||||
const { brain } = await openBrain()
|
||||
const { brain } = await openBrain(undefined, 'defer')
|
||||
await seedWrites(brain)
|
||||
await brain.flush()
|
||||
|
||||
|
|
@ -147,7 +200,9 @@ describe('log authority — the switch, the oracle, the guarded flip', () => {
|
|||
})
|
||||
|
||||
it('a fresh, un-backfilled brain diverges ONLY on the init-time baseline record — every user write is exactly reproduced', async () => {
|
||||
const { brain } = await openBrain()
|
||||
// 'defer': the adopt-at-open default would have backfilled the baseline
|
||||
// already — this pin needs the brain genuinely un-backfilled.
|
||||
const { brain } = await openBrain(undefined, 'defer')
|
||||
await seedWrites(brain)
|
||||
await brain.flush()
|
||||
|
||||
|
|
@ -166,7 +221,10 @@ describe('log authority — the switch, the oracle, the guarded flip', () => {
|
|||
})
|
||||
|
||||
it('THE ORACLE GOES GREEN on a log-complete brain: adds + update + remove, every canonical row exactly reproduced', async () => {
|
||||
const { brain } = await openBrain()
|
||||
// 'defer' + manual backfill: the exact-count pins below (5 generations)
|
||||
// depend on the log holding ONLY this test's writes — the adopt-at-open
|
||||
// default would inject its own backfill generation at init.
|
||||
const { brain } = await openBrain(undefined, 'defer')
|
||||
await seedWrites(brain)
|
||||
await backfillBaseline(brain) // final write — see the helper's contract
|
||||
await brain.flush()
|
||||
|
|
@ -184,7 +242,7 @@ describe('log authority — the switch, the oracle, the guarded flip', () => {
|
|||
})
|
||||
|
||||
it('THE ORACLE NAMES pre-log records: a canonical row no fact ever recorded reports pre-log-record, by id', async () => {
|
||||
const { brain } = await openBrain()
|
||||
const { brain } = await openBrain(undefined, 'defer')
|
||||
await seedWrites(brain)
|
||||
await backfillBaseline(brain)
|
||||
await brain.flush()
|
||||
|
|
@ -226,7 +284,9 @@ describe('log authority — the switch, the oracle, the guarded flip', () => {
|
|||
// and the flip proceeds; ONLY log-AHEAD divergences (the log claims
|
||||
// state canonical denies) refuse, because no backfill can make the log
|
||||
// un-claim a live row. This test stages exactly that incurable shape.
|
||||
const { brain } = await openBrain()
|
||||
// 'defer': the brain must still be tree-authoritative (no artifact) so
|
||||
// the refusal's nothing-written pins below have meaning.
|
||||
const { brain } = await openBrain(undefined, 'defer')
|
||||
const { kept } = await seedWrites(brain)
|
||||
await backfillBaseline(brain)
|
||||
await brain.flush()
|
||||
|
|
@ -254,7 +314,9 @@ describe('log authority — the switch, the oracle, the guarded flip', () => {
|
|||
})
|
||||
|
||||
it('THE FLIP LANDS ON GREEN: the report is the receipt, the artifact is on disk, and durable-at-ack engages immediately', async () => {
|
||||
const { brain } = await openBrain()
|
||||
// 'defer': this pin exercises the EXPLICIT flip — the adopt-at-open
|
||||
// default would have landed it before the test began.
|
||||
const { brain } = await openBrain(undefined, 'defer')
|
||||
await seedWrites(brain)
|
||||
await backfillBaseline(brain)
|
||||
await brain.flush()
|
||||
|
|
@ -284,7 +346,7 @@ describe('log authority — the switch, the oracle, the guarded flip', () => {
|
|||
})
|
||||
|
||||
it('THE SWITCH SURVIVES REOPEN: authority restored at open with no re-verification, durable-at-ack active in the new session', async () => {
|
||||
const { brain, dir } = await openBrain()
|
||||
const { brain, dir } = await openBrain(undefined, 'defer')
|
||||
await seedWrites(brain)
|
||||
await backfillBaseline(brain)
|
||||
await brain.flush()
|
||||
|
|
@ -292,7 +354,10 @@ describe('log authority — the switch, the oracle, the guarded flip', () => {
|
|||
const flipReceipt = brain.logAuthority()
|
||||
await (brain as unknown as { close: () => Promise<void> }).close()
|
||||
|
||||
const { brain: reopened } = await openBrain(dir)
|
||||
// Reopen with 'defer' too: the restored authority below can then ONLY
|
||||
// come from the stored artifact (a stored artifact always wins; had the
|
||||
// default re-adopted, flippedAt/oracle would differ from the receipt).
|
||||
const { brain: reopened } = await openBrain(dir, 'defer')
|
||||
const restored = reopened.logAuthority()
|
||||
expect(restored.authority).toBe('log')
|
||||
// No re-verification happened at open: the restored record IS the stored
|
||||
|
|
@ -308,7 +373,7 @@ describe('log authority — the switch, the oracle, the guarded flip', () => {
|
|||
})
|
||||
|
||||
it('STATE-DIFFERS: canonical drift the write path never saw is named, by id', async () => {
|
||||
const { brain } = await openBrain()
|
||||
const { brain } = await openBrain(undefined, 'defer')
|
||||
const { kept } = await seedWrites(brain)
|
||||
await backfillBaseline(brain)
|
||||
await brain.flush()
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue