Adr 001
Status
Accepted
Context
Organizations and individuals need a systematic way to track, analyze, and mitigate risks. Risk analysis is best understood through a cause-outcome model: causalities lead to unwanted outcomes, and mitigations target either side.
This system will support hierarchical risk scoping through Systems and Components.
Decision
We will build risky, a dedicated risk analysis management daemon with a REST API based on a cause-outcome-mitigation model.
Domain Model
Core Entities
Entity Definitions
| Entity | Attributes | Description |
|---|---|---|
| System | ID, Name, Description, CreatedAt | Top-level container (service, infrastructure) |
| Component | ID, SystemID, Name, Description, Type | Sub-part within a system (database, API, queue) |
| RiskOutcome | ID, Name, Description, SeverityScore (1-5), Scope (system|component), ScopeID | Unwanted event that can occur |
| Causality | ID, Name, Description, LikelihoodScore (1-5), TimeUnit, Scope (system|component), ScopeID | Something that may cause an outcome |
| RiskPair | ID, CausalityID, RiskOutcomeID, BaseScore, CalculatedAt, FinalScore | Junction: Causality Γ Outcome combination |
| Mitigation | ID, RiskPairID, TargetType (causality|outcome), TargetID, Title, Description, ReductionValue (1-5), Status | Action to reduce risk |
Scoring Values
| Scale | Values |
|---|---|
| Severity/Likelihood | 1 (very low) to 5 (very high) |
| Time Units | per_request, per_day, per_week, per_month, per_year |
| Status | planned, in_progress, implemented, verified |
| RiskPair Calculation | Contained in service, refactorable |
Goals
| ID | Goal | Priority |
|---|---|---|
| G1 | Hierarchical risk scoping via Systems and Components | Must |
| G2 | Cause-outcome risk modeling with multiple causalities per outcome | Must |
| G3 | Configurable risk calculation (contained, refactorable) | Must |
| G4 | Mitigation tracking with target selection (causality or outcome) | Must |
| G5 | REST API for full CRUD on all entities | Must |
| G6 | Risk aggregation and querying by system/component | Should |
| G7 | Export/import for bulk operations | Could |
Non-Goals
| ID | Non-Goal | Rationale |
|---|---|---|
| NG1 | Web interface | Out of scope; backend only |
| NG2 | Real-time updates | REST polling sufficient |
| NG3 | Authentication | Network-level security (Tailscale) |
| NG4 | External database | SQLite embedded sufficient |
Technical Stack
| Component | Choice |
|---|---|
| Language | Go 1.24+ |
| HTTP Router | Chi |
| REST Framework | Huma (OpenAPI generation) |
| Database | SQLite (embedded) |
| SQL | sqlc (type-safe) |
| Migrations | golang-migrate |
| Config | Environment vars |
API Endpoints
Systems
GET /api/v1/systems POST /api/v1/systems GET /api/v1/systems/{id} PUT /api/v1/systems/{id} DELETE /api/v1/systems/{id} GET /api/v1/systems/{id}/components GET /api/v1/systems/{id}/risks GET /api/v1/systems/{id}/aggregate-risk
Components
GET /api/v1/systems/{systemId}/components POST /api/v1/systems/{systemId}/components GET /api/v1/components/{id} PUT /api/v1/components/{id} DELETE /api/v1/components/{id} GET /api/v1/components/{id}/risks
Risk Outcomes
GET /api/v1/risk-outcomes POST /api/v1/risk-outcomes GET /api/v1/risk-outcomes/{id} PUT /api/v1/risk-outcomes/{id} DELETE /api/v1/risk-outcomes/{id} GET /api/v1/risk-outcomes/{id}/pairs GET /api/v1/risk-outcomes/{id}/causalities
Causalities
GET /api/v1/causalities POST /api/v1/causalities GET /api/v1/causalities/{id} PUT /api/v1/causalities/{id} DELETE /api/v1/causalities/{id} GET /api/v1/causalities/{id}/outcomes
Risk Pairs
GET /api/v1/risk-pairs POST /api/v1/risk-pairs GET /api/v1/risk-pairs/{id} PUT /api/v1/risk-pairs/{id} DELETE /api/v1/risk-pairs/{id} GET /api/v1/risk-pairs/{id}/mitigations GET /api/v1/risk-pairs/{id}/calculate
Mitigations
GET /api/v1/mitigations POST /api/v1/mitigations GET /api/v1/mitigations/{id} PUT /api/v1/mitigations/{id} DELETE /api/v1/mitigations/{id} PATCH /api/v1/mitigations/{id}/status
Calculation Service Interface
type RiskCalculator interface { // Calculate base score for a risk pair CalculateBase(causality Causality, outcome RiskOutcome) int
// Apply mitigations to get final score
ApplyMitigations(baseScore int, mitigations []Mitigation) int
// Recalculate and persist a risk pair
Recalculate(pairID uuid.UUID) (RiskPair, error)
}
Initial implementation: Base = Severity Γ Likelihood, Final = Base - sum(MitigationReduction)
Calculation Example
| Component | Value |
|---|---|
| Outcome | “Data breach” |
| Outcome Severity | 5 |
| Causality | “Using insecure channels” |
| Causality Likelihood | 5 (always) |
| Base Score | 5 Γ 5 = 25 |
| Mitigation | “Use HTTPS” targeting causality |
| Reduction | -5 |
| Final Score | 20 |
Authors: inful, Count
Date: 2026-02-17
Status: Accepted