119 lines
3.6 KiB
JavaScript
119 lines
3.6 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import test from "node:test";
|
|
|
|
import {
|
|
createCoreDiscoveryClient,
|
|
createCoreGatewayClient,
|
|
} from "../src/core-client.mjs";
|
|
|
|
const gatewayToken = "test-only-gateway-token-with-32-bytes";
|
|
|
|
test("posts a discovery through the authenticated internal Core boundary", async () => {
|
|
let captured;
|
|
const observe = createCoreDiscoveryClient({
|
|
coreUrl: "http://device-control-core:18120",
|
|
gatewayToken,
|
|
fetchImpl: async (url, options) => {
|
|
captured = { url, options };
|
|
return new Response(JSON.stringify({
|
|
ok: true,
|
|
discovery: {
|
|
lifecycleState: "quarantine",
|
|
commandTransport: "disabled",
|
|
},
|
|
}), {
|
|
status: 201,
|
|
headers: { "Content-Type": "application/json" },
|
|
});
|
|
},
|
|
});
|
|
const signal = {
|
|
schemaVersion: "nodedc.device.discovery-signal.v1",
|
|
sessionRef: "session:test",
|
|
};
|
|
const discovery = await observe(signal);
|
|
assert.equal(
|
|
captured.url,
|
|
"http://device-control-core:18120/internal/v1/device-discoveries:observe",
|
|
);
|
|
assert.equal(
|
|
captured.options.headers.Authorization,
|
|
`Bearer ${gatewayToken}`,
|
|
);
|
|
assert.deepEqual(JSON.parse(captured.options.body), signal);
|
|
assert.equal(discovery.lifecycleState, "quarantine");
|
|
});
|
|
|
|
test("fails closed when Core does not return an accepted discovery view", async () => {
|
|
const observe = createCoreDiscoveryClient({
|
|
coreUrl: "http://device-control-core:18120",
|
|
gatewayToken,
|
|
fetchImpl: async () => new Response(JSON.stringify({
|
|
ok: true,
|
|
discovery: {
|
|
lifecycleState: "observed",
|
|
commandTransport: "disabled",
|
|
},
|
|
}), { status: 200 }),
|
|
});
|
|
await assert.rejects(
|
|
() => observe({ schemaVersion: "test" }),
|
|
/device_gateway_core_ingest_contract_invalid/,
|
|
);
|
|
});
|
|
|
|
test("accepts a package only through the explicit Core acceptance contract", async () => {
|
|
let captured;
|
|
const client = createCoreGatewayClient({
|
|
coreUrl: "http://device-control-core:18120",
|
|
gatewayToken,
|
|
fetchImpl: async (url, options) => {
|
|
captured = { url, options };
|
|
const message = JSON.parse(options.body);
|
|
return new Response(JSON.stringify({
|
|
ok: true,
|
|
acceptance: {
|
|
schemaVersion: "nodedc.device-adapter-acceptance.v1",
|
|
acceptanceRef: "acceptance:test-001",
|
|
idempotencyKey: message.idempotencyKey,
|
|
status: "accepted",
|
|
replayed: false,
|
|
acceptedAt: "2026-08-11T12:00:00.000Z",
|
|
},
|
|
}), { status: 201 });
|
|
},
|
|
});
|
|
const message = { idempotencyKey: `sha256:${"a".repeat(64)}` };
|
|
const acceptance = await client.acceptMessage(message);
|
|
assert.equal(
|
|
captured.url,
|
|
"http://device-control-core:18120/internal/v1/gateway/messages:accept",
|
|
);
|
|
assert.equal(acceptance.status, "accepted");
|
|
assert.equal(acceptance.idempotencyKey, message.idempotencyKey);
|
|
});
|
|
|
|
test("rejects a mismatched or non-durable Core package response", async () => {
|
|
const client = createCoreGatewayClient({
|
|
coreUrl: "http://device-control-core:18120",
|
|
gatewayToken,
|
|
fetchImpl: async () => new Response(JSON.stringify({
|
|
ok: true,
|
|
acceptance: {
|
|
schemaVersion: "nodedc.device-adapter-acceptance.v1",
|
|
acceptanceRef: "acceptance:test-001",
|
|
idempotencyKey: `sha256:${"b".repeat(64)}`,
|
|
status: "accepted",
|
|
replayed: false,
|
|
acceptedAt: "2026-08-11T12:00:00.000Z",
|
|
},
|
|
}), { status: 201 }),
|
|
});
|
|
await assert.rejects(
|
|
() => client.acceptMessage({
|
|
idempotencyKey: `sha256:${"a".repeat(64)}`,
|
|
}),
|
|
/device_gateway_core_acceptance_mismatch/,
|
|
);
|
|
});
|