Files
MikrotikManager/backend/src/db/controlled-schema-verification.test.ts
T

152 lines
12 KiB
TypeScript

import assert from "node:assert/strict"
import { createHash, createHmac, randomUUID } from "node:crypto"
import { readFile } from "node:fs/promises"
import { fileURLToPath } from "node:url"
import { test } from "node:test"
import { runInNewContext } from "node:vm"
import ts from "typescript"
import * as model from "./database-schema-control-model.js"
import * as manifest from "./migration-manifest.js"
import { CONTROLLED_MIGRATIONS_SQL } from "./controlled-migrations.js"
import { PARTITION_WRITER_ADVISORY_KEY } from "../services/partition-write-transaction.js"
const canonical = (value: unknown): string => JSON.stringify(value, (_key, item: unknown) => item && typeof item === "object" && !Array.isArray(item) ? Object.fromEntries(Object.entries(item).sort(([a], [b]) => a.localeCompare(b))) : item)
const fingerprint = (value: unknown) => createHash("sha256").update(canonical(value)).digest("hex")
const privateSecretFingerprint = async (value: string, domain: string) => createHmac("sha256", "inert-only-key:" + domain).update(value).digest("hex")
const source = await readFile(new URL("./controlled-schema-verification.ts", import.meta.url), "utf8")
const compiled = ts.transpileModule(source.replaceAll("import.meta.url", JSON.stringify(new URL("./controlled-schema-verification.ts", import.meta.url).href)), { compilerOptions: { module: ts.ModuleKind.CommonJS, target: ts.ScriptTarget.ES2022, esModuleInterop: true } }).outputText
/** Actual verifier source, inert module I/O. Synthetic capture/reference here
* checks control flow only; it is not a production reference or SQL acceptance.
* Root's producer→verifier private PG tests exercise genuine schema/data. */
async function fixture() {
const owner = randomUUID(), epoch = 1, digest = manifest.migrationManifestDigest()
const history = await Promise.all(manifest.MIGRATION_MANIFEST.map(async pin => {
const intent = { id: randomUUID(), epoch, kind: "migration" as const, manifestSha256: digest, artifactSha256: pin.sha256 }
const observationSha256 = await privateSecretFingerprint(fingerprint({ format: "controlled-migration-file-ack-v1", intent, file: pin.file, transaction: pin.transaction, selfMarker: pin.selfMarker, fileCommitAck: true, markerAck: true }), "database-controlled-migration-file-ack-v1")
return { id: intent.id, intent, terminal: { intent, outcome: "observed-success" as const, observationSha256 } }
}))
let state: model.DatabaseSchemaControlState = { format: model.DATABASE_SCHEMA_CONTROL_FORMAT, owner, epoch, phase: "TERMINAL", intent: null, terminal: history.at(-1)!.terminal }
const facts = { reference: "valid" as "valid" | "missing" | "invalid" | "different", badTable: "", badSequence: false, badContext: false, badMarkers: false, forgedLedger: false, markerView: false, loseCommit: false }
const events: string[] = [], releases: boolean[] = []
const context = { backend_pid: "42", transaction_started: "2026-10-25 10:00:00+00" }
const schema = { sha256: "a".repeat(64), sections: {
relations: [{ namespace: "public", name: "schema_migrations", kind: "r", persistence: "p", row_security: false, force_row_security: false }],
columns: [{ namespace: "public", relation: "schema_migrations", name: "id", dropped: false, type: "text" }],
sequences: [{ namespace: "public", name: "servers_id_seq", start: "1" }],
} }
const app = {
query: async (query: string, values: unknown[] = []) => {
events.push(query)
if (query === CONTROLLED_MIGRATIONS_SQL.history) {
const rows = structuredClone(history)
if (facts.forgedLedger) rows[0].terminal.observationSha256 = "a".repeat(64)
return { rows }
}
if (query === CONTROLLED_MIGRATIONS_SQL.markers) return { rows: manifest.MIGRATION_MANIFEST.slice(0, facts.badMarkers ? manifest.MIGRATION_MANIFEST.length - 1 : manifest.MIGRATION_MANIFEST.length).map(pin => ({ id: pin.file.slice(0, -4) })) }
if (query === sql.context) return { rows: [{ ...context }] }
if (query.startsWith("SET ") || query.startsWith("RESET ") || query.startsWith("BEGIN ")) return { rows: [] }
if (query.includes("pg_catalog.pg_advisory_lock(")) { assert.deepEqual(Array.from(values), [PARTITION_WRITER_ADVISORY_KEY]); return { rows: [] } }
if (query.includes("pg_catalog.pg_advisory_unlock(")) return { rows: [{ unlocked: true }] }
if (query === "COMMIT") { if (facts.loseCommit) throw Error("lost readonly COMMIT ACK"); return { rows: [], command: "COMMIT" } }
const data = /\/\* controlled-schema-data:(seed|empty|sequence):([a-z_0-9]+) \*\//.exec(query)
assert(data, "Only fixed production data SQL may execute")
if (data[1] === "seed") {
assert(query.includes("LIMIT 2")); assert(query.includes("- $2::text[]"))
const expected = JSON.parse(String(values[0])); if (data[2] === "server_probe_storage_usage") assert.deepEqual(expected, { scope: "global", admissions: 0, reserved_files: 0, reserved_bytes: 0 }); else if (data[2] === "server_poll_storage_usage") assert.deepEqual(expected, { scope: "global", admissions: 0, reserved_rows: 0, reserved_bytes: 0, compacted_admissions: 0, archive_bytes: 0 }); else assert.equal(expected.id, 1)
}
return { rows: [{ ...context, ...(facts.badContext ? { backend_pid: "43" } : {}), valid: data[1] === "sequence" ? !facts.badSequence : data[2] !== facts.badTable }] }
},
release: (destroy: boolean) => { releases.push(destroy) },
}
const modules: Record<string, unknown> = {
"node:url": { fileURLToPath },
"./database-schema-control.js": { acquireDatabaseSchemaControl: async () => {
events.push("acquire control"); state = model.claimDatabaseSchemaOwnership(state, randomUUID())
return { read: async () => ({ state: structuredClone(state) }), close: async () => { events.push("close control") } }
} },
"./database-schema-control-model.js": { ...model, checkDatabaseSchemaControlState: (value: unknown) => model.checkDatabaseSchemaControlState(structuredClone(value)) },
"./controlled-migrations.js": { CONTROLLED_MIGRATIONS_SQL },
"./migration-manifest.js": manifest,
"./controlled-schema-reference.js": { readControlledSchemaReference: async () => { if (facts.reference === "invalid") throw Error("bad artifact signature"); return facts.reference === "missing" ? null : { ...schema, sha256: facts.reference === "different" ? "b".repeat(64) : schema.sha256 } } },
"./migration-schema-inventory.js": {
captureMigrationSchema: async (_client: unknown, options: unknown) => { events.push("capture schema"); assert.deepEqual(JSON.parse(JSON.stringify(options)), { scope: { applicationNamespaces: ["public"], excludedControlNamespaces: ["mmapp_control"] } }); return { ...schema, sections: { ...schema.sections, relations: [{ ...schema.sections.relations[0], kind: facts.markerView ? "v" : "r" }] } } },
compareMigrationSchemas: (expected: typeof schema, observed: typeof schema) => { events.push("compare schema"); if (expected.sha256 !== observed.sha256) throw Error("schema differs") },
},
"../modules/mcp/security.js": { fingerprint, privateSecretFingerprint },
"../services/partition-write-transaction.js": { PARTITION_WRITER_ADVISORY_KEY },
"./index.js": { pool: { connect: async () => app } },
}
const exports = {} as { verifyControlledSchemaCurrentState(): Promise<{ ready: false; schemaAndDataVerified: false; historicalDataEquivalent: false; currentPristineDataInvariants: boolean; referenceStatus: string; gaps: string[]; dataFacts: unknown[]; sequenceFacts: unknown[] }>; CONTROLLED_SCHEMA_VERIFICATION_SQL: typeof import("./controlled-schema-verification.js").CONTROLLED_SCHEMA_VERIFICATION_SQL }
runInNewContext(compiled, { exports, require: (name: string) => { assert(name in modules, "Unapproved import: " + name); return modules[name] }, URL, Promise, Error, Object, Map, Set, Date, structuredClone }, { filename: "controlled-schema-verification.ts" })
const sql = exports.CONTROLLED_SCHEMA_VERIFICATION_SQL
return { exports, facts, events, releases, run: exports.verifyControlledSchemaCurrentState }
}
test("fixed current snapshot authenticates full ledger and checks bounded data after reference equality", async () => {
const f = await fixture(), result = await f.run()
assert.equal(result.referenceStatus, "matched"); assert.equal(result.currentPristineDataInvariants, true)
assert.equal(result.ready, false); assert.equal(result.schemaAndDataVerified, false); assert.equal(result.historicalDataEquivalent, false)
assert.equal(result.dataFacts.length, manifest.CURRENT_REQUIRED_TABLES.length)
assert.equal(f.events.filter(query => query.startsWith("/* controlled-schema-data:seed:")).length, 18)
assert.equal(result.sequenceFacts.length, 1)
assert(f.events.indexOf("compare schema") < f.events.findIndex(query => query.startsWith("/* controlled-schema-data:")))
assert(f.events.indexOf("BEGIN ISOLATION LEVEL REPEATABLE READ READ ONLY") < f.events.indexOf("capture schema"))
assert.deepEqual(f.releases, [false])
})
test("missing, invalid or different reference never reads application data or grants READY", async () => {
for (const status of ["missing", "invalid", "different"] as const) {
const f = await fixture(); f.facts.reference = status
const result = await f.run()
assert.equal(result.referenceStatus, status); assert.equal(result.ready, false); assert.equal(result.currentPristineDataInvariants, false)
assert(!f.events.some(query => query.startsWith("/* controlled-schema-data:")))
assert(result.gaps.includes("TRUSTED_SCHEMA_REFERENCE_" + status.toUpperCase()))
}
})
test("real data predicate failures remain observed failures, never hidden by matching schema", async () => {
for (const table of ["data_migration", "traffic_flow_settings", "servers"]) {
const f = await fixture(); f.facts.badTable = table
const result = await f.run()
assert.equal(result.referenceStatus, "matched"); assert.equal(result.currentPristineDataInvariants, false); assert.equal(result.ready, false)
}
const f = await fixture(); f.facts.badSequence = true
assert.equal((await f.run()).currentPristineDataInvariants, false)
})
test("forged ACK ledger or marker mismatch refuses rather than returning verification", async () => {
for (const field of ["forgedLedger", "badMarkers"] as const) {
const f = await fixture(); f.facts[field] = true
await assert.rejects(f.run()); assert.deepEqual(f.releases, [true])
assert(!f.events.some(query => query.startsWith("/* controlled-schema-data:")))
}
})
test("marker schema drift refuses before reading a forged marker view", async () => {
const f = await fixture(); f.facts.markerView = true
await assert.rejects(f.run()); assert(!f.events.includes(CONTROLLED_MIGRATIONS_SQL.markers))
})
test("snapshot backend changes or lost read-only COMMIT cannot publish accepted evidence", async () => {
for (const field of ["badContext", "loseCommit"] as const) {
const f = await fixture(); f.facts[field] = true
await assert.rejects(f.run()); assert.deepEqual(f.releases, [true])
}
})
test("data SQL permits only known seed tables and bounded lowercase identifiers", async () => {
const f = await fixture()
assert.throws(() => f.exports.CONTROLLED_SCHEMA_VERIFICATION_SQL.seed("servers"))
assert.throws(() => f.exports.CONTROLLED_SCHEMA_VERIFICATION_SQL.seed('mcp_settings"; SELECT 1'))
})
test("only the three0042 seeds validate current UUIDv4 epochs separately without attesting origin", async () => {
const f = await fixture()
for (const table of ["traffic_settings", "uptime_settings", "internet_path_settings"]) {
const query = f.exports.CONTROLLED_SCHEMA_VERIFICATION_SQL.seed(table)
assert(query.includes("t.poll_configuration_epoch IS NOT NULL"))
assert(query.includes("4[0-9a-f]{3}-[89ab]"))
assert(query.includes("to_jsonb(t) - 'poll_configuration_epoch'"))
f.facts.badTable = table; assert.equal((await f.run()).currentPristineDataInvariants, false)
}
assert(!f.exports.CONTROLLED_SCHEMA_VERIFICATION_SQL.seed("servers_api_ping_settings").includes("poll_configuration_epoch"))
f.facts.badTable = ""
const evidence = await f.run()
assert(evidence.gaps.includes("NONDETERMINISTIC_POLL_EPOCH_ORIGIN_UNATTESTED")); assert.equal(evidence.ready, false)
})