Files
pikasTech-HWLAB/internal/cloud/access-control.test.ts
T
2026-06-01 17:06:11 +08:00

1181 lines
54 KiB
TypeScript

import assert from "node:assert/strict";
import { createServer } from "node:http";
import { test } from "bun:test";
import { createAccessController } from "./access-control.ts";
import { createCloudApiServer } from "./server.ts";
const INTERNAL_TOKEN = "test-internal-token";
test("cloud api access control grants visible device pods and requires device-pod executor", async () => {
let directGatewayDispatches = 0;
const gatewayRegistry = {
isOnline: () => true,
enqueue: async () => {
directGatewayDispatches += 1;
throw new Error("cloud-api must not bypass hwlab-device-pod executor");
},
describe: () => ({ sessions: [] })
};
const server = createCloudApiServer({
env: {
HWLAB_ACCESS_CONTROL_REQUIRED: "1",
HWLAB_BOOTSTRAP_ADMIN_USERNAME: "admin",
HWLAB_BOOTSTRAP_ADMIN_PASSWORD: "admin-pass"
},
gatewayRegistry,
now: () => "2026-05-28T00:00:00.000Z"
});
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
try {
const { port } = server.address();
const adminLogin = await postJson(port, "/auth/login", { username: "admin", password: "admin-pass" });
assert.equal(adminLogin.status, 200);
assert.equal(adminLogin.body.actor.role, "admin");
const adminCookie = adminLogin.cookie;
const userCreate = await postJson(port, "/v1/admin/users", {
username: "alice",
password: "alice-pass",
displayName: "Alice"
}, adminCookie);
assert.equal(userCreate.status, 201);
assert.equal(userCreate.body.user.username, "alice");
assert.equal(JSON.stringify(userCreate.body).includes("alice-pass"), false);
const bobCreate = await postJson(port, "/v1/admin/users", {
username: "bob",
password: "bob-pass",
displayName: "Bob"
}, adminCookie);
assert.equal(bobCreate.status, 201);
const podCreate = await postJson(port, "/v1/admin/device-pods", {
devicePodId: "device-pod-71-freq",
name: "71-FREQ",
profile: {
schemaVersion: 1,
devicePodId: "device-pod-local-spoof",
target: { id: "target-71-freq" },
projectWorkspace: { projectPath: "FirmWare/MDK-ARM/app.uvprojx", targetName: "app" },
route: {
gatewaySessionId: "gws_missing",
resourceId: "res_windows_host",
capabilityId: "cap_device_host_cli",
hostCli: "node tools/device-host-cli.mjs"
}
}
}, adminCookie);
assert.equal(podCreate.status, 201);
assert.equal(podCreate.body.devicePod.devicePodId, "device-pod-71-freq");
assert.notEqual(podCreate.body.devicePod.profileHash, "sha256:a-local-profile-hash");
assert.equal(podCreate.body.devicePod.profile.route.gatewaySessionId, "redacted");
assert.equal(JSON.stringify(podCreate.body).includes("gws_missing"), false);
const secretProfile = await postJson(port, "/v1/admin/device-pods", {
devicePodId: "device-pod-secret",
profile: {
schemaVersion: 1,
target: { id: "target-secret" },
route: {
gatewaySessionId: "gws_secret",
cloudToken: "should-not-be-stored"
}
}
}, adminCookie);
assert.equal(secretProfile.status, 400);
assert.equal(secretProfile.body.error.code, "device_pod_profile_secret_forbidden");
assert.equal(JSON.stringify(secretProfile.body).includes("should-not-be-stored"), false);
const emptyLogin = await postJson(port, "/auth/login", { username: "alice", password: "alice-pass" });
assert.equal(emptyLogin.status, 200);
const aliceCookie = emptyLogin.cookie;
const emptyList = await getJson(port, "/v1/device-pods", aliceCookie);
assert.equal(emptyList.status, 200);
assert.deepEqual(emptyList.body.devicePods, []);
const grant = await postJson(port, "/v1/admin/device-pod-grants", {
devicePodId: "device-pod-71-freq",
userId: userCreate.body.user.id
}, adminCookie);
assert.equal(grant.status, 201);
const bobGrant = await postJson(port, "/v1/admin/device-pod-grants", {
devicePodId: "device-pod-71-freq",
userId: bobCreate.body.user.id
}, adminCookie);
assert.equal(bobGrant.status, 201);
const visible = await getJson(port, "/v1/device-pods", aliceCookie);
assert.equal(visible.status, 200);
assert.equal(visible.body.contractVersion, "device-pod-authority-v1");
assert.equal(visible.body.source.kind, "CLOUD_API_PROFILE_AUTHORITY");
assert.equal(visible.body.source.fake, false);
assert.equal(visible.body.devicePods.length, 1);
assert.equal(visible.body.devicePods[0].devicePodId, "device-pod-71-freq");
assert.match(visible.body.devicePods[0].profileHash, /^sha256:/u);
const status = await getJson(port, "/v1/device-pods/device-pod-71-freq/status", aliceCookie);
assert.equal(status.status, 200);
assert.equal(status.body.devicePodId, "device-pod-71-freq");
assert.equal(status.body.targetId, "target-71-freq");
assert.equal(status.body.profileHash, visible.body.devicePods[0].profileHash);
assert.match(status.body.traceId, /^trc_devicepod_/u);
assert.match(status.body.operationId, /^op_devicepod_/u);
assert.equal(status.body.status, "ok");
assert.equal(status.body.freshness.stale, false);
assert.equal(status.body.blocker, null);
assert.equal(status.body.truncation.truncated, false);
assert.equal(status.body.output.summary, "device-pod status ok");
const job = await postJson(port, "/v1/device-pods/device-pod-71-freq/jobs", {
intent: "workspace.ls",
args: { path: "." }
}, aliceCookie);
assert.equal(job.status, 409);
assert.equal(job.body.status, "blocked");
assert.equal(job.body.blocker.code, "device_pod_executor_unavailable");
assert.equal(job.body.blocker.summary, "HWLAB_DEVICE_POD_URL is not configured; cloud-api will not bypass hwlab-device-pod executor");
assert.equal(job.body.devicePodId, "device-pod-71-freq");
assert.equal(job.body.profileHash, visible.body.devicePods[0].profileHash);
assert.equal(directGatewayDispatches, 0);
const mutatingWithoutLease = await postJson(port, "/v1/device-pods/device-pod-71-freq/jobs", {
intent: "debug.reset",
reason: "reset smoke"
}, aliceCookie);
assert.equal(mutatingWithoutLease.status, 409);
assert.equal(mutatingWithoutLease.body.error.code, "device_lease_required");
assert.equal(mutatingWithoutLease.body.status, "blocked");
assert.equal(mutatingWithoutLease.body.devicePodId, "device-pod-71-freq");
assert.equal(mutatingWithoutLease.body.profileHash, visible.body.devicePods[0].profileHash);
assert.equal(mutatingWithoutLease.body.blocker.code, "device_lease_required");
assert.equal(mutatingWithoutLease.body.freshness.stale, true);
const rejectedJob = await getJson(port, `/v1/device-pods/device-pod-71-freq/jobs/${mutatingWithoutLease.body.job.id}`, aliceCookie);
assert.equal(rejectedJob.status, 200);
assert.equal(rejectedJob.body.job.id, mutatingWithoutLease.body.job.id);
assert.equal(rejectedJob.body.status, "blocked");
assert.equal(rejectedJob.body.blocker.code, "device_lease_required");
const rejectedOutput = await getJson(port, `/v1/device-pods/device-pod-71-freq/jobs/${mutatingWithoutLease.body.job.id}/output`, aliceCookie);
assert.equal(rejectedOutput.status, 200);
assert.equal(rejectedOutput.body.truncation.truncated, false);
assert.match(rejectedOutput.body.output.error, /requires an active device lease/u);
const mutatingWithoutReason = await postJson(port, "/v1/device-pods/device-pod-71-freq/jobs", {
intent: "debug.reset"
}, aliceCookie);
assert.equal(mutatingWithoutReason.status, 400);
assert.equal(mutatingWithoutReason.body.error.code, "device_job_reason_required");
assert.equal(mutatingWithoutReason.body.status, "blocked");
assert.equal(mutatingWithoutReason.body.devicePodId, "device-pod-71-freq");
assert.equal(mutatingWithoutReason.body.profileHash, visible.body.devicePods[0].profileHash);
assert.equal(mutatingWithoutReason.body.blocker.code, "device_job_reason_required");
assert.equal(mutatingWithoutReason.body.freshness.stale, true);
const mutatingWithInvalidLease = await postJson(port, "/v1/device-pods/device-pod-71-freq/jobs", {
intent: "debug.reset",
reason: "reset smoke",
leaseToken: "invalid-lease-token"
}, aliceCookie);
assert.equal(mutatingWithInvalidLease.status, 409);
assert.equal(mutatingWithInvalidLease.body.error.code, "device_lease_invalid");
assert.equal(mutatingWithInvalidLease.body.status, "blocked");
assert.equal(mutatingWithInvalidLease.body.devicePodId, "device-pod-71-freq");
assert.equal(mutatingWithInvalidLease.body.profileHash, visible.body.devicePods[0].profileHash);
assert.equal(mutatingWithInvalidLease.body.blocker.code, "device_lease_invalid");
assert.equal(mutatingWithInvalidLease.body.freshness.stale, true);
const lease = await postJson(port, "/v1/device-pods/device-pod-71-freq/leases", {
reason: "exclusive reset smoke",
ttlSeconds: 60
}, aliceCookie);
assert.equal(lease.status, 201);
assert.equal(lease.body.contractVersion, "device-pod-lease-v1");
assert.equal(lease.body.lease.devicePodId, "device-pod-71-freq");
assert.equal(lease.body.lease.holderUserId, userCreate.body.user.id);
assert.equal(typeof lease.body.leaseToken, "string");
assert.equal(JSON.stringify(lease.body.lease).includes(lease.body.leaseToken), false);
const currentLease = await getJson(port, "/v1/device-pods/device-pod-71-freq/leases/current", aliceCookie);
assert.equal(currentLease.status, 200);
assert.equal(currentLease.body.lease.holderUserId, userCreate.body.user.id);
const releaseWithoutToken = await fetch(`http://127.0.0.1:${port}/v1/device-pods/device-pod-71-freq/leases/current`, {
method: "DELETE",
headers: { cookie: aliceCookie }
});
assert.equal(releaseWithoutToken.status, 404);
assert.equal((await releaseWithoutToken.json()).released, false);
const currentAfterMissingToken = await getJson(port, "/v1/device-pods/device-pod-71-freq/leases/current", aliceCookie);
assert.equal(currentAfterMissingToken.status, 200);
assert.equal(currentAfterMissingToken.body.lease.holderUserId, userCreate.body.user.id);
const bobLogin = await postJson(port, "/auth/login", { username: "bob", password: "bob-pass" });
assert.equal(bobLogin.status, 200);
const bobLeaseConflict = await postJson(port, "/v1/device-pods/device-pod-71-freq/leases", {
reason: "exclusive reset smoke"
}, bobLogin.cookie);
assert.equal(bobLeaseConflict.status, 409);
assert.equal(bobLeaseConflict.body.error.code, "device_lease_conflict");
assert.equal(bobLeaseConflict.body.lease.holderUserId, userCreate.body.user.id);
const bobListWithoutPrivateGrant = await getJson(port, "/v1/device-pods", bobLogin.cookie);
assert.equal(bobListWithoutPrivateGrant.status, 200);
assert.equal(bobListWithoutPrivateGrant.body.devicePods.length, 1);
const privatePodCreate = await postJson(port, "/v1/admin/device-pods", {
devicePodId: "device-pod-private",
profile: { schemaVersion: 1, target: { id: "target-private" }, route: { gatewaySessionId: "gws_private" } }
}, adminCookie);
assert.equal(privatePodCreate.status, 201);
const bobPrivateStatus = await getJson(port, "/v1/device-pods/device-pod-private/status", bobLogin.cookie);
assert.equal(bobPrivateStatus.status, 403);
assert.equal(bobPrivateStatus.body.error.code, "device_pod_forbidden");
const bobMissingStatus = await getJson(port, "/v1/device-pods/device-pod-missing/status", bobLogin.cookie);
assert.equal(bobMissingStatus.status, 404);
assert.equal(bobMissingStatus.body.error.code, "device_pod_not_found");
const mutatingWithLease = await postJson(port, "/v1/device-pods/device-pod-71-freq/jobs", {
intent: "debug.reset",
reason: "reset smoke with lease",
leaseToken: lease.body.leaseToken
}, aliceCookie);
assert.equal(mutatingWithLease.status, 409);
assert.equal(mutatingWithLease.body.status, "blocked");
assert.equal(mutatingWithLease.body.lease.holderUserId, userCreate.body.user.id);
assert.equal(mutatingWithLease.body.blocker.code, "device_pod_executor_unavailable");
assert.equal(directGatewayDispatches, 0);
const release = await fetch(`http://127.0.0.1:${port}/v1/device-pods/device-pod-71-freq/leases/current`, {
method: "DELETE",
headers: { cookie: aliceCookie, "x-hwlab-device-lease-token": lease.body.leaseToken }
});
assert.equal(release.status, 200);
assert.equal((await release.json()).released, true);
const bobLease = await postJson(port, "/v1/device-pods/device-pod-71-freq/leases", {
reason: "exclusive reset smoke after release"
}, bobLogin.cookie);
assert.equal(bobLease.status, 201);
assert.equal(bobLease.body.lease.holderUserId, bobCreate.body.user.id);
const events = await getJson(port, "/v1/device-pods/device-pod-71-freq/events", aliceCookie);
assert.equal(events.status, 200);
assert.equal(events.body.events[0].blocker.code, "device_pod_executor_unavailable");
const unsupported = await postJson(port, "/v1/device-pods/device-pod-71-freq/jobs", {
intent: "debug.erase-all",
args: {}
}, aliceCookie);
assert.equal(unsupported.status, 400);
assert.equal(unsupported.body.error.code, "unsupported_device_job_intent");
const revoke = await fetch(`http://127.0.0.1:${port}/v1/admin/device-pod-grants/device-pod-71-freq/${bobCreate.body.user.id}`, {
method: "DELETE",
headers: { cookie: adminCookie }
});
assert.equal(revoke.status, 200);
const revoked = await revoke.json();
assert.equal(revoked.devicePodId, "device-pod-71-freq");
assert.equal(revoked.userId, bobCreate.body.user.id);
assert.equal(revoked.releasedLease.holderUserId, bobCreate.body.user.id);
assert.equal(revoked.releasedLease.active, false);
const afterRevoke = await getJson(port, "/v1/device-pods", bobLogin.cookie);
assert.equal(afterRevoke.status, 200);
assert.deepEqual(afterRevoke.body.devicePods, []);
} finally {
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
}
});
test("cloud api stores and restores Code Agent conversations by authenticated account", async () => {
const server = createCloudApiServer({
env: {
HWLAB_ACCESS_CONTROL_REQUIRED: "1",
HWLAB_BOOTSTRAP_ADMIN_USERNAME: "admin",
HWLAB_BOOTSTRAP_ADMIN_PASSWORD: "admin-pass"
},
now: () => "2026-05-31T07:30:00.000Z"
});
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
try {
const { port } = server.address();
const adminLogin = await postJson(port, "/auth/login", { username: "admin", password: "admin-pass" });
const adminCookie = adminLogin.cookie;
const aliceCreate = await postJson(port, "/v1/admin/users", { username: "alice", password: "alice-pass" }, adminCookie);
const bobCreate = await postJson(port, "/v1/admin/users", { username: "bob", password: "bob-pass" }, adminCookie);
assert.equal(aliceCreate.status, 201);
assert.equal(bobCreate.status, 201);
const aliceLogin = await postJson(port, "/auth/login", { username: "alice", password: "alice-pass" });
const bobLogin = await postJson(port, "/auth/login", { username: "bob", password: "bob-pass" });
const stored = await putJson(port, "/v1/agent/conversations/cnv_account_sync", {
projectId: "prj_device_pod_workbench",
sessionId: "ses_account_sync",
threadId: "thread-account-sync",
lastTraceId: "trc_account_sync",
sessionStatus: "idle",
messages: [
{ id: "msg_user", role: "user", title: "用户", text: "在吗", status: "sent", conversationId: "cnv_account_sync", sessionId: "ses_account_sync", threadId: "thread-account-sync" },
{ id: "msg_agent", role: "agent", title: "Agent", text: "在", status: "completed", traceId: "trc_account_sync", conversationId: "cnv_account_sync", sessionId: "ses_account_sync", threadId: "thread-account-sync" }
]
}, aliceLogin.cookie);
assert.equal(stored.status, 200);
assert.equal(stored.body.conversation.conversationId, "cnv_account_sync");
assert.equal(stored.body.conversation.sessionId, "ses_account_sync");
assert.equal(stored.body.conversation.threadId, "thread-account-sync");
assert.equal(stored.body.conversation.status, "idle");
assert.equal(stored.body.conversation.messages.length, 2);
const aliceList = await getJson(port, "/v1/agent/conversations?projectId=prj_device_pod_workbench", aliceLogin.cookie);
assert.equal(aliceList.status, 200);
assert.equal(aliceList.body.count, 1);
assert.equal(aliceList.body.defaultConversation.conversationId, "cnv_account_sync");
assert.equal(aliceList.body.defaultConversation.messages[1].text, "在");
assert.equal(aliceList.body.defaultConversation.valuesRedacted, true);
const bobList = await getJson(port, "/v1/agent/conversations?projectId=prj_device_pod_workbench", bobLogin.cookie);
assert.equal(bobList.status, 200);
assert.deepEqual(bobList.body.conversations, []);
const bobDirect = await getJson(port, "/v1/agent/conversations/cnv_account_sync", bobLogin.cookie);
assert.equal(bobDirect.status, 404);
assert.equal(bobDirect.body.error.code, "agent_conversation_not_found");
const logout = await postJson(port, "/auth/logout", {}, aliceLogin.cookie);
assert.equal(logout.status, 200);
const relogin = await postJson(port, "/auth/login", { username: "alice", password: "alice-pass" });
const restored = await getJson(port, "/v1/agent/conversations/cnv_account_sync", relogin.cookie);
assert.equal(restored.status, 200);
assert.equal(restored.body.conversation.threadId, "thread-account-sync");
assert.equal(restored.body.conversation.messages[0].text, "在吗");
} finally {
await new Promise((resolve, reject) => {
server.close((error) => (error ? reject(error) : resolve()));
});
}
});
test("access controller restores AgentRun mapping by Code Agent traceId", async () => {
const accessController = createAccessController({ now: () => "2026-06-01T00:00:00.000Z" });
await accessController.recordAgentSessionOwner({
ownerUserId: "usr_agent_owner",
sessionId: "ses_agentrun_trace_lookup",
projectId: "prj_v02_code_agent",
conversationId: "cnv_agentrun_trace_lookup",
threadId: "thread-agentrun-trace-lookup",
traceId: "trc_agentrun_trace_lookup",
status: "running",
session: {
source: "hwlab-cloud-api-agentrun-v01-adapter",
agentRun: {
adapter: "agentrun-v01",
runId: "run_trace_lookup",
commandId: "cmd_trace_lookup",
jobName: "agentrun-v01-runner-trace-lookup",
namespace: "agentrun-v01",
backendProfile: "deepseek",
valuesPrinted: false
},
valuesRedacted: true
}
});
const restored = await accessController.getAgentSessionByTraceId("trc_agentrun_trace_lookup");
assert.equal(restored.id, "ses_agentrun_trace_lookup");
assert.equal(restored.lastTraceId, "trc_agentrun_trace_lookup");
assert.equal(restored.session.agentRun.runId, "run_trace_lookup");
assert.equal(restored.session.agentRun.commandId, "cmd_trace_lookup");
assert.equal(restored.session.agentRun.namespace, "agentrun-v01");
});
test("cloud api protects device-pod routes when access control is required", async () => {
const server = createCloudApiServer({
env: { HWLAB_ACCESS_CONTROL_REQUIRED: "1" },
now: () => "2026-05-28T00:00:00.000Z"
});
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
try {
const { port } = server.address();
const response = await fetch(`http://127.0.0.1:${port}/v1/device-pods`);
assert.equal(response.status, 401);
const payload = await response.json();
assert.equal(payload.error.code, "auth_required");
} finally {
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
}
});
test("cloud api issues a redacted Code Agent device-pod session with admin device access", async () => {
const accessController = createAccessController({
env: {
HWLAB_ACCESS_CONTROL_REQUIRED: "1",
HWLAB_BOOTSTRAP_ADMIN_ID: "usr_v02_admin",
HWLAB_BOOTSTRAP_ADMIN_USERNAME: "admin",
HWLAB_BOOTSTRAP_ADMIN_PASSWORD: "admin-pass"
},
now: () => "2026-05-28T00:00:00.000Z"
});
const server = createCloudApiServer({
env: {
HWLAB_ACCESS_CONTROL_REQUIRED: "1",
HWLAB_BOOTSTRAP_ADMIN_ID: "usr_v02_admin",
HWLAB_BOOTSTRAP_ADMIN_USERNAME: "admin",
HWLAB_BOOTSTRAP_ADMIN_PASSWORD: "admin-pass"
},
accessController,
now: () => "2026-05-28T00:00:00.000Z"
});
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
try {
const { port } = server.address();
const adminLogin = await postJson(port, "/auth/login", { username: "admin", password: "admin-pass" });
await postJson(port, "/v1/admin/device-pods", {
devicePodId: "device-pod-71-freq",
profile: { schemaVersion: 1, target: { id: "target-71-freq" }, route: { gatewaySessionId: "gws_unused" } }
}, adminLogin.cookie);
const agentAuth = await accessController.createCodeAgentDevicePodSession();
assert.equal(agentAuth.actor.id, "usr_v02_admin");
assert.equal(agentAuth.actor.role, "admin");
assert.equal(agentAuth.tokenSource, "code-agent-device-pod-session");
assert.equal(agentAuth.valuesRedacted, true);
assert.equal(typeof agentAuth.token, "string");
assert.equal(JSON.stringify(agentAuth.session).includes(agentAuth.token), false);
const status = await getJson(port, "/v1/device-pods/device-pod-71-freq/status", null, {
"x-hwlab-session-token": agentAuth.token
});
assert.equal(status.status, 200);
assert.equal(status.body.devicePodId, "device-pod-71-freq");
assert.equal(status.body.actor.id, "usr_v02_admin");
assert.equal(status.body.actor.role, "admin");
assert.equal(JSON.stringify(status.body).includes(agentAuth.token), false);
} finally {
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
}
});
test("cloud api creates device lease holder session before lease insert", async () => {
const accessController = createAccessController({
env: {
HWLAB_ACCESS_CONTROL_REQUIRED: "1",
HWLAB_BOOTSTRAP_ADMIN_USERNAME: "admin",
HWLAB_BOOTSTRAP_ADMIN_PASSWORD: "admin-pass"
},
now: () => "2026-05-28T00:00:00.000Z"
});
const store = accessController.store;
const leaseOrder = [];
const holderSessions = new Set();
const recordAgentSessionOwner = store.recordAgentSessionOwner.bind(store);
store.recordAgentSessionOwner = async (input) => {
leaseOrder.push(`record:${input.sessionId}`);
holderSessions.add(input.sessionId);
return recordAgentSessionOwner(input);
};
const acquireDeviceLease = store.acquireDeviceLease.bind(store);
store.acquireDeviceLease = async (input) => {
leaseOrder.push(`acquire:${input.holderSessionId}`);
if (!holderSessions.has(input.holderSessionId)) throw new Error("holder_session_fk_missing");
return acquireDeviceLease(input);
};
const server = createCloudApiServer({
env: {
HWLAB_ACCESS_CONTROL_REQUIRED: "1",
HWLAB_BOOTSTRAP_ADMIN_USERNAME: "admin",
HWLAB_BOOTSTRAP_ADMIN_PASSWORD: "admin-pass"
},
accessController,
now: () => "2026-05-28T00:00:00.000Z"
});
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
try {
const { port } = server.address();
const adminLogin = await postJson(port, "/auth/login", { username: "admin", password: "admin-pass" });
const userCreate = await postJson(port, "/v1/admin/users", { username: "alice", password: "alice-pass" }, adminLogin.cookie);
await postJson(port, "/v1/admin/device-pods", {
devicePodId: "device-pod-71-freq",
profile: { schemaVersion: 1, target: { id: "target-71-freq" }, route: { gatewaySessionId: "gws_unused" } }
}, adminLogin.cookie);
await postJson(port, "/v1/admin/device-pod-grants", { devicePodId: "device-pod-71-freq", userId: userCreate.body.user.id }, adminLogin.cookie);
const aliceLogin = await postJson(port, "/auth/login", { username: "alice", password: "alice-pass" });
const lease = await postJson(port, "/v1/device-pods/device-pod-71-freq/leases", {
agentSessionId: "ses_fk_order_test",
reason: "fk order smoke",
ttlSeconds: 60
}, aliceLogin.cookie);
assert.equal(lease.status, 201);
assert.equal(lease.body.acquired, true);
assert.equal(lease.body.lease.holderSessionId, "ses_fk_order_test");
assert.deepEqual(leaseOrder, ["record:ses_fk_order_test", "acquire:ses_fk_order_test"]);
} finally {
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
}
});
test("cloud api dispatches authorized device jobs to the internal device-pod executor", async () => {
const executorRequests = [];
const executor = createServer(async (request, response) => {
const body = await requestJson(request);
executorRequests.push({ method: request.method, url: request.url, internalService: request.headers["x-hwlab-internal-service"], internalToken: request.headers["x-hwlab-internal-token"], body });
if (request.method === "POST" && body.args?.path === "src") {
response.writeHead(202, { "content-type": "application/json; charset=utf-8" });
response.end(JSON.stringify({
accepted: true,
status: "running",
contractVersion: "device-pod-executor-v1",
devicePodId: "device-pod-71-freq",
traceId: body.traceId,
operationId: body.operationId,
job: { id: body.jobId, devicePodId: body.devicePodId, status: "running", intent: body.intent, reason: body.reason, traceId: body.traceId, operationId: body.operationId },
blocker: null
}));
return;
}
if (request.method === "GET" && request.url.endsWith("/output")) {
response.writeHead(200, { "content-type": "application/json; charset=utf-8" });
response.end(JSON.stringify({
accepted: true,
status: "completed",
contractVersion: "device-pod-executor-v1",
devicePodId: "device-pod-71-freq",
traceId: "trc_executor_refresh",
operationId: "op_executor_refresh",
job: { id: request.url.split("/").at(-2), devicePodId: "device-pod-71-freq", status: "completed", intent: "workspace.ls" },
output: { text: "executor output", bytes: 15, truncation: { maxBytes: 12000, truncated: false } },
text: "executor output"
}));
return;
}
response.writeHead(409, { "content-type": "application/json; charset=utf-8" });
response.end(JSON.stringify({
accepted: false,
status: "blocked",
contractVersion: "device-pod-executor-v1",
devicePodId: "device-pod-71-freq",
traceId: body.traceId,
operationId: body.operationId,
job: { id: body.jobId, devicePodId: body.devicePodId, status: "blocked", intent: body.intent, reason: body.reason, traceId: body.traceId, operationId: body.operationId },
blocker: { code: "gateway_dispatch_unavailable", layer: "device-pod", retryable: true, summary: "executor test blocker" },
output: { text: "executor output", bytes: 15, truncation: { maxBytes: 12000, truncated: false } }
}));
});
await new Promise((resolve) => executor.listen(0, "127.0.0.1", resolve));
const executorPort = executor.address().port;
const server = createCloudApiServer({
env: {
HWLAB_ACCESS_CONTROL_REQUIRED: "1",
HWLAB_BOOTSTRAP_ADMIN_USERNAME: "admin",
HWLAB_BOOTSTRAP_ADMIN_PASSWORD: "admin-pass",
HWLAB_DEVICE_POD_INTERNAL_TOKEN: INTERNAL_TOKEN,
HWLAB_DEVICE_POD_URL: `http://127.0.0.1:${executorPort}`
},
now: () => "2026-05-28T00:00:00.000Z"
});
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
try {
const { port } = server.address();
const adminLogin = await postJson(port, "/auth/login", { username: "admin", password: "admin-pass" });
const userCreate = await postJson(port, "/v1/admin/users", { username: "alice", password: "alice-pass" }, adminLogin.cookie);
await postJson(port, "/v1/admin/device-pods", {
devicePodId: "device-pod-71-freq",
profile: { schemaVersion: 1, target: { id: "target-71-freq" }, route: { gatewaySessionId: "gws_unused" } }
}, adminLogin.cookie);
await postJson(port, "/v1/admin/device-pod-grants", { devicePodId: "device-pod-71-freq", userId: userCreate.body.user.id }, adminLogin.cookie);
const aliceLogin = await postJson(port, "/auth/login", { username: "alice", password: "alice-pass" });
const job = await postJson(port, "/v1/device-pods/device-pod-71-freq/jobs", { intent: "workspace.ls", args: { path: "." } }, aliceLogin.cookie);
assert.equal(job.status, 409);
assert.equal(job.body.blocker.code, "gateway_dispatch_unavailable");
assert.equal(job.body.job.status, "blocked");
assert.equal(executorRequests.length, 1);
assert.equal(executorRequests[0].internalService, "hwlab-cloud-api");
assert.equal(executorRequests[0].internalToken, INTERNAL_TOKEN);
assert.equal(executorRequests[0].body.profileHash, job.body.profileHash);
assert.equal(executorRequests[0].body.ownerUserId, userCreate.body.user.id);
assert.equal(executorRequests[0].body.intent, "workspace.ls");
const stored = await getJson(port, `/v1/device-pods/device-pod-71-freq/jobs/${job.body.job.id}`, aliceLogin.cookie);
assert.equal(stored.status, 200);
assert.equal(stored.body.job.id, job.body.job.id);
assert.equal(stored.body.blocker.code, "gateway_dispatch_unavailable");
const runningJob = await postJson(port, "/v1/device-pods/device-pod-71-freq/jobs", { intent: "workspace.ls", args: { path: "src" } }, aliceLogin.cookie);
assert.equal(runningJob.status, 202);
assert.equal(runningJob.body.status, "running");
const output = await getJson(port, `/v1/device-pods/device-pod-71-freq/jobs/${runningJob.body.job.id}/output`, aliceLogin.cookie);
assert.equal(output.status, 200);
assert.equal(output.body.status, "completed");
assert.equal(output.body.blocker, null);
assert.equal(output.body.freshness.stale, false);
assert.equal(output.body.output.text, "executor output");
assert.equal(output.body.truncation.truncated, false);
assert.ok(executorRequests.some((item) => item.method === "GET" && item.url.endsWith(`/jobs/${runningJob.body.job.id}/output`)));
const events = await getJson(port, "/v1/device-pods/device-pod-71-freq/events", aliceLogin.cookie);
const completedEvent = events.body.events.find((event) => event.refs.jobId === runningJob.body.job.id);
assert.equal(completedEvent.status, "completed");
assert.equal(completedEvent.blocker, null);
} finally {
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
await new Promise((resolve, reject) => executor.close((error) => (error ? reject(error) : resolve())));
}
});
test("cloud api bounds device-pod job output payloads", async () => {
const longText = "x".repeat(13000);
const executor = createServer(async (request, response) => {
const body = await requestJson(request);
response.writeHead(200, { "content-type": "application/json; charset=utf-8" });
response.end(JSON.stringify({
accepted: true,
status: "completed",
contractVersion: "device-pod-executor-v1",
devicePodId: "device-pod-71-freq",
traceId: body.traceId,
operationId: body.operationId,
job: { id: body.jobId, devicePodId: body.devicePodId, status: "completed", intent: body.intent },
output: { text: longText, nested: { kept: true } },
text: longText
}));
});
await new Promise((resolve) => executor.listen(0, "127.0.0.1", resolve));
const executorPort = executor.address().port;
const server = createCloudApiServer({
env: {
HWLAB_ACCESS_CONTROL_REQUIRED: "1",
HWLAB_BOOTSTRAP_ADMIN_USERNAME: "admin",
HWLAB_BOOTSTRAP_ADMIN_PASSWORD: "admin-pass",
HWLAB_DEVICE_POD_INTERNAL_TOKEN: INTERNAL_TOKEN,
HWLAB_DEVICE_POD_URL: `http://127.0.0.1:${executorPort}`
},
now: () => "2026-05-28T00:00:00.000Z"
});
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
try {
const { port } = server.address();
const adminLogin = await postJson(port, "/auth/login", { username: "admin", password: "admin-pass" });
const userCreate = await postJson(port, "/v1/admin/users", { username: "alice", password: "alice-pass" }, adminLogin.cookie);
await postJson(port, "/v1/admin/device-pods", {
devicePodId: "device-pod-71-freq",
profile: { schemaVersion: 1, target: { id: "target-71-freq" }, route: { gatewaySessionId: "gws_unused" } }
}, adminLogin.cookie);
await postJson(port, "/v1/admin/device-pod-grants", { devicePodId: "device-pod-71-freq", userId: userCreate.body.user.id }, adminLogin.cookie);
const aliceLogin = await postJson(port, "/auth/login", { username: "alice", password: "alice-pass" });
const job = await postJson(port, "/v1/device-pods/device-pod-71-freq/jobs", { intent: "workspace.ls", args: { path: "." } }, aliceLogin.cookie);
assert.equal(job.status, 200);
const output = await getJson(port, `/v1/device-pods/device-pod-71-freq/jobs/${job.body.job.id}/output`, aliceLogin.cookie);
assert.equal(output.status, 200);
assert.equal(output.body.bytes, 12000);
assert.equal(output.body.text.length, 12000);
assert.equal(output.body.output.text.length, 12000);
assert.equal(output.body.truncation.truncated, true);
assert.equal(output.body.truncation.originalBytes, 13000);
assert.equal(output.body.output.omitted.reason, "device_job_output_truncated");
assert.equal(JSON.stringify(output.body).includes(longText), false);
} finally {
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
await new Promise((resolve, reject) => executor.close((error) => (error ? reject(error) : resolve())));
}
});
test("cloud api routes device-pod probe GET requests through executor jobs", async () => {
const executorRequests = [];
const executor = createServer(async (request, response) => {
const body = await requestJson(request);
executorRequests.push({ method: request.method, url: request.url, body });
const text = body.intent === "debug.chip-id" ? "chip-id: 0x12345678" : "uart tail output";
response.writeHead(200, { "content-type": "application/json; charset=utf-8" });
response.end(JSON.stringify({
accepted: true,
status: "completed",
contractVersion: "device-pod-executor-v1",
devicePodId: body.devicePodId,
traceId: body.traceId,
operationId: body.operationId,
job: { id: body.jobId, devicePodId: body.devicePodId, status: "completed", intent: body.intent },
output: { text },
text
}));
});
await new Promise((resolve) => executor.listen(0, "127.0.0.1", resolve));
const executorPort = executor.address().port;
const server = createCloudApiServer({
env: {
HWLAB_ACCESS_CONTROL_REQUIRED: "1",
HWLAB_BOOTSTRAP_ADMIN_USERNAME: "admin",
HWLAB_BOOTSTRAP_ADMIN_PASSWORD: "admin-pass",
HWLAB_DEVICE_POD_INTERNAL_TOKEN: INTERNAL_TOKEN,
HWLAB_DEVICE_POD_URL: `http://127.0.0.1:${executorPort}`
},
now: () => "2026-05-28T00:00:00.000Z"
});
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
try {
const { port } = server.address();
const adminLogin = await postJson(port, "/auth/login", { username: "admin", password: "admin-pass" });
const userCreate = await postJson(port, "/v1/admin/users", { username: "alice", password: "alice-pass" }, adminLogin.cookie);
await postJson(port, "/v1/admin/device-pods", {
devicePodId: "device-pod-71-freq",
profile: { schemaVersion: 1, target: { id: "target-71-freq" }, route: { gatewaySessionId: "gws_unused" } }
}, adminLogin.cookie);
await postJson(port, "/v1/admin/device-pod-grants", { devicePodId: "device-pod-71-freq", userId: userCreate.body.user.id }, adminLogin.cookie);
const aliceLogin = await postJson(port, "/auth/login", { username: "alice", password: "alice-pass" });
const chip = await getJson(port, "/v1/device-pods/device-pod-71-freq/debug-probe/chip-id", aliceLogin.cookie);
assert.equal(chip.status, 200);
assert.equal(chip.body.interface, "debug-probe");
assert.equal(chip.body.intent, "debug.chip-id");
assert.equal(chip.body.job.intent, "debug.chip-id");
assert.equal(chip.body.output.text, "chip-id: 0x12345678");
assert.equal(chip.body.source.fake, false);
const uart = await getJson(port, "/v1/device-pods/device-pod-71-freq/io-probe/uart/1/tail?durationMs=250&maxBytes=20", aliceLogin.cookie);
assert.equal(uart.status, 200);
assert.equal(uart.body.interface, "io-probe");
assert.equal(uart.body.intent, "io.uart.read");
assert.equal(uart.body.output.text, "uart tail output");
assert.equal(uart.body.truncation.maxBytes, 20);
assert.equal(executorRequests.length, 2);
assert.equal(executorRequests[0].method, "POST");
assert.equal(executorRequests[0].body.intent, "debug.chip-id");
assert.equal(executorRequests[0].body.ownerUserId, userCreate.body.user.id);
assert.equal(executorRequests[1].body.intent, "io.uart.read");
assert.deepEqual(executorRequests[1].body.args, { uartId: "uart/1", durationMs: 250, maxBytes: 20 });
const events = await getJson(port, "/v1/device-pods/device-pod-71-freq/events", aliceLogin.cookie);
assert.equal(events.status, 200);
assert.ok(events.body.events.some((event) => event.intent === "debug.chip-id"));
assert.ok(events.body.events.some((event) => event.intent === "io.uart.read"));
} finally {
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
await new Promise((resolve, reject) => executor.close((error) => (error ? reject(error) : resolve())));
}
});
test("cloud api internal device-pod gateway dispatch is service-only and fail-closed without online gateway", async () => {
const server = createCloudApiServer({
env: { HWLAB_ACCESS_CONTROL_REQUIRED: "1", HWLAB_DEVICE_POD_INTERNAL_TOKEN: INTERNAL_TOKEN },
now: () => "2026-05-28T00:00:00.000Z"
});
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
try {
const { port } = server.address();
const external = await postJson(port, "/v1/internal/device-pod/gateway-dispatch", { params: {} });
assert.equal(external.status, 403);
assert.equal(external.body.error.code, "device_pod_internal_authority_required");
const headerOnly = await postJson(port, "/v1/internal/device-pod/gateway-dispatch", {
id: "req_devicepod_dispatch_test",
params: {
gatewaySessionId: "gws_missing",
resourceId: "res_devicepod_test",
capabilityId: "cap_device_host_cli",
operationId: "op_devicepod_dispatch_test",
traceId: "trc_devicepod_dispatch_test",
input: { command: "node tools/device-host-cli.mjs health" }
}
}, null, { "x-hwlab-internal-service": "hwlab-device-pod" });
assert.equal(headerOnly.status, 403);
assert.equal(headerOnly.body.error.code, "device_pod_internal_authority_required");
const blocked = await postJson(port, "/v1/internal/device-pod/gateway-dispatch", {
id: "req_devicepod_dispatch_test",
params: {
gatewaySessionId: "gws_missing",
resourceId: "res_devicepod_test",
capabilityId: "cap_device_host_cli",
operationId: "op_devicepod_dispatch_test",
traceId: "trc_devicepod_dispatch_test",
input: { command: "node tools/device-host-cli.mjs health" }
}
}, null, devicePodInternalHeaders());
assert.equal(blocked.status, 409);
assert.equal(blocked.body.blocker.code, "gateway_dispatch_unavailable");
} finally {
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
}
});
test("cloud api internal device-pod gateway dispatch uses gateway poll result", async () => {
const server = createCloudApiServer({
env: { HWLAB_ACCESS_CONTROL_REQUIRED: "1", HWLAB_ENVIRONMENT: "v02", HWLAB_DEVICE_POD_INTERNAL_TOKEN: INTERNAL_TOKEN },
now: () => "2026-05-28T00:00:00.000Z"
});
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
try {
const { port } = server.address();
const poll = await postJson(port, "/v1/gateway/poll", {
serviceId: "hwlab-gateway",
gatewayId: "gtw_devicepod_test",
gatewaySessionId: "gws_devicepod_test",
resourceId: "res_devicepod_test",
capabilities: [{ capabilityId: "cap_device_host_cli", resourceId: "res_devicepod_test" }]
});
assert.equal(poll.status, 200);
const dispatchPromise = postJson(port, "/v1/internal/device-pod/gateway-dispatch", {
id: "req_devicepod_dispatch_test",
params: {
gatewaySessionId: "gws_devicepod_test",
resourceId: "res_devicepod_test",
capabilityId: "cap_device_host_cli",
operationId: "op_devicepod_dispatch_test",
traceId: "trc_devicepod_dispatch_test",
input: { command: "node tools/device-host-cli.mjs health", timeoutMs: 1000 }
}
}, null, devicePodInternalHeaders());
const queued = await postJson(port, "/v1/gateway/poll", { gatewayId: "gtw_devicepod_test", gatewaySessionId: "gws_devicepod_test" });
assert.equal(queued.status, 200);
assert.equal(queued.body.type, "request");
assert.equal(queued.body.request.meta.environment, "v02");
assert.equal(queued.body.request.method, "hardware.invoke.shell");
assert.equal(queued.body.request.params.input.command, "node tools/device-host-cli.mjs health");
const result = await postJson(port, "/v1/gateway/result", {
gatewayId: "gtw_devicepod_test",
gatewaySessionId: "gws_devicepod_test",
response: {
jsonrpc: "2.0",
id: queued.body.request.id,
result: {
accepted: true,
status: "succeeded",
shellExecuted: true,
dispatchStatus: "succeeded",
stdout: "host cli ok",
exitCode: 0,
gatewaySessionId: "gws_devicepod_test"
}
}
});
assert.equal(result.status, 200);
const dispatch = await dispatchPromise;
assert.equal(dispatch.status, 200);
assert.equal(dispatch.body.meta.environment, "v02");
assert.equal(dispatch.body.result.status, "completed");
assert.equal(dispatch.body.result.dispatch.stdout, "host cli ok");
} finally {
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
}
});
test("cloud api exposes v1 access status routes and returns structured REST errors", async () => {
const server = createCloudApiServer({
env: { HWLAB_ACCESS_CONTROL_REQUIRED: "1" },
now: () => "2026-05-28T00:00:00.000Z"
});
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
try {
const { port } = server.address();
const session = await getJson(port, "/v1/auth/session");
assert.equal(session.status, 200);
assert.equal(session.body.authenticated, false);
assert.equal(session.body.setupRequired, true);
assert.equal(session.body.contractVersion, "user-access-v1");
const access = await getJson(port, "/v1/access/status");
assert.equal(access.status, 200);
assert.equal(access.body.accessControlRequired, true);
assert.equal(access.body.routes.currentUser, "/v1/users/me");
const setup = await getJson(port, "/v1/setup/status");
assert.equal(setup.status, 200);
assert.equal(setup.body.setupRequired, true);
assert.equal(setup.body.bootstrapAdminConfigured, false);
const me = await getJson(port, "/v1/users/me");
assert.equal(me.status, 401);
assert.equal(me.body.error.code, "auth_required");
const missing = await getJson(port, "/v1/not-implemented");
assert.equal(missing.status, 404);
assert.equal(missing.body.error.code, "not_found");
assert.equal(missing.body.error.audit.source.serviceId, "hwlab-cloud-api");
} finally {
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
}
});
test("cloud api first-admin setup opens access when bootstrap secret is absent", async () => {
const server = createCloudApiServer({
env: { HWLAB_ACCESS_CONTROL_REQUIRED: "1" },
now: () => "2026-05-28T00:00:00.000Z"
});
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
try {
const { port } = server.address();
const before = await getJson(port, "/v1/setup/status");
assert.equal(before.status, 200);
assert.equal(before.body.setupRequired, true);
assert.equal(before.body.bootstrapAdminConfigured, false);
assert.equal(before.body.routes.firstAdminSetup, "/v1/setup/first-admin");
const setup = await postJson(port, "/v1/setup/first-admin", {
username: "admin",
password: "admin-pass",
displayName: "Initial Admin",
devicePod: {
devicePodId: "device-pod-71-freq",
name: "71-FREQ",
profile: {
schemaVersion: 1,
devicePodId: "device-pod-seed-spoof",
target: { id: "target-71-freq" },
route: {
gatewaySessionId: "gws_first_admin_seed",
resourceId: "res_windows_host",
capabilityId: "cap_device_host_cli",
hostWorkspaceRoot: "F:\\Work\\Project",
hostCli: "node tools/device-host-cli.mjs"
}
}
}
});
assert.equal(setup.status, 201);
assert.equal(setup.body.created, true);
assert.equal(setup.body.authenticated, true);
assert.equal(setup.body.actor.role, "admin");
assert.equal(setup.body.actor.username, "admin");
assert.equal(setup.body.setupRequired, false);
assert.deepEqual(setup.body.devicePodBootstrap, { requested: 1, initialized: 1 });
assert.equal(setup.body.devicePodsInitialized[0].devicePod.devicePodId, "device-pod-71-freq");
assert.equal(setup.body.devicePodsInitialized[0].grant.userId, setup.body.actor.id);
assert.match(setup.body.devicePodsInitialized[0].devicePod.profileHash, /^sha256:/u);
assert.equal(setup.body.devicePodsInitialized[0].devicePod.profile.route.gatewaySessionId, "redacted");
assert.equal(JSON.stringify(setup.body).includes("device-pod-seed-spoof"), false);
assert.equal(JSON.stringify(setup.body).includes("admin-pass"), false);
assert.equal(JSON.stringify(setup.body).includes("gws_first_admin_seed"), false);
assert.equal(JSON.stringify(setup.body).includes("F:\\Work\\Project"), false);
assert.equal(typeof setup.cookie, "string");
const session = await getJson(port, "/v1/users/me", setup.cookie);
assert.equal(session.status, 200);
assert.equal(session.body.actor.role, "admin");
assert.equal(JSON.stringify(session.body).includes("passwordHash"), false);
const second = await postJson(port, "/v1/setup/first-admin", {
username: "other-admin",
password: "other-pass"
});
assert.equal(second.status, 409);
assert.equal(second.body.error.code, "setup_already_completed");
const pods = await getJson(port, "/v1/device-pods", setup.cookie);
assert.equal(pods.status, 200);
assert.equal(pods.body.devicePods.length, 1);
assert.equal(pods.body.devicePods[0].devicePodId, "device-pod-71-freq");
assert.match(pods.body.devicePods[0].profileHash, /^sha256:/u);
const job = await postJson(port, "/v1/device-pods/device-pod-71-freq/jobs", {
intent: "workspace.ls",
args: { path: "." }
}, setup.cookie);
assert.equal(job.status, 409);
assert.equal(job.body.devicePodId, "device-pod-71-freq");
assert.equal(job.body.blocker.code, "device_pod_executor_unavailable");
const login = await postJson(port, "/auth/login", { username: "admin", password: "admin-pass" });
assert.equal(login.status, 200);
assert.equal(login.body.actor.role, "admin");
} finally {
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
}
});
test("cloud api bootstrap password synchronizes existing admin", async () => {
const now = () => "2026-05-28T00:00:00.000Z";
const firstAccessController = createAccessController({
env: { HWLAB_ACCESS_CONTROL_REQUIRED: "1" },
now
});
const firstServer = createCloudApiServer({
accessController: firstAccessController,
env: { HWLAB_ACCESS_CONTROL_REQUIRED: "1" },
now
});
await new Promise((resolve) => firstServer.listen(0, "127.0.0.1", resolve));
try {
const { port } = firstServer.address();
const setup = await postJson(port, "/v1/setup/first-admin", {
username: "admin",
password: "old-pass"
});
assert.equal(setup.status, 201);
} finally {
await new Promise((resolve, reject) => firstServer.close((error) => (error ? reject(error) : resolve())));
}
const syncAccessController = createAccessController({
store: firstAccessController.store,
env: {
HWLAB_ACCESS_CONTROL_REQUIRED: "1",
HWLAB_BOOTSTRAP_ADMIN_ID: "usr_v02_admin",
HWLAB_BOOTSTRAP_ADMIN_USERNAME: "admin",
HWLAB_BOOTSTRAP_ADMIN_PASSWORD: "rotated-pass"
},
now
});
const server = createCloudApiServer({
accessController: syncAccessController,
env: { HWLAB_ACCESS_CONTROL_REQUIRED: "1" },
now
});
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
try {
const { port } = server.address();
const oldLogin = await postJson(port, "/auth/login", { username: "admin", password: "old-pass" });
assert.equal(oldLogin.status, 401);
const rotatedLogin = await postJson(port, "/auth/login", { username: "admin", password: "rotated-pass" });
assert.equal(rotatedLogin.status, 200);
assert.equal(rotatedLogin.body.actor.username, "admin");
assert.equal(rotatedLogin.body.actor.role, "admin");
assert.equal(JSON.stringify(rotatedLogin.body).includes("rotated-pass"), false);
} finally {
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
}
});
test("cloud api first-admin setup validates device-pod seed before creating admin", async () => {
const server = createCloudApiServer({
env: { HWLAB_ACCESS_CONTROL_REQUIRED: "1" },
now: () => "2026-05-28T00:00:00.000Z"
});
await new Promise((resolve) => server.listen(0, "127.0.0.1", resolve));
try {
const { port } = server.address();
const invalid = await postJson(port, "/v1/setup/first-admin", {
username: "admin",
password: "admin-pass",
devicePod: { devicePodId: "device-pod-71-freq" }
});
assert.equal(invalid.status, 400);
assert.equal(invalid.body.error.code, "invalid_params");
const before = await getJson(port, "/v1/setup/status");
assert.equal(before.status, 200);
assert.equal(before.body.setupRequired, true);
const ambiguous = await postJson(port, "/v1/setup/first-admin", {
username: "admin",
password: "admin-pass",
devicePod: { devicePodId: "device-pod-71-freq", profile: { schemaVersion: 1 } },
devicePods: [{ devicePodId: "device-pod-alt", profile: { schemaVersion: 1 } }]
});
assert.equal(ambiguous.status, 400);
assert.equal(ambiguous.body.error.code, "invalid_params");
const secretSeed = await postJson(port, "/v1/setup/first-admin", {
username: "admin",
password: "admin-pass",
devicePod: {
devicePodId: "device-pod-71-freq",
profile: {
schemaVersion: 1,
target: { id: "target-71-freq" },
route: { gatewaySessionId: "gws_seed" },
databaseUrl: "postgres://user:pass@example.invalid/hwlab"
}
}
});
assert.equal(secretSeed.status, 400);
assert.equal(secretSeed.body.error.code, "device_pod_profile_secret_forbidden");
assert.equal(JSON.stringify(secretSeed.body).includes("postgres://"), false);
const afterSecretSeed = await getJson(port, "/v1/setup/status");
assert.equal(afterSecretSeed.status, 200);
assert.equal(afterSecretSeed.body.setupRequired, true);
const setup = await postJson(port, "/v1/setup/first-admin", {
username: "admin",
password: "admin-pass"
});
assert.equal(setup.status, 201);
assert.equal(setup.body.actor.role, "admin");
assert.deepEqual(setup.body.devicePodBootstrap, { requested: 0, initialized: 0 });
} finally {
await new Promise((resolve, reject) => server.close((error) => (error ? reject(error) : resolve())));
}
});
async function postJson(port, path, body, cookie = null, extraHeaders = {}) {
const response = await fetch(`http://127.0.0.1:${port}${path}`, {
method: "POST",
headers: {
"content-type": "application/json",
...(cookie ? { cookie } : {}),
...extraHeaders
},
body: JSON.stringify(body)
});
return {
status: response.status,
cookie: response.headers.get("set-cookie"),
body: await response.json()
};
}
function devicePodInternalHeaders(extra = {}) {
return { ...extra, "x-hwlab-internal-service": "hwlab-device-pod", "x-hwlab-internal-token": INTERNAL_TOKEN };
}
async function putJson(port, path, body, cookie = null, extraHeaders = {}) {
const response = await fetch(`http://127.0.0.1:${port}${path}`, {
method: "PUT",
headers: {
"content-type": "application/json",
...(cookie ? { cookie } : {}),
...extraHeaders
},
body: JSON.stringify(body)
});
return {
status: response.status,
body: await response.json(),
cookie: response.headers.get("set-cookie")
};
}
async function getJson(port, path, cookie = null, extraHeaders = {}) {
const response = await fetch(`http://127.0.0.1:${port}${path}`, {
headers: {
...(cookie ? { cookie } : {}),
...extraHeaders
}
});
return {
status: response.status,
body: await response.json()
};
}
async function requestJson(request) {
const chunks = [];
for await (const chunk of request) chunks.push(chunk);
const text = Buffer.concat(chunks).toString("utf8").trim();
return text ? JSON.parse(text) : {};
}