import { constants, accessSync, readFileSync, statSync } from "node:fs"; import { basename, dirname, join } from "node:path"; import { createRequire } from "node:module"; import { resolveRuntimeBindings } from "../backend/src/workspaces/bindings.js"; import { renderRuntimeConfig } from "../backend/src/workspaces/runtime-renderer.js"; const requireFromBackend = createRequire(new URL("../backend/package.json", import.meta.url)); const { parse } = requireFromBackend("yaml") as { parse: (value: string) => any }; const [renderedPath, workspacePath, profile] = process.argv.slice(2); if (!renderedPath || !workspacePath || (profile !== "local" && profile !== "server")) { throw new Error("usage: task13-runtime-fixture-check RENDERED_JSON WORKSPACE_YAML local|server"); } const config = JSON.parse(readFileSync(renderedPath, "utf8")); const workspace = parse(readFileSync(workspacePath, "utf8")); const core = config.services?.core; const frontend = config.services?.frontend; if (!core || !frontend) throw new Error("fixture render must contain core and frontend"); const expected = { THT_WS_TASK13_SMOKE_DWH_TRANSPORT: "postgres_direct", THT_WS_TASK13_SMOKE_DWH_HOST: "dwh.task13.invalid", THT_WS_TASK13_SMOKE_DWH_PORT: "5432", THT_WS_TASK13_SMOKE_DWH_USER: "task13_reader", THT_WS_TASK13_SMOKE_DWH_PASSWORD_FILE: "/run/secrets/thothii.secrets", THT_WS_TASK13_SMOKE_VECTOR_TRANSPORT: "pgvector_direct", THT_WS_TASK13_SMOKE_VECTOR_HOST: "vector.task13.invalid", THT_WS_TASK13_SMOKE_VECTOR_PORT: "5432", THT_WS_TASK13_SMOKE_VECTOR_USER: "task13_vector_reader", THT_WS_TASK13_SMOKE_VECTOR_PASSWORD_FILE: "/run/secrets/thothii.secrets", THT_WS_TASK13_SMOKE_EMBEDDING_BASE_URL: profile === "local" ? `http://${config.name}-llm:9000` : "https://embedding.task13.invalid", }; for (const [name, value] of Object.entries(expected)) { if (core.environment?.[name] !== value) { throw new Error(`core runtime binding ${name} is ${JSON.stringify(core.environment?.[name])}, want ${JSON.stringify(value)}`); } if (Object.hasOwn(frontend.environment || {}, name)) { throw new Error(`runtime binding escaped to frontend: ${name}`); } } const bundle = config.secrets?.thothii_secrets; const bundleSource = bundle?.file; if (typeof bundleSource !== "string" || !statSync(bundleSource).isFile()) { throw new Error("fixture secret bundle source is not a regular file"); } accessSync(bundleSource, constants.R_OK); const coreBundle = (core.secrets || []).filter( (secret: any) => secret.source === "thothii_secrets" && secret.target === "thothii.secrets", ); if (coreBundle.length !== 1) throw new Error("core lacks exactly one runtime secret bundle mount"); if ((frontend.secrets || []).length !== 0) throw new Error("frontend received a runtime secret"); const mounts = core.volumes || []; for (const target of [ "/home/thoth/.pi/agent/auth.json", "/home/thoth/.pi/agent/models.json", "/home/thoth/.pi/agent/settings.json", ]) { const selected = mounts.filter((mount: any) => mount.target === target); if (selected.length !== 1 || selected[0].type !== "bind" || !selected[0].read_only) { throw new Error(`Pi fixture mount is not one read-only bind: ${target}`); } accessSync(selected[0].source, constants.R_OK); if (profile === "server") { const parent = mounts.find((mount: any) => mount.target === "/home/thoth/.pi"); const hidden = join(parent.source, "agent", basename(target)); if (!statSync(hidden).isFile()) throw new Error(`server parent root lacks ${hidden}`); } } const resolverEnvironment = { ...core.environment }; resolverEnvironment.THT_WS_TASK13_SMOKE_DWH_PASSWORD_FILE = bundleSource; resolverEnvironment.THT_WS_TASK13_SMOKE_VECTOR_PASSWORD_FILE = bundleSource; const bindings = resolveRuntimeBindings(workspace, resolverEnvironment, [dirname(bundleSource)]); for (const [role, binding] of Object.entries(bindings)) { if ((binding as any).missing.length !== 0) { throw new Error(`workspace resolver reports missing ${role} bindings: ${(binding as any).missing.join(",")}`); } } const runtime = parse(renderRuntimeConfig(workspace, bindings, { sessions: "/data/sessions", artifacts: "/data/artifacts", indexes: "/data/indexes", })); if (runtime.database.host !== expected.THT_WS_TASK13_SMOKE_DWH_HOST || runtime.database.user !== expected.THT_WS_TASK13_SMOKE_DWH_USER || runtime.database.password_file !== bundleSource) { throw new Error("workspace resolver produced the wrong DWH runtime"); } if (runtime.vector_db.host !== expected.THT_WS_TASK13_SMOKE_VECTOR_HOST || runtime.vector_db.user !== expected.THT_WS_TASK13_SMOKE_VECTOR_USER || runtime.vector_db.password_file !== bundleSource) { throw new Error("workspace resolver produced the wrong vector runtime"); } if (runtime.embeddings.base_url !== expected.THT_WS_TASK13_SMOKE_EMBEDDING_BASE_URL) { throw new Error("workspace resolver produced the wrong embedding runtime"); } const secret = readFileSync(bundleSource, "utf8").trim(); if (JSON.stringify(config).includes(secret) || JSON.stringify(runtime).includes(secret)) { throw new Error("fixture render or resolver output leaked secret content"); }