feat(api): add device identity guard and Prometheus metrics
- Persist device identity observations and expose fleet identity summaries. - Block device control actions when identity verification fails. - Add metrics collection and a Prometheus scrape endpoint.
This commit is contained in:
@@ -20,7 +20,8 @@ export type DeviceActionErrorCode =
|
||||
| 'VALIDATION_FAILED'
|
||||
| 'SESSION_INVALID'
|
||||
| 'UPSTREAM_FAILED'
|
||||
| 'NOT_DISPATCHED';
|
||||
| 'NOT_DISPATCHED'
|
||||
| 'IDENTITY_UNCONFIRMED';
|
||||
|
||||
export class DeviceActionError extends Error {
|
||||
constructor(
|
||||
@@ -192,6 +193,12 @@ export interface DeviceActionServiceOptions {
|
||||
readonly ensureSession?: (instanceId: string, origin: string, force?: boolean) => Promise<void>;
|
||||
readonly now?: () => Date;
|
||||
readonly id?: () => string;
|
||||
/**
|
||||
* The identity guard. A node whose reported hardware stopped matching its record, or whose
|
||||
* identity is claimed by another record, is not safe to control: the command would land on a
|
||||
* device the operator is not looking at. Unbinding stays available because it is the way out.
|
||||
*/
|
||||
readonly identities?: { isBlocked(instanceId: string): boolean };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -239,6 +246,8 @@ export class DeviceActionService {
|
||||
const session = this.options.sessions.sessionFor(instanceId);
|
||||
if (session && session.origin !== instance.origin)
|
||||
throw new DeviceActionError('SESSION_INVALID');
|
||||
if (action.id !== 'hub.unbind' && this.options.identities?.isBlocked(instanceId))
|
||||
throw new DeviceActionError('IDENTITY_UNCONFIRMED');
|
||||
|
||||
const values = this.#validate(action, params);
|
||||
const { path, query, body } = this.#assemble(action, values);
|
||||
|
||||
Reference in New Issue
Block a user