import assert from "node:assert/strict"; import test from "node:test"; import { createLocalPreviewDeviceCore } from "./device-core-client.mjs"; import { createDeviceManagerAuth } from "./device-manager-auth.mjs"; import { createDeviceManagerServer } from "./device-manager-server.mjs"; test("Device Manager BFF exposes an empty, mutation-driven project workspace", async (t) => { const auth = createDeviceManagerAuth({ env: { NODEDC_DEVICE_MANAGER_AUTH_REQUIRED: "false" }, }); const coreClient = createLocalPreviewDeviceCore(); const server = createDeviceManagerServer({ auth, coreClient }); await new Promise((resolve, reject) => { server.once("error", reject); server.listen(0, "127.0.0.1", resolve); }); t.after(() => new Promise((resolve) => server.close(resolve))); const address = server.address(); const baseUrl = `http://127.0.0.1:${address.port}`; const session = await getJson(`${baseUrl}/api/device-manager/session`); assert.equal(session.session.actor.hubRole, "owner"); assert.equal(session.session.actor.userRef, "user:local-device-admin"); assert.deepEqual((await getJson(`${baseUrl}/api/device-manager/projects`)).projects, []); await postJson(`${baseUrl}/api/device-manager/owner-scopes:ensure`, { scopeKind: "personal", ownerRef: "user:local-device-admin", displayName: "Local Device Admin", }, { "X-NODEDC-Hub-Role": "viewer", "X-NODEDC-User-Ref": "user:spoofed-browser", }); const created = await postJson(`${baseUrl}/api/device-manager/projects:ensure`, { scopeKind: "personal", ownerRef: "user:local-device-admin", projectKey: "device-sandbox", name: "Device sandbox", description: "Created only through the canonical command path", }); const projectRef = created.result.project.projectRef; const projects = (await getJson(`${baseUrl}/api/device-manager/projects`)).projects; assert.equal(projects.length, 1); assert.equal(projects[0].projectKey, "device-sandbox"); assert.equal(projects[0].ownerScope.ownerRef, "user:local-device-admin"); await postJson(`${baseUrl}/api/device-manager/collections:ensure`, { projectRef, collectionKey: "pilot-devices", name: "Pilot devices", description: null, }); await postJson(`${baseUrl}/api/device-manager/adapter-packages:ensure`, { packageKey: "generic-sensor", displayName: "Generic sensor", publisherRef: "publisher:nodedc", lifecycleState: "active", }); await postJson(`${baseUrl}/api/device-manager/edges:ensure`, { edgeKey: "preview-edge", displayName: "Preview Edge", deploymentRef: "deployment:preview-edge", lifecycleState: "provisioning", }); await postJson(`${baseUrl}/api/device-manager/project-grants:upsert`, { projectRef, principalKind: "group", principalRef: "group:preview-viewers", projectRole: "viewer", capabilityAllow: [], capabilityDeny: [], lifecycleState: "active", }); const workspace = await getJson( `${baseUrl}/api/device-manager/projects/${encodeURIComponent(projectRef)}/workspace`, ); assert.equal(workspace.workspace.project.projectRef, projectRef); assert.equal(workspace.workspace.collections[0].collectionKey, "pilot-devices"); assert.equal(workspace.workspace.adapterPackages[0].packageKey, "generic-sensor"); assert.equal(workspace.workspace.edges[0].edgeKey, "preview-edge"); assert.equal(workspace.workspace.grants.length, 2); assert.equal(workspace.workspace.policies.commandTransport, "disabled"); assert.deepEqual(workspace.workspace.devices, []); const missingKey = await fetch(`${baseUrl}/api/device-manager/projects:ensure`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({}), }); assert.equal(missingKey.status, 400); assert.equal((await missingKey.json()).error, "device_idempotency_key_invalid"); }); async function getJson(url) { const response = await fetch(url, { headers: { accept: "application/json" } }); const body = await response.json(); assert.equal(response.status, 200, JSON.stringify(body)); assert.equal(body.ok, true); return body; } async function postJson(url, body, headers = {}) { const response = await fetch(url, { method: "POST", headers: { accept: "application/json", "content-type": "application/json", "idempotency-key": `device-manager-test-${crypto.randomUUID()}`, ...headers, }, body: JSON.stringify(body), }); const payload = await response.json(); assert.equal(response.status, 200, JSON.stringify(payload)); assert.equal(payload.ok, true); return payload; }