Files
git.stella-ops.org/docs/modules/findings-ledger/prep/2025-11-20-ledger-risk-66-prep.md
master d519782a8f
Some checks failed
Docs CI / lint-and-preview (push) Has been cancelled
prep docs and service updates
2025-11-21 06:56:36 +00:00

51 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Ledger Risk Schema Prep — PREP-LEDGER-RISK-66-001/002
Status: Prep complete (2025-11-20)
Owners: Findings Ledger Guild · Risk Engine Guild
Scope: Contract + data model for PREP-LEDGER-RISK-66-001/002 (risk scoring fields and deterministic upsert).
## Field definitions (canonical finding projection)
- `risk_score` (numeric, 0100, 2dp) — monotonic per `(finding_id, profile_version)`; computed by Risk Engine.
- `risk_severity` (enum) — derived mapping: `critical >= 90`, `high >= 70`, `medium >= 40`, `low >= 10`, `informational < 10`.
- `risk_profile_version` (string) — semantic version of the scoring policy/profile; required.
- `risk_explanation_id` (uuid/string) — pointer to Risk Engine explanation payload stored in Risk service (not duplicated in ledger).
- `risk_event_sequence` (long) — ledger sequence of the last applied risk event; enforces monotonic updates.
- `risk_updated_at` (ISO-8601 UTC) — when the score was last written.
## Storage and indexes (MongoDB)
- Collection: `findings` (existing). Add fields above to the projection document.
- Unique compound index: `{ tenant: 1, finding_id: 1, risk_profile_version: 1 }`.
- Query helper index for exports/UI: `{ tenant: 1, risk_severity: 1, risk_score: -1, observed_at: -1 }`.
- TTL: none; scores are historical but superseded by deterministic upsert described below.
## Deterministic upsert flow (LEDGER-RISK-66-002)
1. Risk Engine emits `RiskScoreApplied` event with `{tenant, finding_id, profile_version, score, explanation_id, event_sequence}`.
2. Handler loads current projection by `(tenant, finding_id)`; compares `(profile_version, event_sequence)`:
- If incoming `event_sequence` < stored `risk_event_sequence` ignore (idempotent).
- If equal idempotent update allowed only when score/severity unchanged.
- If greater write new values and set `risk_event_sequence = event_sequence`.
3. All writes recorded in ledger append with same event_sequence for audit; projection updates deterministic by sequence ordering.
4. Exports (`/ledger/export/findings`) surface these fields; snapshot bundles reuse the same shape.
## API/SDK contract hooks
- OAS baseline will mark all four fields in the finding shapes (canonical + compact) as optional today, required once migrations finish.
- `/ledger/export/findings` filters: `risk_profile_version` (already reserved), add `risk_severity` and `risk_score_min/max` in the next OAS bump.
- UI/SDK must treat missing `risk_profile_version` as not yet scored”.
## Migration/rollout plan (LEDGER-RISK-66-001)
- Step 1: Add fields and indexes behind feature flag `RiskScoringEnabled` (default off).
- Step 2: Backfill for latest profile per tenant using Risk Engine batch export; write via deterministic upsert to enforce ordering.
- Step 3: Enable streaming ingestion of `RiskScoreApplied` events; monitor lag via metric `ledger_risk_score_apply_lag_seconds`.
- Step 4: Flip default for `RiskScoringEnabled` to on after backfill success criteria:
- 99.9% of existing findings have `risk_profile_version` populated.
- No rejected events due to sequence regressions in the last 24h.
- Step 5: Update OAS/SDK to mark fields required; notify UI/Export consumers.
## Observability
- Log: `ledger.risk.apply` with tenant, finding_id, profile_version, score, event_sequence, applied (bool).
- Metrics: `ledger_risk_apply_total{result}`; `ledger_risk_score_latest{severity}` gauges per tenant.
- Tracing: span `ledger.risk.apply` tagging `profile_version`, `event_sequence`, `idempotent`.
## Handoff
- This document is the prep artefact for PREP-LEDGER-RISK-66-001/002. Implementation tasks wire schema + deterministic upsert and extend exports/OAS accordingly.