GitHub
10/31/2026, 1:39 PMReplica() pattern. With the replica off, behaviour is unchanged.
Routed to the replica
• Node detail activity chart: query and carve history (Queries, Carves).
• Audit log list (AuditLogManager.GetPaged).
• Vulnerability views: findings, summary, advisory, per-node report and feed status.
• Posture node data: risk level and uptime in the node list and node detail, and the node posture page.
New Replica() methods
• `Carves.Replica()`: no S3 client and no event publisher.
• `PostureManager.Replica()`: keeps Evidence, so risk levels match the primary.
• `vulns.Reader.Replica()`: Reader.DB stays the primary, because RequestSync ("Sync now") writes through it.
Deliberately left on the primary
• Query and carve lists and detail pages: users land there right after creating a query, and a lagging replica could return a 404.
• Posture checks, profiles and the score endpoint: admins edit checks and immediately check the result.
• Node tags: a just-added tag must show up on the next list refresh.
Docs: the db.read comment in deploy/config/api.yml and the --db-read-enabled usage text list the routed areas.
Security and operational impact
• Only display paths move. Authorization, enrollment, node-key lookups and the query and carve lifecycle are unchanged.
• Replica reads can be a moment out of date, so a just-recorded audit entry or posture result may appear a little later.
Validation
• go vet ./... and go test ./... pass.
• New tests for Replica() on Carves, PostureManager and `vulns.Reader`:
• each copy reads from the replica;
• each falls back to the manager itself when no replica is configured;
• side-effect fields are dropped (S3, events);
• Evidence is kept for posture;
• Reader.DB stays the primary.
• Not validated against a real Postgres or MySQL replica.
jmpsec/osctrlGitHub
10/31/2026, 1:43 PM