418 lines
16 KiB
JavaScript
418 lines
16 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
import {
|
|
buildDevRuntimePostflightReport,
|
|
parseArgs
|
|
} from "./dev-runtime-postflight.mjs";
|
|
|
|
test("check mode is source-only and does not attempt live reads or M3 writes", async () => {
|
|
const report = await buildDevRuntimePostflightReport(parseArgs(["--check"]), {
|
|
m3SourceBuilder: async () => ({
|
|
mode: "source-static",
|
|
summary: {
|
|
status: "pass",
|
|
classification: "source_static_contract_checked",
|
|
trustedGreen: false,
|
|
result: "source checked"
|
|
}
|
|
}),
|
|
now: () => "2026-05-23T00:00:00.000Z"
|
|
});
|
|
|
|
assert.equal(report.conclusion.status, "pass");
|
|
assert.equal(report.actions.healthLiveReadAttempted, false);
|
|
assert.equal(report.actions.v1ReadAttempted, false);
|
|
assert.equal(report.actions.m3MutationAttempted, false);
|
|
assert.equal(report.safety.secretValuesPrinted, false);
|
|
});
|
|
|
|
test("live mode refuses without explicit DEV confirmations", async () => {
|
|
const report = await buildDevRuntimePostflightReport(parseArgs(["--live"]), {
|
|
now: () => "2026-05-23T00:00:00.000Z"
|
|
});
|
|
|
|
assert.equal(report.conclusion.status, "blocked");
|
|
assert.equal(report.safetyRefusal, true);
|
|
assert.equal(report.actions.healthLiveReadAttempted, false);
|
|
assert.equal(report.actions.m3MutationAttempted, false);
|
|
});
|
|
|
|
test("live mode skips M3 writes when /health/live durable runtime is blocked", async () => {
|
|
const report = await buildDevRuntimePostflightReport(
|
|
parseArgs(["--live", "--confirm-dev", "--confirmed-non-production"]),
|
|
{
|
|
httpGetJson: async (url) => ({ ok: true, status: 200, json: apiPayload({ ready: url.endsWith("/v1") }) }),
|
|
m3Runner: async () => {
|
|
throw new Error("M3 runner should not run before durable readiness is green");
|
|
},
|
|
now: () => "2026-05-23T00:00:00.000Z"
|
|
}
|
|
);
|
|
|
|
assert.equal(report.conclusion.status, "blocked");
|
|
assert.equal(report.actions.healthLiveReadAttempted, true);
|
|
assert.equal(report.actions.v1ReadAttempted, true);
|
|
assert.equal(report.actions.m3MutationAttempted, false);
|
|
assert.equal(report.m3.status, "not_run");
|
|
assert.equal(report.blockers.some((blocker) => blocker.scope === "api-health-live"), true);
|
|
assertStructuredBlockers(report.blockers);
|
|
assert.match(report.blockers.find((blocker) => blocker.scope === "api-health-live").reason, /auth_blocked/u);
|
|
assert.equal(JSON.stringify(report).includes("postgresql://"), false);
|
|
});
|
|
|
|
test("live mode requires /v1 durable readiness before M3 writes", async () => {
|
|
const report = await buildDevRuntimePostflightReport(
|
|
parseArgs(["--live", "--confirm-dev", "--confirmed-non-production"]),
|
|
{
|
|
httpGetJson: async (url) => ({ ok: true, status: 200, json: apiPayload({ ready: !url.endsWith("/v1") }) }),
|
|
m3Runner: async () => {
|
|
throw new Error("M3 runner should not run when /v1 is blocked");
|
|
},
|
|
now: () => "2026-05-23T00:00:00.000Z"
|
|
}
|
|
);
|
|
|
|
assert.equal(report.conclusion.status, "blocked");
|
|
assert.equal(report.actions.m3MutationAttempted, false);
|
|
assert.equal(report.blockers.some((blocker) => blocker.scope === "api-v1"), true);
|
|
assertStructuredBlockers(report.blockers);
|
|
});
|
|
|
|
test("live mode requires /v1 to expose the controlled M3 IO route before M3 writes", async () => {
|
|
const report = await buildDevRuntimePostflightReport(
|
|
parseArgs(["--live", "--confirm-dev", "--confirmed-non-production"]),
|
|
{
|
|
httpGetJson: async (url) => {
|
|
const payload = apiPayload({ ready: true });
|
|
if (url.endsWith("/v1")) {
|
|
delete payload.m3IoControl;
|
|
}
|
|
return { ok: true, status: 200, json: payload };
|
|
},
|
|
m3Runner: async () => {
|
|
throw new Error("M3 runner should not run when /v1 omits the M3 IO contract");
|
|
},
|
|
now: () => "2026-05-23T00:00:00.000Z"
|
|
}
|
|
);
|
|
|
|
assert.equal(report.conclusion.status, "blocked");
|
|
assert.equal(report.actions.m3MutationAttempted, false);
|
|
assert.equal(report.blockers.some((blocker) =>
|
|
blocker.scope === "api-v1" &&
|
|
blocker.summary.includes("controlled M3 IO route")
|
|
), true);
|
|
assertStructuredBlockers(report.blockers);
|
|
});
|
|
|
|
test("live mode does not mistake DB live evidence for durable runtime readiness", async () => {
|
|
const report = await buildDevRuntimePostflightReport(
|
|
parseArgs(["--live", "--confirm-dev", "--confirmed-non-production"]),
|
|
{
|
|
httpGetJson: async () => ({ ok: true, status: 200, json: tcpOnlyPayload() }),
|
|
m3Runner: async () => {
|
|
throw new Error("M3 runner should not run when only TCP/SecretRef DB readiness is green");
|
|
},
|
|
now: () => "2026-05-23T00:00:00.000Z"
|
|
}
|
|
);
|
|
|
|
assert.equal(report.conclusion.status, "blocked");
|
|
assert.equal(report.apiHealth.db.connected, true);
|
|
assert.equal(report.apiHealth.db.liveDbEvidence, true);
|
|
assert.equal(report.apiHealth.runtime.durable, false);
|
|
assert.equal(report.apiHealth.readiness.durabilityReady, false);
|
|
assert.equal(report.actions.m3MutationAttempted, false);
|
|
assert.equal(report.blockers.some((blocker) => blocker.scope === "api-health-live"), true);
|
|
assertStructuredBlockers(report.blockers);
|
|
});
|
|
|
|
test("live mode blocks auth, schema, and migration durable readiness before M3 writes", async () => {
|
|
for (const [blocker, queryResult, blockedLayer] of [
|
|
["runtime_durable_adapter_auth_blocked", "auth_blocked", "auth"],
|
|
["runtime_durable_adapter_schema_blocked", "schema_blocked", "schema"],
|
|
["runtime_durable_adapter_migration_blocked", "migration_blocked", "migration"]
|
|
]) {
|
|
const report = await buildDevRuntimePostflightReport(
|
|
parseArgs(["--live", "--confirm-dev", "--confirmed-non-production"]),
|
|
{
|
|
httpGetJson: async () => ({ ok: true, status: 200, json: apiPayload({ ready: false, blocker, queryResult, blockedLayer }) }),
|
|
m3Runner: async () => {
|
|
throw new Error("M3 runner should not run when durable readiness is blocked");
|
|
},
|
|
now: () => "2026-05-23T00:00:00.000Z"
|
|
}
|
|
);
|
|
|
|
assert.equal(report.conclusion.status, "blocked");
|
|
assert.equal(report.actions.m3MutationAttempted, false);
|
|
assert.equal(report.m3.status, "not_run");
|
|
assert.equal(report.apiHealth.runtimeDurableReadiness.classification, blocker);
|
|
assert.equal(report.apiHealth.runtimeDurableReadiness.evidence.queryResult, queryResult);
|
|
assert.equal(report.apiV1.runtimeDurableReadiness.classification, blocker);
|
|
assertStructuredBlockers(report.blockers);
|
|
}
|
|
});
|
|
|
|
test("live mode treats durable_readiness_ready queryResult as ready, not blocked", async () => {
|
|
const report = await buildDevRuntimePostflightReport(
|
|
parseArgs(["--live", "--confirm-dev", "--confirmed-non-production"]),
|
|
{
|
|
httpGetJson: async () => ({ ok: true, status: 200, json: apiPayload({ ready: true, queryResult: "durable_readiness_ready" }) }),
|
|
m3Runner: async () => m3GreenReport(),
|
|
now: () => "2026-05-23T00:00:00.000Z"
|
|
}
|
|
);
|
|
|
|
assert.equal(report.conclusion.status, "pass");
|
|
assert.equal(report.actions.m3MutationAttempted, true);
|
|
assert.equal(report.apiHealth.runtimeDurableReadiness.ready, true);
|
|
assert.equal(report.apiHealth.runtimeDurableReadiness.evidence.queryResult, "durable_readiness_ready");
|
|
assert.equal(report.blockers.length, 0);
|
|
});
|
|
|
|
test("live mode records M3 true/false durable green evidence", async () => {
|
|
const report = await buildDevRuntimePostflightReport(
|
|
parseArgs(["--live", "--confirm-dev", "--confirmed-non-production"]),
|
|
{
|
|
httpGetJson: async () => ({ ok: true, status: 200, json: apiPayload({ ready: true }) }),
|
|
m3Runner: async () => m3GreenReport(),
|
|
now: () => "2026-05-23T00:00:00.000Z"
|
|
}
|
|
);
|
|
|
|
assert.equal(report.conclusion.status, "pass");
|
|
assert.equal(report.actions.m3MutationAttempted, true);
|
|
assert.equal(report.actions.m3MutationAllowed, true);
|
|
assert.equal(report.m3.trustedGreen, true);
|
|
assert.equal(report.m3.operationCount, 4);
|
|
assert.equal(report.m3.persisted, true);
|
|
assert.equal(report.m3.persistenceContract.ready, true);
|
|
assert.deepEqual(report.m3.persistenceContract.sequence.map((item) => [item.id, item.observedValue, item.persisted]), [
|
|
["write-do1-true", true, true],
|
|
["read-di1-true", true, true],
|
|
["write-do1-false", false, true],
|
|
["read-di1-false", false, true]
|
|
]);
|
|
assert.deepEqual(report.m3.operations.map((operation) => operation.resultValue), [true, true, false, false]);
|
|
assert.equal(report.blockers.length, 0);
|
|
});
|
|
|
|
test("live mode accepts 4 DEV-LIVE persisted green operations even when legacy summary says source_contract_failed", async () => {
|
|
const m3 = m3GreenReport();
|
|
m3.summary.status = "blocked";
|
|
m3.summary.classification = "source_contract_failed";
|
|
m3.summary.trustedGreen = false;
|
|
m3.summary.result = "legacy source/static contract failed";
|
|
const report = await buildDevRuntimePostflightReport(
|
|
parseArgs(["--live", "--confirm-dev", "--confirmed-non-production"]),
|
|
{
|
|
httpGetJson: async () => ({ ok: true, status: 200, json: apiPayload({ ready: true }) }),
|
|
m3Runner: async () => m3,
|
|
now: () => "2026-05-23T00:00:00.000Z"
|
|
}
|
|
);
|
|
|
|
assert.equal(report.conclusion.status, "pass");
|
|
assert.equal(report.m3.persisted, true);
|
|
assert.equal(report.m3.persistenceContract.ready, true);
|
|
assert.equal(report.m3.operationCount, 4);
|
|
assert.deepEqual(report.m3.persistenceContract.sequence.map((item) => [
|
|
item.id,
|
|
item.observedValue,
|
|
item.evidenceGreen,
|
|
item.persisted
|
|
]), [
|
|
["write-do1-true", true, true, true],
|
|
["read-di1-true", true, true, true],
|
|
["write-do1-false", false, true, true],
|
|
["read-di1-false", false, true, true]
|
|
]);
|
|
assert.equal(report.blockers.some((blocker) =>
|
|
blocker.scope === "m3-durable-postflight" &&
|
|
blocker.evidence?.classification === "source_contract_failed"
|
|
), false);
|
|
});
|
|
|
|
test("live mode blocks when M3 operation evidence is not durable green", async () => {
|
|
const m3 = m3GreenReport();
|
|
m3.liveOperations[1].evidenceState.durable = false;
|
|
const report = await buildDevRuntimePostflightReport(
|
|
parseArgs(["--live", "--confirm-dev", "--confirmed-non-production"]),
|
|
{
|
|
httpGetJson: async () => ({ ok: true, status: 200, json: apiPayload({ ready: true }) }),
|
|
m3Runner: async () => m3,
|
|
now: () => "2026-05-23T00:00:00.000Z"
|
|
}
|
|
);
|
|
|
|
assert.equal(report.conclusion.status, "blocked");
|
|
assert.equal(report.blockers.some((blocker) => blocker.scope === "m3-durable-postflight"), true);
|
|
assert.equal(report.m3.persistenceContract.ready, false);
|
|
assertStructuredBlockers(report.blockers);
|
|
});
|
|
|
|
test("live mode blocks when M3 true/false persisted sequence is incomplete", async () => {
|
|
const m3 = m3GreenReport();
|
|
m3.liveOperations = m3.liveOperations.slice(0, 3);
|
|
const report = await buildDevRuntimePostflightReport(
|
|
parseArgs(["--live", "--confirm-dev", "--confirmed-non-production"]),
|
|
{
|
|
httpGetJson: async () => ({ ok: true, status: 200, json: apiPayload({ ready: true }) }),
|
|
m3Runner: async () => m3,
|
|
now: () => "2026-05-23T00:00:00.000Z"
|
|
}
|
|
);
|
|
|
|
assert.equal(report.conclusion.status, "blocked");
|
|
assert.equal(report.m3.persistenceContract.ready, false);
|
|
assert.equal(report.m3.persistenceContract.sequence.at(-1).status, "missing");
|
|
assert.equal(report.blockers.some((blocker) => blocker.scope === "m3-durable-postflight"), true);
|
|
assertStructuredBlockers(report.blockers);
|
|
});
|
|
|
|
function assertStructuredBlockers(blockers) {
|
|
assert.ok(blockers.length > 0);
|
|
for (const blocker of blockers) {
|
|
assert.equal(typeof blocker.scope, "string");
|
|
assert.equal(typeof blocker.reason, "string");
|
|
assert.equal(typeof blocker.impact, "string");
|
|
assert.equal(typeof blocker.safeNextAction, "string");
|
|
assert.equal(typeof blocker.retryable, "boolean");
|
|
assert.notEqual(blocker.reason, "");
|
|
assert.notEqual(blocker.impact, "");
|
|
assert.notEqual(blocker.safeNextAction, "");
|
|
}
|
|
}
|
|
|
|
function apiPayload({
|
|
ready,
|
|
blocker = "runtime_durable_adapter_auth_blocked",
|
|
queryResult = ready ? "durable_readiness_ready" : "auth_blocked",
|
|
blockedLayer = "auth"
|
|
}) {
|
|
return {
|
|
serviceId: "hwlab-cloud-api",
|
|
environment: "dev",
|
|
status: ready ? "ready" : "blocked",
|
|
ready,
|
|
db: {
|
|
ready,
|
|
connected: ready,
|
|
liveDbEvidence: ready,
|
|
endpointSource: "secret-url-host",
|
|
connectionResult: ready ? "connected" : "connected",
|
|
runtimeReadiness: {
|
|
ready,
|
|
status: ready ? "ready" : "blocked",
|
|
blocker: ready ? null : blocker,
|
|
queryResult,
|
|
requiredEvidence: "runtime_adapter_schema_migration_read_query"
|
|
}
|
|
},
|
|
runtime: {
|
|
adapter: "postgres",
|
|
durable: ready,
|
|
durableRequested: true,
|
|
ready,
|
|
status: ready ? "ready" : "blocked",
|
|
blocker: ready ? null : blocker,
|
|
liveRuntimeEvidence: ready,
|
|
connection: {
|
|
queryResult
|
|
},
|
|
durabilityContract: {
|
|
requiredEvidence: "runtime_adapter_schema_migration_read_query",
|
|
blockedLayer: ready ? null : blockedLayer
|
|
},
|
|
gates: {
|
|
ssl: gate(true),
|
|
auth: gate(ready || !["auth"].includes(blockedLayer), blockedLayer === "auth" ? blocker : null),
|
|
schema: gate(ready || !["schema"].includes(blockedLayer), blockedLayer === "schema" ? blocker : null),
|
|
migration: gate(ready || !["migration"].includes(blockedLayer), blockedLayer === "migration" ? blocker : null),
|
|
durability: gate(ready, blocker)
|
|
}
|
|
},
|
|
readiness: {
|
|
ready,
|
|
status: ready ? "ready" : "blocked",
|
|
durability: {
|
|
ready,
|
|
status: ready ? "ready" : "blocked",
|
|
blocker: ready ? null : blocker,
|
|
blockedLayer: ready ? null : blockedLayer,
|
|
queryResult
|
|
}
|
|
},
|
|
blockerCodes: ready ? []
|
|
: [blocker],
|
|
m3IoControl: {
|
|
route: "/v1/m3/io",
|
|
status: "available",
|
|
contractVersion: "m3-io-control-v1",
|
|
boundaries: {
|
|
directFrontendGatewayOrBoxAccess: false,
|
|
genericHardwareRpcExposedToFrontend: false
|
|
}
|
|
}
|
|
};
|
|
}
|
|
|
|
function tcpOnlyPayload() {
|
|
const payload = apiPayload({ ready: false });
|
|
payload.db.ready = true;
|
|
payload.db.connected = true;
|
|
payload.db.liveDbEvidence = true;
|
|
payload.db.connectionResult = "connected";
|
|
payload.db.runtimeReadiness.blocker = "runtime_durable_adapter_query_blocked";
|
|
payload.db.runtimeReadiness.queryResult = "query_blocked";
|
|
payload.runtime.blocker = "runtime_durable_adapter_query_blocked";
|
|
payload.runtime.durabilityContract.blockedLayer = "durability_query";
|
|
payload.runtime.gates.auth = gate(true);
|
|
payload.runtime.gates.schema = gate(true);
|
|
payload.runtime.gates.migration = gate(true);
|
|
payload.runtime.gates.durability = gate(false, "runtime_durable_adapter_query_blocked");
|
|
payload.readiness.durability.blockedLayer = "durability_query";
|
|
payload.blockerCodes = ["runtime_durable_adapter_query_blocked"];
|
|
return payload;
|
|
}
|
|
|
|
function gate(ready, blocker = null) {
|
|
return {
|
|
checked: true,
|
|
ready,
|
|
status: ready ? "ready" : "blocked",
|
|
blocker: ready ? null : blocker
|
|
};
|
|
}
|
|
|
|
function m3GreenReport() {
|
|
const values = [true, true, false, false];
|
|
return {
|
|
mode: "dev-live",
|
|
summary: {
|
|
status: "pass",
|
|
classification: "trusted_green",
|
|
trustedGreen: true,
|
|
result: "DEV-LIVE M3 IO control path and durable trusted records are green."
|
|
},
|
|
liveOperations: values.map((value, index) => ({
|
|
id: ["write-do1-true", "read-di1-true", "write-do1-false", "read-di1-false"][index],
|
|
action: index % 2 === 0 ? "do.write" : "di.read",
|
|
status: "succeeded",
|
|
operationId: `op_${index}`,
|
|
traceId: `trc_${index}`,
|
|
auditId: `aud_${index}`,
|
|
evidenceId: `ev_${index}`,
|
|
resultValue: value,
|
|
evidenceState: {
|
|
status: "green",
|
|
durable: true,
|
|
sourceKind: "DEV-LIVE",
|
|
writeStatus: "persisted"
|
|
}
|
|
}))
|
|
};
|
|
}
|