feat(device-core): add idempotent project management

This commit is contained in:
Codex
2026-08-10 17:27:07 +03:00
parent 336602c7ca
commit 70bafdd028
10 changed files with 2260 additions and 2 deletions
@@ -8,6 +8,7 @@ import { createControlCoreApp } from "../src/app.mjs";
const gatewayToken = "test-only-gateway-token-with-32-bytes";
const identifierPepper = "test-only-identifier-pepper-with-32-bytes";
const managementToken = "test-only-management-token-with-32-bytes";
const fakeImei = "000000000000001";
test("health reports database readiness and disabled command transport", async () => {
@@ -24,6 +25,7 @@ test("health reports database readiness and disabled command transport", async (
service: "nodedc-device-control-core",
database: "ready",
discoveryIngest: "disabled",
managementApi: "disabled",
commandTransport: "disabled",
});
} finally {
@@ -31,6 +33,210 @@ test("health reports database readiness and disabled command transport", async (
}
});
test("management API is closed by default", async () => {
const runtime = await startTestServer({
repository: {
health: async () => "ready",
},
});
try {
const response = await fetch(
`${runtime.baseUrl}/internal/v1/management/owner-scopes:ensure`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: "{}",
},
);
assert.equal(response.status, 404);
assert.equal((await response.json()).error, "device_management_api_disabled");
} finally {
await runtime.close();
}
});
test("management API cannot start without its repository boundary and strong token", () => {
assert.throws(
() => createControlCoreApp({
managementApiEnabled: true,
managementToken,
repository: { health: async () => "ready" },
}),
/device_management_repository_required/,
);
assert.throws(
() => createControlCoreApp({
managementApiEnabled: true,
managementToken: "short",
repository: {
health: async () => "ready",
executeManagementCommand: async () => ({}),
},
}),
/device_management_token_invalid/,
);
});
test("management API requires service auth and an idempotency key", async () => {
const runtime = await startTestServer({
managementApiEnabled: true,
managementToken,
repository: {
health: async () => "ready",
executeManagementCommand: async () => {
throw new Error("must_not_execute");
},
},
});
try {
const unauthorized = await fetch(
`${runtime.baseUrl}/internal/v1/management/owner-scopes:ensure`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: "{}",
},
);
assert.equal(unauthorized.status, 401);
const missingIdempotency = await fetch(
`${runtime.baseUrl}/internal/v1/management/owner-scopes:ensure`,
{
method: "POST",
headers: managementHeaders({ includeIdempotency: false }),
body: JSON.stringify(ownerScopeCommand()),
},
);
assert.equal(missingIdempotency.status, 400);
assert.equal(
(await missingIdempotency.json()).error,
"device_management_header_required",
);
} finally {
await runtime.close();
}
});
test("management API forwards only normalized actor and command data", async () => {
let executed;
const runtime = await startTestServer({
managementApiEnabled: true,
managementToken,
repository: {
health: async () => "ready",
executeManagementCommand: async (value) => {
executed = value;
return {
replayed: false,
result: {
created: true,
ownerScope: {
ownerScopeRef: "owner-scope:11111111-1111-4111-8111-111111111111",
scopeKind: "company",
ownerRef: "client:example",
displayName: "Example Company",
lifecycleState: "active",
},
},
};
},
},
});
try {
const response = await fetch(
`${runtime.baseUrl}/internal/v1/management/owner-scopes:ensure`,
{
method: "POST",
headers: managementHeaders(),
body: JSON.stringify(ownerScopeCommand()),
},
);
assert.equal(response.status, 200);
assert.equal(response.headers.get("idempotency-key"), "phase2-test-0001");
assert.equal(response.headers.get("idempotency-replayed"), "false");
assert.match(executed.requestDigest, /^sha256:[a-f0-9]{64}$/);
assert.equal(executed.commandKind, "owner_scope.ensure");
assert.deepEqual(executed.command, ownerScopeCommand());
assert.deepEqual(executed.actor, {
userRef: "user:engineer",
hubRole: "admin",
groupRefs: ["group:engineers", "group:operators"],
ownerScopes: [{ scopeKind: "company", ownerRef: "client:example" }],
});
assert.equal((await response.json()).result.created, true);
} finally {
await runtime.close();
}
});
test("management API rejects unexpected fields before repository execution", async () => {
let executions = 0;
const runtime = await startTestServer({
managementApiEnabled: true,
managementToken,
repository: {
health: async () => "ready",
executeManagementCommand: async () => {
executions += 1;
return { replayed: false, result: {} };
},
},
});
try {
const response = await fetch(
`${runtime.baseUrl}/internal/v1/management/owner-scopes:ensure`,
{
method: "POST",
headers: managementHeaders(),
body: JSON.stringify({
...ownerScopeCommand(),
credential: "must-never-cross-boundary",
}),
},
);
assert.equal(response.status, 400);
assert.match(
(await response.json()).error,
/device_management_command_field_unexpected:credential/,
);
assert.equal(executions, 0);
} finally {
await runtime.close();
}
});
test("management API exposes a repository idempotency conflict without retrying", async () => {
let executions = 0;
const runtime = await startTestServer({
managementApiEnabled: true,
managementToken,
repository: {
health: async () => "ready",
executeManagementCommand: async () => {
executions += 1;
const error = new Error("device_idempotency_key_conflict");
error.statusCode = 409;
throw error;
},
},
});
try {
const response = await fetch(
`${runtime.baseUrl}/internal/v1/management/owner-scopes:ensure`,
{
method: "POST",
headers: managementHeaders(),
body: JSON.stringify(ownerScopeCommand()),
},
);
assert.equal(response.status, 409);
assert.equal((await response.json()).error, "device_idempotency_key_conflict");
assert.equal(executions, 1);
} finally {
await runtime.close();
}
});
test("discovery ingest is closed by default", async () => {
const runtime = await startTestServer({
repository: {
@@ -127,6 +333,26 @@ function fakeSignal() {
};
}
function managementHeaders({ includeIdempotency = true } = {}) {
return {
Authorization: `Bearer ${managementToken}`,
"Content-Type": "application/json",
...(includeIdempotency ? { "Idempotency-Key": "phase2-test-0001" } : {}),
"X-NODEDC-User-Ref": "user:engineer",
"X-NODEDC-Hub-Role": "admin",
"X-NODEDC-Group-Refs": "group:operators,group:engineers",
"X-NODEDC-Owner-Scopes": "company=client:example",
};
}
function ownerScopeCommand() {
return {
scopeKind: "company",
ownerRef: "client:example",
displayName: "Example Company",
};
}
async function startTestServer(options) {
const server = createControlCoreApp(options);
await new Promise((resolve, reject) => {