diff --git a/src/gateway/server-methods/devices.test.ts b/src/gateway/server-methods/devices.test.ts index 00057eb1f684..caa40903f463 100644 --- a/src/gateway/server-methods/devices.test.ts +++ b/src/gateway/server-methods/devices.test.ts @@ -1193,8 +1193,13 @@ describe("deviceHandlers", () => { }), }, ); + const captured = captureSecurityEvents(); - await deviceHandlers["device.pair.reject"](opts); + try { + await deviceHandlers["device.pair.reject"](opts); + } finally { + captured.stop(); + } expect(rejectDevicePairingMock).toHaveBeenCalledWith("req-2"); expect(opts.respond).toHaveBeenCalledWith( @@ -1202,5 +1207,21 @@ describe("deviceHandlers", () => { { requestId: "req-2", deviceId: "device-2", rejectedAtMs: 456 }, undefined, ); + expect(captured.events).toHaveLength(1); + expect(captured.events[0]).toMatchObject({ + action: "device.pairing.rejected", + outcome: "success", + severity: "low", + actor: { + kind: "operator", + role: "admin", + }, + target: { kind: "device", idHash: expect.stringMatching(/^sha256:[a-f0-9]{12}$/u) }, + policy: { id: "gateway.device-pairing", decision: "allow" }, + control: { id: "device.pair.reject", family: "auth" }, + }); + const serialized = JSON.stringify(captured.events); + expect(serialized).not.toContain("device-1"); + expect(serialized).not.toContain("device-2"); }); }); diff --git a/src/gateway/server-methods/devices.ts b/src/gateway/server-methods/devices.ts index 4296ef742718..78e2c168d754 100644 --- a/src/gateway/server-methods/devices.ts +++ b/src/gateway/server-methods/devices.ts @@ -256,7 +256,7 @@ function emitDevicePairingDeniedSecurityEvent(params: { } function emitDevicePairingLifecycleSecurityEvent(params: { - action: "device.pairing.approved" | "device.pairing.removed"; + action: "device.pairing.approved" | "device.pairing.rejected" | "device.pairing.removed"; severity: DiagnosticSecurityEventInput["severity"]; authz: DeviceSessionAuthz; targetDeviceId: string; @@ -513,11 +513,11 @@ export const deviceHandlers: GatewayRequestHandlers = { respond(false, undefined, errorShape(ErrorCodes.INVALID_REQUEST, "unknown requestId")); return; } - emitDevicePairingDeniedSecurityEvent({ + emitDevicePairingLifecycleSecurityEvent({ + action: "device.pairing.rejected", authz, targetDeviceId: rejected.deviceId, controlId: "device.pair.reject", - reason: "operator-rejected", severity: "low", }); context.broadcast(