clusterflux-public/scripts/cli-happy-path-live-smoke.js
Clusterflux release a6b866e279 Public release release-5792a1a4e1cb
Source commit: 5792a1a4e1cb24ff71b1535d4b582ef980880752

Public tree identity: sha256:eea1f740446827ef10e4892923c13f13077c9e03438f2bf53d7f90536fb4cf95
2026-07-17 03:20:45 +02:00

3871 lines
125 KiB
JavaScript

#!/usr/bin/env node
const assert = require("assert");
const cp = require("child_process");
const crypto = require("crypto");
const fs = require("fs");
const https = require("https");
const os = require("os");
const path = require("path");
const { DapClient } = require("./dap-client");
const { agentIdentity, signedAgentWorkflowRequest } = require("./agent-signing");
const { coordinatorWireRequest } = require("./coordinator-wire");
const {
nodeIdentity,
nodeIdentityFromPrivateKey,
signedNodeHeartbeat,
signedNodeRequest,
} = require("./node-signing");
const { configurePodmanTestEnvironment } = require("./podman-test-env");
const repo = path.resolve(__dirname, "..");
configurePodmanTestEnvironment(repo);
if (
!process.env.CLUSTERFLUX_PODMAN_NIX_SHELL &&
cp.spawnSync("podman", ["--version"], { stdio: "ignore" }).status !== 0 &&
cp.spawnSync("nix", ["--version"], { stdio: "ignore" }).status === 0
) {
cp.execFileSync(
"nix",
["shell", "nixpkgs#podman", "--command", "node", __filename],
{
cwd: repo,
env: { ...process.env, CLUSTERFLUX_PODMAN_NIX_SHELL: "1" },
stdio: "inherit",
}
);
process.exit(0);
}
const releaseRoot = path.resolve(
process.env.CLUSTERFLUX_PUBLIC_RELEASE_DIR ||
path.join(repo, "target/public-release")
);
const acceptanceRoot = path.join(repo, "target/acceptance");
const manifestPath = path.join(releaseRoot, "public-release-manifest.json");
const reportPath = path.join(acceptanceRoot, "cli-happy-path-live.json");
const serviceEndpoint = "https://clusterflux.michelpaulissen.com";
const serviceAddr =
process.env.CLUSTERFLUX_PUBLIC_RELEASE_SERVICE_ADDR ||
"clusterflux.michelpaulissen.com:443";
const browserOpenCommand =
process.env.CLUSTERFLUX_PUBLIC_RELEASE_BROWSER_OPEN_COMMAND;
const reuseSessionFile =
process.env.CLUSTERFLUX_CLI_HAPPY_PATH_REUSE_SESSION_FILE;
const enabled = process.env.CLUSTERFLUX_CLI_HAPPY_PATH_LIVE === "1";
const strictFullRelease = process.env.CLUSTERFLUX_STRICT_FULL_RELEASE === "1";
const strictVpsRestart = process.env.CLUSTERFLUX_STRICT_VPS_RESTART === "1";
const strictVpsHost = process.env.CLUSTERFLUX_STRICT_VPS_HOST;
const strictVpsIdentity = process.env.CLUSTERFLUX_STRICT_VPS_IDENTITY;
const strictServiceUnit =
process.env.CLUSTERFLUX_STRICT_SERVICE_UNIT ||
"clusterflux-hosted.service";
const strictSoakSeconds = Number(
process.env.CLUSTERFLUX_STRICT_SOAK_SECONDS || "300"
);
const commands = [];
function requireEnabled() {
if (!enabled) {
throw new Error(
"CLUSTERFLUX_CLI_HAPPY_PATH_LIVE=1 is required because this runs the live CLI happy path"
);
}
if (!browserOpenCommand && !reuseSessionFile) {
throw new Error(
"CLUSTERFLUX_PUBLIC_RELEASE_BROWSER_OPEN_COMMAND or CLUSTERFLUX_CLI_HAPPY_PATH_REUSE_SESSION_FILE is required"
);
}
if (
strictFullRelease &&
!process.env.CLUSTERFLUX_SECOND_TENANT_SESSION_FILE
) {
throw new Error(
"CLUSTERFLUX_STRICT_FULL_RELEASE=1 requires CLUSTERFLUX_SECOND_TENANT_SESSION_FILE for live isolation and quota independence"
);
}
if (strictFullRelease && !process.env.CLUSTERFLUX_EXPIRED_USER_SESSION_FILE) {
throw new Error(
"CLUSTERFLUX_STRICT_FULL_RELEASE=1 requires CLUSTERFLUX_EXPIRED_USER_SESSION_FILE"
);
}
if (strictFullRelease && !strictVpsRestart) {
throw new Error(
"CLUSTERFLUX_STRICT_FULL_RELEASE=1 requires CLUSTERFLUX_STRICT_VPS_RESTART=1"
);
}
if (strictVpsRestart && (!strictVpsHost || !strictVpsIdentity)) {
throw new Error(
"strict VPS restart requires CLUSTERFLUX_STRICT_VPS_HOST and CLUSTERFLUX_STRICT_VPS_IDENTITY"
);
}
if (
!Number.isInteger(strictSoakSeconds) ||
strictSoakSeconds < 120 ||
strictSoakSeconds > 1800
) {
throw new Error("CLUSTERFLUX_STRICT_SOAK_SECONDS must be an integer from 120 to 1800");
}
}
function readJson(file) {
return JSON.parse(fs.readFileSync(file, "utf8"));
}
function ensureDir(dir) {
fs.mkdirSync(dir, { recursive: true });
}
function sha256(bytes) {
return `sha256:${crypto.createHash("sha256").update(bytes).digest("hex")}`;
}
function nonInteractiveGitEnv(extra = {}) {
return {
...process.env,
GIT_TERMINAL_PROMPT: "0",
GIT_ASKPASS: process.env.GIT_ASKPASS || "/bin/false",
SSH_ASKPASS: process.env.SSH_ASKPASS || "/bin/false",
GIT_SSH_COMMAND:
process.env.GIT_SSH_COMMAND ||
"ssh -o BatchMode=yes -o NumberOfPasswordPrompts=0",
...extra,
};
}
function commandEnv(command, env) {
if (command !== "git") return env;
return nonInteractiveGitEnv(env);
}
function recordCommand(command, args) {
const redacted = [];
let hideNext = false;
for (const argument of args) {
if (hideNext) {
redacted.push("<redacted>");
hideNext = false;
} else {
redacted.push(argument);
hideNext = ["--enrollment-grant", "--admin-token"].includes(argument);
}
}
commands.push([command, ...redacted].join(" "));
}
function run(command, args, options = {}) {
recordCommand(command, args);
return cp.execFileSync(command, args, {
cwd: repo,
encoding: "utf8",
stdio: ["ignore", "pipe", "pipe"],
timeout: 15 * 60 * 1000,
...options,
env: commandEnv(command, options.env),
});
}
function parseJsonOutput(output) {
const trimmed = output.trim();
if (!trimmed) throw new Error("expected JSON output, got empty stdout");
try {
return JSON.parse(trimmed);
} catch (_) {
// Commands may print progress before their final JSON report.
}
const lines = trimmed.split(/\r?\n/).filter(Boolean);
for (let index = lines.length - 1; index >= 0; index -= 1) {
try {
return JSON.parse(lines.slice(index).join("\n"));
} catch (_) {
// Keep scanning for the trailing JSON value.
}
}
throw new Error(`could not parse JSON output:\n${trimmed}`);
}
function runJson(command, args, options = {}) {
return parseJsonOutput(run(command, args, options));
}
function authenticatedRequest(sessionSecret, request) {
return {
type: "authenticated",
session_secret: sessionSecret,
request,
};
}
function sendHostedControl(payload) {
const body = Buffer.from(
JSON.stringify(coordinatorWireRequest(payload, "strict-live"))
);
const url = new URL("/api/v1/control", serviceEndpoint);
return new Promise((resolve, reject) => {
const request = https.request(
url,
{
method: "POST",
headers: {
"content-type": "application/json",
"content-length": body.length,
},
timeout: 30_000,
},
(response) => {
const chunks = [];
response.on("data", (chunk) => chunks.push(chunk));
response.on("end", () => {
const responseBody = Buffer.concat(chunks).toString("utf8");
if (response.statusCode < 200 || response.statusCode >= 300) {
reject(
new Error(
`hosted control HTTP ${response.statusCode}: ${responseBody}`
)
);
return;
}
try {
resolve(JSON.parse(responseBody));
} catch (error) {
reject(
new Error(`hosted control returned invalid JSON: ${error.message}`)
);
}
});
}
);
request.on("timeout", () =>
request.destroy(new Error("hosted control request timed out"))
);
request.on("error", reject);
request.end(body);
});
}
function sendHostedControlDroppingResponse(payload) {
const body = Buffer.from(
JSON.stringify(coordinatorWireRequest(payload, "strict-live-dropped-response"))
);
const url = new URL("/api/v1/control", serviceEndpoint);
return new Promise((resolve, reject) => {
let settled = false;
const request = https.request(
url,
{
method: "POST",
headers: {
"content-type": "application/json",
"content-length": body.length,
},
timeout: 30_000,
},
(response) => {
settled = true;
const statusCode = response.statusCode;
response.destroy();
resolve({ status_code: statusCode, response_body_consumed: false });
}
);
request.on("timeout", () =>
request.destroy(new Error("hosted dropped-response request timed out"))
);
request.on("error", (error) => {
if (!settled) reject(error);
});
request.end(body);
});
}
function sendHostedLoginStatus(extraHeaders = {}) {
const body = Buffer.from(
JSON.stringify(
coordinatorWireRequest(
{ type: "begin_oidc_browser_login" },
`strict-live-login-${Date.now()}-${Math.random()}`
)
)
);
const url = new URL("/api/v1/login", serviceEndpoint);
return new Promise((resolve, reject) => {
const request = https.request(
url,
{
method: "POST",
headers: {
"content-type": "application/json",
"content-length": body.length,
...extraHeaders,
},
timeout: 30_000,
},
(response) => {
const chunks = [];
response.on("data", (chunk) => chunks.push(chunk));
response.on("end", () =>
resolve({
status_code: response.statusCode,
body: Buffer.concat(chunks).toString("utf8"),
})
);
}
);
request.on("timeout", () =>
request.destroy(new Error("hosted login request timed out"))
);
request.on("error", reject);
request.end(body);
});
}
async function runHostedLoginIsolationBeforeRestart() {
const scenarioStartedAt = Date.now();
const controlBefore = await sendHostedControl({ type: "ping" });
assert.strictEqual(controlBefore.type, "pong");
const statuses = [];
let limited;
for (let index = 0; index < 128; index += 1) {
const response = await sendHostedLoginStatus();
statuses.push(response.status_code);
if (response.status_code === 429) {
limited = response;
break;
}
assert.strictEqual(response.status_code, 200, response.body);
}
assert(limited, `hosted login route was not rate limited: ${statuses.join(",")}`);
const spoofed = await sendHostedLoginStatus({
forwarded: "for=203.0.113.99",
"x-forwarded-for": "203.0.113.99",
"x-real-ip": "203.0.113.99",
});
assert.strictEqual(
spoofed.status_code,
429,
"caller-supplied forwarding headers bypassed the client rate limit"
);
const remoteBody = JSON.stringify(
coordinatorWireRequest(
{ type: "begin_oidc_browser_login" },
`strict-vps-login-${Date.now()}`
)
);
const remoteStatus = Number(
run(
"ssh",
sshArgs(
"curl",
"--silent",
"--show-error",
"--output",
"/dev/null",
"--write-out=%{http_code}",
"-HContent-Type:application/json",
`--data-binary=${remoteBody}`,
`${serviceEndpoint}/api/v1/login`
)
).trim()
);
assert.strictEqual(
remoteStatus,
200,
"one client exhausted the browser-login allowance for a different client"
);
const controlAfter = await sendHostedControl({ type: "ping" });
assert.strictEqual(controlAfter.type, "pong");
return {
scenario_started_at_ms: scenarioStartedAt,
local_statuses: statuses,
local_limited_status: limited.status_code,
forwarding_spoof_status: spoofed.status_code,
independent_vps_client_status: remoteStatus,
control_route_before: controlBefore.type,
control_route_after: controlAfter.type,
};
}
async function finishHostedLoginIsolationAfterRestart(evidence) {
const control = await sendHostedControl({ type: "ping" });
assert.strictEqual(control.type, "pong");
const response = await sendHostedLoginStatus();
assert(
[200, 429].includes(response.status_code),
`login route did not recover after service restart: ${response.status_code} ${response.body}`
);
evidence.after_service_restart = {
control_route: control.type,
login_route_status: response.status_code,
};
evidence.duration_ms = Date.now() - evidence.scenario_started_at_ms;
delete evidence.scenario_started_at_ms;
return evidence;
}
function assertDenied(response, pattern, label) {
assert.strictEqual(response.type, "error", `${label}: ${JSON.stringify(response)}`);
assert.match(response.message, pattern, `${label}: ${JSON.stringify(response)}`);
return {
denied: true,
category: response.error?.category || null,
message: response.message,
};
}
function readNodeCredential(projectDir, node) {
const directory = path.join(projectDir, ".clusterflux", "nodes");
for (const file of fs.readdirSync(directory)) {
if (!file.endsWith(".json")) continue;
const absolute = path.join(directory, file);
const credential = readJson(absolute);
if (credential.node === node) return { absolute, credential };
}
throw new Error(`persisted credential for ${node} was not found`);
}
function directoryStats(root) {
if (!fs.existsSync(root)) return { files: 0, bytes: 0 };
let files = 0;
let bytes = 0;
const visit = (directory) => {
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
const absolute = path.join(directory, entry.name);
if (entry.isDirectory()) visit(absolute);
else if (entry.isFile()) {
files += 1;
bytes += fs.statSync(absolute).size;
}
}
};
visit(root);
return { files, bytes };
}
function shellQuote(argument) {
return `'${String(argument).replaceAll("'", "'\"'\"'")}'`;
}
function sshArgs(...remoteArgs) {
assert(strictVpsHost && strictVpsIdentity);
return [
"-i",
path.resolve(strictVpsIdentity.replace(/^~(?=\/)/, os.homedir())),
"-o",
"BatchMode=yes",
strictVpsHost,
remoteArgs.map(shellQuote).join(" "),
];
}
function strictInfrastructureSample(projectDir) {
const memory = Object.fromEntries(
run(
"ssh",
sshArgs(
"systemctl",
"show",
strictServiceUnit,
"--property=MemoryCurrent",
"--property=MemoryPeak"
)
)
.trim()
.split(/\r?\n/)
.map((line) => line.split("="))
);
const serviceDisk = Number(
run(
"ssh",
sshArgs("du", "-sb", "/var/lib/clusterflux-public-release")
)
.trim()
.split(/\s+/)[0]
);
const database = run(
"ssh",
sshArgs(
"runuser",
"-u",
"postgres",
"--",
"psql",
"-d",
"clusterflux",
"-AtF,"
),
{
input:
"SELECT pg_database_size('clusterflux'), (SELECT count(*) FROM clusterflux_tenants), (SELECT count(*) FROM clusterflux_projects), (SELECT count(*) FROM clusterflux_node_identities), (SELECT count(*) FROM clusterflux_cli_sessions);\n",
stdio: ["pipe", "pipe", "pipe"],
}
)
.trim()
.split(",")
.map(Number);
assert(Number.isFinite(Number(memory.MemoryCurrent)));
assert(Number.isFinite(Number(memory.MemoryPeak)));
assert.strictEqual(database.length, 5);
return {
sampled_at_epoch_ms: Date.now(),
service_memory_current_bytes: Number(memory.MemoryCurrent),
service_memory_peak_bytes: Number(memory.MemoryPeak),
service_state_disk_bytes: serviceDisk,
postgres_database_bytes: database[0],
durable_rows: {
tenants: database[1],
projects: database[2],
node_identities: database[3],
cli_sessions: database[4],
},
local_node_state: directoryStats(path.join(projectDir, ".clusterflux")),
};
}
function executable(root, name) {
return path.join(root, "bin", process.platform === "win32" ? `${name}.exe` : name);
}
function binaryArchive(manifest) {
const platform = `${os.platform()}-${os.arch()}`;
const asset = manifest.assets.find(
(candidate) =>
candidate.name.startsWith("clusterflux-public-binaries-") &&
candidate.name.includes(platform)
);
assert(asset, `missing released binary archive for ${platform}`);
assert(fs.existsSync(asset.file), `missing released binary archive ${asset.file}`);
return asset.file;
}
function publicRepoUrl(manifest) {
const url =
process.env.CLUSTERFLUX_PUBLIC_REPO_URL ||
process.env.CLUSTERFLUX_PUBLIC_REPO_REMOTE ||
manifest.public_repo_url ||
manifest.public_repo_remote;
assert(url, "public repository URL is required");
assert(url.includes("git.michelpaulissen.com"));
return url;
}
function stagePublicCheckout(manifest, checkout) {
const candidateTree = process.env.CLUSTERFLUX_LIVE_PUBLIC_TREE;
if (candidateTree) {
const source = path.resolve(candidateTree);
assert.strictEqual(
source,
path.resolve(manifest.public_tree),
"explicit live candidate tree must be the tree recorded by the release manifest"
);
fs.cpSync(source, checkout, { recursive: true });
return {
kind: "local_filtered_release_candidate",
path: source,
published: false,
};
}
run("git", ["clone", "--depth", "1", publicRepoUrl(manifest), checkout]);
return {
kind: "published_forgejo_checkout",
url: publicRepoUrl(manifest),
published: true,
};
}
function delay(milliseconds) {
return new Promise((resolve) => setTimeout(resolve, milliseconds));
}
async function waitForCli(label, action, predicate, timeoutMs = 10 * 60 * 1000) {
const deadline = Date.now() + timeoutMs;
let lastValue;
let lastError;
while (Date.now() < deadline) {
try {
lastValue = action();
if (predicate(lastValue)) return lastValue;
lastError = undefined;
} catch (error) {
lastError = error;
}
await delay(250);
}
throw new Error(
`${label} timed out; last value=${JSON.stringify(lastValue)}${
lastError ? `; last error=${lastError.message}` : ""
}`
);
}
function spawnJsonLines(command, args, options) {
recordCommand(command, args);
const child = cp.spawn(command, args, {
...options,
stdio: ["ignore", "pipe", "pipe"],
});
let stdout = "";
let stderr = "";
const values = [];
const waiters = [];
function deliver(value) {
values.push(value);
for (let index = waiters.length - 1; index >= 0; index -= 1) {
const waiter = waiters[index];
if (waiter.predicate(value)) {
waiters.splice(index, 1);
clearTimeout(waiter.timer);
waiter.resolve(value);
}
}
}
child.stdout.on("data", (chunk) => {
stdout += chunk.toString();
while (stdout.includes("\n")) {
const newline = stdout.indexOf("\n");
const line = stdout.slice(0, newline).trim();
stdout = stdout.slice(newline + 1);
if (!line) continue;
try {
deliver(JSON.parse(line));
} catch (_) {
// Non-JSON progress stays out of the evidence report.
}
}
});
child.stderr.on("data", (chunk) => {
stderr += chunk.toString();
});
function waitFor(predicate, label, timeoutMs = 120000) {
const existing = values.find(predicate);
if (existing) return Promise.resolve(existing);
return new Promise((resolve, reject) => {
const waiter = { predicate, resolve, reject, timer: undefined };
waiter.timer = setTimeout(() => {
const index = waiters.indexOf(waiter);
if (index >= 0) waiters.splice(index, 1);
reject(new Error(`${label} timed out\n${stderr}`));
}, timeoutMs);
waiters.push(waiter);
});
}
child.once("exit", (code) => {
for (const waiter of waiters.splice(0)) {
clearTimeout(waiter.timer);
waiter.reject(new Error(`${waiter.label || "child"} exited with ${code}\n${stderr}`));
}
});
return { child, values, waitFor, stderr: () => stderr };
}
async function stopChild(child) {
if (!child || child.exitCode !== null) return;
child.kill("SIGTERM");
const exited = new Promise((resolve) => child.once("exit", resolve));
const forced = delay(5000).then(() => {
if (child.exitCode === null) child.kill("SIGKILL");
});
await Promise.race([exited, forced]);
if (child.exitCode === null) await exited;
}
function rawTaskEvents(report) {
return report?.events?.response?.events || [];
}
function nodeDescriptor(status, node) {
return status?.response?.descriptors?.find(
(descriptor) => descriptor.id === node || descriptor.node === node
);
}
function completedFlagship(events) {
const completedDefinitions = new Set(
events
.filter((event) => event.terminal_state === "completed")
.map((event) => event.task_definition)
);
return (
completedDefinitions.has("prepare_source") &&
completedDefinitions.has("compile_linux") &&
completedDefinitions.has("package_release") &&
events.some(
(event) =>
event.executor === "coordinator_main" && event.terminal_state === "completed"
)
);
}
function contentAddressedArtifactId(event, logicalName) {
const digest = event?.artifact_digest;
if (typeof digest !== "string" || !/^sha256:[0-9a-f]{64}$/.test(digest)) {
return null;
}
const artifactId = `${logicalName}-${digest.slice("sha256:".length)}`;
return event.artifact_path?.endsWith(`/vfs/artifacts/${artifactId}`)
? artifactId
: null;
}
async function prepareLiveNodeCredentialSecurity({
clusterflux,
projectDir,
scope,
tenant,
project,
suffix,
}) {
const node = `security-node-${suffix}`;
const grant = runJson(clusterflux, ["node", "enroll", ...scope], {
cwd: projectDir,
});
const attach = runJson(
clusterflux,
[
"node",
"attach",
"--coordinator",
serviceEndpoint,
"--tenant",
tenant,
"--project-id",
project,
"--node",
node,
"--enrollment-grant",
grant.enrollment_grant.grant,
"--json",
],
{ cwd: projectDir }
);
assert.strictEqual(attach.boundary.used_enrollment_exchange, true);
const stored = readNodeCredential(projectDir, node);
const identity = nodeIdentityFromPrivateKey(stored.credential.private_key);
assert.strictEqual(identity.publicKey, stored.credential.public_key);
const heartbeat = {
type: "node_heartbeat",
node,
node_signature: signedNodeHeartbeat(node, identity, {
nonce: `strict-valid-${suffix}`,
}),
};
const valid = await sendHostedControl(heartbeat);
assert.strictEqual(valid.type, "node_heartbeat");
const replay = assertDenied(
await sendHostedControl(heartbeat),
/nonce.*already.*used|replay/i,
"replayed node credential"
);
const expired = assertDenied(
await sendHostedControl({
type: "node_heartbeat",
node,
node_signature: signedNodeHeartbeat(node, identity, {
nonce: `strict-expired-${suffix}`,
issuedAtEpochSeconds: Math.floor(Date.now() / 1000) - 3600,
}),
}),
/expired|clock skew/i,
"expired node credential"
);
const forgedIdentity = nodeIdentity("strict-forged-node", node);
const forged = assertDenied(
await sendHostedControl({
type: "node_heartbeat",
node,
node_signature: signedNodeHeartbeat(node, forgedIdentity, {
nonce: `strict-forged-${suffix}`,
}),
}),
/signature|public key/i,
"forged node credential"
);
const originalCapabilityBody = {
type: "report_node_capabilities",
tenant,
project,
node,
capabilities: {
os: "Linux",
arch: process.arch === "x64" ? "x86_64" : process.arch,
capabilities: [],
environment_backends: [],
source_providers: [],
},
cached_environment_digests: [],
dependency_cache_digests: [],
source_snapshots: [],
artifact_locations: [],
direct_connectivity: false,
online: true,
};
const modifiedEnvelope = signedNodeRequest(
node,
identity,
"report_node_capabilities",
originalCapabilityBody,
{ nonce: `strict-modified-${suffix}` }
);
modifiedEnvelope.request.online = false;
const bodyModified = assertDenied(
await sendHostedControl(modifiedEnvelope),
/signature/i,
"body-modified node credential"
);
return {
node,
identity,
credential_path: stored.absolute,
credential_digest: sha256(fs.readFileSync(stored.absolute)),
capability_body: originalCapabilityBody,
evidence: {
valid_request: valid.type,
replay,
expired,
forged,
body_modified: bodyModified,
},
};
}
async function runLiveAgentCredentialSecurity({
clusterfluxDap,
clusterflux,
projectDir,
scope,
sessionSecret,
tenant,
project,
suffix,
bundle,
securityNode,
workerRuntime,
}) {
const agent = `security-agent-${suffix}`;
const identity = agentIdentity("strict-live-agent", agent);
const added = runJson(
clusterflux,
["key", "add", ...scope, "--agent", agent, "--public-key", identity.publicKey],
{ cwd: projectDir }
);
assert.strictEqual(added.command, "key add");
const processId = `vp-agent-security-${suffix}`;
const unsigned = {
type: "start_process",
tenant,
project,
actor_agent: agent,
process: processId,
restart: false,
};
const validRequest = signedAgentWorkflowRequest(identity, unsigned, {
nonce: `strict-agent-valid-${suffix}`,
});
const valid = await sendHostedControl(validRequest);
assert.strictEqual(valid.type, "process_started", JSON.stringify(valid));
const replay = assertDenied(
await sendHostedControl(validRequest),
/nonce.*already.*used|replay/i,
"replayed agent credential"
);
const expired = assertDenied(
await sendHostedControl(
signedAgentWorkflowRequest(
identity,
{ ...unsigned, process: `${processId}-expired` },
{
nonce: `strict-agent-expired-${suffix}`,
issuedAtEpochSeconds: Math.floor(Date.now() / 1000) - 3600,
}
)
),
/expired|clock skew/i,
"expired agent credential"
);
const modifiedRequest = signedAgentWorkflowRequest(
identity,
{ ...unsigned, process: `${processId}-modified` },
{ nonce: `strict-agent-modified-${suffix}` }
);
modifiedRequest.restart = true;
const bodyModified = assertDenied(
await sendHostedControl(modifiedRequest),
/signature/i,
"body-modified agent credential"
);
const forgedIdentity = agentIdentity("strict-live-forged-agent", agent);
const forged = assertDenied(
await sendHostedControl(
signedAgentWorkflowRequest(
forgedIdentity,
{ ...unsigned, process: `${processId}-forged` },
{
nonce: `strict-agent-forged-${suffix}`,
publicKeyFingerprint: identity.publicKeyFingerprint,
}
)
),
/signature|public key/i,
"forged agent credential"
);
const fakeEnvironmentDigest = sha256(
Buffer.from(`strict-debug-missing-participant-${suffix}`)
);
const fakeCapabilityBody = {
...securityNode.capability_body,
cached_environment_digests: [fakeEnvironmentDigest],
online: true,
};
const mainTask = `ti:${processId}:main`;
const fakeTask = `missing-debug-participant-${suffix}`;
const mainLaunchBody = {
type: "launch_task",
tenant,
project,
actor_agent: agent,
task_spec: {
tenant,
project,
process: processId,
task_definition: bundle.entryStableId,
task_instance: mainTask,
dispatch: {
kind: "coordinator_node_wasm",
export: bundle.entryExport,
abi: "entrypoint_v1",
},
environment_id: null,
environment: null,
environment_digest: null,
required_capabilities: [],
dependency_cache: null,
source_snapshot: null,
required_artifacts: [],
args: [],
vfs_epoch: valid.epoch,
bundle_digest: bundle.digest,
},
wait_for_node: true,
artifact_path: `/vfs/artifacts/${mainTask}-output.txt`,
wasm_module_base64: bundle.moduleBase64,
};
let mainLaunch;
let directTaskV1;
let fakeLaunch;
let liveParentTask;
let liveParentAssignment;
let realDebugLaunch;
const realDebugTask = `real-debug-participant-${suffix}`;
let workerPaused = false;
const baselineContainers = new Set(
run("podman", ["ps", "-q"])
.trim()
.split(/\s+/)
.filter(Boolean)
);
try {
mainLaunch = await sendHostedControl(
signedAgentWorkflowRequest(identity, mainLaunchBody, {
nonce: `strict-agent-main-${suffix}`,
})
);
assert.strictEqual(mainLaunch.type, "main_launched", JSON.stringify(mainLaunch));
assert.strictEqual(mainLaunch.task_instance, mainTask);
assert.strictEqual(mainLaunch.state, "running");
assert.strictEqual(mainLaunch.actor.kind, "agent");
assert.strictEqual(mainLaunch.actor.authenticated_without_browser, true);
liveParentAssignment = await workerRuntime.worker.waitFor(
(value) =>
value.node_status === "assignment_started" &&
value.node === workerRuntime.node &&
value.process === processId &&
value.task_assignment_response?.task_spec?.dispatch?.abi === "task_v1",
"agent main to dispatch a live child to the real worker",
120000
);
liveParentTask = liveParentAssignment.virtual_thread;
assert.strictEqual(typeof liveParentTask, "string");
assert.notStrictEqual(liveParentTask, "");
assert.strictEqual(
workerRuntime.child.kill("SIGSTOP"),
true,
"failed to pause the real worker after observing its live child"
);
workerPaused = true;
const fakeCapabilities = await sendHostedControl(
signedNodeRequest(
securityNode.node,
securityNode.identity,
"report_node_capabilities",
fakeCapabilityBody,
{ nonce: `strict-agent-fake-capabilities-${suffix}` }
)
);
assert.strictEqual(
fakeCapabilities.type,
"node_capabilities_recorded",
JSON.stringify(fakeCapabilities)
);
const fakeTaskSpec = {
tenant,
project,
process: processId,
task_definition: "task_add_one",
task_instance: fakeTask,
dispatch: {
kind: "coordinator_node_wasm",
export: null,
abi: "task_v1",
},
environment_id: "strict-debug-missing-participant",
environment: null,
environment_digest: fakeEnvironmentDigest,
required_capabilities: [],
dependency_cache: null,
source_snapshot: null,
required_artifacts: [],
args: [{ SmallJson: 41 }],
vfs_epoch: valid.epoch,
bundle_digest: bundle.digest,
};
directTaskV1 = assertDenied(
await sendHostedControl(
signedAgentWorkflowRequest(
identity,
{
type: "launch_task",
tenant,
project,
actor_agent: agent,
task_spec: fakeTaskSpec,
wait_for_node: false,
artifact_path: `/vfs/artifacts/${fakeTask}.txt`,
wasm_module_base64: bundle.moduleBase64,
},
{ nonce: `strict-agent-direct-task-v1-${suffix}` }
)
),
/external callers.*EntrypointV1|TaskV1 requires an authenticated live parent/i,
"external direct TaskV1 launch"
);
const liveParentSpec =
liveParentAssignment.task_assignment_response.task_spec;
realDebugLaunch = await sendHostedControl(
signedNodeRequest(
workerRuntime.node,
workerRuntime.identity,
"launch_child_task",
{
type: "launch_child_task",
tenant,
project,
process: processId,
node: workerRuntime.node,
parent_task: liveParentTask,
task_spec: {
tenant,
project,
process: processId,
task_definition: "abort_probe",
task_instance: realDebugTask,
dispatch: {
kind: "coordinator_node_wasm",
export: null,
abi: "task_v1",
},
environment_id: liveParentSpec.environment_id,
environment: liveParentSpec.environment,
environment_digest: liveParentSpec.environment_digest,
required_capabilities: ["Command"],
dependency_cache: null,
source_snapshot: liveParentSpec.source_snapshot,
required_artifacts: [],
args: [],
vfs_epoch: valid.epoch,
bundle_digest: bundle.digest,
},
wait_for_node: false,
artifact_path: `/vfs/artifacts/${realDebugTask}.txt`,
wasm_module_base64: bundle.moduleBase64,
},
{ nonce: `strict-real-debug-participant-${suffix}` }
)
);
assert.strictEqual(
realDebugLaunch.type,
"task_launched",
JSON.stringify(realDebugLaunch)
);
const fakeLaunchBody = {
type: "launch_child_task",
tenant,
project,
process: processId,
node: workerRuntime.node,
parent_task: liveParentTask,
task_spec: fakeTaskSpec,
wait_for_node: false,
artifact_path: `/vfs/artifacts/${fakeTask}.txt`,
wasm_module_base64: bundle.moduleBase64,
};
fakeLaunch = await sendHostedControl(
signedNodeRequest(
workerRuntime.node,
workerRuntime.identity,
"launch_child_task",
fakeLaunchBody,
{ nonce: `strict-parent-runtime-fake-task-${suffix}` }
)
);
assert.strictEqual(fakeLaunch.type, "task_launched", JSON.stringify(fakeLaunch));
assert.strictEqual(fakeLaunch.placement.node, securityNode.node);
} finally {
if (workerPaused) {
assert.strictEqual(
workerRuntime.child.kill("SIGCONT"),
true,
"failed to resume the real worker after authenticated child launch"
);
}
}
await workerRuntime.worker.waitFor(
(value) =>
value.node_status === "assignment_started" &&
value.virtual_thread === realDebugTask,
"real Podman debug participant to start",
120_000
);
const debugClient = new DapClient({
cwd: projectDir,
command: clusterfluxDap,
args: [],
env: { ...process.env },
});
const initialize = debugClient.send("initialize", {
adapterID: "clusterflux",
linesStartAt1: true,
columnsStartAt1: true,
});
await debugClient.response(initialize, "initialize");
const attachRequest = debugClient.send("attach", {
entry: "build",
project: projectDir,
processId,
runtimeBackend: "live-services",
coordinatorEndpoint: serviceEndpoint,
});
await debugClient.response(attachRequest, "attach");
await debugClient.waitFor(
(message) => message.type === "event" && message.event === "initialized"
);
const configurationDone = debugClient.send("configurationDone");
await debugClient.response(configurationDone, "configurationDone");
const attachDeadline = Date.now() + 120_000;
let attachedThreads = [];
while (Date.now() < attachDeadline) {
const threadsRequest = debugClient.send("threads");
attachedThreads = (
await debugClient.response(threadsRequest, "threads")
).body.threads;
if (attachedThreads.length > 0) break;
await delay(100);
}
assert(attachedThreads.length > 0, "DAP attach reported no live threads");
const freezeStartedAt = Date.now();
const pauseRequest = debugClient.send("pause", {
threadId: attachedThreads[0].id,
});
await debugClient.response(pauseRequest, "pause");
const dapPartialStop = await debugClient.waitFor(
(message) =>
message.type === "event" &&
message.event === "stopped" &&
message.body.reason === "pause",
30_000
);
assert.strictEqual(dapPartialStop.body.allThreadsStopped, false);
const epochRequest = debugClient.send("evaluate", {
expression: "debug_epoch",
context: "watch",
});
const freeze = {
epoch: Number(
(await debugClient.response(epochRequest, "evaluate")).body.result
),
};
assert(Number.isSafeInteger(freeze.epoch) && freeze.epoch > 0);
const partialFreeze = await sendHostedControl(
authenticatedRequest(sessionSecret, {
type: "inspect_debug_epoch",
process: processId,
epoch: freeze.epoch,
})
);
assert.strictEqual(partialFreeze.type, "debug_epoch_status");
assert.strictEqual(partialFreeze.partially_frozen, true, JSON.stringify(partialFreeze));
assert.strictEqual(partialFreeze.fully_frozen, false);
assert.strictEqual(partialFreeze.failed, true);
assert.match(
partialFreeze.failure_messages.join("; "),
/did not acknowledge frozen state within \d+ ms/
);
const podmanStates = runJson("podman", ["ps", "--all", "--format", "json"]);
const pausedContainers = podmanStates.filter((container) => {
const id = container.Id || container.ID || container.IdHex || "";
const state = String(container.State || container.Status || "").toLowerCase();
return !baselineContainers.has(id) && state.includes("paused");
});
assert(
pausedContainers.length > 0,
`partial Debug Epoch did not pause a real Podman container: ${JSON.stringify(
podmanStates
)}`
);
const pausedContainerIds = pausedContainers.map(
(container) => container.Id || container.ID || container.IdHex
);
const mismatchedDigest = sha256(Buffer.from(`strict-nested-mismatch-${suffix}`));
const mismatchedChild = await sendHostedControl(
signedNodeRequest(
securityNode.node,
securityNode.identity,
"launch_child_task",
{
type: "launch_child_task",
tenant,
project,
process: processId,
node: securityNode.node,
parent_task: fakeTask,
task_spec: {
tenant,
project,
process: processId,
task_definition: "task_add_one",
task_instance: `${fakeTask}:child:mismatched-environment`,
dispatch: {
kind: "coordinator_node_wasm",
export: null,
abi: "task_v1",
},
environment_id: "strict-nested-mismatch",
environment: null,
environment_digest: mismatchedDigest,
required_capabilities: [],
dependency_cache: null,
source_snapshot: null,
required_artifacts: [],
args: [{ SmallJson: 41 }],
vfs_epoch: valid.epoch,
bundle_digest: bundle.digest,
},
wait_for_node: false,
artifact_path: `/vfs/artifacts/${fakeTask}-mismatched-child.txt`,
wasm_module_base64: bundle.moduleBase64,
},
{ nonce: `strict-nested-mismatch-${suffix}` }
)
);
const nestedEnvironmentMismatch = assertDenied(
mismatchedChild,
/environment|digest|compatible|placement|no node/i,
"nested environment mismatch"
);
const continueStartedAt = Date.now();
const continueRequest = debugClient.send("continue", {
threadId: dapPartialStop.body.threadId,
});
await debugClient.response(continueRequest, "continue");
const continueResponseMs = Date.now() - continueStartedAt;
assert(
continueResponseMs < 2_000,
`partial-freeze continue blocked for ${continueResponseMs} ms`
);
await delay(1000);
const resumed = await sendHostedControl(
authenticatedRequest(sessionSecret, {
type: "inspect_debug_epoch",
process: processId,
epoch: freeze.epoch,
})
);
assert.strictEqual(resumed.type, "debug_epoch_status");
const resumedAcknowledgements = resumed.acknowledgements.filter(
(acknowledgement) => acknowledgement.state === "running"
);
assert(resumedAcknowledgements.length > 0, JSON.stringify(resumed));
const resumedPodmanStates = runJson("podman", ["ps", "--format", "json"]);
assert(
!resumedPodmanStates.some((container) => {
const id = container.Id || container.ID || container.IdHex || "";
const state = String(container.State || container.Status || "").toLowerCase();
return pausedContainerIds.includes(id) && state.includes("paused");
}),
`DAP continue left a Clusterflux container paused: ${JSON.stringify(
resumedPodmanStates
)}`
);
await debugClient.close();
const completed = await waitForCli(
"agent-authenticated coordinator main and child workflow completion",
() =>
runJson(clusterflux, ["task", "list", ...scope, "--process", processId], {
cwd: projectDir,
}),
(tasks) => completedFlagship(rawTaskEvents(tasks)),
120000
);
const completedEvents = rawTaskEvents(completed);
const concurrentCompileTasks = [
...new Set(
completedEvents
.filter(
(event) =>
event.task_definition === "compile_linux" &&
event.terminal_state === "completed"
)
.map((event) => event.task)
),
];
assert(concurrentCompileTasks.length >= 2, JSON.stringify(completedEvents));
const revoked = runJson(
clusterflux,
["key", "revoke", ...scope, "--agent", agent, "--yes"],
{ cwd: projectDir }
);
assert.strictEqual(revoked.command, "key revoke");
const revokedUse = assertDenied(
await sendHostedControl(
signedAgentWorkflowRequest(
identity,
{ ...unsigned, process: `${processId}-revoked` },
{ nonce: `strict-agent-revoked-${suffix}` }
)
),
/revoked/i,
"revoked agent credential"
);
return {
agent,
valid_request: valid.type,
replay,
expired,
forged,
body_modified: bodyModified,
revoked: revokedUse,
workflow: {
process: processId,
main_launch: mainLaunch.type,
external_direct_task_v1: directTaskV1,
child_launch: fakeLaunch.type,
child_parent: liveParentTask,
real_debug_child_launch: realDebugLaunch.type,
real_debug_child: realDebugTask,
actor_kind: mainLaunch.actor.kind,
authenticated_without_browser: mainLaunch.actor.authenticated_without_browser,
flagship_completed: completedFlagship(completedEvents),
concurrent_compile_tasks: concurrentCompileTasks,
},
partial_freeze: {
epoch: freeze.epoch,
elapsed_ms: Date.now() - freezeStartedAt,
partially_frozen: partialFreeze.partially_frozen,
fully_frozen: partialFreeze.fully_frozen,
dap_all_threads_stopped: dapPartialStop.body.allThreadsStopped,
dap_continue_response_ms: continueResponseMs,
podman_paused_container_ids: pausedContainerIds,
warning: partialFreeze.failure_messages,
resumed_participants: resumedAcknowledgements.map(
(acknowledgement) => acknowledgement.task
),
},
nested_environment_mismatch: nestedEnvironmentMismatch,
};
}
async function runSecondTenantIsolation({
firstTenant,
firstProject,
firstProcess,
firstNode,
firstArtifact,
manifest,
}) {
const file = process.env.CLUSTERFLUX_SECOND_TENANT_SESSION_FILE;
const evidenceFile = process.env.CLUSTERFLUX_SECOND_TENANT_EVIDENCE_FILE;
if (!file && evidenceFile) {
const evidenceBytes = fs.readFileSync(path.resolve(evidenceFile));
const previous = JSON.parse(evidenceBytes);
const isolation = previous.tenant_isolation;
assert.strictEqual(isolation?.executed, true);
assert.notStrictEqual(isolation.second_tenant, firstTenant);
assert.strictEqual(isolation.project?.denied, true);
assert.strictEqual(isolation.process_hidden, true);
assert.strictEqual(isolation.node_hidden, true);
assert.strictEqual(isolation.tasks_and_logs?.denied, true);
assert.strictEqual(isolation.debug?.denied, true);
assert.strictEqual(isolation.debug?.audited, true);
assert.strictEqual(isolation.debug?.charged_debug_read_bytes, 0);
assert.strictEqual(isolation.artifact_and_download?.denied, true);
assert.strictEqual(isolation.process_control?.denied, true);
const previousDeployment = previous.release_binding?.deployment;
const currentDeployment = deploymentProvenance();
assert.strictEqual(
previousDeployment?.hosted_service_sha256,
currentDeployment.hosted_service_sha256,
"reused isolation evidence must target the exact deployed hosted binary"
);
assert.deepStrictEqual(
previous.release_binding?.binary_digests,
manifest.binary_digests,
"reused isolation evidence must target the exact public binaries"
);
return {
...isolation,
reused_from_immutable_evidence: {
report_sha256: sha256(evidenceBytes),
source_commit: previous.source_commit,
hosted_service_sha256: currentDeployment.hosted_service_sha256,
public_binary_digests: manifest.binary_digests,
},
};
}
if (!file) return { executed: false, reason: "second tenant session not supplied" };
const second = readJson(path.resolve(file));
assert.strictEqual(second.coordinator, serviceEndpoint);
assert(second.session_secret, "second tenant session omitted its session secret");
assert.notStrictEqual(
second.tenant,
firstTenant,
"isolation proof requires a genuinely distinct hosted tenant"
);
const call = (request) =>
sendHostedControl(authenticatedRequest(second.session_secret, request));
const project = assertDenied(
await call({ type: "select_project", project: firstProject }),
/outside|not visible|tenant|project/i,
"cross-tenant project selection"
);
const processes = await call({ type: "list_processes" });
assert.strictEqual(
processes.type,
"process_statuses",
JSON.stringify(processes)
);
assert(!JSON.stringify(processes).includes(firstProcess));
const nodes = await call({ type: "list_node_descriptors" });
assert.strictEqual(nodes.type, "node_descriptors", JSON.stringify(nodes));
assert(!JSON.stringify(nodes).includes(firstNode));
const tasksAndLogs = assertDenied(
await call({ type: "list_task_events", process: firstProcess }),
/outside|scope|tenant|project|not active|requires an active|unknown/i,
"cross-tenant task and log listing"
);
const debugResponse = await call({
type: "debug_attach",
process: firstProcess,
});
assert.strictEqual(debugResponse.type, "debug_attach", JSON.stringify(debugResponse));
assert.strictEqual(debugResponse.authorization?.allowed, false);
assert.strictEqual(debugResponse.audit_event?.allowed, false);
assert.match(
debugResponse.authorization?.reason || "",
/outside|scope|permission|tenant|project|not active|unknown/i
);
assert.strictEqual(debugResponse.charged_debug_read_bytes, 0);
const debug = {
denied: true,
reason: debugResponse.authorization.reason,
audited: true,
charged_debug_read_bytes: debugResponse.charged_debug_read_bytes,
};
const artifact = assertDenied(
await call({
type: "create_artifact_download_link",
artifact: firstArtifact,
max_bytes: 1024,
ttl_seconds: 60,
}),
/outside|scope|tenant|project|not found|unavailable/i,
"cross-tenant artifact download"
);
const control = assertDenied(
await call({ type: "abort_process", process: firstProcess }),
/outside|scope|tenant|project|not active|requires an active|unknown/i,
"cross-tenant process control"
);
return {
executed: true,
second_tenant: second.tenant,
project,
process_hidden: true,
node_hidden: true,
tasks_and_logs: tasksAndLogs,
debug,
artifact_and_download: artifact,
process_control: control,
};
}
async function runLiveSoak({
clusterflux,
projectDir,
scope,
securityNode,
}) {
if (!strictVpsRestart) {
return { executed: false, reason: "strict VPS measurement access not supplied" };
}
const runReport = runJson(
clusterflux,
["run", "build", "--project", ".", "--json"],
{ cwd: projectDir }
);
assert.strictEqual(runReport.status, "main_launched");
const processId = runReport.process;
const parked = await waitForCli(
"soak coordinator main to park without a capable node",
() =>
runJson(
clusterflux,
["process", "status", ...scope, "--process", processId],
{ cwd: projectDir }
),
(status) =>
status.live_process?.main_state === "running" &&
status.live_process?.main_wait_state === "waiting_for_task" &&
status.current_task_count === 0 &&
status.live_process?.connected_nodes?.length === 0,
120000
);
const pollSecurityNode = (nonce) =>
sendHostedControl(
signedNodeRequest(
securityNode.node,
securityNode.identity,
"poll_task_assignment",
{
type: "poll_task_assignment",
tenant: securityNode.capability_body.tenant,
project: securityNode.capability_body.project,
node: securityNode.node,
},
{ nonce }
)
);
const drainedPriorAssignments = [];
for (let drainIndex = 0; drainIndex < 16; drainIndex += 1) {
const poll = await pollSecurityNode(
`strict-soak-drain-${drainIndex}-${Date.now()}`
);
assert.strictEqual(poll.type, "task_assignment", JSON.stringify(poll));
if (poll.assignment === null) break;
assert.notStrictEqual(
poll.assignment.process,
processId,
"soak process unexpectedly received a task assignment"
);
drainedPriorAssignments.push({
process: poll.assignment.process,
task: poll.assignment.task,
});
assert(drainIndex < 15, "pre-soak assignment drain did not quiesce");
}
const startedAt = Date.now();
const deadline = startedAt + strictSoakSeconds * 1000;
const samples = [];
let sampleIndex = 0;
while (true) {
const capabilities = await sendHostedControl(
signedNodeRequest(
securityNode.node,
securityNode.identity,
"report_node_capabilities",
securityNode.capability_body,
{ nonce: `strict-soak-capabilities-${sampleIndex}-${Date.now()}` }
)
);
assert.strictEqual(
capabilities.type,
"node_capabilities_recorded",
JSON.stringify(capabilities)
);
const poll = await pollSecurityNode(
`strict-soak-poll-${sampleIndex}-${Date.now()}`
);
assert.strictEqual(poll.type, "task_assignment", JSON.stringify(poll));
assert.strictEqual(poll.assignment, null);
const status = runJson(
clusterflux,
["process", "status", ...scope, "--process", processId],
{ cwd: projectDir }
);
assert.strictEqual(status.live_process.main_wait_state, "waiting_for_task");
samples.push(strictInfrastructureSample(projectDir));
sampleIndex += 1;
if (Date.now() >= deadline) break;
await delay(Math.min(30_000, deadline - Date.now()));
}
const currentMemory = samples.map(
(sample) => sample.service_memory_current_bytes
);
const serviceDisk = samples.map((sample) => sample.service_state_disk_bytes);
const databaseDisk = samples.map((sample) => sample.postgres_database_bytes);
const localDisk = samples.map((sample) => sample.local_node_state.bytes);
const spread = (values) => Math.max(...values) - Math.min(...values);
assert(spread(currentMemory) <= 128 * 1024 * 1024);
assert(spread(serviceDisk) <= 16 * 1024 * 1024);
assert(spread(databaseDisk) <= 32 * 1024 * 1024);
assert(spread(localDisk) <= 16 * 1024 * 1024);
assert.deepStrictEqual(
samples.at(-1).durable_rows,
samples[0].durable_rows,
"durable object counts grew during the parked-process soak"
);
const aborted = runJson(
clusterflux,
["process", "abort", ...scope, "--process", processId, "--yes"],
{ cwd: projectDir }
);
assert.strictEqual(aborted.abort_request.process_slot_released, true);
return {
executed: true,
process: processId,
duration_seconds: Math.floor((Date.now() - startedAt) / 1000),
sample_interval_seconds: 30,
sample_count: samples.length,
parked_main: {
main_state: parked.live_process.main_state,
main_wait_state: parked.live_process.main_wait_state,
},
drained_prior_assignments: drainedPriorAssignments,
signed_node_poll_cycles: samples.length,
memory_spread_bytes: spread(currentMemory),
service_disk_spread_bytes: spread(serviceDisk),
postgres_disk_spread_bytes: spread(databaseDisk),
local_node_state_spread_bytes: spread(localDisk),
samples,
};
}
async function revokeSecurityNode({
clusterflux,
projectDir,
scope,
securityNode,
}) {
const revoked = runJson(
clusterflux,
["node", "revoke", ...scope, "--node", securityNode.node, "--yes"],
{ cwd: projectDir }
);
assert.strictEqual(revoked.command, "node revoke");
const denied = assertDenied(
await sendHostedControl({
type: "node_heartbeat",
node: securityNode.node,
node_signature: signedNodeHeartbeat(
securityNode.node,
securityNode.identity,
{ nonce: `strict-node-revoked-${Date.now()}` }
),
}),
/revoked|unknown node|not recognized|not enrolled/i,
"revoked node credential"
);
return { node: securityNode.node, denied };
}
async function runLiveQuotaPreallocation({ sessionSecret, suffix }) {
const readSpawnQuota = async () => {
const status = await sendHostedControl(
authenticatedRequest(sessionSecret, { type: "quota_status" })
);
assert.strictEqual(status.type, "quota_status", JSON.stringify(status));
const limit = status.limits?.limits?.Spawn;
const usage = status.usage?.Spawn;
const windowSeconds = status.window_seconds?.Spawn;
const windowStarted = status.window_started_epoch_seconds?.Spawn;
assert(Number.isInteger(limit) && limit > 0, JSON.stringify(status));
assert(Number.isInteger(usage) && usage >= 0, JSON.stringify(status));
assert(
Number.isInteger(windowSeconds) && windowSeconds > 0,
JSON.stringify(status)
);
assert(Number.isInteger(windowStarted), JSON.stringify(status));
return { limit, usage, windowSeconds, windowStarted };
};
let spawnQuota = await readSpawnQuota();
const windowElapsed = Math.max(
0,
Math.floor(Date.now() / 1000) - spawnQuota.windowStarted
);
if (spawnQuota.usage > 0 || windowElapsed > 1) {
await delay(
Math.max(1000, (spawnQuota.windowSeconds - windowElapsed + 1) * 1000)
);
spawnQuota = await readSpawnQuota();
}
let denial;
let deniedProcess;
let acceptedStarts = 0;
const maxAttempts = spawnQuota.limit - spawnQuota.usage + 2;
for (let index = 0; index < maxAttempts; index += 1) {
const processId = `vp-quota-${suffix}-${index}`;
const started = await sendHostedControl(
authenticatedRequest(sessionSecret, {
type: "start_process",
process: processId,
restart: false,
})
);
if (started.type === "error") {
assert.match(started.message, /quota|spawn|limit|community tier/i);
denial = started;
deniedProcess = processId;
break;
}
assert.strictEqual(started.type, "process_started", JSON.stringify(started));
acceptedStarts += 1;
const aborted = await sendHostedControl(
authenticatedRequest(sessionSecret, {
type: "abort_process",
process: processId,
})
);
assert.strictEqual(aborted.type, "process_aborted", JSON.stringify(aborted));
}
assert(
denial,
`live community-tier spawn quota was not reached in ${maxAttempts} attempts`
);
const processes = await sendHostedControl(
authenticatedRequest(sessionSecret, { type: "list_processes" })
);
assert.strictEqual(
processes.type,
"process_statuses",
JSON.stringify(processes)
);
assert(
!JSON.stringify(processes).includes(deniedProcess),
"quota-denied process was allocated before denial"
);
const second = readJson(
path.resolve(process.env.CLUSTERFLUX_SECOND_TENANT_SESSION_FILE)
);
assert.notStrictEqual(second.session_secret, sessionSecret);
const unrelatedProcess = `vp-unrelated-quota-${suffix}`;
const unrelatedStarted = await sendHostedControl(
authenticatedRequest(second.session_secret, {
type: "start_process",
process: unrelatedProcess,
restart: false,
})
);
assert.strictEqual(
unrelatedStarted.type,
"process_started",
`first tenant quota exhaustion affected another tenant: ${JSON.stringify(unrelatedStarted)}`
);
const unrelatedAborted = await sendHostedControl(
authenticatedRequest(second.session_secret, {
type: "abort_process",
process: unrelatedProcess,
})
);
assert.strictEqual(
unrelatedAborted.type,
"process_aborted",
JSON.stringify(unrelatedAborted)
);
return {
limit: spawnQuota.limit,
initial_usage: spawnQuota.usage,
window_seconds: spawnQuota.windowSeconds,
accepted_starts_before_denial: acceptedStarts,
denied_process: deniedProcess,
denial: {
type: denial.type,
category: denial.error?.category || null,
message: denial.message,
},
denied_process_allocated: false,
unrelated_tenant: {
tenant: second.tenant,
process: unrelatedProcess,
start: unrelatedStarted.type,
abort: unrelatedAborted.type,
unaffected_by_first_tenant_quota: true,
},
};
}
async function runLongJoinProof({ clusterflux, projectDir, scope }) {
const startedAt = Date.now();
const runReport = runJson(
clusterflux,
["run", "long-join", "--project", ".", "--json"],
{ cwd: projectDir }
);
assert.strictEqual(runReport.status, "main_launched");
const terminal = await waitForCli(
"controlled task longer than two minutes",
() =>
runJson(
clusterflux,
["task", "list", ...scope, "--process", runReport.process],
{ cwd: projectDir }
),
(tasks) =>
rawTaskEvents(tasks).some(
(event) =>
event.task_definition === "long_join_probe" &&
event.terminal_state === "completed"
),
5 * 60 * 1000
);
const completed = rawTaskEvents(terminal).find(
(event) =>
event.task_definition === "long_join_probe" &&
event.terminal_state === "completed"
);
const durationSeconds = Math.floor((Date.now() - startedAt) / 1000);
assert(durationSeconds > 120);
const released = await waitForCli(
"long join process automatic slot release",
() =>
runJson(
clusterflux,
["process", "status", ...scope, "--process", runReport.process],
{ cwd: projectDir }
),
(status) => status.state === "not_active",
120000
);
return {
process: runReport.process,
task: completed.task,
terminal_state: completed.terminal_state,
result: completed.result,
duration_seconds: durationSeconds,
process_state: released.state,
};
}
async function runRepeatedParkWakeProof({ clusterflux, projectDir, scope }) {
const runReport = runJson(
clusterflux,
["run", "park-wake", "--project", ".", "--json"],
{ cwd: projectDir }
);
assert.strictEqual(runReport.status, "main_launched");
const terminal = await waitForCli(
"repeated coordinator-main park/wake completion",
() =>
runJson(
clusterflux,
["task", "list", ...scope, "--process", runReport.process],
{ cwd: projectDir }
),
(tasks) => {
const completed = new Set(
rawTaskEvents(tasks)
.filter(
(event) =>
event.task_definition === "task_add_one" &&
event.terminal_state === "completed"
)
.map((event) => event.task)
);
return completed.size >= 16;
},
120000
);
const completedTasks = [
...new Set(
rawTaskEvents(terminal)
.filter(
(event) =>
event.task_definition === "task_add_one" &&
event.terminal_state === "completed"
)
.map((event) => event.task)
),
];
const released = await waitForCli(
"park/wake process automatic slot release",
() =>
runJson(
clusterflux,
["process", "status", ...scope, "--process", runReport.process],
{ cwd: projectDir }
),
(status) => status.state === "not_active",
120000
);
return {
process: runReport.process,
completed_cycles: completedTasks.length,
task_instances: completedTasks,
terminal_state: released.state,
};
}
async function runDroppedConnectionRollback({
clusterflux,
projectDir,
scope,
}) {
const scenarioStartedAt = Date.now();
const processId = "vp-current";
const attempted = cp.spawnSync(
clusterflux,
["run", "build", "--project", ".", "--json"],
{
cwd: projectDir,
env: {
...process.env,
CLUSTERFLUX_TEST_DROP_RESPONSE_AFTER_OPERATION: "start_process",
},
encoding: "utf8",
timeout: 5 * 60 * 1000,
}
);
assert.notStrictEqual(
attempted.status,
0,
`response-loss run unexpectedly succeeded: ${attempted.stdout}`
);
assert.match(
`${attempted.stderr}\n${attempted.stdout}`,
/closed.*without a response|transport|response/i
);
const released = await waitForCli(
"CLI launch guard rollback after lost start response",
() =>
runJson(
clusterflux,
["process", "status", ...scope, "--process", processId],
{ cwd: projectDir }
),
(status) => status.state === "not_active",
30000
);
return {
duration_ms: Date.now() - scenarioStartedAt,
process: processId,
failure_injection: "control transport dropped start_process response",
cli_exit_status: attempted.status,
rollback: "automatic CLI launch guard abort_process",
terminal_state: released.state,
};
}
async function runLiveBandwidthPreallocation({
sessionSecret,
artifact,
maxBytes,
}) {
const scenarioStartedAt = Date.now();
const before = relayDurableState();
const partialLink = await sendHostedControl(
authenticatedRequest(sessionSecret, {
type: "create_artifact_download_link",
artifact,
max_bytes: maxBytes,
ttl_seconds: 300,
})
);
assert.strictEqual(
partialLink.type,
"artifact_download_link",
JSON.stringify(partialLink)
);
const partialToken = partialLink.link.scoped_token_digest;
let partialChunk;
const partialDeadline = Date.now() + 120_000;
while (Date.now() < partialDeadline) {
const response = await sendHostedControl(
authenticatedRequest(sessionSecret, {
type: "open_artifact_download_stream",
artifact,
max_bytes: maxBytes,
token_digest: partialToken,
chunk_bytes: 16,
})
);
assert.strictEqual(
response.type,
"artifact_download_stream",
JSON.stringify(response)
);
if (response.content_bytes_available === true) {
partialChunk = response;
break;
}
await delay(50);
}
assert(partialChunk, "artifact relay did not return the first partial chunk");
assert.strictEqual(partialChunk.content_eof, false);
assert.strictEqual(partialChunk.streamed_bytes, 16);
const partialRevoked = await sendHostedControl(
authenticatedRequest(sessionSecret, {
type: "revoke_artifact_download_link",
artifact,
token_digest: partialToken,
})
);
assert.strictEqual(
partialRevoked.type,
"artifact_download_link_revoked",
JSON.stringify(partialRevoked)
);
const afterPartialAbandon = relayDurableState();
assert(afterPartialAbandon.ingress_used > before.ingress_used);
assert(afterPartialAbandon.egress_used > before.egress_used);
assert(
afterPartialAbandon.abandoned_or_failed_used >
before.abandoned_or_failed_used
);
let denial;
const acceptedReservations = [];
for (let index = 0; index < 64; index += 1) {
const response = await sendHostedControl(
authenticatedRequest(sessionSecret, {
type: "create_artifact_download_link",
artifact,
max_bytes: maxBytes,
ttl_seconds: 300,
})
);
if (response.type === "error") {
assert.match(
response.message,
/artifact relay.*(?:concurrency|period byte budget)|bandwidth|reservation/i
);
denial = response;
break;
}
assert.strictEqual(response.type, "artifact_download_link", JSON.stringify(response));
acceptedReservations.push(response.link.scoped_token_digest);
}
assert(denial, "artifact relay preallocation was not denied in 64 reservations");
for (const tokenDigest of acceptedReservations) {
const revoked = await sendHostedControl(
authenticatedRequest(sessionSecret, {
type: "revoke_artifact_download_link",
artifact,
token_digest: tokenDigest,
})
);
assert.strictEqual(
revoked.type,
"artifact_download_link_revoked",
JSON.stringify(revoked)
);
}
const afterRelease = relayDurableState();
assert.strictEqual(
Object.keys(afterRelease.reservations || {}).length,
Object.keys(before.reservations || {}).length
);
return {
scenario_started_at_ms: scenarioStartedAt,
artifact,
accepted_reservations_before_denial: acceptedReservations.length,
bytes_served_before_denial: partialChunk.streamed_bytes,
partial_abandon: {
ingress_delta: afterPartialAbandon.ingress_used - before.ingress_used,
egress_delta: afterPartialAbandon.egress_used - before.egress_used,
abandoned_delta:
afterPartialAbandon.abandoned_or_failed_used -
before.abandoned_or_failed_used,
reservation_released: !(partialToken in afterRelease.reservations),
},
durable_before: before,
durable_after_release: afterRelease,
denial: {
type: denial.type,
category: denial.error?.category || null,
message: denial.message,
},
};
}
function relayDurableState() {
if (!strictVpsRestart) {
throw new Error("strict relay accounting requires VPS Postgres access");
}
const output = run(
"ssh",
sshArgs(
"sudo",
"-u",
"postgres",
"psql",
"-d",
"clusterflux",
"-At",
"-c",
"SELECT record::text FROM clusterflux_artifact_relay_state WHERE singleton = TRUE"
)
).trim();
assert.notStrictEqual(output, "", "artifact relay durable state was not persisted");
return JSON.parse(output.split(/\r?\n/).filter(Boolean).at(-1));
}
async function waitForHostedControlReady(timeoutMs = 60_000) {
const deadline = Date.now() + timeoutMs;
let lastError;
while (Date.now() < deadline) {
try {
const ping = await sendHostedControl({ type: "ping" });
if (ping.type === "pong") return ping;
lastError = new Error(JSON.stringify(ping));
} catch (error) {
lastError = error;
}
await delay(500);
}
throw new Error(`hosted service did not recover: ${lastError}`);
}
async function runRelayEmergencyDisable({
sessionSecret,
artifact,
maxBytes,
}) {
if (!strictVpsRestart) {
throw new Error("strict relay disable proof requires VPS systemd access");
}
const dropInDir = `/run/systemd/system/${strictServiceUnit}.d`;
const dropInPath = `${dropInDir}/90-strict-relay-disable.conf`;
run("ssh", sshArgs("sudo", "mkdir", "-p", dropInDir));
cp.execFileSync("ssh", sshArgs("sudo", "tee", dropInPath), {
cwd: repo,
input: "[Service]\nEnvironment=CLUSTERFLUX_HOSTED_RELAY_DISABLED=true\n",
stdio: ["pipe", "ignore", "inherit"],
});
let disabled;
try {
run(
"ssh",
sshArgs(
"sudo",
"systemctl",
"daemon-reload"
)
);
run(
"ssh",
sshArgs("sudo", "systemctl", "restart", strictServiceUnit)
);
await waitForHostedControlReady();
disabled = assertDenied(
await sendHostedControl(
authenticatedRequest(sessionSecret, {
type: "create_artifact_download_link",
artifact,
max_bytes: maxBytes,
ttl_seconds: 60,
})
),
/artifact relay is disabled/i,
"emergency-disabled artifact relay"
);
} finally {
run("ssh", sshArgs("sudo", "rm", "-f", dropInPath));
run("ssh", sshArgs("sudo", "systemctl", "daemon-reload"));
run(
"ssh",
sshArgs("sudo", "systemctl", "restart", strictServiceUnit)
);
await waitForHostedControlReady();
}
const restored = await sendHostedControl(
authenticatedRequest(sessionSecret, {
type: "create_artifact_download_link",
artifact,
max_bytes: maxBytes,
ttl_seconds: 60,
})
);
assert.strictEqual(restored.type, "artifact_download_link", JSON.stringify(restored));
const revoked = await sendHostedControl(
authenticatedRequest(sessionSecret, {
type: "revoke_artifact_download_link",
artifact,
token_digest: restored.link.scoped_token_digest,
})
);
assert.strictEqual(revoked.type, "artifact_download_link_revoked");
return {
disabled,
restored: restored.type,
restored_reservation_released: revoked.type,
runtime_drop_in_removed: true,
};
}
function deploymentProvenance() {
if (!strictVpsRestart) return null;
const systemGeneration = run(
"ssh",
sshArgs("readlink", "-f", "/run/current-system")
).trim();
const mainPid = run(
"ssh",
sshArgs(
"systemctl",
"show",
strictServiceUnit,
"--property=MainPID",
"--value"
)
).trim();
assert.match(mainPid, /^[1-9][0-9]*$/, "hosted service has no live MainPID");
const executable = run(
"ssh",
sshArgs("readlink", "-f", `/proc/${mainPid}/exe`)
).trim();
const binarySha256 = run(
"ssh",
sshArgs("sha256sum", `/proc/${mainPid}/exe`)
)
.trim()
.split(/\s+/)[0];
const fragment = run(
"ssh",
sshArgs("systemctl", "show", strictServiceUnit, "--property=FragmentPath", "--value")
).trim();
const serviceUnitSha256 = run(
"ssh",
sshArgs("sha256sum", fragment)
)
.trim()
.split(/\s+/)[0];
return {
system_generation: systemGeneration,
hosted_service_executable: executable,
hosted_service_sha256: `sha256:${binarySha256}`,
service_unit: fragment,
service_unit_sha256: `sha256:${serviceUnitSha256}`,
};
}
function configurationProvenance() {
const configRepo = path.resolve(
process.env.CLUSTERFLUX_DEPLOYMENT_CONFIG_REPO ||
path.join(repo, "..", "michelpaulissen.com")
);
const status = run("git", ["status", "--short"], { cwd: configRepo }).trim();
return {
repository: configRepo,
revision: run("git", ["rev-parse", "HEAD"], { cwd: configRepo }).trim(),
clean: status === "",
status: status || null,
};
}
async function restartHostedServiceAndResume({
clusterflux,
clusterfluxNode,
projectDir,
scope,
workerArgs,
workerNode,
credentialPath,
credentialDigest,
}) {
if (!strictVpsRestart) {
return {
executed: false,
reason: "strict VPS restart access not supplied",
worker: null,
};
}
const before = deploymentProvenance();
run("ssh", sshArgs("systemctl", "restart", strictServiceUnit));
const deadline = Date.now() + 120000;
let ping;
let lastError;
while (Date.now() < deadline) {
try {
ping = await sendHostedControl({ type: "ping" });
if (ping.type === "pong") break;
} catch (error) {
lastError = error;
}
await delay(500);
}
assert.strictEqual(
ping?.type,
"pong",
`hosted service did not recover after restart: ${lastError?.message || "no pong"}`
);
const afterFirstRestart = deploymentProvenance();
assert.strictEqual(afterFirstRestart.system_generation, before.system_generation);
assert.strictEqual(
afterFirstRestart.hosted_service_sha256,
before.hosted_service_sha256
);
const projects = runJson(clusterflux, ["project", "list", ...scope], {
cwd: projectDir,
});
assert(projects.project_count >= 1, "CLI session/project did not survive restart");
const ephemeralRun = runJson(
clusterflux,
["run", "build", "--project", ".", "--json"],
{ cwd: projectDir }
);
assert.strictEqual(ephemeralRun.status, "main_launched");
const ephemeralProcess = ephemeralRun.process;
await waitForCli(
"pre-restart ephemeral main to park",
() =>
runJson(
clusterflux,
["process", "status", ...scope, "--process", ephemeralProcess],
{ cwd: projectDir }
),
(status) => status.live_process?.main_wait_state === "waiting_for_node",
120000
);
run("ssh", sshArgs("systemctl", "restart", strictServiceUnit));
const secondDeadline = Date.now() + 120000;
ping = undefined;
lastError = undefined;
while (Date.now() < secondDeadline) {
try {
ping = await sendHostedControl({ type: "ping" });
if (ping.type === "pong") break;
} catch (error) {
lastError = error;
}
await delay(500);
}
assert.strictEqual(
ping?.type,
"pong",
`hosted service did not recover after ephemeral-state restart: ${
lastError?.message || "no pong"
}`
);
const after = deploymentProvenance();
assert.strictEqual(after.system_generation, before.system_generation);
assert.strictEqual(after.hosted_service_sha256, before.hosted_service_sha256);
const oldStatus = runJson(
clusterflux,
["process", "status", ...scope, "--process", ephemeralProcess],
{ cwd: projectDir }
);
assert.strictEqual(oldStatus.state, "not_active");
assert.strictEqual(sha256(fs.readFileSync(credentialPath)), credentialDigest);
const worker = spawnJsonLines(clusterfluxNode, workerArgs, {
cwd: projectDir,
env: { ...process.env },
});
const ready = await worker.waitFor(
(value) => value.node_status === "ready",
"persisted worker ready after hosted service restart"
);
assert.strictEqual(ready.node, workerNode);
assert.strictEqual(sha256(fs.readFileSync(credentialPath)), credentialDigest);
const restartedRun = runJson(
clusterflux,
["run", "build", "--project", ".", "--json"],
{ cwd: projectDir }
);
assert.strictEqual(restartedRun.status, "main_launched");
const restartedProcess = restartedRun.process;
const completed = await waitForCli(
"new process completion after hosted service restart",
() =>
runJson(
clusterflux,
["task", "list", ...scope, "--process", restartedProcess],
{ cwd: projectDir }
),
(tasks) => completedFlagship(rawTaskEvents(tasks)),
5 * 60 * 1000
);
const completedEvent = rawTaskEvents(completed).find(
(event) =>
event.executor === "coordinator_main" &&
event.terminal_state === "completed"
);
assert(completedEvent, "post-restart flagship omitted its completed main event");
return {
executed: true,
account_project_session_preserved: true,
node_identity_preserved: true,
old_process_terminated_honestly: true,
terminated_ephemeral_process: ephemeralProcess,
new_process: restartedProcess,
new_process_result: completedEvent.result,
before,
after_first_restart: afterFirstRestart,
after,
worker,
};
}
async function finishUserCredentialSecurity({
clusterflux,
projectDir,
scope,
sessionSecret,
}) {
const forged = assertDenied(
await sendHostedControl(
authenticatedRequest(
`forged-session-${crypto.randomBytes(24).toString("hex")}`,
{ type: "list_projects" }
)
),
/not recognized|invalid|authentication|session/i,
"forged user session"
);
let expired = null;
const expiredFile = process.env.CLUSTERFLUX_EXPIRED_USER_SESSION_FILE;
if (expiredFile) {
const oldSession = readJson(path.resolve(expiredFile));
assert(oldSession.session_secret, "expired session evidence omitted its secret");
expired = assertDenied(
await sendHostedControl(
authenticatedRequest(oldSession.session_secret, { type: "list_projects" })
),
/expired|not recognized/i,
"expired user session"
);
} else if (strictFullRelease) {
throw new Error(
"strict full release requires CLUSTERFLUX_EXPIRED_USER_SESSION_FILE for a genuinely expired hosted session"
);
}
const logout = runJson(clusterflux, ["logout", ...scope, "--yes"], {
cwd: projectDir,
});
assert.strictEqual(logout.server_session_revocation.revoked, true);
const revoked = assertDenied(
await sendHostedControl(
authenticatedRequest(sessionSecret, { type: "list_projects" })
),
/revoked|not recognized/i,
"revoked user session"
);
return { forged, expired, revoked };
}
async function dapVariables(client, variablesReference) {
const request = client.send("variables", { variablesReference });
return (await client.response(request, "variables")).body.variables;
}
async function runSameDefinitionDapIdentity({
clusterfluxDap,
clusterflux,
projectDir,
scope,
}) {
const scenarioStartedAt = Date.now();
const baselineContainers = new Set(
run("podman", ["ps", "-q"])
.trim()
.split(/\s+/)
.filter(Boolean)
);
const client = new DapClient({
cwd: projectDir,
command: clusterfluxDap,
args: [],
env: { ...process.env },
});
let disconnected = false;
try {
const initialize = client.send("initialize", {
adapterID: "clusterflux",
linesStartAt1: true,
columnsStartAt1: true,
});
await client.response(initialize, "initialize");
const launch = client.send("launch", {
entry: "identity",
project: projectDir,
runtimeBackend: "live-services",
coordinatorEndpoint: serviceEndpoint,
});
await client.response(launch, "launch");
await client.waitFor(
(message) => message.type === "event" && message.event === "initialized"
);
const configurationDone = client.send("configurationDone");
await client.response(configurationDone, "configurationDone");
const mainThreadDeadline = Date.now() + 5 * 60 * 1000;
let mainThread;
while (Date.now() < mainThreadDeadline) {
const threadsRequest = client.send("threads");
const threads = (await client.response(threadsRequest, "threads")).body
.threads;
mainThread = threads.find((thread) => /coordinator main/i.test(thread.name));
if (mainThread) break;
await delay(100);
}
assert(mainThread, "identity entry did not report its coordinator main");
const processRequest = client.send("evaluate", {
expression: "virtual_process_id",
context: "watch",
});
const processId = (await client.response(processRequest, "evaluate")).body
.result;
const identityContainerDeadline = Date.now() + 2 * 60 * 1000;
let identityContainerIds = new Set();
let maximumNewContainerCount = 0;
let lastPodmanStates = [];
while (Date.now() < identityContainerDeadline) {
const containers = runJson("podman", ["ps", "--format", "json"]);
lastPodmanStates = containers;
identityContainerIds = new Set(
containers
.map((container) => container.Id || container.ID || container.IdHex || "")
.filter((id) => id && !baselineContainers.has(id))
);
maximumNewContainerCount = Math.max(
maximumNewContainerCount,
identityContainerIds.size
);
if (identityContainerIds.size >= 2) break;
await delay(100);
}
const identityTaskSnapshot =
identityContainerIds.size >= 2
? null
: runJson(
clusterflux,
["task", "list", ...scope, "--process", processId],
{ cwd: projectDir }
);
assert(
identityContainerIds.size >= 2,
`identity entry did not start two same-definition Podman containers; max=${maximumNewContainerCount} tasks=${JSON.stringify(
identityTaskSnapshot
)} podman=${JSON.stringify(lastPodmanStates)}`
);
const pause = client.send("pause", { threadId: mainThread.id });
await client.response(pause, "pause");
const paused = await client.waitFor(
(message) =>
message.type === "event" &&
message.event === "stopped" &&
message.body.reason === "pause",
30_000
);
assert.strictEqual(typeof paused.body.allThreadsStopped, "boolean");
const podmanStates = runJson("podman", ["ps", "--all", "--format", "json"]);
const clusterfluxPausedContainers = podmanStates.filter((container) => {
const id = container.Id || container.ID || container.IdHex || "";
const state = String(container.State || container.Status || "").toLowerCase();
return identityContainerIds.has(id) && state.includes("paused");
});
assert(
clusterfluxPausedContainers.length >= 2,
`expected two newly paused Clusterflux containers: ${JSON.stringify(
podmanStates
)}`
);
const threadsRequest = client.send("threads");
const threads = (await client.response(threadsRequest, "threads")).body
.threads;
const identityThreads = threads.filter((thread) =>
/identity probe/i.test(thread.name)
);
assert.strictEqual(
identityThreads.length,
2,
`expected two same-definition DAP threads: ${JSON.stringify(threads)}`
);
assert.notStrictEqual(identityThreads[0].id, identityThreads[1].id);
const threadEvidence = [];
for (const threadRecord of identityThreads) {
const stackRequest = client.send("stackTrace", {
threadId: threadRecord.id,
startFrame: 0,
levels: 1,
});
const frames = (await client.response(stackRequest, "stackTrace")).body
.stackFrames;
assert.strictEqual(frames.length, 1);
const scopesRequest = client.send("scopes", { frameId: frames[0].id });
const scopes = (await client.response(scopesRequest, "scopes")).body.scopes;
const argsScope = scopes.find(
(scopeRecord) => scopeRecord.name === "Task Args and Handles"
);
const runtimeScope = scopes.find(
(scopeRecord) => scopeRecord.name === "Clusterflux Runtime"
);
assert(argsScope && runtimeScope);
const args = await dapVariables(client, argsScope.variablesReference);
const runtime = await dapVariables(client, runtimeScope.variablesReference);
const runtimeValue = (name) =>
runtime.find((variable) => variable.name === name)?.value;
assert.strictEqual(runtimeValue("state"), "Frozen");
threadEvidence.push({
thread_id: threadRecord.id,
task_instance: runtimeValue("virtual_thread"),
attempt_id: runtimeValue("task_attempt_id"),
arguments: args.map((variable) => ({
name: variable.name,
value: variable.value,
})),
});
}
assert.notStrictEqual(
threadEvidence[0].task_instance,
threadEvidence[1].task_instance
);
assert.notStrictEqual(threadEvidence[0].attempt_id, threadEvidence[1].attempt_id);
const argumentText = threadEvidence
.flatMap((record) => record.arguments.map((argument) => argument.value))
.join(" ");
assert.match(argumentText, /slow-first/);
assert.match(argumentText, /fast-second/);
const continued = client.send("continue", {
threadId: paused.body.threadId,
});
await client.response(continued, "continue");
await client.waitFor(
(message) => message.type === "event" && message.event === "terminated",
5 * 60 * 1000
);
const taskList = runJson(
clusterflux,
["task", "list", ...scope, "--process", processId],
{ cwd: projectDir }
);
const identityEvents = rawTaskEvents(taskList).filter(
(event) =>
event.task_definition === "identity_probe" &&
event.terminal_state === "completed"
);
assert.strictEqual(identityEvents.length, 2, JSON.stringify(identityEvents));
assert.notStrictEqual(identityEvents[0].task, identityEvents[1].task);
assert.notStrictEqual(identityEvents[0].attempt_id, identityEvents[1].attempt_id);
assert.match(JSON.stringify(identityEvents[0].result), /fast-second/);
assert.match(JSON.stringify(identityEvents[1].result), /slow-first/);
const released = await waitForCli(
"same-definition identity process release",
() =>
runJson(
clusterflux,
["process", "status", ...scope, "--process", processId],
{ cwd: projectDir }
),
(status) => status.state === "not_active",
120_000
);
await client.close();
disconnected = true;
return {
duration_ms: Date.now() - scenarioStartedAt,
process: processId,
thread_evidence: threadEvidence,
completion_order: identityEvents.map((event) => ({
task_instance: event.task,
attempt_id: event.attempt_id,
result: event.result,
})),
podman_paused_container_ids: clusterfluxPausedContainers.map(
(container) => container.Id || container.ID || container.IdHex
),
dap_all_threads_stopped: paused.body.allThreadsStopped,
terminal_state: released.state,
};
} finally {
if (!disconnected) {
await client.close().catch(() => {
if (client.child.exitCode === null) client.child.kill("SIGKILL");
});
}
}
}
async function runLiveDapEditRestart({
clusterfluxDap,
clusterflux,
projectDir,
scope,
worker,
}) {
const scenarioStartedAt = Date.now();
const sourcePath = fs.realpathSync(path.join(projectDir, "src/build.rs"));
const originalSource = fs.readFileSync(sourcePath, "utf8");
const sourceLines = originalSource.split(/\r?\n/);
const lineFor = (needle) => {
const line = sourceLines.findIndex((candidate) => candidate.includes(needle)) + 1;
assert(line > 0, `flagship source omitted ${needle}`);
return line;
};
const mainLine = lineFor("pub async fn restart_main()");
const taskLine = lineFor("fn task_trap(");
const client = new DapClient({
cwd: projectDir,
command: clusterfluxDap,
args: [],
env: { ...process.env },
});
let sourceRestored = false;
let disconnected = false;
try {
const initialize = client.send("initialize", {
adapterID: "clusterflux",
linesStartAt1: true,
columnsStartAt1: true,
});
await client.response(initialize, "initialize");
const launch = client.send("launch", {
entry: "restart",
project: projectDir,
runtimeBackend: "live-services",
coordinatorEndpoint: serviceEndpoint,
});
await client.response(launch, "launch");
await client.waitFor(
(message) => message.type === "event" && message.event === "initialized"
);
const configurationStartedAt = Date.now();
const configurationDone = client.send("configurationDone");
await client.response(configurationDone, "configurationDone");
const configurationResponseMs = Date.now() - configurationStartedAt;
assert(
configurationResponseMs < 2_000,
`configurationDone blocked for ${configurationResponseMs} ms`
);
const threadDeadline = Date.now() + 5 * 60 * 1000;
let runningThreads = [];
while (Date.now() < threadDeadline) {
const threadsRequest = client.send("threads");
runningThreads = (await client.response(threadsRequest, "threads")).body
.threads;
if (runningThreads.length > 0) break;
await delay(100);
}
assert(runningThreads.length > 0, "asynchronous live DAP launch reported no threads");
const pauseStartedAt = Date.now();
const pause = client.send("pause", { threadId: runningThreads[0].id });
await client.response(pause, "pause");
const pauseResponseMs = Date.now() - pauseStartedAt;
assert(pauseResponseMs < 2_000, `pause blocked for ${pauseResponseMs} ms`);
const mainStop = await client.waitFor(
(message) =>
message.type === "event" &&
message.event === "stopped" &&
message.body.reason === "pause"
);
assert.strictEqual(mainStop.body.allThreadsStopped, true);
const inspectStartedAt = Date.now();
const commandStatus = client.send("evaluate", {
expression: "command_status",
context: "watch",
});
const inspected = await client.response(commandStatus, "evaluate");
const inspectionResponseMs = Date.now() - inspectStartedAt;
assert(
inspectionResponseMs < 2_000,
`inspection blocked for ${inspectionResponseMs} ms`
);
assert.match(inspected.body.result, /debug epoch|frozen/i);
const breakpointStartedAt = Date.now();
const setBreakpoints = client.send("setBreakpoints", {
source: { path: sourcePath },
breakpoints: [{ line: taskLine }],
});
const breakpointResponse = await client.response(setBreakpoints, "setBreakpoints");
const breakpointResponseMs = Date.now() - breakpointStartedAt;
assert(
breakpointResponseMs < 2_000,
`setBreakpoints blocked for ${breakpointResponseMs} ms`
);
assert.deepStrictEqual(
breakpointResponse.body.breakpoints.map((breakpoint) => breakpoint.verified),
[true]
);
const continueStartedAt = Date.now();
const mainContinue = client.send("continue", {
threadId: mainStop.body.threadId,
});
await client.response(mainContinue, "continue");
const continueResponseMs = Date.now() - continueStartedAt;
assert(
continueResponseMs < 2_000,
`continue blocked for ${continueResponseMs} ms`
);
const taskStop = await client.waitFor(
(message) =>
message.seq > mainStop.seq &&
message.type === "event" &&
message.event === "stopped" &&
message.body.reason === "breakpoint"
);
assert.strictEqual(taskStop.body.allThreadsStopped, true);
assert.notStrictEqual(taskStop.body.threadId, mainStop.body.threadId);
const stackTrace = client.send("stackTrace", {
threadId: taskStop.body.threadId,
startFrame: 0,
levels: 1,
});
const taskFrames = (await client.response(stackTrace, "stackTrace")).body
.stackFrames;
assert.strictEqual(taskFrames[0].line, taskLine);
const scopesRequest = client.send("scopes", { frameId: taskFrames[0].id });
const scopes = (await client.response(scopesRequest, "scopes")).body.scopes;
const argsScope = scopes.find(
(candidate) => candidate.name === "Task Args and Handles"
);
const runtimeScope = scopes.find(
(candidate) => candidate.name === "Clusterflux Runtime"
);
assert(argsScope && runtimeScope);
const taskArgs = await dapVariables(client, argsScope.variablesReference);
assert(
taskArgs.some(
(variable) =>
variable.name === "arg_0" && String(variable.value).includes("0")
)
);
const runtime = await dapVariables(client, runtimeScope.variablesReference);
assert(
runtime.some(
(variable) =>
variable.name === "runtime_backend" && variable.value === "LiveServices"
)
);
assert(
runtime.some(
(variable) => variable.name === "state" && variable.value === "Frozen"
)
);
const dapProcess = runtime.find(
(variable) => variable.name === "virtual_process_id"
)?.value;
assert.match(dapProcess || "", /^vp-[0-9a-f]{12}$/);
const taskContinue = client.send("continue", { threadId: taskStop.body.threadId });
await client.response(taskContinue, "continue");
const failedStop = await client.waitFor(
(message) =>
message.seq > taskStop.seq &&
message.type === "event" &&
message.event === "stopped" &&
message.body.reason === "exception",
5 * 60 * 1000
);
assert.strictEqual(failedStop.body.allThreadsStopped, false);
const beforeEdit = runJson(
clusterflux,
["task", "list", ...scope, "--process", dapProcess],
{ cwd: projectDir }
);
const originalTaskEvent = rawTaskEvents(beforeEdit).find(
(event) =>
event.task_definition === "task_trap" &&
event.terminal_state === "failed"
);
assert(originalTaskEvent, "DAP restart entry omitted its original child event");
assert(originalTaskEvent.attempt_id, "failed attempt omitted its identity");
const originalTaskBody = `pub extern "C" fn task_trap(_input: i32) -> i32 {
#[cfg(target_arch = "wasm32")]
core::arch::wasm32::unreachable();
#[cfg(not(target_arch = "wasm32"))]
panic!("intentional task trap")
}`;
const replacementTaskBody = `pub extern "C" fn task_trap(_input: i32) -> i32 {
_input + 42 // strict hosted compatible restart probe
}`;
const editedSource = originalSource.replace(originalTaskBody, replacementTaskBody);
assert.notStrictEqual(editedSource, originalSource);
fs.writeFileSync(sourcePath, editedSource);
const restartFrame = client.send("restartFrame", {
frameId: taskFrames[0].id,
});
const restartResponse = await client.response(restartFrame, "restartFrame");
const restartedStop = await client.waitFor(
(message) =>
message.seq > restartResponse.seq &&
message.type === "event" &&
message.event === "stopped" &&
message.body.reason === "breakpoint"
);
assert.strictEqual(restartedStop.body.allThreadsStopped, true);
const restartedContinue = client.send("continue", {
threadId: restartedStop.body.threadId,
});
await client.response(restartedContinue, "continue");
const restartedNodeReport = await worker.waitFor(
(value) =>
value.node_status === "completed" &&
value.virtual_thread === originalTaskEvent.task &&
value.task_assignment_response?.task_spec?.task_definition ===
"task_trap",
"edited task to execute on the live restarted node",
5 * 60 * 1000
);
assert.strictEqual(
restartedNodeReport.node_status,
"completed",
`edited task restart failed on the live node: ${JSON.stringify(restartedNodeReport)}`
);
assert.match(restartedNodeReport.stdout_tail, /"SmallJson":42/);
const restartedTask = restartedNodeReport.virtual_thread;
const afterEdit = await waitForCli(
"edited live task event",
() =>
runJson(clusterflux, ["task", "list", ...scope, "--process", dapProcess], {
cwd: projectDir,
}),
(tasks) =>
rawTaskEvents(tasks).some(
(event) =>
event.task === restartedTask &&
event.terminal_state === "completed" &&
JSON.stringify(event.result) === JSON.stringify({ SmallJson: 42 })
),
5 * 60 * 1000
);
const restartedEvent = rawTaskEvents(afterEdit).find(
(event) =>
event.task === restartedTask &&
event.terminal_state === "completed" &&
JSON.stringify(event.result) === JSON.stringify({ SmallJson: 42 })
);
assert(restartedEvent, "replacement attempt omitted its completed event");
assert(restartedEvent.attempt_id, "replacement attempt omitted its identity");
assert.notStrictEqual(restartedEvent.attempt_id, originalTaskEvent.attempt_id);
await client.waitFor(
(message) => message.type === "event" && message.event === "terminated",
5 * 60 * 1000
);
const disconnectStartedAt = Date.now();
await client.close();
disconnected = true;
const disconnectResponseMs = Date.now() - disconnectStartedAt;
assert(
disconnectResponseMs < 2_000,
`disconnect blocked for ${disconnectResponseMs} ms`
);
fs.writeFileSync(sourcePath, originalSource);
sourceRestored = true;
return {
duration_ms: Date.now() - scenarioStartedAt,
process: dapProcess,
main_source_line: mainLine,
task_breakpoint_line: taskLine,
launch_started_without_breakpoint: true,
configuration_response_ms: configurationResponseMs,
pause_response_ms: pauseResponseMs,
inspection_response_ms: inspectionResponseMs,
breakpoint_response_ms: breakpointResponseMs,
continue_response_ms: continueResponseMs,
disconnect_response_ms: disconnectResponseMs,
pause_all_threads_stopped: mainStop.body.allThreadsStopped,
task_all_threads_stopped: taskStop.body.allThreadsStopped,
original_task_instance: originalTaskEvent.task,
original_attempt: originalTaskEvent.attempt_id,
restarted_task_instance: restartedTask,
restarted_attempt: restartedEvent.attempt_id,
restarted_result: restartedEvent.result,
compatible_source_edit: "task_trap: trap -> input + 42",
original_arguments_preserved: true,
clean_vfs_boundary_used: true,
};
} finally {
if (!sourceRestored) fs.writeFileSync(sourcePath, originalSource);
if (!disconnected) {
await client.close().catch(() => {
if (client.child.exitCode === null) client.child.kill("SIGKILL");
});
}
}
}
async function main() {
requireEnabled();
const manifest = readJson(manifestPath);
assert.strictEqual(manifest.kind, "clusterflux-public-release");
assert.strictEqual(manifest.default_hosted_coordinator_endpoint, serviceEndpoint);
assert.strictEqual(serviceAddr, "clusterflux.michelpaulissen.com:443");
const workRoot = fs.mkdtempSync(path.join(os.tmpdir(), "clusterflux-cli-happy-"));
const installDir = path.join(workRoot, "install");
const checkout = path.join(workRoot, "public-repo");
const downloadPath = path.join(workRoot, "release.tar");
const extractedArtifact = path.join(workRoot, "artifact");
ensureDir(installDir);
run("tar", ["-xzf", binaryArchive(manifest), "-C", installDir]);
const publicSource = stagePublicCheckout(manifest, checkout);
const clusterflux = executable(installDir, "clusterflux");
const clusterfluxNode = executable(installDir, "clusterflux-node");
const clusterfluxDap = executable(installDir, "clusterflux-debug-dap");
const projectDir = path.join(checkout, "examples/launch-build-demo");
const suffix = String(Date.now());
const workerNode = `worker-${suffix}`;
let loginSession;
let receivedDefaultProject;
if (reuseSessionFile) {
const sourceSessionPath = path.resolve(reuseSessionFile);
const sourceProjectPath = path.join(path.dirname(sourceSessionPath), "project.json");
const sourceSession = readJson(sourceSessionPath);
const sourceProject = readJson(sourceProjectPath);
assert.strictEqual(sourceSession.kind, "human");
assert.strictEqual(sourceSession.coordinator, serviceEndpoint);
assert.strictEqual(sourceProject.coordinator, serviceEndpoint);
assert.strictEqual(sourceProject.tenant, sourceSession.tenant);
assert.strictEqual(sourceProject.project, sourceSession.project);
assert.strictEqual(sourceProject.user, sourceSession.user);
assert(
Number(sourceSession.expires_at) > Math.floor(Date.now() / 1000) + 300,
"reused CLI session expires too soon for the live journey"
);
const destinationConfig = path.join(projectDir, ".clusterflux");
ensureDir(destinationConfig);
fs.copyFileSync(sourceSessionPath, path.join(destinationConfig, "session.json"));
fs.copyFileSync(sourceProjectPath, path.join(destinationConfig, "project.json"));
fs.chmodSync(path.join(destinationConfig, "session.json"), 0o600);
fs.chmodSync(path.join(destinationConfig, "project.json"), 0o644);
loginSession = sourceSession;
receivedDefaultProject = true;
} else {
const login = runJson(
clusterflux,
["login", "--browser", "--json"],
{
cwd: projectDir,
env: { ...process.env, CLUSTERFLUX_BROWSER_OPEN_COMMAND: browserOpenCommand },
}
);
assert.strictEqual(login.plan.coordinator, serviceEndpoint);
assert.strictEqual(login.boundary.scoped_cli_session_received, true);
assert.strictEqual(login.boundary.provider_tokens_exposed_to_cli, false);
assert.strictEqual(login.boundary.provider_tokens_sent_to_nodes, false);
loginSession = login.coordinator_response.session;
assert(loginSession, "hosted browser login omitted its scoped session");
receivedDefaultProject =
typeof loginSession.project === "string" && loginSession.project.length > 0;
assert(receivedDefaultProject, "login did not return its server-owned project");
}
const sessionSecret =
loginSession.cli_session_secret || loginSession.session_secret;
assert(sessionSecret, "hosted browser login omitted the CLI session credential");
const tenant = loginSession.tenant;
const project = loginSession.project;
const user = loginSession.user;
for (const [name, value] of Object.entries({ tenant, project, user })) {
assert.strictEqual(typeof value, "string", `hosted session omitted ${name}`);
assert.notStrictEqual(value, "", `hosted session returned an empty ${name}`);
}
const scope = [
"--coordinator",
serviceEndpoint,
"--tenant",
tenant,
"--project-id",
project,
"--user",
user,
"--json",
];
if (!reuseSessionFile) {
const projectInit = runJson(
clusterflux,
[
"project",
"init",
...scope,
"--new-project",
project,
"--name",
"CLI Happy Path",
"--yes",
],
{ cwd: projectDir }
);
assert.strictEqual(projectInit.command, "project init");
assert.strictEqual(projectInit.project_config_written, true);
assert.strictEqual(projectInit.coordinator_response.type, "project_created");
}
const projectList = runJson(clusterflux, ["project", "list", ...scope], {
cwd: projectDir,
});
assert(projectList.project_count >= 1);
const projectSelect = runJson(
clusterflux,
["project", "select", ...scope, project],
{ cwd: projectDir }
);
assert.strictEqual(projectSelect.command, "project select");
const inspection = runJson(clusterflux, ["inspect", "--project", ".", "--json"], {
cwd: projectDir,
});
assert(
inspection.metadata.environments.some((environment) => environment.name === "linux")
);
assert(Array.isArray(inspection.source_provider_statuses));
assert(inspection.source_provider_manifest);
const runReport = runJson(
clusterflux,
["run", "build", "--project", ".", "--json"],
{ cwd: projectDir }
);
assert.strictEqual(runReport.command, "run");
assert.strictEqual(runReport.status, "main_launched");
assert.strictEqual(runReport.task_launch.type, "main_launched");
const processId = runReport.process;
const parkedStatus = await waitForCli(
"hosted coordinator main to park before node enrollment",
() =>
runJson(
clusterflux,
["process", "status", ...scope, "--process", processId],
{ cwd: projectDir }
),
(status) =>
status.live_process?.main_state === "running" &&
status.live_process?.main_wait_state === "waiting_for_node" &&
status.live_process?.connected_nodes?.length === 0,
120000
);
const grant = runJson(clusterflux, ["node", "enroll", ...scope], {
cwd: projectDir,
});
assert.strictEqual(grant.command, "node enroll");
const attach = runJson(
clusterflux,
[
"node",
"attach",
"--coordinator",
serviceEndpoint,
"--tenant",
tenant,
"--project-id",
project,
"--node",
workerNode,
"--enrollment-grant",
grant.enrollment_grant.grant,
"--json",
],
{ cwd: projectDir }
);
assert.strictEqual(attach.command, "node attach");
assert.strictEqual(attach.boundary.used_enrollment_exchange, true);
const credentialDir = path.join(projectDir, ".clusterflux", "nodes");
const credentialFiles = fs
.readdirSync(credentialDir)
.filter((file) => file.endsWith(".json"));
assert.strictEqual(credentialFiles.length, 1, "expected one persisted node credential");
const credentialPath = path.join(credentialDir, credentialFiles[0]);
const credentialBefore = fs.readFileSync(credentialPath);
const credentialDigest = sha256(credentialBefore);
if (process.platform !== "win32") {
assert.strictEqual(fs.statSync(credentialPath).mode & 0o777, 0o600);
}
const workerArgs = [
"--coordinator",
serviceEndpoint,
"--tenant",
tenant,
"--project-id",
project,
"--node",
workerNode,
"--worker",
"--project-root",
projectDir,
"--assignment-poll-ms",
"500",
"--emit-ready",
];
const spawnWorker = () =>
spawnJsonLines(clusterfluxNode, workerArgs, {
cwd: projectDir,
env: { ...process.env },
});
let worker = spawnWorker();
try {
const firstReady = await worker.waitFor(
(value) => value.node_status === "ready",
"first persisted worker ready"
);
assert.strictEqual(firstReady.node, workerNode);
const initiallyOnline = runJson(
clusterflux,
["node", "status", ...scope, "--node", workerNode],
{ cwd: projectDir }
);
assert.strictEqual(nodeDescriptor(initiallyOnline, workerNode)?.online, true);
const completedTasks = await waitForCli(
"real hosted flagship completion",
() =>
runJson(clusterflux, ["task", "list", ...scope, "--process", processId], {
cwd: projectDir,
}),
(tasks) => completedFlagship(rawTaskEvents(tasks))
);
const firstEvents = rawTaskEvents(completedTasks);
assert(
firstEvents
.filter((event) => event.executor === "node")
.every((event) => event.node === workerNode)
);
assert(
firstEvents.some(
(event) =>
event.task_definition === "package_release" &&
event.terminal_state === "completed" &&
contentAddressedArtifactId(event, "release.tar")
)
);
const releasedFlagshipStatus = await waitForCli(
"completed flagship process to release its active slot",
() =>
runJson(
clusterflux,
["process", "status", ...scope, "--process", processId],
{ cwd: projectDir }
),
(status) => status.state === "not_active",
120000
);
const offlineStartedAt = Date.now();
await stopChild(worker.child);
const observedOffline = await waitForCli(
"server-derived worker stale/offline transition",
() =>
runJson(clusterflux, ["node", "status", ...scope, "--node", workerNode], {
cwd: projectDir,
}),
(status) => nodeDescriptor(status, workerNode)?.online === false,
120000
);
worker = spawnWorker();
const secondReady = await worker.waitFor(
(value) => value.node_status === "ready",
"restarted persisted worker ready"
);
assert.strictEqual(secondReady.node, workerNode);
assert.strictEqual(sha256(fs.readFileSync(credentialPath)), credentialDigest);
const nodeStatus = await waitForCli(
"server-derived worker online recovery",
() =>
runJson(clusterflux, ["node", "status", ...scope, "--node", workerNode], {
cwd: projectDir,
}),
(status) => nodeDescriptor(status, workerNode)?.online === true,
30000
);
assert(JSON.stringify(nodeStatus.response).includes(workerNode));
assert.strictEqual(sha256(fs.readFileSync(credentialPath)), credentialDigest);
const nodeLivenessTransition = {
initial_online: nodeDescriptor(initiallyOnline, workerNode).online,
stale_offline: nodeDescriptor(observedOffline, workerNode).online,
recovered_online: nodeDescriptor(nodeStatus, workerNode).online,
offline_detection_ms: Date.now() - offlineStartedAt,
persisted_identity_reused: true,
};
const processStatus = runJson(
clusterflux,
["process", "status", ...scope, "--process", processId],
{ cwd: projectDir }
);
assert.strictEqual(processStatus.command, "process status");
assert(processStatus.current_task_count >= firstEvents.length);
const logs = runJson(
clusterflux,
["logs", ...scope, "--process", processId],
{ cwd: projectDir }
);
assert(logs.log_entries.length >= 4);
const artifacts = runJson(
clusterflux,
["artifact", "list", ...scope, "--process", processId],
{ cwd: projectDir }
);
const releaseArtifact = artifacts.artifacts.find((artifact) => {
const digest = artifact.digest;
return (
typeof digest === "string" &&
/^sha256:[0-9a-f]{64}$/.test(digest) &&
artifact.artifact === `release.tar-${digest.slice("sha256:".length)}`
);
});
assert(releaseArtifact, "hosted flagship did not publish release.tar");
assert.strictEqual(releaseArtifact.state, "metadata_flushed");
const download = runJson(
clusterflux,
[
"artifact",
"download",
...scope,
releaseArtifact.artifact,
"--to",
downloadPath,
],
{ cwd: projectDir }
);
assert.strictEqual(download.download_session.link_issued, true);
assert.strictEqual(download.local_download.local_bytes_written_by_cli, true);
assert.strictEqual(download.local_download.verified_digest, releaseArtifact.digest);
assert.strictEqual(sha256(fs.readFileSync(downloadPath)), releaseArtifact.digest);
ensureDir(extractedArtifact);
const archiveEntries = run("tar", ["-tf", downloadPath]);
assert.match(archiveEntries, /(?:^|\n)hello-clusterflux(?:\n|$)/);
run("tar", ["-xf", downloadPath, "-C", extractedArtifact]);
const builtExecutable = path.join(extractedArtifact, "hello-clusterflux");
assert(fs.existsSync(builtExecutable));
const builtOutput = run(builtExecutable, []).trim();
assert.strictEqual(builtOutput, "hello from a real Clusterflux build");
const dapEditRestart = await runLiveDapEditRestart({
clusterfluxDap,
clusterflux,
projectDir,
scope,
worker,
});
const restart = runJson(
clusterflux,
["process", "restart", ...scope, "--process", dapEditRestart.process, "--yes"],
{ cwd: projectDir }
);
assert.strictEqual(restart.restart_request.accepted, true);
const cancel = runJson(
clusterflux,
["process", "cancel", ...scope, "--process", dapEditRestart.process, "--yes"],
{ cwd: projectDir }
);
assert.strictEqual(cancel.cancel_request.accepted, true);
const releasedDap = await waitForCli(
"cancelled DAP process slot release",
() =>
runJson(
clusterflux,
["process", "status", ...scope, "--process", dapEditRestart.process],
{ cwd: projectDir }
),
(status) => status.state === "not_active",
120000
);
assert.strictEqual(releasedDap.state, "not_active");
const identityWorkerNode = `identity-worker-${suffix}`;
const identityWorkerGrant = runJson(
clusterflux,
["node", "enroll", ...scope],
{ cwd: projectDir }
);
runJson(
clusterflux,
[
"node",
"attach",
"--coordinator",
serviceEndpoint,
"--tenant",
tenant,
"--project-id",
project,
"--node",
identityWorkerNode,
"--enrollment-grant",
identityWorkerGrant.enrollment_grant.grant,
"--json",
],
{ cwd: projectDir }
);
const identityWorker = spawnJsonLines(
clusterfluxNode,
[
"--coordinator",
serviceEndpoint,
"--tenant",
tenant,
"--project-id",
project,
"--node",
identityWorkerNode,
"--worker",
"--project-root",
projectDir,
"--assignment-poll-ms",
"500",
"--emit-ready",
],
{ cwd: projectDir, env: { ...process.env } }
);
let sameDefinitionIdentity;
try {
const identityWorkerReady = await identityWorker.waitFor(
(value) => value.node_status === "ready",
"same-definition identity worker ready"
);
assert.strictEqual(identityWorkerReady.node, identityWorkerNode);
await waitForCli(
"same-definition identity worker online",
() =>
runJson(
clusterflux,
["node", "status", ...scope, "--node", identityWorkerNode],
{ cwd: projectDir }
),
(status) => nodeDescriptor(status, identityWorkerNode)?.online === true,
30_000
);
await stopChild(worker.child);
worker = spawnWorker();
const refreshedPrimaryReady = await worker.waitFor(
(value) => value.node_status === "ready",
"same-definition primary worker capability refresh"
);
assert.strictEqual(refreshedPrimaryReady.node, workerNode);
const primaryStatus = await waitForCli(
"same-definition primary worker online after refresh",
() =>
runJson(
clusterflux,
["node", "status", ...scope, "--node", workerNode],
{ cwd: projectDir }
),
(status) => nodeDescriptor(status, workerNode)?.online === true,
30_000
);
const identityStatus = runJson(
clusterflux,
["node", "status", ...scope, "--node", identityWorkerNode],
{ cwd: projectDir }
);
const primarySnapshots =
nodeDescriptor(primaryStatus, workerNode)?.source_snapshots || [];
const identitySnapshots =
nodeDescriptor(identityStatus, identityWorkerNode)?.source_snapshots || [];
assert(
primarySnapshots.some((snapshot) => identitySnapshots.includes(snapshot)),
`same-definition workers do not share a current source snapshot: ${JSON.stringify({
primarySnapshots,
identitySnapshots,
})}`
);
sameDefinitionIdentity = await runSameDefinitionDapIdentity({
clusterfluxDap,
clusterflux,
projectDir,
scope,
});
} finally {
await stopChild(identityWorker.child);
runJson(
clusterflux,
["node", "revoke", ...scope, "--node", identityWorkerNode, "--yes"],
{ cwd: projectDir }
);
}
const repeatedParkWake = await runRepeatedParkWakeProof({
clusterflux,
projectDir,
scope,
});
const longJoin = await runLongJoinProof({
clusterflux,
projectDir,
scope,
});
const tenantIsolation = await runSecondTenantIsolation({
firstTenant: tenant,
firstProject: project,
firstProcess: dapEditRestart.process,
firstNode: workerNode,
firstArtifact: releaseArtifact.artifact,
manifest,
});
const securityNode = await prepareLiveNodeCredentialSecurity({
clusterflux,
projectDir,
scope,
tenant,
project,
suffix,
bundle: {
digest: runReport.bundle_digest,
moduleBase64: fs
.readFileSync(
path.resolve(projectDir, runReport.bundle_build.bundle_artifact.module)
)
.toString("base64"),
entryExport: runReport.entry_export,
entryStableId: runReport.entry_stable_id,
},
});
const droppedConnectionRollback = await runDroppedConnectionRollback({
clusterflux,
projectDir,
scope,
});
const bandwidthPreallocation = await runLiveBandwidthPreallocation({
sessionSecret,
artifact: releaseArtifact.artifact,
maxBytes: download.local_download.bytes_written,
});
const relayEmergencyDisable = await runRelayEmergencyDisable({
sessionSecret,
artifact: releaseArtifact.artifact,
maxBytes: download.local_download.bytes_written,
});
const agentCredentialSecurity = await runLiveAgentCredentialSecurity({
clusterfluxDap,
clusterflux,
projectDir,
scope,
sessionSecret,
tenant,
project,
suffix,
bundle: {
digest: runReport.bundle_digest,
moduleBase64: fs
.readFileSync(
path.resolve(projectDir, runReport.bundle_build.bundle_artifact.module)
)
.toString("base64"),
entryExport: runReport.entry_export,
entryStableId: runReport.entry_stable_id,
},
securityNode,
workerRuntime: {
node: workerNode,
child: worker.child,
worker,
identity: nodeIdentityFromPrivateKey(
readNodeCredential(projectDir, workerNode).credential.private_key
),
},
});
await stopChild(worker.child);
const liveSoak = await runLiveSoak({
clusterflux,
projectDir,
scope,
securityNode,
});
const revokedNodeCredential = await revokeSecurityNode({
clusterflux,
projectDir,
scope,
securityNode,
});
const quotaPreallocation = await runLiveQuotaPreallocation({
sessionSecret,
suffix,
});
const hostedLoginIsolation = await runHostedLoginIsolationBeforeRestart();
const serviceRestart = await restartHostedServiceAndResume({
clusterflux,
clusterfluxNode,
projectDir,
scope,
workerArgs,
workerNode,
credentialPath,
credentialDigest,
});
if (serviceRestart.worker) worker = serviceRestart.worker;
const relayAfterRestart = relayDurableState();
assert(
relayAfterRestart.ingress_used >=
bandwidthPreallocation.durable_after_release.ingress_used
);
assert(
relayAfterRestart.egress_used >=
bandwidthPreallocation.durable_after_release.egress_used
);
assert(
relayAfterRestart.abandoned_or_failed_used >=
bandwidthPreallocation.durable_after_release.abandoned_or_failed_used
);
bandwidthPreallocation.durable_after_restart = relayAfterRestart;
bandwidthPreallocation.restart_persistence = true;
bandwidthPreallocation.duration_ms =
Date.now() - bandwidthPreallocation.scenario_started_at_ms;
delete bandwidthPreallocation.scenario_started_at_ms;
await finishHostedLoginIsolationAfterRestart(hostedLoginIsolation);
const userCredentialSecurity = await finishUserCredentialSecurity({
clusterflux,
projectDir,
scope,
sessionSecret,
});
const configProvenance = configurationProvenance();
const concurrentCompileTasks = [
...new Set(
firstEvents
.filter(
(event) =>
event.task_definition === "compile_linux" &&
event.terminal_state === "completed"
)
.map((event) => event.task)
),
];
assert(concurrentCompileTasks.length >= 2);
const strictRequirementLedger = [
{ id: "01_authenticated_project", passed: Boolean(sessionSecret && tenant && project) },
{ id: "02_project_commands", passed: projectList.project_count >= 1 && projectSelect.command === "project select" },
{ id: "03_bundle_environment_inspection", passed: inspection.metadata.environments.some((environment) => environment.name === "linux") },
{ id: "04_main_parks_before_node", passed: parkedStatus.live_process.main_wait_state === "waiting_for_node" },
{ id: "05_enrollment_and_persisted_credential", passed: attach.boundary.used_enrollment_exchange === true && secondReady.node === workerNode },
{ id: "06_server_derived_node_liveness", passed: nodeLivenessTransition.initial_online === true && nodeLivenessTransition.stale_offline === false && nodeLivenessTransition.recovered_online === true },
{ id: "07_real_flagship_and_artifact", passed: completedFlagship(firstEvents) && Boolean(releaseArtifact) && builtOutput === "hello from a real Clusterflux build" },
{ id: "08_same_definition_concurrency", passed: sameDefinitionIdentity.thread_evidence.length === 2 && sameDefinitionIdentity.completion_order.length === 2 && sameDefinitionIdentity.podman_paused_container_ids.length >= 2 && sameDefinitionIdentity.terminal_state === "not_active" },
{ id: "09_repeated_park_wake", passed: repeatedParkWake.completed_cycles >= 16 && repeatedParkWake.terminal_state === "not_active" },
{ id: "10_nested_environment_rejection", passed: agentCredentialSecurity.nested_environment_mismatch.denied === true },
{ id: "11_partial_freeze_warning_resume", passed: agentCredentialSecurity.partial_freeze.partially_frozen === true && agentCredentialSecurity.partial_freeze.dap_all_threads_stopped === false && agentCredentialSecurity.partial_freeze.podman_paused_container_ids.length > 0 && agentCredentialSecurity.partial_freeze.resumed_participants.length > 0 },
{ id: "12_live_dap_edit_restart", passed: dapEditRestart.clean_vfs_boundary_used === true },
{ id: "13_long_join_and_process_lifecycle", passed: longJoin.duration_seconds > 120 && longJoin.terminal_state === "completed" && releasedFlagshipStatus.state === "not_active" && restart.restart_request.accepted === true && cancel.cancel_request.accepted === true },
{ id: "14_tenant_isolation", passed: tenantIsolation.executed === true && tenantIsolation.process_hidden === true && tenantIsolation.node_hidden === true },
{ id: "15_user_credential_hostility", passed: Boolean(userCredentialSecurity.expired && userCredentialSecurity.forged && userCredentialSecurity.revoked) },
{ id: "16_node_credential_hostility", passed: securityNode.evidence.replay.denied === true && securityNode.evidence.expired.denied === true && securityNode.evidence.forged.denied === true && revokedNodeCredential.denied.denied === true },
{ id: "17_agent_workflow_and_credentials", passed: agentCredentialSecurity.workflow.flagship_completed === true && agentCredentialSecurity.workflow.authenticated_without_browser === true && agentCredentialSecurity.workflow.external_direct_task_v1.denied === true && agentCredentialSecurity.workflow.child_launch === "task_launched" && agentCredentialSecurity.revoked.denied === true },
{ id: "18_dropped_response_rollback", passed: droppedConnectionRollback.cli_exit_status !== 0 && droppedConnectionRollback.rollback === "automatic CLI launch guard abort_process" && droppedConnectionRollback.terminal_state === "not_active" },
{ id: "19_quota_and_bandwidth_preallocation", passed: quotaPreallocation.denied_process_allocated === false && quotaPreallocation.unrelated_tenant.unaffected_by_first_tenant_quota === true && bandwidthPreallocation.bytes_served_before_denial > 0 && bandwidthPreallocation.partial_abandon.ingress_delta > 0 && bandwidthPreallocation.partial_abandon.egress_delta > 0 && bandwidthPreallocation.partial_abandon.abandoned_delta > 0 && bandwidthPreallocation.partial_abandon.reservation_released === true && bandwidthPreallocation.restart_persistence === true && relayEmergencyDisable.disabled.denied === true && relayEmergencyDisable.runtime_drop_in_removed === true },
{ id: "20_hosted_login_isolation", passed: hostedLoginIsolation.local_limited_status === 429 && hostedLoginIsolation.forwarding_spoof_status === 429 && hostedLoginIsolation.independent_vps_client_status === 200 && hostedLoginIsolation.control_route_after === "pong" && hostedLoginIsolation.after_service_restart.control_route === "pong" },
{ id: "21_soak_restart_and_provenance", passed: liveSoak.executed === true && serviceRestart.executed === true && manifest.source_tree_clean === true && configProvenance.clean === true },
];
const fullReleasePassed =
strictFullRelease &&
strictRequirementLedger.every((requirement) => requirement.passed === true);
const namedScenarios = [
{
id: "A",
name: "real asynchronous DAP lifecycle",
status: "passed",
duration_ms: dapEditRestart.duration_ms,
},
{
id: "B",
name: "same-definition task identity",
status: "passed",
duration_ms: sameDefinitionIdentity.duration_ms,
},
{
id: "C",
name: "real partial Podman freeze",
status: "passed",
duration_ms: agentCredentialSecurity.partial_freeze.elapsed_ms,
},
{
id: "D",
name: "actual CLI launch rollback",
status: "passed",
duration_ms: droppedConnectionRollback.duration_ms,
},
{
id: "E",
name: "hosted login isolation",
status: "passed",
duration_ms: hostedLoginIsolation.duration_ms,
},
{
id: "F",
name: "relay accounting",
status: "passed",
duration_ms: bandwidthPreallocation.duration_ms,
},
];
const report = {
kind: "clusterflux-cli-happy-path-live",
release_name: manifest.release_name,
source_commit: manifest.source_commit,
public_tree_identity: manifest.public_tree_identity,
service_addr: serviceAddr,
default_hosted_coordinator_endpoint: serviceEndpoint,
public_repository_url: publicSource.published ? publicSource.url : null,
public_source: publicSource,
tenant,
project,
worker_node: workerNode,
process: processId,
signed_in: true,
fresh_hosted_login: !reuseSessionFile,
reused_scoped_cli_session: Boolean(reuseSessionFile),
received_default_project: receivedDefaultProject,
process_started_before_node: true,
parked_main_observed: {
main_state: parkedStatus.live_process.main_state,
main_wait_state: parkedStatus.live_process.main_wait_state,
connected_nodes: parkedStatus.live_process.connected_nodes,
},
node_enrollment_grants_used: 2,
persisted_node_credential_mode:
process.platform === "win32" ? null : fs.statSync(credentialPath).mode & 0o777,
persisted_node_credential_digest: credentialDigest,
node_restarted_without_grant: true,
restarted_node_ready: secondReady.node,
node_liveness_transition: nodeLivenessTransition,
flagship_terminal_state: releasedFlagshipStatus.state,
flagship_task_definitions: [
"prepare_source",
"compile_linux",
"package_release",
],
rootless_podman_flagship_completed: true,
downstream_release_artifact: releaseArtifact,
artifact_download: {
bytes_written: download.local_download.bytes_written,
verified_digest: download.local_download.verified_digest,
executable_output: builtOutput,
},
flagship_process_released_automatically: true,
concurrent_same_definition_tasks: sameDefinitionIdentity,
flagship_same_definition_task_instances: concurrentCompileTasks,
repeated_park_wake: repeatedParkWake,
long_join: longJoin,
live_dap_edit_restart: dapEditRestart,
process_restart_requested: true,
process_cancel_requested: true,
dap_process_aborted: true,
tenant_isolation: tenantIsolation,
credential_security: {
user: userCredentialSecurity,
node: {
node: securityNode.node,
credential_digest: securityNode.credential_digest,
...securityNode.evidence,
revoked: revokedNodeCredential.denied,
},
agent: agentCredentialSecurity,
},
quota_preallocation: quotaPreallocation,
bandwidth_preallocation: bandwidthPreallocation,
relay_emergency_disable: relayEmergencyDisable,
hosted_login_isolation: hostedLoginIsolation,
dropped_connection_rollback: droppedConnectionRollback,
live_soak: liveSoak,
hosted_service_restart: {
...serviceRestart,
worker: undefined,
},
release_binding: {
manifest: manifestPath,
source_commit: manifest.source_commit,
source_tree_clean: manifest.source_tree_clean,
public_tree_identity: manifest.public_tree_identity,
binary_digests: manifest.binary_digests,
deployment: serviceRestart.after || deploymentProvenance(),
configuration: configProvenance,
},
commands,
named_scenarios: namedScenarios,
scenario_skips: [],
strict_requirement_ledger: strictRequirementLedger,
acceptance_result: fullReleasePassed ? "passed" : "partial",
};
ensureDir(path.dirname(reportPath));
fs.writeFileSync(reportPath, `${JSON.stringify(report, null, 2)}\n`);
if (strictFullRelease && !fullReleasePassed) {
const failed = strictRequirementLedger
.filter((requirement) => requirement.passed !== true)
.map((requirement) => requirement.id);
throw new Error(`strict full release failed: ${failed.join(", ")}`);
}
console.log(`CLI happy-path live smoke passed: ${reportPath}`);
} finally {
await stopChild(worker?.child);
}
}
main().catch((error) => {
console.error(error.stack || error.message);
process.exit(1);
});