/* ADR-0092: Unit tests for passport staleness helpers — isBordbuchDriftBookkeepingOnly and dropTrailingBookkeepingEntries over real bordbuch entries appended via appendBordbuchEntry. Not a contract source of truth — the module under test owns the authoritative behavior; fixtures are minimal scaffolding only. ADR-0092: initial staleness helper tests. */ import { test, expect, describe, beforeEach, afterEach } from "vitest"; import { mkdtempSync, mkdirSync, rmSync } from "node:fs"; import { join } from "node:path"; import { tmpdir } from "node:os"; import { BOOKKEEPING_BORDBUCH_KINDS, isBordbuchDriftBookkeepingOnly, dropTrailingBookkeepingEntries, } from "./passport-staleness.ts"; import { appendBordbuchEntry, readBordbuch } from "../bordbuch/bordbuch-io.ts"; let tmpDir: string; let werkstattRoot: string; const systemId = "acme"; beforeEach(() => { tmpDir = mkdtempSync(join(tmpdir(), "passport-staleness-")); werkstattRoot = join(tmpDir, "werkstatt"); // resolveCacheClonePath resolves to a sibling of the werkstatt root — // inside tmpDir, so afterEach cleanup removes the whole fixture. mkdirSync(werkstattRoot, { recursive: true }); mkdirSync(join(tmpDir, "systems-cache", systemId), { recursive: true }); }); afterEach(() => { rmSync(tmpDir, { recursive: true, force: true }); }); async function append(kind: "mirror-sync" | "operator-note" | "mission-open" | "handover") { return appendBordbuchEntry( werkstattRoot, systemId, kind, `test ${kind}`, "test", kind === "mission-open" ? { missionId: "acme-m000001" } : undefined, ); } describe("ADR-0092: isBordbuchDriftBookkeepingOnly", () => { test("tolerates a mirror-sync appended after the recorded head", async () => { const head = (await append("operator-note")).hash; await append("mirror-sync"); const entries = await readBordbuch(werkstattRoot, systemId); expect(isBordbuchDriftBookkeepingOnly(entries, head)).toBe(true); }); test("tolerates multiple trailing bookkeeping entries", async () => { const head = (await append("operator-note")).hash; await append("mirror-sync"); await append("mirror-sync"); const entries = await readBordbuch(werkstattRoot, systemId); expect(isBordbuchDriftBookkeepingOnly(entries, head)).toBe(true); }); test("a state-changing entry after the recorded head marks real drift", async () => { const head = (await append("operator-note")).hash; await append("mission-open"); const entries = await readBordbuch(werkstattRoot, systemId); expect( isBordbuchDriftBookkeepingOnly(entries, head), "a mission-open tail is state-changing — the passport must go stale", ).toBe(false); }); test("bookkeeping followed by a state-changing entry marks real drift", async () => { const head = (await append("operator-note")).hash; await append("mirror-sync"); await append("mission-open"); const entries = await readBordbuch(werkstattRoot, systemId); expect(isBordbuchDriftBookkeepingOnly(entries, head)).toBe(false); }); test("no drift at all is not a bookkeeping-only drift (fail-safe)", async () => { const head = (await append("operator-note")).hash; const entries = await readBordbuch(werkstattRoot, systemId); expect(isBordbuchDriftBookkeepingOnly(entries, head)).toBe(false); }); test("a null recorded head tolerates an all-bookkeeping ledger", async () => { await append("mirror-sync"); await append("mirror-sync"); const entries = await readBordbuch(werkstattRoot, systemId); expect(isBordbuchDriftBookkeepingOnly(entries, null)).toBe(true); }); test("a null recorded head with any state-changing entry marks real drift", async () => { await append("mirror-sync"); await append("operator-note"); const entries = await readBordbuch(werkstattRoot, systemId); expect(isBordbuchDriftBookkeepingOnly(entries, null)).toBe(false); }); test("a recorded head absent from the ledger fails safe", async () => { await append("mirror-sync"); const entries = await readBordbuch(werkstattRoot, systemId); expect( isBordbuchDriftBookkeepingOnly(entries, "sha256:does-not-exist"), "an unresolvable recorded head can never prove bookkeeping-only drift", ).toBe(false); }); }); describe("ADR-0092: dropTrailingBookkeepingEntries", () => { test("strips a trailing mirror-sync run, exposing the last state-significant entry", async () => { await append("handover"); await append("mirror-sync"); const entries = await readBordbuch(werkstattRoot, systemId); const significant = dropTrailingBookkeepingEntries(entries); expect(significant).toHaveLength(1); expect(significant[significant.length - 1].kind).toBe("handover"); }); test("returns the ledger unchanged when the tail is state-significant", async () => { await append("mirror-sync"); await append("handover"); const entries = await readBordbuch(werkstattRoot, systemId); const significant = dropTrailingBookkeepingEntries(entries); expect(significant).toHaveLength(2); expect(significant[significant.length - 1].kind).toBe("handover"); }); test("an all-bookkeeping ledger reduces to empty", async () => { await append("mirror-sync"); const entries = await readBordbuch(werkstattRoot, systemId); expect(dropTrailingBookkeepingEntries(entries)).toHaveLength(0); }); }); describe("ADR-0092: BOOKKEEPING_BORDBUCH_KINDS", () => { test("contains mirror-sync", () => { expect(BOOKKEEPING_BORDBUCH_KINDS.has("mirror-sync")).toBe(true); }); });