Files
pikasTech-HWLAB/scripts/src/m3-io-control-e2e.mjs
T
2026-05-24 02:43:55 +00:00

984 lines
31 KiB
JavaScript

import { randomUUID } from "node:crypto";
import { mkdir, readFile, writeFile } from "node:fs/promises";
import path from "node:path";
import { fileURLToPath } from "node:url";
import {
M3_IO_CHAIN,
M3_IO_CONTROL_CONTRACT_VERSION,
M3_IO_CONTROL_ROUTE,
describeM3IoControl
} from "../../internal/cloud/m3-io-control.mjs";
export const M3_IO_E2E_CONTRACT_VERSION = "m3-io-control-e2e-v1";
export const defaultFrontendUrl = "http://74.48.78.17:16666/";
export const defaultApiUrl = "http://74.48.78.17:16667/v1/m3/io";
export const controlPathReachablePersistenceBlocked = "control_path_reachable_trusted_persistence_blocked";
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "../..");
const labels = Object.freeze({
source: "SOURCE",
local: "LOCAL",
dryRun: "DRY-RUN",
devLive: "DEV-LIVE",
blocked: "BLOCKED"
});
const forbiddenLiveFlags = Object.freeze([
"--prod",
"--production",
"--real-hardware",
"--read-secret",
"--read-token",
"--deploy",
"--apply",
"--restart",
"--restart-runtime",
"--restart-unidesk",
"--restart-code-queue",
"--restart-backend-core"
]);
const valueFlags = new Set(["--report", "--output", "--url", "--api-url", "--target", "--timeout-ms"]);
const booleanFlags = new Set([
"--live",
"--confirm-dev",
"--confirmed-non-production",
"--expect-non-prod",
"--source",
"--source-static",
"--dry-run",
"--pretty",
...forbiddenLiveFlags
]);
export function parseM3IoControlE2eArgs(argv = []) {
const flags = new Set();
const values = new Map();
for (let index = 0; index < argv.length; index += 1) {
const arg = argv[index];
if (!arg.startsWith("--")) {
throw new Error(`unexpected positional argument: ${arg}`);
}
if (valueFlags.has(arg)) {
const value = argv[index + 1];
if (!value || value.startsWith("--")) {
throw new Error(`${arg} requires a value`);
}
values.set(arg.slice(2), value);
index += 1;
continue;
}
if (!booleanFlags.has(arg)) {
throw new Error(`unknown flag: ${arg}`);
}
flags.add(arg);
}
const target = values.get("target") ?? (values.has("api-url") ? "api" : "frontend");
if (!["frontend", "api"].includes(target)) {
throw new Error("--target must be frontend or api");
}
const timeoutMs = parsePositiveInteger(values.get("timeout-ms"), 8000);
return {
flags,
values,
live: flags.has("--live"),
source: flags.has("--source") || flags.has("--source-static"),
dryRun: flags.has("--dry-run"),
confirmDev: flags.has("--confirm-dev"),
confirmedNonProduction: flags.has("--confirmed-non-production") || flags.has("--expect-non-prod"),
target,
frontendUrl: values.get("url") ?? defaultFrontendUrl,
apiUrl: values.get("api-url") ?? defaultApiUrl,
reportPath: values.get("report") ?? values.get("output") ?? null,
timeoutMs,
pretty: flags.has("--pretty")
};
}
export function requireM3IoControlE2eGates(args) {
for (const flag of forbiddenLiveFlags) {
if (args.flags.has(flag)) {
throw new Error(`${flag} is forbidden for the DEV M3 IO control harness`);
}
}
if (!args.live) {
return {
mode: "source-static",
liveWriteAllowed: false,
mutationAllowed: false
};
}
if (args.dryRun || args.source) {
throw new Error("--live cannot be combined with --dry-run, --source, or --source-static");
}
if (!args.confirmDev || !args.confirmedNonProduction) {
throw new Error("live mode requires --live --confirm-dev --confirmed-non-production");
}
return {
mode: "dev-live",
liveWriteAllowed: true,
mutationAllowed: true
};
}
export function expectedM3IoLiveSequence() {
return [
{
id: "write-do1-true",
method: "POST",
path: M3_IO_CONTROL_ROUTE,
action: "do.write",
expectedValue: true,
mutatesDevState: true,
request: doWriteRequest(true)
},
{
id: "read-di1-true",
method: "POST",
path: M3_IO_CONTROL_ROUTE,
action: "di.read",
expectedValue: true,
mutatesDevState: false,
request: diReadRequest()
},
{
id: "write-do1-false",
method: "POST",
path: M3_IO_CONTROL_ROUTE,
action: "do.write",
expectedValue: false,
mutatesDevState: true,
request: doWriteRequest(false)
},
{
id: "read-di1-false",
method: "POST",
path: M3_IO_CONTROL_ROUTE,
action: "di.read",
expectedValue: false,
mutatesDevState: false,
request: diReadRequest()
}
];
}
export async function buildM3IoControlSourceReport(options = {}) {
const root = options.repoRoot ?? repoRoot;
const checks = await runM3IoControlSourceChecks({ repoRoot: root });
const classification = checks.every((check) => check.status === "pass")
? "source_static_contract_checked"
: "source_contract_failed";
const status = classification === "source_static_contract_checked" ? "pass" : "blocked";
return {
tool: "m3-io-control-e2e",
contractVersion: M3_IO_E2E_CONTRACT_VERSION,
mode: "source-static",
sourceKind: labels.source,
evidenceLabels: evidenceLabelDescriptions(),
liveMutation: {
attempted: false,
allowed: false,
reason: "Default SOURCE/static mode never POSTs to DEV and never mutates simulator state."
},
endpoints: {
frontendSameOriginBase: defaultFrontendUrl,
frontendSameOriginPath: M3_IO_CONTROL_ROUTE,
cloudApiPath: M3_IO_CONTROL_ROUTE,
directCloudApiEndpoint: defaultApiUrl,
gatewayBoxPatchPanelDirectCallsAllowed: false
},
dryRunPlan: {
sourceKind: labels.dryRun,
liveWriteWillRun: false,
sequence: expectedM3IoLiveSequence().map((step) => ({
id: step.id,
method: step.method,
path: step.path,
action: step.action,
expectedValue: step.expectedValue,
mutatesDevState: step.mutatesDevState
}))
},
checks,
summary: {
status,
classification,
trustedGreen: false,
observedAt: isoNow(),
result: status === "pass"
? "SOURCE/static M3 IO control contract passed; DEV-LIVE was not run."
: "SOURCE/static M3 IO control contract failed; DEV-LIVE must not run until fixed."
}
};
}
export async function runM3IoControlSourceChecks({ repoRoot: root = repoRoot } = {}) {
const [serverSource, jsonRpcSource, m3Source, appSource, htmlSource, artifactPublisherSource] = await Promise.all([
readRepoText(root, "internal/cloud/server.mjs"),
readRepoText(root, "internal/cloud/json-rpc.mjs"),
readRepoText(root, "internal/cloud/m3-io-control.mjs"),
readRepoText(root, "web/hwlab-cloud-web/app.mjs"),
readRepoText(root, "web/hwlab-cloud-web/index.html"),
readRepoText(root, "scripts/dev-artifact-publish.mjs")
]);
const contract = describeM3IoControl({
env: {
HWLAB_M3_IO_CONTROL_ENABLED: "true"
}
});
const frontendGuardrails = checkFrontendNoDirectRuntimeCalls({
appSource,
htmlSource,
artifactPublisherSource
});
const requestSchema = validateExpectedRequestSchemas(expectedM3IoLiveSequence());
const responseSchema = validateM3IoSourceResponseContract(m3Source);
return [
checkResult(
"route-name-contract",
contract.route === M3_IO_CONTROL_ROUTE &&
M3_IO_CONTROL_ROUTE === "/v1/m3/io" &&
contract.contractVersion === M3_IO_CONTROL_CONTRACT_VERSION,
"cloud-api route is /v1/m3/io with the m3-io-control-v1 contract.",
{
route: contract.route,
contractVersion: contract.contractVersion,
evidenceLevel: labels.source
}
),
checkResult(
"m3-chain-contract",
routeChainMatches(contract.chain),
"M3 chain is box-simu-1 DO1 -> hwlab-patch-panel -> box-simu-2 DI1.",
{
chain: contract.chain,
evidenceLevel: labels.source
}
),
checkResult(
"cloud-api-rest-route-contract",
serverSource.includes("url.pathname === M3_IO_CONTROL_ROUTE") &&
serverSource.includes("handleM3IoControlHttp") &&
serverSource.includes("m3IoControl: describeM3IoControl"),
"cloud-api exposes GET/POST /v1/m3/io and advertises it from /v1.",
{
route: M3_IO_CONTROL_ROUTE,
evidenceLevel: labels.source
}
),
checkResult(
"cloud-api-json-rpc-method-contract",
jsonRpcSource.includes("M3_IO_RPC_METHODS.doWrite") &&
jsonRpcSource.includes("M3_IO_RPC_METHODS.diRead") &&
jsonRpcSource.includes('handleM3IoRpc("do.write"') &&
jsonRpcSource.includes('handleM3IoRpc("di.read"'),
"cloud-api JSON-RPC exposes M3 do.write and di.read through the same controlled handler.",
{
methods: ["m3.io.do.write", "m3.io.di.read"],
evidenceLevel: labels.source
}
),
checkResult(
"request-schema-contract",
requestSchema.status === "pass",
"Expected DEV live sequence uses only do.write on DO1 and di.read on DI1.",
{
issues: requestSchema.issues,
sequence: requestSchema.sequence,
evidenceLevel: labels.dryRun
}
),
checkResult(
"response-schema-contract",
responseSchema.status === "pass",
"M3 IO responses carry operationId, traceId, auditId, evidenceId, evidenceState, and frontendBypass=false.",
{
issues: responseSchema.issues,
evidenceLevel: labels.source
}
),
checkResult(
"frontend-same-origin-guardrail",
frontendGuardrails.status === "pass",
"Cloud Web only calls same-origin /v1/m3/io for the user control path and has no direct gateway/box/patch-panel fetches.",
{
fetchTargets: frontendGuardrails.fetchTargets,
issues: frontendGuardrails.issues,
evidenceLevel: labels.source
}
)
];
}
export function checkFrontendNoDirectRuntimeCalls({ appSource, htmlSource = "", artifactPublisherSource = "" }) {
const source = `${appSource}\n${htmlSource}`;
const fetchTargets = literalFetchTargets(appSource);
const issues = [];
const allowedSameOriginTargets = new Set([
"/help.md",
"/health/live",
"/v1",
"/v1/diagnostics/gate",
"/v1/live-builds",
"/v1/agent/chat",
"/v1/m3/io",
"/v1/m3/status",
"/json-rpc"
]);
for (const target of fetchTargets) {
if (!target.startsWith("/")) {
issues.push(`frontend fetch target is not same-origin relative: ${target}`);
}
if (target.startsWith("/") && !allowedSameOriginTargets.has(target)) {
issues.push(`frontend fetch target is not in the allowed same-origin set: ${target}`);
}
}
const directRuntimePatterns = [
/\bfetch(?:Json)?\(\s*["'`][^"'`]*(?:gateway-simu|box-simu|patch-panel|:7101|:7201|:7301)/iu,
/\bfetch(?:Json)?\(\s*["'`]https?:\/\//iu,
/https?:\/\/[^"'`\s]*(?:gateway-simu|box-simu|patch-panel|:7101|:7201|:7301)/iu,
/(?:\/invoke|\/sync\/tick)/iu
];
for (const pattern of directRuntimePatterns) {
if (pattern.test(source)) {
issues.push(`frontend source matches forbidden direct runtime pattern: ${pattern.source}`);
}
}
const actionBody = functionBody(appSource, "runM3IoAction");
if (!/fetchJson\("\/v1\/m3\/io"/u.test(actionBody)) {
issues.push("runM3IoAction must POST through same-origin /v1/m3/io");
}
if (/fetchJson\(["'`](?!\/v1\/m3\/(?:io|status))/u.test(actionBody) || /\bfetch\(/u.test(actionBody)) {
issues.push("runM3IoAction must not call any path other than fetchJson(\"/v1/m3/io\") or fetchJson(\"/v1/m3/status\")");
}
if (!/if \(!m3ControlCanOperate\(\)\)/u.test(actionBody)) {
issues.push("runM3IoAction must fail closed before POST when M3 readiness is blocked");
}
const readinessBody = functionBody(appSource, "m3ControlCanOperate");
for (const [pattern, label] of [
[/readiness\?\.status === "ready"/u, "readiness.status=ready"],
[/readiness\?\.controlReady === true/u, "readiness.controlReady=true"],
[/readiness\?\.sourceKind === "DEV-LIVE"/u, "readiness.sourceKind=DEV-LIVE"],
[/readiness\?\.evidenceLevel === "DEV-LIVE"/u, "readiness.evidenceLevel=DEV-LIVE"]
]) {
if (!pattern.test(readinessBody)) {
issues.push(`m3ControlCanOperate must require ${label}`);
}
}
if (!/url\.pathname === "\/v1\/m3\/io"/u.test(artifactPublisherSource)) {
issues.push("cloud-web artifact server must proxy same-origin /v1/m3/io to cloud-api");
}
if (!/\/v1\/m3\/status/u.test(artifactPublisherSource)) {
issues.push("cloud-web artifact server must proxy same-origin /v1/m3/status to cloud-api");
}
return {
status: issues.length === 0 ? "pass" : "fail",
fetchTargets,
issues
};
}
export function validateExpectedRequestSchemas(sequence) {
const issues = [];
for (const step of sequence) {
if (step.path !== M3_IO_CONTROL_ROUTE || step.method !== "POST") {
issues.push(`${step.id} must POST ${M3_IO_CONTROL_ROUTE}`);
}
if (!["do.write", "di.read"].includes(step.request.action)) {
issues.push(`${step.id} action is invalid`);
}
if (step.request.action === "do.write") {
if (
step.request.gatewayId !== M3_IO_CHAIN.sourceGatewayId ||
step.request.resourceId !== M3_IO_CHAIN.sourceResourceId ||
step.request.boxId !== M3_IO_CHAIN.sourceBoxId ||
step.request.port !== M3_IO_CHAIN.sourcePort ||
typeof step.request.value !== "boolean"
) {
issues.push(`${step.id} must write ${M3_IO_CHAIN.sourceResourceId}:${M3_IO_CHAIN.sourcePort} with a boolean value`);
}
}
if (step.request.action === "di.read") {
if (
step.request.gatewayId !== M3_IO_CHAIN.targetGatewayId ||
step.request.resourceId !== M3_IO_CHAIN.targetResourceId ||
step.request.boxId !== M3_IO_CHAIN.targetBoxId ||
step.request.port !== M3_IO_CHAIN.targetPort ||
Object.hasOwn(step.request, "value")
) {
issues.push(`${step.id} must read ${M3_IO_CHAIN.targetResourceId}:${M3_IO_CHAIN.targetPort} without a value`);
}
}
}
return {
status: issues.length === 0 ? "pass" : "fail",
issues,
sequence: sequence.map((step) => ({
id: step.id,
action: step.request.action,
gatewayId: step.request.gatewayId,
resourceId: step.request.resourceId,
boxId: step.request.boxId,
port: step.request.port,
value: Object.hasOwn(step.request, "value") ? step.request.value : undefined
}))
};
}
export function validateM3IoSourceResponseContract(m3Source) {
const requiredPatterns = [
/operationId:\s*input\.operation\.operationId/u,
/traceId:\s*input\.meta\.traceId/u,
/auditId:\s*records\.auditEvent\.auditId/u,
/evidenceId:\s*records\.evidenceRecord\.evidenceId/u,
/gatewaySessionId:\s*target\.gatewaySessionId/u,
/resourceId:\s*target\.resourceId/u,
/port:\s*target\.port/u,
/value:\s*target\.value/u,
/const\s+audit\s*=\s*auditState\(/u,
/const\s+evidence\s*=\s*evidenceState\(/u,
/auditState:\s*audit/u,
/evidenceState:\s*evidence/u,
/durableStatus:\s*durableStatus\(/u,
/blockerClassification:\s*redactedBlockerClassification\(/u,
/persistence:\s*persistenceSummary\(/u,
/describeM3IoControlLive/u,
/buildM3IoReadiness/u,
/controlReady:\s*false/u,
/frontendBypass:\s*false/u,
/patchPanelOnlyPropagation:\s*true/u,
/sourceKind:\s*"DEV-LIVE"/u,
/sourceKind:\s*"BLOCKED"/u
];
const issues = requiredPatterns
.filter((pattern) => !pattern.test(m3Source))
.map((pattern) => `missing response contract pattern: ${pattern.source}`);
return {
status: issues.length === 0 ? "pass" : "fail",
issues
};
}
export function validateM3IoLiveResponse(payload, step) {
const issues = [];
if (!payload || typeof payload !== "object" || Array.isArray(payload)) {
return {
status: "fail",
issues: ["response body must be a JSON object"]
};
}
for (const field of ["status", "accepted", "action", "chain", "controlPath", "traceId", "evidenceState"]) {
if (!Object.hasOwn(payload, field)) {
issues.push(`missing ${field}`);
}
}
for (const field of ["operationId", "auditId", "evidenceId"]) {
if (payload.status === "succeeded" && !stringValue(payload[field])) {
issues.push(`missing ${field} on succeeded response`);
}
}
if (payload.action !== step.action) {
issues.push(`expected action ${step.action}, got ${payload.action}`);
}
if (payload.controlPath?.frontendBypass !== false) {
issues.push("controlPath.frontendBypass must be false");
}
if (payload.controlPath?.cloudApi !== true || payload.controlPath?.gatewaySimu !== true || payload.controlPath?.boxSimu !== true) {
issues.push("controlPath must prove cloudApi, gatewaySimu, and boxSimu were used");
}
if (step.action === "do.write" && payload.controlPath?.patchPanel !== true) {
issues.push("do.write must prove patchPanel=true");
}
if (payload.chain && !routeChainMatches(payload.chain)) {
issues.push("response chain does not match the required M3 DO1->DI1 route");
}
if (payload.status === "succeeded") {
const actualValue = payload.result?.value;
if (actualValue !== step.expectedValue) {
issues.push(`expected result.value ${String(step.expectedValue)}, got ${String(actualValue)}`);
}
}
return {
status: issues.length === 0 ? "pass" : "fail",
issues
};
}
export function classifyM3IoControlReport(report) {
const sourceChecks = report.checks ?? [];
const operations = report.liveOperations ?? [];
if (operations.length === 0) {
if (sourceChecks.some((check) => check.status !== "pass")) {
return {
status: "blocked",
classification: "source_contract_failed",
trustedGreen: false
};
}
return {
status: "pass",
classification: "source_static_contract_checked",
trustedGreen: false
};
}
if (operations.some((operation) => operation.status === "unreachable" || operation.status === "http_error")) {
return {
status: "blocked",
classification: "control_path_unreachable",
trustedGreen: false
};
}
if (operations.some((operation) => operation.status !== "succeeded" || operation.schema?.status === "fail")) {
return {
status: "blocked",
classification: "control_path_blocked",
trustedGreen: false
};
}
const expectedSequence = expectedM3IoLiveSequence();
if (operations.length !== expectedSequence.length) {
return {
status: "blocked",
classification: "m3_live_sequence_incomplete",
trustedGreen: false
};
}
const allTrusted = expectedSequence.every((step, index) => {
const operation = operations[index] ?? {};
return operation.id === step.id &&
operation.action === step.action &&
operation.sourceKind === labels.devLive &&
operation.resultValue === step.expectedValue &&
stringValue(operation.operationId) &&
stringValue(operation.traceId) &&
stringValue(operation.auditId) &&
stringValue(operation.evidenceId) &&
operation.evidenceState?.status === "green" &&
operation.evidenceState?.sourceKind === labels.devLive &&
operation.evidenceState?.durable === true &&
operation.evidenceState?.writeStatus === "persisted";
});
if (!allTrusted) {
return {
status: "blocked",
classification: controlPathReachablePersistenceBlocked,
trustedGreen: false
};
}
return {
status: "pass",
classification: "trusted_green",
trustedGreen: true
};
}
export async function runM3IoControlLiveReport(args, sourceReport) {
const endpoint = resolveM3IoEndpoint(args);
const contractProbe = await requestJson(endpoint.href, {
method: "GET",
timeoutMs: args.timeoutMs
});
const operations = [];
const sourceChecks = sourceReport.checks ?? [];
if (!contractProbe.ok) {
operations.push({
id: "contract-probe",
status: "unreachable",
sourceKind: labels.devLive,
endpoint: endpoint.href,
httpStatus: contractProbe.status,
error: contractProbe.error
});
} else if (contractProbe.body?.route !== M3_IO_CONTROL_ROUTE || !routeChainMatches(contractProbe.body?.chain)) {
operations.push({
id: "contract-probe",
status: "blocked",
sourceKind: labels.devLive,
endpoint: endpoint.href,
httpStatus: contractProbe.status,
error: "live /v1/m3/io contract did not match the source M3 route"
});
} else {
for (const step of expectedM3IoLiveSequence()) {
const operation = await postM3IoLiveStep(endpoint.href, step, args.timeoutMs);
operations.push(operation);
if (operation.status !== "succeeded") {
break;
}
}
}
const report = {
...sourceReport,
mode: "dev-live",
sourceKind: labels.devLive,
liveMutation: {
attempted: true,
allowed: true,
reason: "DEV live mode was explicitly gated by --live --confirm-dev --confirmed-non-production."
},
endpoints: {
...sourceReport.endpoints,
selectedTarget: args.target,
selectedEndpoint: endpoint.href,
selectedEndpointKind: endpoint.kind
},
contractProbe: {
ok: contractProbe.ok,
status: contractProbe.status,
route: contractProbe.body?.route ?? null,
chain: contractProbe.body?.chain ?? null,
error: contractProbe.error ?? null
},
liveOperations: operations,
summary: {
...sourceReport.summary,
observedAt: isoNow()
}
};
report.summary = {
...report.summary,
...classifyM3IoControlReport({ checks: sourceChecks, liveOperations: operations })
};
report.summary.result = resultTextForClassification(report.summary.classification);
return report;
}
export function resolveM3IoEndpoint(args) {
const endpoint = args.target === "api"
? new URL(args.apiUrl)
: new URL(M3_IO_CONTROL_ROUTE, args.frontendUrl);
const port = endpoint.port || (endpoint.protocol === "http:" ? "80" : "443");
const allowed =
endpoint.protocol === "http:" &&
endpoint.hostname === "74.48.78.17" &&
endpoint.pathname === M3_IO_CONTROL_ROUTE &&
((args.target === "frontend" && port === "16666") || (args.target === "api" && port === "16667"));
if (!allowed) {
throw new Error("live endpoint must match target: frontend uses DEV http://74.48.78.17:16666/v1/m3/io; api uses DEV http://74.48.78.17:16667/v1/m3/io");
}
return {
href: endpoint.href,
kind: port === "16666" ? "cloud-web-same-origin" : "cloud-api-direct",
port: Number(port)
};
}
export async function runM3IoControlE2eCli(argv = []) {
const args = parseM3IoControlE2eArgs(argv);
const gates = requireM3IoControlE2eGates(args);
const sourceReport = await buildM3IoControlSourceReport();
const report = gates.mode === "dev-live"
? await runM3IoControlLiveReport(args, sourceReport)
: sourceReport;
if (args.reportPath) {
await writeReport(args.reportPath, report);
}
process.stdout.write(`${JSON.stringify(report, null, args.pretty ? 2 : 0)}\n`);
return report.summary.status === "pass" ? 0 : 1;
}
export function formatM3IoControlE2eFailure(error) {
return {
tool: "m3-io-control-e2e",
contractVersion: M3_IO_E2E_CONTRACT_VERSION,
status: "error",
sourceKind: labels.blocked,
error: {
message: error instanceof Error ? error.message : String(error)
}
};
}
async function postM3IoLiveStep(endpoint, step, timeoutMs) {
const traceId = `trc_m3_io_e2e_${step.id.replaceAll("-", "_")}_${randomUUID()}`;
const requestId = `req_m3_io_e2e_${step.id.replaceAll("-", "_")}_${randomUUID()}`;
const body = {
...step.request,
projectId: M3_IO_CHAIN.projectId,
traceId,
requestId,
actorId: "usr_hwlab_m3_io_e2e"
};
const response = await requestJson(endpoint, {
method: "POST",
body,
timeoutMs,
headers: {
"x-trace-id": traceId,
"x-request-id": requestId,
"x-actor-id": "usr_hwlab_m3_io_e2e"
}
});
if (!response.ok) {
return {
id: step.id,
action: step.action,
status: response.status === 0 ? "unreachable" : "http_error",
sourceKind: labels.devLive,
endpoint,
httpStatus: response.status,
error: response.error,
request: redactLiveRequest(body)
};
}
const schema = validateM3IoLiveResponse(response.body, step);
return {
id: step.id,
action: step.action,
status: response.body?.status === "succeeded" && schema.status === "pass" ? "succeeded" : "blocked",
sourceKind: labels.devLive,
endpoint,
httpStatus: response.status,
request: redactLiveRequest(body),
schema,
operationId: response.body?.operationId ?? null,
traceId: response.body?.traceId ?? traceId,
auditId: response.body?.auditId ?? null,
evidenceId: response.body?.evidenceId ?? null,
evidenceState: response.body?.evidenceState ?? null,
accepted: response.body?.accepted ?? null,
resultValue: response.body?.result?.value,
blocker: response.body?.blocker ?? null,
controlPath: response.body?.controlPath ?? null
};
}
async function requestJson(url, { method = "GET", body, timeoutMs = 8000, headers = {} } = {}) {
const controller = new AbortController();
const timer = setTimeout(() => controller.abort(), timeoutMs);
try {
const response = await fetch(url, {
method,
headers: body === undefined
? {
accept: "application/json",
...headers
}
: {
accept: "application/json",
"content-type": "application/json",
...headers
},
body: body === undefined ? undefined : JSON.stringify(body),
signal: controller.signal
});
const text = await response.text();
let parsed = null;
try {
parsed = text ? JSON.parse(text) : null;
} catch {
parsed = null;
}
return {
ok: response.ok,
status: response.status,
body: parsed,
error: response.ok ? null : parsed?.error?.message ?? parsed?.blocker?.message ?? response.statusText
};
} catch (error) {
return {
ok: false,
status: 0,
body: null,
error: error.name === "AbortError" ? `request timed out after ${timeoutMs}ms` : error.message
};
} finally {
clearTimeout(timer);
}
}
function doWriteRequest(value) {
return {
action: "do.write",
gatewayId: M3_IO_CHAIN.sourceGatewayId,
resourceId: M3_IO_CHAIN.sourceResourceId,
boxId: M3_IO_CHAIN.sourceBoxId,
port: M3_IO_CHAIN.sourcePort,
value
};
}
function diReadRequest() {
return {
action: "di.read",
gatewayId: M3_IO_CHAIN.targetGatewayId,
resourceId: M3_IO_CHAIN.targetResourceId,
boxId: M3_IO_CHAIN.targetBoxId,
port: M3_IO_CHAIN.targetPort
};
}
function routeChainMatches(chain) {
return chain?.sourceGatewayId === M3_IO_CHAIN.sourceGatewayId &&
chain?.sourceResourceId === M3_IO_CHAIN.sourceResourceId &&
chain?.sourceBoxId === M3_IO_CHAIN.sourceBoxId &&
chain?.sourcePort === M3_IO_CHAIN.sourcePort &&
chain?.targetGatewayId === M3_IO_CHAIN.targetGatewayId &&
chain?.targetResourceId === M3_IO_CHAIN.targetResourceId &&
chain?.targetBoxId === M3_IO_CHAIN.targetBoxId &&
chain?.targetPort === M3_IO_CHAIN.targetPort &&
chain?.patchPanelServiceId === M3_IO_CHAIN.patchPanelServiceId;
}
function checkResult(id, ok, summary, details = {}) {
return {
id,
status: ok ? "pass" : "fail",
sourceKind: details.evidenceLevel ?? labels.source,
summary,
...details
};
}
function literalFetchTargets(source) {
return [...source.matchAll(/\b(?:fetch|fetchJson)\(\s*(["'`])([^"'`]+)\1/gu)]
.map((match) => match[2])
.filter((target) => !target.includes("${"));
}
function functionBody(source, functionName) {
const match = source.match(new RegExp(`function\\s+${escapeRegExp(functionName)}\\s*\\([^)]*\\)\\s*\\{`, "u"));
if (!match) return "";
let depth = 0;
for (let index = match.index + match[0].length - 1; index < source.length; index += 1) {
const char = source[index];
if (char === "{") depth += 1;
if (char === "}") {
depth -= 1;
if (depth === 0) return source.slice(match.index, index + 1);
}
}
return "";
}
function resultTextForClassification(classification) {
if (classification === "trusted_green") {
return "DEV-LIVE M3 IO control path and durable trusted records are green.";
}
if (classification === controlPathReachablePersistenceBlocked) {
return "DEV-LIVE control path was reachable, but runtime durable/trusted persistence was blocked; not trusted green.";
}
if (classification === "control_path_blocked") {
return "DEV-LIVE M3 IO control path returned a blocked or schema-invalid operation.";
}
if (classification === "control_path_unreachable") {
return "DEV-LIVE M3 IO control endpoint was unreachable or non-2xx.";
}
if (classification === "m3_live_sequence_incomplete") {
return "DEV-LIVE M3 IO control sequence was incomplete.";
}
if (classification === "source_contract_failed") {
return "SOURCE/static contract failed.";
}
return "SOURCE/static M3 IO control contract passed; DEV-LIVE was not run.";
}
function evidenceLabelDescriptions() {
return [
{
label: labels.source,
meaning: "Checked-in source or static contract; no runtime mutation."
},
{
label: labels.local,
meaning: "Local/in-process fixture evidence only; not a live DEV claim."
},
{
label: labels.dryRun,
meaning: "Planned sequence or schema validation; no live DEV POST."
},
{
label: labels.devLive,
meaning: "Explicitly gated DEV HTTP execution through cloud-web/cloud-api only."
},
{
label: labels.blocked,
meaning: "Cannot promote to trusted green."
}
];
}
function redactLiveRequest(body) {
return {
action: body.action,
gatewayId: body.gatewayId,
resourceId: body.resourceId,
boxId: body.boxId,
port: body.port,
value: Object.hasOwn(body, "value") ? body.value : undefined,
projectId: body.projectId,
traceId: body.traceId,
requestId: body.requestId,
actorId: body.actorId
};
}
function stringValue(value) {
return typeof value === "string" && value.trim().length > 0;
}
function parsePositiveInteger(value, fallback) {
if (value === undefined) return fallback;
const parsed = Number.parseInt(value, 10);
if (!Number.isInteger(parsed) || parsed <= 0) {
throw new Error("numeric value must be a positive integer");
}
return parsed;
}
async function readRepoText(root, relativePath) {
return readFile(path.join(root, relativePath), "utf8");
}
async function writeReport(reportPath, report) {
const absolute = path.resolve(repoRoot, reportPath);
if (!absolute.startsWith(`${repoRoot}${path.sep}`)) {
throw new Error("report path must stay inside the repository");
}
await mkdir(path.dirname(absolute), { recursive: true });
await writeFile(absolute, `${JSON.stringify(report, null, 2)}\n`);
}
function isoNow() {
return new Date().toISOString();
}
function escapeRegExp(value) {
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
}