feat(device-plane): add universal adapter acceptance boundary
This commit is contained in:
@@ -1,7 +1,10 @@
|
||||
import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
|
||||
import { createCoreDiscoveryClient } from "../src/core-client.mjs";
|
||||
import {
|
||||
createCoreDiscoveryClient,
|
||||
createCoreGatewayClient,
|
||||
} from "../src/core-client.mjs";
|
||||
|
||||
const gatewayToken = "test-only-gateway-token-with-32-bytes";
|
||||
|
||||
@@ -41,14 +44,14 @@ test("posts a discovery through the authenticated internal Core boundary", async
|
||||
assert.equal(discovery.lifecycleState, "quarantine");
|
||||
});
|
||||
|
||||
test("fails closed when Core does not return a quarantine view", async () => {
|
||||
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: "claimed",
|
||||
lifecycleState: "observed",
|
||||
commandTransport: "disabled",
|
||||
},
|
||||
}), { status: 200 }),
|
||||
@@ -58,3 +61,58 @@ test("fails closed when Core does not return a quarantine view", async () => {
|
||||
/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/,
|
||||
);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user