import assert from "node:assert/strict"; import { readFile } from "node:fs/promises"; import path from "node:path"; import { test } from "bun:test"; import { fileURLToPath } from "node:url"; import { TABLES, assertProtocolRecord, assertProtocolRecords } from "../protocol/index.mjs"; import { CLOUD_CORE_MIGRATIONS, CLOUD_CORE_MIGRATION_ID, CLOUD_RUNTIME_DURABLE_ADAPTER_SCHEMA_VERSION, CLOUD_RUNTIME_DURABLE_MIGRATION_TABLE, CLOUD_RUNTIME_DURABLE_MIGRATION_TABLE_COLUMNS, CLOUD_RUNTIME_DURABLE_TABLE_COLUMNS, FROZEN_CLOUD_CORE_TABLES, assertFrozenCloudCoreTables, requiredRuntimeDurableColumns } from "./schema.ts"; const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../.."); test("cloud core schema keeps the frozen L0 table names", () => { assert.deepEqual(FROZEN_CLOUD_CORE_TABLES, TABLES); assertFrozenCloudCoreTables(); assert.equal(CLOUD_CORE_MIGRATIONS[0].connectsToDatabase, false); }); test("initial migration skeleton declares every frozen table", async () => { const sql = await readFile(path.join(repoRoot, "internal/db/migrations/0001_cloud_core_skeleton.sql"), "utf8"); for (const table of TABLES) { assert.match(sql, new RegExp(`CREATE TABLE IF NOT EXISTS ${table}\\b`), `missing ${table}`); } assert.match(sql, /\brequest_id\b/); assert.match(sql, /\bactor\b/); assert.match(sql, /\bsource\b/); assert.match(sql, /\boperation\b/); assert.match(sql, /\btarget\b/); assert.match(sql, /\bresult\b/); assert.match(sql, /\btimestamp\b/); }); test("initial migration exposes columns required by the durable runtime adapter", async () => { const sql = await readFile(path.join(repoRoot, "internal/db/migrations/0001_cloud_core_skeleton.sql"), "utf8"); assert.ok(requiredRuntimeDurableColumns().length > 0); for (const [table, columns] of Object.entries(CLOUD_RUNTIME_DURABLE_TABLE_COLUMNS)) { const tableMatch = sql.match(new RegExp(`CREATE TABLE IF NOT EXISTS ${table}\\s*\\(([\\s\\S]*?)\\);`, "u")); assert.ok(tableMatch, `missing ${table}`); for (const column of columns) { assert.match(tableMatch[1], new RegExp(`\\b${column}\\b`), `missing ${table}.${column}`); } } const migrationMatch = sql.match( new RegExp(`CREATE TABLE IF NOT EXISTS ${CLOUD_RUNTIME_DURABLE_MIGRATION_TABLE}\\s*\\(([\\s\\S]*?)\\);`, "u") ); assert.ok(migrationMatch, `missing ${CLOUD_RUNTIME_DURABLE_MIGRATION_TABLE}`); for (const column of CLOUD_RUNTIME_DURABLE_MIGRATION_TABLE_COLUMNS) { assert.match(migrationMatch[1], new RegExp(`\\b${column}\\b`), `missing migration ledger column ${column}`); } assert.match(sql, new RegExp(`'${CLOUD_CORE_MIGRATION_ID}'`, "u")); assert.match(sql, new RegExp(`'${CLOUD_RUNTIME_DURABLE_ADAPTER_SCHEMA_VERSION}'`, "u")); assert.equal(CLOUD_CORE_MIGRATIONS[0].runtimeDurableMigrationTable, CLOUD_RUNTIME_DURABLE_MIGRATION_TABLE); }); test("initial migration declares Workbench fact backfill sources", async () => { const sql = await readFile(path.join(repoRoot, "internal/db/migrations/0001_cloud_core_skeleton.sql"), "utf8"); for (const [target, source] of [ ["workbench_sessions", "agent_sessions"], ["workbench_trace_events", "agent_trace_events"], ["workbench_turns", "workbench_projection_state"], ["workbench_projection_checkpoints", "workbench_projection_state"] ]) { assert.match(sql, new RegExp(`INSERT INTO ${target} \\(`, "u"), `missing ${target} backfill`); assert.match(sql, new RegExp(`FROM ${source}\\b`, "u"), `missing ${source} source for ${target}`); } assert.match(sql, /ON CONFLICT \(session_id\) DO NOTHING/u); assert.match(sql, /ON CONFLICT \(trace_id\) DO NOTHING/u); const traceBackfillMatch = sql.match(/INSERT INTO workbench_trace_events \([\s\S]*?ON CONFLICT DO NOTHING;/u); assert.ok(traceBackfillMatch, "missing workbench_trace_events idempotent backfill"); assert.match(traceBackfillMatch[0], /ROW_NUMBER\(\) OVER \(PARTITION BY trace_id ORDER BY occurred_at, id\)/u); assert.match(traceBackfillMatch[0], /durable_projection_seq/u); assert.match(sql, /duplicate_trace_source_events/u); assert.match(sql, /workbench_trace_events:/u); assert.match(sql, /trace_event_projected_seq_conflicts/u); assert.match(sql, /COUNT\(\*\) <> COUNT\(DISTINCT projected_seq\)/u); assert.match(sql, /DROP INDEX IF EXISTS idx_workbench_trace_events_trace_projected_seq/u); assert.match(sql, /CREATE UNIQUE INDEX idx_workbench_trace_events_trace_projected_seq/u); }); test("protocol record guards catch schema drift before runtime writes", () => { assertProtocolRecord("gatewaySession", { gatewaySessionId: "gws_01J00000000000000000000000", projectId: "prj_01J00000000000000000000000", serviceId: "hwlab-gateway", gatewayId: "gtw_01J00000000000000000000000", endpoint: "http://127.0.0.1:7101", status: "connected", environment: "dev", startedAt: "2026-05-21T00:00:00.000Z", lastSeenAt: "2026-05-21T00:00:00.000Z" }); assertProtocolRecords("boxCapability", [ { capabilityId: "cap_01J00000000000000000000000", resourceId: "res_01J00000000000000000000000", projectId: "prj_01J00000000000000000000000", name: "shell.exec", direction: "bidirectional", valueType: "object", mutatesState: true, createdAt: "2026-05-21T00:00:00.000Z", updatedAt: "2026-05-21T00:00:00.000Z" } ]); assert.throws( () => assertProtocolRecord("evidenceRecord", { evidenceId: "evd_01J00000000000000000000000", projectId: "prj_01J00000000000000000000000", operationId: "op_01J00000000000000000000000", kind: "trace", uri: "memory://hwlab/evidence/evd_01J00000000000000000000000", sha256: "0".repeat(64), serviceId: "hwlab-cloud-api", environment: "dev", createdAt: "2026-05-21T00:00:00.000Z", evidenceType: "trace" }), /evidenceRecord.evidenceType is not part of the frozen protocol schema/ ); });