feat(device-plane): supervise pinned edge channels in core

This commit is contained in:
Codex
2026-08-11 20:14:55 +03:00
parent 6461e7fca8
commit be964eccb7
18 changed files with 1217 additions and 70 deletions
@@ -27,6 +27,12 @@ test("health reports database readiness and disabled command transport", async (
database: "ready",
discoveryIngest: "disabled",
managementApi: "disabled",
edgeChannels: {
enabled: false,
configured: 0,
accepted: 0,
degraded: 0,
},
commandTransport: "disabled",
});
} finally {
@@ -0,0 +1,22 @@
import assert from "node:assert/strict";
import { readFile } from "node:fs/promises";
import test from "node:test";
const migrationUrl = new URL(
"../migrations/013_device_edge_channels.sql",
import.meta.url,
);
test("Edge channel migration extends the canonical Edge without storing keys", async () => {
const sql = await readFile(migrationUrl, "utf8");
assert.match(sql, /alter table device_edges/);
assert.match(sql, /channel_endpoint text/);
assert.match(sql, /channel_generation_ref text/);
assert.match(sql, /channel_trust_bundle_ref text/);
assert.match(sql, /channel_certificate_identities jsonb/);
assert.match(sql, /channel_lifecycle_state in \('disabled', 'active', 'revoked'\)/);
assert.match(sql, /where channel_lifecycle_state = 'active'/);
assert.doesNotMatch(sql, /private[_ ]?key/i);
assert.doesNotMatch(sql, /password/i);
});
@@ -0,0 +1,115 @@
import assert from "node:assert/strict";
import test from "node:test";
import {
createDeviceEdgeChannelSupervisor,
} from "../src/edge-channel-supervisor.mjs";
test("supervisor reconciles one in-process client per active Edge", async () => {
let registrations = [registration("channel-generation:1")];
const clients = [];
const supervisor = createDeviceEdgeChannelSupervisor({
repository: {
listActiveEdgeChannelRegistrations: async () => registrations,
},
gatewayIngest: {
observeDiscovery: async () => ({}),
acceptMessage: async () => ({}),
},
coreIdentity: {
identityRef: "workload:device-control-core",
key: "test-key",
cert: "test-cert",
},
readPeerTrust: async () => "test-edge-certificate",
clientFactory: (options) => {
const state = { started: 0, stopped: 0, options };
clients.push(state);
return {
async start() { state.started += 1; },
async stop() { state.stopped += 1; },
status: () => ({ channel: "accepted", lastErrorCode: null }),
};
},
reconcileIntervalMs: 300_000,
});
await supervisor.start();
assert.equal(clients.length, 1);
assert.equal(supervisor.status().accepted, 1);
assert.equal(clients[0].options.registration.channelGeneration, "channel-generation:1");
await supervisor.reconcile();
assert.equal(clients.length, 1);
registrations = [registration("channel-generation:2")];
await supervisor.reconcile();
assert.equal(clients.length, 2);
assert.equal(clients[0].stopped, 1);
assert.equal(clients[1].started, 1);
registrations = [];
await supervisor.reconcile();
assert.equal(clients[1].stopped, 1);
assert.equal(supervisor.status().configured, 0);
assert.equal(JSON.stringify(supervisor.status()).includes("155.212"), false);
await supervisor.stop();
});
test("supervisor keeps a failed trust enrollment isolated from other Edges", async () => {
const supervisor = createDeviceEdgeChannelSupervisor({
repository: {
listActiveEdgeChannelRegistrations: async () => [
registration("channel-generation:1", "edge:good"),
registration("channel-generation:1", "edge:bad"),
],
},
gatewayIngest: {
observeDiscovery: async () => ({}),
acceptMessage: async () => ({}),
},
coreIdentity: {
identityRef: "workload:device-control-core",
key: "test-key",
cert: "test-cert",
},
readPeerTrust: async ({ registration: value }) => {
if (value.edgeRegistrationId === "edge:bad") {
throw new Error("device_edge_channel_trust_bundle_identity_mismatch");
}
return "test-edge-certificate";
},
clientFactory: () => ({
start: async () => undefined,
stop: async () => undefined,
status: () => ({ channel: "accepted", lastErrorCode: null }),
}),
reconcileIntervalMs: 300_000,
});
await supervisor.start();
const status = supervisor.status();
assert.equal(status.configured, 2);
assert.equal(status.accepted, 1);
assert.equal(status.degraded, 1);
assert.equal(status.commandTransport, "disabled");
assert.equal(status.edges.find((item) => item.edgeRegistrationId === "edge:bad")
.lastErrorCode, "device_edge_channel_trust_bundle_identity_mismatch");
await supervisor.stop();
});
function registration(channelGeneration, edgeRegistrationId = "edge:pilot") {
return {
edgeRegistrationId,
endpoint: "https://155.212.211.15:8443/",
servername: "155.212.211.15",
channelGeneration,
trustBundleRef: "edge-trust:moscow-edge",
certificateIdentities: [{
generationRef: "edge-identity:1",
fingerprint: "AA:".repeat(31) + "AA",
status: "active",
}],
lifecycleState: "active",
};
}
@@ -0,0 +1,87 @@
import assert from "node:assert/strict";
import test from "node:test";
import {
DEVICE_ADAPTER_MESSAGE_SCHEMA,
DEVICE_DISCOVERY_SIGNAL_SCHEMA,
} from "../../../packages/device-protocol-contract/src/index.mjs";
import { createDeviceGatewayIngest } from "../src/gateway-ingest.mjs";
const identifierPepper = "test-only-identifier-pepper-with-32-bytes";
const rawImei = "000000000000001";
test("shared gateway ingest masks identifiers for HTTP and Edge callers", async () => {
const stored = [];
const ingest = createDeviceGatewayIngest({
identifierPepper,
repository: {
async upsertQuarantineDiscovery(value) {
stored.push(value);
return {
created: true,
value: { ...value.safeView, discoveryRef: "discovery:test" },
};
},
async acceptAdapterMessage(value) {
stored.push(value);
return {
schemaVersion: "nodedc.device-adapter-acceptance.v1",
acceptanceRef: "acceptance:test",
idempotencyKey: value.safeView.idempotencyKey,
status: "accepted",
replayed: false,
acceptedAt: "2026-08-11T12:00:00.000Z",
};
},
},
});
const discovery = await ingest.observeDiscovery(discoverySignal());
const acceptance = await ingest.acceptMessage(adapterMessage());
assert.equal(discovery.value.identifier.masked, "***********0001");
assert.equal(acceptance.status, "accepted");
assert.match(stored[0].identifierDigest, /^hmac-sha256:[a-f0-9]{64}$/);
assert.match(stored[1].requestDigest, /^sha256:[a-f0-9]{64}$/);
assert.equal(JSON.stringify(stored).includes(rawImei), false);
});
function discoverySignal() {
return {
schemaVersion: DEVICE_DISCOVERY_SIGNAL_SCHEMA,
sessionRef: "session:test",
modelProfileRef: "arusnavi.b2.internal.v1",
protocol: "INTERNAL",
observedAt: "2026-08-11T12:00:00.000Z",
identifier: { kind: "imei", value: rawImei },
evidence: {
transport: "tcp",
bytesObserved: 16,
framingStatus: "verified",
specificationRef: "arusnavi.internal.framing.test-v1",
},
};
}
function adapterMessage() {
return {
schemaVersion: DEVICE_ADAPTER_MESSAGE_SCHEMA,
edgeRef: "edge:test",
adapterRef: "arusnavi-b2",
protocolProfileRef: "arusnavi.b2.internal.v1",
protocol: "INTERNAL",
sessionRef: "session:test",
messageRef: "package:1:test",
messageType: "telemetry.package",
sequence: 1,
observedAt: "2026-08-11T12:00:00.000Z",
idempotencyKey: `sha256:${"a".repeat(64)}`,
identifier: { kind: "imei", value: rawImei },
payloadSchemaRef: "arusnavi.internal.package-metadata.v1",
payload: {
packageNumber: 1,
packetCount: 1,
packageDigest: `sha256:${"b".repeat(64)}`,
},
};
}
@@ -143,6 +143,62 @@ test("shared catalog and Edge authority requires the Hub owner ceiling", () => {
);
});
test("normalizes only a pinned Core-initiated public Edge channel", () => {
const command = normalizeInfrastructureManagementCommand("edge.ensure", {
edgeKey: "moscow-edge",
displayName: "Moscow Edge",
deploymentRef: "deployment:device-edge/moscow-1",
lifecycleState: "active",
channel: {
endpoint: "https://155.212.211.15:8443/",
servername: "155.212.211.15",
generationRef: "channel-generation:1",
trustBundleRef: "edge-trust:moscow-edge",
certificateIdentities: [{
generationRef: "edge-identity:1",
fingerprint: "AA:".repeat(31) + "AA",
status: "active",
}],
lifecycleState: "active",
},
});
assert.equal(command.channel.endpoint, "https://155.212.211.15:8443/");
assert.equal(command.channel.lifecycleState, "active");
assert.equal(command.channel.certificateIdentities.length, 1);
for (const endpoint of [
"https://127.0.0.1:8443/",
"https://192.168.1.1:8443/",
"https://155.212.211.15:9921/",
"http://155.212.211.15:8443/",
]) {
assert.throws(
() => normalizeInfrastructureManagementCommand("edge.ensure", {
edgeKey: "bad-edge",
displayName: "Bad Edge",
channel: { ...command.channel, endpoint },
}),
/device_edge_channel_endpoint_invalid/,
);
}
assert.throws(
() => normalizeInfrastructureManagementCommand("edge.ensure", {
edgeKey: "bad-edge",
displayName: "Bad Edge",
channel: { ...command.channel, servername: "example.invalid" },
}),
/device_edge_channel_servername_mismatch/,
);
assert.throws(
() => normalizeInfrastructureManagementCommand("edge.ensure", {
edgeKey: "bad-edge",
displayName: "Bad Edge",
channel: { lifecycleState: "disabled", endpoint: command.channel.endpoint },
}),
/device_edge_channel_disabled_configuration_invalid/,
);
});
function actor(hubRole) {
return normalizeManagementActor({
userRef: "user:platform-admin",
@@ -192,6 +192,48 @@ test("stores enrollment digest but returns and audits only its masked projection
assert.equal(client.released, true);
});
test("lists only bounded active Edge channel registrations without secrets", async () => {
const client = scriptedClient([
step("begin transaction read only"),
step("from device_edges", {
rows: [{
id: edgeId,
channel_endpoint: "https://155.212.211.15:8443/",
channel_servername: "155.212.211.15",
channel_generation_ref: "channel-generation:1",
channel_trust_bundle_ref: "edge-trust:moscow-edge",
channel_certificate_identities: [{
generationRef: "edge-identity:1",
fingerprint: "AA:".repeat(31) + "AA",
status: "active",
}],
channel_lifecycle_state: "active",
}],
}),
step("commit"),
]);
const repository = repositoryWithClient(client);
const registrations = await repository.listActiveEdgeChannelRegistrations(8);
assert.deepEqual(registrations[0], {
edgeRegistrationId: `edge:${edgeId}`,
endpoint: "https://155.212.211.15:8443/",
servername: "155.212.211.15",
channelGeneration: "channel-generation:1",
trustBundleRef: "edge-trust:moscow-edge",
certificateIdentities: [{
generationRef: "edge-identity:1",
fingerprint: "AA:".repeat(31) + "AA",
status: "active",
}],
lifecycleState: "active",
});
assert.equal(JSON.stringify(registrations).includes("private"), false);
assert.equal(client.remaining(), 0);
assert.equal(client.released, true);
});
function managementActor(hubRole) {
return normalizeManagementActor({
userRef: "user:platform-owner",