Compliance Evaluation
Proxima Console includes a compliance evaluation system that maps healthcheck evidence to structured compliance frameworks, producing per-control verdicts and aggregate compliance scores at the host, environment, and client level. It also supports manual attestations for controls that require human review and compliance exceptions for accepted risk waivers.
Overview
The compliance system sits on top of the healthcheck system and adds a structured compliance layer:
- Frameworks define collections of compliance controls (e.g. Proxima Best Practices)
- Controls are individual compliance requirements within a framework (e.g. "SSH access hardened")
- Control mappings link controls to evidence sources (healthcheck rules)
- Evaluations are per-control verdicts (pass/fail/unknown) computed from healthcheck results
- Attestations are human-submitted verdicts for manual or hybrid controls
- Exceptions are approved risk waivers that override a control's failure status
- Rollups aggregate evaluations into framework-level scores at host, environment, and client scope
Architecture
Evaluation Flow
- Healthcheck run completes -- The healthcheck worker processes scanner results from the agent and stores them in the
healthcheck_resultstable. - Trigger message -- The healthcheck worker publishes a
proxima.compliance.evaluatemessage on the COMPLIANCE NATS JetStream stream containing thehost_id,run_id,environment_id, andclient_id. - Compliance worker consumes -- The
ComplianceConsumerWorkerpicks up the message using a durable pull consumer (backend-compliance-worker). - Ensure asset -- The worker ensures an asset record exists for the host (the asset layer is a generic identity abstraction for compliance scoping).
- Load frameworks -- All enabled frameworks are fetched from the database.
- Load evidence -- Healthcheck results for the run and the slug-to-ruleID mapping are loaded. If
run_idis nil (e.g. from a manual re-evaluation trigger), the latest run for the host is used. - Check exceptions -- Active exceptions for the host scope are loaded. Any control with an active exception is marked
exceptedregardless of evidence. - Check attestations -- Active attestations for the host scope are loaded. Manual/hybrid controls with attestations use the attested status.
- Evaluate controls -- For each enabled framework, the worker loads controls and their mappings, then evaluates each control against the healthcheck evidence:
- Excepted controls: status is set to
excepted(exception overrides everything). - Attested controls: status is taken from the attestation (
pass,fail, orwarning). - Automated controls with mappings: each mapping's
source_ref(a healthcheck rule slug) is checked against the results using the mapping'soperator(e.g.status_is). If any mapping fails, the control fails. - Manual controls with no mappings and no attestation: status is set to
pending_manual_review. - Automated controls with no mappings: status is set to
unknown.
- Excepted controls: status is set to
- Store evaluations -- Evaluations are upserted in bulk (keyed on
control_id + scope_type + scope_id), so re-evaluation overwrites previous results. - Metrics recorded -- The
proxima_compliance_evaluations_totalcounter is incremented per evaluation, labeled by framework and status.
Concepts
Frameworks
A framework is a collection of compliance controls. Frameworks have a source_type of either builtin (shipped with Proxima) or custom (user-defined). Each framework has a slug, name, version, score_thresholds (for pass/warning/fail coloring), and can be enabled or disabled.
Controls
Controls are individual compliance requirements within a framework. Each control has:
| Field | Description |
|---|---|
code | Human-readable identifier (e.g. SEC-SSH-001) |
title | Short description (e.g. "SSH access hardened") |
category | Grouping: security, patch_and_vuln, observability, networking, system, docker, backup |
severity | critical, high, medium, or low |
control_type | automated (scanner evidence), manual (human attestation), or hybrid (both) |
parent_control_id | Optional parent for hierarchical controls |
enabled | Can be toggled on/off |
Control Mappings
Mappings connect controls to evidence sources. Each mapping specifies:
- source_type -- The kind of evidence (e.g.
healthcheck_rule) - source_ref -- Reference to the evidence item (e.g. a healthcheck rule slug like
ssh-root-login-disabled) - operator -- Evaluation logic (e.g.
status_is) - expected_value -- The expected result (e.g.
pass) - weight -- Relative weight for scoring (default
1.0)
A single control can have multiple mappings. All mappings must pass for the control to pass.
Evaluation Statuses
| Status | Meaning |
|---|---|
pass | All mapped evidence meets expectations |
fail | One or more mappings failed |
warning | Non-critical deviation detected |
unknown | No evidence found for any mapping |
not_applicable | Control does not apply to this asset |
excepted | Control failure is accepted (risk exception) |
pending_manual_review | Manual control awaiting human attestation |
Scoring
Framework scores are computed as a ratio between 0 and 1:
score = passed / (passed + failed)
Controls with unknown, not_applicable, excepted, or pending_manual_review status are excluded from the score calculation. The frontend displays scores as percentages (e.g. a score of 0.85 is shown as 85%).
Each framework has configurable score_thresholds that determine the visual indicator:
| Threshold | Default | Color |
|---|---|---|
good | 0.8 | Green |
warning | 0.5 | Amber |
| Below warning | — | Red |
Manual Attestations
Manual attestations allow authorized users to provide human verdicts for manual or hybrid controls -- controls that cannot be fully evaluated through automated evidence (e.g. "Backup restore tested").
Each attestation records:
| Field | Description |
|---|---|
control_id | The control being attested |
scope_type | Scope level: asset, environment, or client |
scope_id | The specific host, environment, or client UUID |
status | Verdict: pass, fail, or warning |
attested_by | User ID of the attester |
attested_at | Timestamp of the attestation |
expires_at | Optional expiry date (attestation becomes stale after this) |
note | Free-text justification or evidence description |
Lifecycle:
- User creates an attestation via the API or UI for a specific control + scope
- On the next compliance evaluation, the attested status overrides
pending_manual_review - Creating, updating, or deleting an attestation automatically triggers re-evaluation
- If
expires_atis set and passes, the attestation is no longer considered active
Compliance Exceptions
Exceptions are approved risk waivers that accept a control's failure. When an exception is active for a control, the evaluation status is overridden to excepted, and the control is excluded from the pass/fail score calculation.
Each exception records:
| Field | Description |
|---|---|
control_id | The control being excepted |
scope_type | Scope level: asset, environment, or client |
scope_id | The specific host, environment, or client UUID |
reason | Business justification for accepting the risk |
approved_by | User ID of the approver |
approved_at | Timestamp of approval |
expires_at | Optional expiry date |
status | active, expired, or revoked |
Lifecycle:
- User creates an exception with a justification
- On the next compliance evaluation, the control status becomes
excepted - Creating, updating, or deleting an exception automatically triggers re-evaluation
- An exception expiry worker periodically checks for overdue exceptions and marks them
expired - Expired exceptions no longer override the control status -- the control reverts to its evidence-based verdict on the next evaluation
Re-evaluation Triggers
Compliance evaluations are triggered in three ways:
- Automatic -- When a healthcheck run completes, the healthcheck worker publishes a
proxima.compliance.evaluatemessage. This is the primary trigger. - Manual -- Users can trigger a re-evaluation via
POST /api/v1/hosts/{hostID}/compliance/evaluate. This returns202 Acceptedand publishes the same NATS message withrun_idset to nil (the worker uses the latest available run). - Side-effect -- Creating, updating, or deleting an attestation or exception for an asset-scoped control automatically publishes a re-evaluation trigger for the affected host.
Proxima Best Practices Framework
The proxima-best-practices framework is a builtin framework shipped with Proxima Console. It contains 26 controls across 7 categories, covering practical infrastructure security and operational baselines.
Controls by Category
| Category | Count | Controls |
|---|---|---|
| Security | 8 | SSH hardened, firewall enabled, audit tooling, file permissions, authentication hardened, kernel hardened, certificates valid, security updates |
| Patch & Vulnerability | 2 | No critical CVEs, no high CVEs |
| Observability | 3 | Monitoring active, logging configured, time sync configured |
| Networking | 3 | Minimal open ports, DNS configured, Docker network isolated |
| System | 4 | Disk usage healthy, kernel up to date, tmp mount separated, swap configured |
| Docker | 3 | Security baseline (no root/privileged/host network), operational baseline (resource limits/healthchecks/logging), version current |
| Backup | 3 | Backup service running, recent backups exist, restore tested (manual) |
Control Reference
| Code | Title | Severity | Type | Evidence |
|---|---|---|---|---|
SEC-SSH-001 | SSH access hardened | critical | automated | ssh-root-login-disabled, ssh-max-auth-tries, ssh-password-auth-disabled |
SEC-FW-001 | Firewall enabled | high | automated | firewall-enabled |
SEC-AUDIT-001 | Audit tooling installed | high | automated | auditd-running |
SEC-PERMS-001 | Sensitive file permissions | high | automated | filesystem-permissions, no-suid-dangerous |
SEC-AUTH-001 | Authentication hardened | high | automated | no-empty-passwords, fail2ban-running |
SEC-SYSCTL-001 | Kernel hardened | medium | automated | sysctl-hardened, core-dumps-disabled, ip-forwarding-disabled |
SEC-CERT-001 | Certificates valid | high | automated | certificates-valid |
SEC-UPDATE-001 | Security updates applied | critical | automated | updates-available |
VULN-CRIT-001 | No critical CVEs | critical | automated | trivy-no-critical-cves |
VULN-HIGH-001 | No high CVEs | high | automated | trivy-no-high-cves |
OBS-MON-001 | Monitoring active | high | automated | monitoring-agent-running |
OBS-LOG-001 | Logging configured | medium | automated | log-rotation-configured |
OBS-NTP-001 | Time sync configured | medium | automated | ntp-synchronized |
NET-PORTS-001 | Minimal open ports | medium | automated | open-ports-minimal |
NET-DNS-001 | DNS configured | medium | automated | dns-configured |
NET-DOCKER-001 | Docker network isolated | medium | automated | docker-network-isolated |
SYS-DISK-001 | Disk usage healthy | high | automated | disk-usage-healthy |
SYS-KERNEL-001 | Kernel up to date | medium | automated | kernel-up-to-date |
SYS-TMP-001 | Tmp mount separated | low | automated | tmp-mount-separate |
SYS-SWAP-001 | Swap configured | low | automated | swap-enabled |
DOC-SEC-001 | Docker security baseline | high | automated | docker-no-root-containers, docker-no-privileged, docker-no-host-network |
DOC-OPS-001 | Docker operational baseline | medium | automated | docker-resource-limits, docker-healthchecks, docker-logging-configured |
DOC-VER-001 | Docker version current | medium | automated | docker-version-current |
BKP-SVC-001 | Backup service running | high | automated | backup-service-running |
BKP-RECENT-001 | Recent backups exist | critical | automated | db-backup-recent |
BKP-RESTORE-001 | Restore tested | critical | manual | (manual attestation) |
Frontend UI
Compliance data is displayed at three levels in the Proxima Console frontend:
Host Compliance Tab
Each host detail page includes a Compliance tab that shows:
- Framework score cards -- One card per framework showing the compliance percentage, pass/fail/unknown counts, and a color-coded indicator based on
score_thresholds - Controls table -- A sortable, filterable table of all control evaluations for the host, with columns for status, control code, title, category, and severity
- Expandable rows -- Clicking a control row expands it to show the evaluation reason, evidence summary (key-value pairs from healthcheck results), and any active attestation or exception details
- Status and category filters -- Dropdown filters above the table to narrow by evaluation status or control category
- Inline badges -- Controls with active attestations show an "Attested" badge; controls with active exceptions show an "Excepted" badge
- Row actions -- Each row has a dropdown menu to add/edit attestations or add/revoke exceptions
Environment Compliance Tab
Each environment detail page includes a Compliance tab that shows:
- Framework score cards -- Aggregated scores across all active hosts in the environment
- Host comparison table -- Side-by-side compliance scores per host, sortable by score
- Top failed controls -- A ranked list of controls failing across the most hosts, with fail counts and severity
Client Compliance Tab
Each client detail page includes a Compliance tab that shows:
- Framework score cards -- Aggregated scores across all active hosts across all environments
- Top failed controls -- Client-wide view of most common compliance failures
- Expiring exceptions -- Exceptions expiring within 30 days, with control and host context
Management
The Compliance Settings admin page (/admin/compliance) provides full CRUD management for frameworks, controls, and control mappings. Access requires the compliance:read permission; mutations require compliance:write or compliance:delete.
Admin Page Layout
The page uses a two-panel master-detail layout:
- Left panel -- Framework list with source type badges (
builtin/custom), enabled toggles, and action menus - Right panel -- Controls table for the selected framework, with expandable rows showing remediation text and mappings
Frameworks
Frameworks can be custom (user-created) or builtin (shipped with Proxima).
| Action | Custom | Builtin |
|---|---|---|
| Create | Yes | -- |
| Edit (name, description, thresholds, enabled) | Yes | Yes |
| Delete | Yes | No (403 Forbidden) |
| Reset to defaults | -- | Yes |
Reset to defaults restores a builtin framework's controls to their original seeded state and removes any user-added controls.
Controls
Each control belongs to a framework and defines a compliance requirement.
| Field | Description |
|---|---|
code | Unique identifier within the framework (e.g., SEC-1) |
title | Human-readable name |
category | Grouping: security, patch_and_vuln, observability, networking, system, docker, backup |
severity | Impact level: critical, high, medium, low |
control_type | How evaluated: automated, manual, hybrid |
remediation | Markdown guidance for fixing failures (rendered in evaluation detail rows) |
Control Mappings
Mappings link a control to evidence sources. All mappings must pass for the control to pass.
| Field | Description |
|---|---|
source_type | Evidence source (e.g., healthcheck) |
source_ref | Specific check reference (e.g., lynis-ssh-1) |
operator | Comparison operator (e.g., status_is, gte) |
expected_value | Value to match against |
weight | Relative importance (default 1.0) |
Permissions
| Permission | Grants |
|---|---|
compliance:read | View frameworks, controls, mappings, and the admin page |
compliance:write | Create and edit frameworks, controls, and mappings |
compliance:delete | Delete custom frameworks, controls, and mappings |
API Endpoints
Frameworks
| Method | Path | Description |
|---|---|---|
GET | /api/v1/frameworks | List all compliance frameworks |
GET | /api/v1/frameworks/{id} | Get a single framework by ID |
POST | /api/v1/frameworks | Create custom framework |
PUT | /api/v1/frameworks/{id} | Update framework |
DELETE | /api/v1/frameworks/{id} | Delete custom framework |
POST | /api/v1/frameworks/{id}/reset | Reset builtin framework to defaults |
Controls
| Method | Path | Description |
|---|---|---|
GET | /api/v1/frameworks/{id}/controls | List controls for a framework (paginated, filterable by category, severity, control_type) |
GET | /api/v1/controls/{id} | Get a single control with remediation |
POST | /api/v1/frameworks/{id}/controls | Create control in a framework |
PUT | /api/v1/controls/{id} | Update control |
DELETE | /api/v1/controls/{id} | Delete control |
Control Mappings
| Method | Path | Description |
|---|---|---|
GET | /api/v1/controls/{id}/mappings | List mappings for a control |
POST | /api/v1/controls/{id}/mappings | Create mapping for a control |
GET | /api/v1/mappings/{id} | Get a single mapping |
PUT | /api/v1/mappings/{id} | Update mapping |
DELETE | /api/v1/mappings/{id} | Delete mapping |
Host Compliance
| Method | Path | Description |
|---|---|---|
GET | /api/v1/hosts/{hostID}/compliance | Get compliance posture for a host (per-framework scores) |
GET | /api/v1/hosts/{hostID}/compliance/evaluations | List compliance evaluations for a host (paginated, filterable by status, framework_id) |
POST | /api/v1/hosts/{hostID}/compliance/evaluate | Trigger compliance re-evaluation for a host (returns 202 Accepted) |
Rollups and Insights
| Method | Path | Description |
|---|---|---|
GET | /api/v1/environments/{envID}/compliance | Get compliance rollup for an environment |
GET | /api/v1/environments/{envID}/compliance/top-failures | Top failing controls in an environment (query: limit, default 10, max 50) |
GET | /api/v1/clients/{id}/compliance | Get compliance rollup for a client |
GET | /api/v1/clients/{id}/compliance/top-failures | Top failing controls across a client (query: limit, default 10, max 50) |
GET | /api/v1/clients/{id}/compliance/expiring-exceptions | Exceptions expiring within N days (query: days, default 30, max 365) |
Attestations
| Method | Path | Description |
|---|---|---|
POST | /api/v1/attestations | Create a manual attestation (body: control_id, scope_type, scope_id, status, note, expires_at) |
GET | /api/v1/attestations?scope_type=&scope_id= | List attestations for a scope (filterable by control_id) |
PUT | /api/v1/attestations/{id} | Update an attestation (body: status, note, expires_at) |
DELETE | /api/v1/attestations/{id} | Delete an attestation |
Exceptions
| Method | Path | Description |
|---|---|---|
POST | /api/v1/exceptions | Create a compliance exception (body: control_id, scope_type, scope_id, reason, expires_at) |
GET | /api/v1/exceptions?scope_type=&scope_id= | List exceptions for a scope (filterable by control_id, status) |
PUT | /api/v1/exceptions/{id} | Update an exception (body: reason, expires_at, status) |
DELETE | /api/v1/exceptions/{id} | Delete an exception |
Database Schema
The compliance system adds eight tables:
| Table | Purpose |
|---|---|
assets | Generic asset identity layer for compliance scoping |
frameworks | Compliance frameworks (builtin and custom) with score_thresholds |
controls | Individual controls within a framework |
control_mappings | Maps controls to evidence sources with evaluation logic |
control_evaluations | Per-control verdicts at asset/environment/client scope |
control_evidence_links | Links evaluations to the evidence that produced them |
manual_attestations | Human-submitted verdicts for manual/hybrid controls |
exceptions | Approved risk waivers with optional expiry |
Key Files
| File | Description |
|---|---|
backend/internal/api/compliance_handler.go | REST API handler for compliance scores, evaluations, rollups, and re-evaluation trigger |
backend/internal/api/compliance_framework_handler.go | CRUD handler for compliance framework management |
backend/internal/api/compliance_control_handler.go | CRUD handler for control and mapping management |
backend/internal/api/attestation_handler.go | CRUD handler for manual attestations |
backend/internal/api/exception_handler.go | CRUD handler for compliance exceptions |
backend/internal/api/compliance_trigger.go | Shared helper for publishing compliance re-evaluation messages |
backend/internal/worker/compliance.go | Compliance evaluation logic (pure + I/O) including attestation/exception integration |
backend/internal/worker/compliance_consumer.go | NATS JetStream consumer for compliance triggers |
backend/internal/worker/exception_expiry.go | Ticker-based worker that expires overdue exceptions |
backend/internal/store/compliance_store.go | Database operations for frameworks, controls, evaluations, scores |
backend/internal/store/attestation_store.go | Database operations for manual attestations |
backend/internal/store/exception_store.go | Database operations for compliance exceptions |
backend/internal/domain/compliance.go | Domain types: Framework, Control, ControlMapping, ControlEvaluation, ManualAttestation, Exception |
backend/migrations/000029_compliance_foundation.up.sql | Schema + seed data (Proxima Best Practices framework) |
backend/migrations/000033_attestations_exceptions.up.sql | Schema for attestations and exceptions |
frontend/src/components/compliance/ | React components: ControlsTable, FrameworkScoreCard, ControlStatusBadge, EvidenceDetail, CompliancePostureSection, etc. |
Related
- Healthcheck & Compliance -- Healthcheck scanner system that produces the evidence consumed by compliance evaluation
- Prometheus Metrics Reference -- Compliance-related Prometheus metrics
- OpenTelemetry Tracing Reference -- Compliance-related spans