import assert from "node:assert/strict" import { test } from "node:test" import { acquireDatabaseSchemaControl, DATABASE_SCHEMA_CONTROL_SQL as sql, type DatabaseSchemaControlClient } from "./database-schema-control.js" import { initialDatabaseSchemaControlState, DatabaseSchemaControlError, type DatabaseSchemaControlState } from "./database-schema-control-model.js" const id = "00000000-0000-4000-8000-000000000001", otherId = "00000000-0000-4000-8000-000000000002", hash = "a".repeat(64) const command = (intentId = id) => ({ type: "begin" as const, id: intentId, kind: "restore" as const, manifestSha256: hash, artifactSha256: hash }) /** Inert protocol emulator: does not claim PostgreSQL durability. Root's * private PG suite must independently test these SQL strings/commit windows. */ function fixture() { let durable = { revision: "0", state: initialDatabaseSchemaControlState() }, intents = new Map() let lock: number | undefined, sessions = 0 const calls: string[] = [], releases: boolean[] = [] const faults = { at: "", afterCommit: false, commitTag: "COMMIT" as string | undefined }, empty = { rows: [] as Record[] } const pool = { connect: async (): Promise => { const session = ++sessions let tx: typeof durable | undefined, history: typeof intents | undefined return { query: async (query, values = []) => { calls.push(query) if (query === faults.at && !faults.afterCommit) throw new Error("injected SQL refusal") if (query === sql.acquire) { if (lock !== undefined) return { rows: [{ acquired: false }] }; lock = session; return { rows: [{ acquired: true }] } } if (query === sql.unlock) { assert.equal(lock, session); lock = undefined; return { rows: [{ unlocked: true }] } } if (query === "BEGIN") { assert(!tx); tx = structuredClone(durable); history = structuredClone(intents); return empty } if (query.startsWith("SET LOCAL ")) { assert(tx); return empty } if (query === sql.read) { assert(tx); return { rows: [structuredClone(tx)] } } if (query === sql.beginIntent) { assert(history); if (history.has(String(values[0]))) throw new Error("duplicate intent"); history.set(String(values[0]), { intent: JSON.parse(String(values[1])), terminal: null }); return { rows: [{ id: values[0] }] } } if (query === sql.terminalIntent) { const row = history?.get(String(values[0])); if (!row || row.terminal) return empty; row.terminal = JSON.parse(String(values[1])); return { rows: [{ id: values[0] }] } } if (query === sql.readIntent) { const row = history?.get(String(values[0])); return { rows: row ? [structuredClone(row)] : [] } } if (query === sql.write) { assert(tx); if (values[1] !== tx.revision) return empty; tx = { revision: String(BigInt(tx.revision) + 1n), state: JSON.parse(String(values[0])) as DatabaseSchemaControlState }; return { rows: [structuredClone(tx)] } } if (query === "COMMIT") { assert(tx && history); durable = tx; intents = history; tx = undefined; history = undefined; if (faults.at === query && faults.afterCommit) throw new Error("lost COMMIT ACK"); return { ...empty, command: faults.commitTag } } throw new Error("Unexpected SQL: " + query) }, release: destroy => { releases.push(Boolean(destroy)); tx = undefined; history = undefined; if (lock === session) lock = undefined }, } } } return { pool, calls, releases, faults, read: () => structuredClone(durable), intents: () => structuredClone(intents), corrupt: (change: (state: DatabaseSchemaControlState) => void) => change(durable.state) } } test("acquisition commits quarantine before returning, no DDL or application SQL", async () => { const f = fixture(), handle = await acquireDatabaseSchemaControl(f.pool) assert.equal(f.read().state.epoch, 1) assert.equal(f.calls.at(-1), "COMMIT") assert.equal((await handle.admission()).ready, false) assert(f.calls.includes("SET LOCAL synchronous_commit = on")) assert(!f.calls.some(query => /CREATE|DROP|public\./.test(query))) await handle.close(); assert.deepEqual(f.releases, [false]) }) test("second owner cannot acquire a live session lease", async () => { const f = fixture(), first = await acquireDatabaseSchemaControl(f.pool) await assert.rejects(acquireDatabaseSchemaControl(f.pool), DatabaseSchemaControlError) assert.equal(f.read().state.epoch, 1) await first.close() const second = await acquireDatabaseSchemaControl(f.pool) assert.equal(f.read().state.epoch, 2) await second.close() }) test("intent and terminal history are atomically published with control CAS", async () => { const f = fixture(), handle = await acquireDatabaseSchemaControl(f.pool) await handle.transition(command()) assert(f.intents().has(id)); assert.equal(f.read().state.phase, "INTENT") await handle.transition({ type: "terminal", id, outcome: "observed-success", observationSha256: hash }) assert(f.intents().get(id)?.terminal) assert.equal((await handle.admission()).ready, false) await handle.close() }) test("historical id reuse refuses after subsequent operations", async () => { const f = fixture(), handle = await acquireDatabaseSchemaControl(f.pool) for (const current of [id, otherId]) { await handle.transition(command(current)) await handle.transition({ type: "terminal", id: current, outcome: "observed-success", observationSha256: hash }) } await assert.rejects(handle.transition(command())) assert.equal(f.read().state.terminal?.intent.id, otherId) assert.equal(f.releases.at(-1), true) }) test("failed CAS rolls back intent publication and discards owner", async () => { const f = fixture(), handle = await acquireDatabaseSchemaControl(f.pool) f.faults.at = sql.write await assert.rejects(handle.transition(command())) assert.equal(f.intents().size, 0); assert.equal(f.read().state.intent, null) await assert.rejects(handle.read()) assert.equal(f.releases.at(-1), true) }) test("lost intent COMMIT ACK persists unknown intent but poisons old handle", async () => { const f = fixture(), handle = await acquireDatabaseSchemaControl(f.pool) f.faults.at = "COMMIT"; f.faults.afterCommit = true await assert.rejects(handle.transition(command()), error => error instanceof DatabaseSchemaControlError && error.outcomeUnknown) assert.equal(f.read().state.intent?.id, id) await assert.rejects(handle.admission()) f.faults.at = "" const restarted = await acquireDatabaseSchemaControl(f.pool) assert.equal(f.read().state.epoch, 2) assert.equal((await restarted.admission()).reason, "UNRESOLVED_INTENT") await assert.rejects(restarted.transition({ type: "terminal", id, outcome: "observed-success", observationSha256: hash })) }) test("lost terminal ACK never produces READY after fresh ownership", async () => { const f = fixture(), handle = await acquireDatabaseSchemaControl(f.pool) await handle.transition(command()) f.faults.at = "COMMIT"; f.faults.afterCommit = true await assert.rejects(handle.transition({ type: "terminal", id, outcome: "observed-success", observationSha256: hash })) f.faults.at = "" const restarted = await acquireDatabaseSchemaControl(f.pool) assert.equal(f.read().state.terminal?.outcome, "observed-success") assert.equal((await restarted.admission()).ready, false) await restarted.close() }) test("restarted owner may durably record interrupted-unknown but stays quarantined", async () => { const f = fixture(), first = await acquireDatabaseSchemaControl(f.pool) await first.transition(command()); await first.close() const next = await acquireDatabaseSchemaControl(f.pool) await next.transition({ type: "terminal", id, outcome: "interrupted-unknown", observationSha256: hash }) assert.equal(f.read().state.intent, null) assert.equal((await next.admission()).ready, false) await next.close() }) test("concurrent use of one handle refuses without duplicate publication", async () => { const f = fixture(), handle = await acquireDatabaseSchemaControl(f.pool) const first = handle.transition(command()) await assert.rejects(handle.transition(command(otherId))) await first assert.equal(f.intents().size, 1) await handle.close(); await handle.close() await assert.rejects(handle.read()) }) test("caller mutation after transition cannot change durable command or history", async () => { const f = fixture(), handle = await acquireDatabaseSchemaControl(f.pool), mutable = command() const pending = handle.transition(mutable) mutable.id = otherId await pending assert.equal(f.read().state.intent?.id, id) assert(f.intents().has(id)); assert(!f.intents().has(otherId)) await handle.close() }) test("unknown command policy bytes refuse before SQL and leave owner usable", async () => { const f = fixture(), handle = await acquireDatabaseSchemaControl(f.pool), before = f.calls.length await assert.rejects(handle.transition({ ...command(), policy: { ready: true } } as ReturnType)) assert.equal(f.calls.length, before) assert.equal((await handle.admission()).ready, false) await handle.close() }) test("tampered state cannot disagree with independently stored intent history", async () => { const f = fixture(), handle = await acquireDatabaseSchemaControl(f.pool) await handle.transition(command()) f.corrupt(state => { state.intent!.artifactSha256 = "b".repeat(64) }) await assert.rejects(handle.read()) assert.equal(f.releases.at(-1), true) await assert.rejects(acquireDatabaseSchemaControl(f.pool)) assert.equal(f.read().state.epoch, 1) }) test("accessor commands refuse without invocation or database IO", async () => { const f = fixture(), handle = await acquireDatabaseSchemaControl(f.pool), before = f.calls.length let invoked = false const accessor = command() Object.defineProperty(accessor, "id", { enumerable: true, get: () => { invoked = true; return id } }) await assert.rejects(handle.transition(accessor)) assert.equal(invoked, false); assert.equal(f.calls.length, before) await handle.close() }) for (const tag of ["ROLLBACK", "", undefined]) { test(`unconfirmed COMMIT command ${String(tag)} destroys owner and never returns a grant`, async () => { const f = fixture(), handle = await acquireDatabaseSchemaControl(f.pool) f.faults.commitTag = tag await assert.rejects(handle.transition(command()), error => error instanceof DatabaseSchemaControlError && error.outcomeUnknown) assert.equal(f.releases.at(-1), true) await assert.rejects(handle.read(), DatabaseSchemaControlError) // Even if the server committed, no readback replays or upgrades the ACK. assert.equal(f.calls.filter(query => query === sql.beginIntent).length, 1) f.faults.commitTag = "COMMIT" const restarted = await acquireDatabaseSchemaControl(f.pool) assert.equal((await restarted.admission()).ready, false) await restarted.close() }) test(`claim COMMIT command ${String(tag)} refuses before a usable owner exists`, async () => { const f = fixture() f.faults.commitTag = tag await assert.rejects(acquireDatabaseSchemaControl(f.pool), error => error instanceof DatabaseSchemaControlError && error.outcomeUnknown) assert.deepEqual(f.releases, [true]) assert.equal(f.calls.filter(query => query === sql.beginIntent).length, 0) }) } for (const tag of ["ROLLBACK", "", undefined]) { test(`terminal COMMIT command ${String(tag)} cannot publish an acknowledged outcome`, async () => { const f = fixture(), handle = await acquireDatabaseSchemaControl(f.pool) await handle.transition(command()) f.faults.commitTag = tag await assert.rejects(handle.transition({ type: "terminal", id, outcome: "observed-success", observationSha256: hash }), error => error instanceof DatabaseSchemaControlError && error.outcomeUnknown) assert.equal(f.releases.at(-1), true) await assert.rejects(handle.admission(), DatabaseSchemaControlError) assert.equal(f.calls.filter(query => query === sql.terminalIntent).length, 1) f.faults.commitTag = "COMMIT" const restarted = await acquireDatabaseSchemaControl(f.pool) assert.equal((await restarted.admission()).ready, false) await restarted.close() }) }