refactor(backend): replica guard helper for security routes (#797)

* refactor(backend): extract replica guard helper for security routes

Adds blockIfReplica(res, resource) in middleware/fleetSyncGuards.ts and
replaces six inline FleetSyncService.getRole() === 'replica' checks
across the security policies and CVE suppressions endpoints.

Error responses now use a uniform shape:
  403 { error: 'Cannot modify <resource> on a replica instance.
    Connect to the primary.', code: 'REPLICA_READ_ONLY' }

The new code field gives callers a stable discriminator without
matching prose.

Closes #750

* test(suppressions): match stable REPLICA_READ_ONLY code instead of prose

The replica guard helper exposes a stable code field for callers to
discriminate without grepping the human-readable error string. Switch
the replica-rejection assertion to use that code so the test no longer
breaks when the unified error template wording is tuned.
This commit is contained in:
Anso
2026-04-27 00:29:38 -04:00
committed by GitHub
parent 82894164e2
commit add3abaece
3 changed files with 31 additions and 25 deletions
+23
View File
@@ -0,0 +1,23 @@
import type { Response } from 'express';
import { FleetSyncService } from '../services/FleetSyncService';
/**
* Reject mutation attempts on a replica Sencho. Returns true (and writes a
* 403 response) when this instance is acting as a replica; the caller
* should `return` immediately. Returns false on a control instance so the
* route handler can continue.
*
* Replicas mirror security configuration (scan policies, CVE suppressions)
* from the control node and reject local writes to keep the fleet
* authoritative source single.
*/
export function blockIfReplica(res: Response, resource: string): boolean {
if (FleetSyncService.getRole() === 'replica') {
res.status(403).json({
error: `Cannot modify ${resource} on a replica instance. Connect to the primary.`,
code: 'REPLICA_READ_ONLY',
});
return true;
}
return false;
}