Trust Score
/[locale]/trust-score shows a single number plus the per-category
breakdown. The algorithm processes every signal_streams row that arrived
in the last 30 days.
Algorithm
- Collect every signal with
severity NOT IN (NULL, 'info')from the last 30 days for the tenant. - Severity → numeric weight:
info=0 low=1 medium=4 high=15 critical=40
- Per category:
category_score = max(0, 100 - sum(weights) * scaling_factor)withscaling_factor = 1.0. A single critical alone drops -40 (100 → 60), three criticals clamp to 0. score_total= weighted average across the eight categories, usingtrust_score_weights.configas the weights.
Eight categories
| Key | Default weight | Sources that feed in |
|---|---|---|
cves | 15 | supply_chain (Phase 4.2) |
compliance | 20 | license_check (1.8) |
identity | 15 | secrets_scan, endpoint_posture, identity_audit, auth_geo |
ai_risk | 10 | (ai_traces.pii_hits via separate path) |
process_dna | 10 | clock_check, container_posture |
cert_dns | 10 | cert_scan(_internal), ct_monitor, dns_check |
backup | 10 | backup_check |
incident_response | 10 | (alert lifecycle, Phase 5.1) |
Per-tenant override via POST /api/v1/trust-score/weights
(admin/owner + TOTP in production).
Reproducibility
inputs_hash = sha256(window_start.Unix || window_end.Unix || sorted [signal_id|severity|category]).
The worker only writes a new snapshot when inputs_hash differs from the
previous row — no empty time-series between findings.
Endpoints
GET /api/v1/trust-score/currentGET /api/v1/trust-score/history?window=90d 1h..365dGET /api/v1/trust-score/category/:cat/contributors top 20 per categoryGET /api/v1/trust-score/explain top 10 across allPOST /api/v1/trust-score/weights admin + TOTP-prodHistory default window is 90 days; the weights API accepts exactly the 8 keys above, sum > 0.
Under the hood
- Table:
trust_score_snapshots(computed_at, tenant_id, score_total, category_scores JSONB, weights_version, inputs_hash) - Weights:
trust_score_weights(id PK, tenant_id NULLABLE, weights_version, config JSONB)— NULL tenant_id = global defaultdefault-v1 - Calculator:
hub/api/trust_score/calculator.go— testable viaCalculator.CalculateAt(ctx, tenant, now)