KRIs & sources
A KRI is a numeric value with a threshold. A source is the thing that writes that value on a schedule. Together they are the backbone of every dashboard Draxis produces.
The KRI
A Key Risk Indicator has:
- A slug — the stable contract between connector and KRI (e.g.
critical_cves_unpatched_gt_30d). - A name and description for humans.
- A source — the
kri_sourcethat writes values. - Thresholds (
warn,critical) and a direction (higher-is-worse/lower-is-worse). - Links to one or more risks and a business outcome.
A KRI without links to risks and outcomes is valid but useless — it shows up on the dashboard but doesn’t roll up. The onboarding flow won’t let you finish until each KRI is wired.
The source
A kri_source is a per-tenant connection to an integration. It stores:
- Source type + vendor ID — the pair that resolves to a connector.
- API endpoint — the vendor URL (auto-filled for fixed-URL vendors).
- Auth type and encrypted credentials.
- Schedule —
daily(default),hourly, ormanual. - Extra config — non-secret JSON (e.g.
{"customer_id":"abc"}for Google Workspace).
How the runner writes values
- The scheduler wakes up and resolves every source whose next-run time has passed.
- For each source, the dispatcher looks up the connector by
vendor_idand callsrun(ctx). - The connector fetches data from the vendor, computes each KRI value, and runs
UPDATE kri SET value = ?, updated_at = ? WHERE source_id = ? AND id = ?. - If a KRI slug is missing, the row is counted as
rowsSkipped— it means the tenant hasn’t wired that KRI yet. Not an error. - The run row is written with
rowsWritten,rowsSkipped, and a summary of items fetched.
Rollups
Dashboards compute three levels of rollup:
- Per-KRI colour (green / amber / red) from its thresholds.
- Per-risk severity from the KRIs and controls linked to that risk.
- Per-outcome severity from the risks linked to the outcome.
See Platform overview for how KRIs, risks, controls, and outcomes relate.
Manual KRIs
Not every KRI needs an integration. For values that only a human knows (e.g. “has the quarterly board risk review happened?”), create the KRI without a source and edit its value by hand. The updated_at ages the same way as an automated value, so stale manual values show up in the Draxis staleness report.
API
GET /api/kri-sources— list sources.PUT /api/kri-sources/<id>— create / update.POST /api/kri-sources/<id>/test— probe connectivity.POST /api/kri-sources/<id>/run— trigger a run now.GET /api/kri-sources/<id>/runs— run history.GET /api/kris,PUT /api/kris/<id>— KRI CRUD.