Skip to content
crafted signal

Core Concepts

Risks

The Risk Ops Board turns each company attack path into a tracked risk with a state machine, priority score, and lifecycle audit trail. Hunt, accept residual, escalate, or schedule a re-hunt — the loop closes back into coverage.

Overview

A risk in CraftedSignal is a company attack path with state. The threat model declares what the attacker could do; the Risk Ops Board tracks what you are doing about each one.

Every accepted attack path becomes a risk. Each risk carries a priority score, a coverage percentage, a state, and a full audit trail of every transition. The Risks page is where analysts triage, hunt, and close out exposure — and where the threat feed surfaces new candidates as briefs land.

Risks live at /dashboard/threat-model/risks. The drawer opens on row click.


The state machine

Every risk moves through a deterministic lifecycle. Each transition is recorded in the lifecycle timeline with the actor, timestamp, and reason.

StateMeaning
suggestedGenerated by the threat model or feed bridge, awaiting review
acceptedAn analyst has approved the risk for investigation
huntingA hunt anchored to this risk is running
evidence_gatheredHunt completed; an evidence summary is attached
mitigatedA detection rule was promoted from the hunt; the risk is covered
active_threatEvidence indicates ongoing exploitation — escalate to IR
residual_acceptedRisk acknowledged with no further action
rejectedTerminal — the risk does not apply
  • suggestedaccepted or rejected
  • acceptedhunting, residual_accepted, or rejected
  • huntingevidence_gathered (or back to accepted to pause)
  • evidence_gatheredmitigated, active_threat, or residual_accepted
  • mitigatedhunting (when a scheduled re-hunt fires)
  • active_threathunting or residual_accepted
  • residual_acceptedhunting (analyst reopens)
  • rejected is terminal

State pills in the drawer use a fixed color scheme: blue (hunting), amber (evidence_gathered), emerald (mitigated), red (active_threat), zinc (residual_accepted), slate (default).


Priority

Each risk carries a 0–100 priority score. The board sorts by priority descending so the most urgent risks surface first.

priority = severity × likelihood × (1 − coverage) × staleness × scale
  • Severity and likelihood are declared on the risk (low = 0.25, medium = 0.5, high = 0.75, critical = 1.0).
  • Coverage is the fraction of attack-path steps detected by at least one rule. A risk with no rules pinned to any step has coverage 0; a risk with full per-step coverage has coverage 1.
  • Staleness boosts risks that haven’t been hunted recently. Capped at 3× — a risk that has never been hunted always sits at the maximum boost.
  • The scale factor normalizes the worst case (critical × critical × fully uncovered × never hunted) to 100.

Priority recomputes:

  • On every load of the Risks page (rate-limited to once per minute per company).
  • Whenever a detection’s MITRE techniques change (auto-rebinds coverage edges).
  • Whenever a hunt is promoted to a rule (the new edge re-anchors the risk).

Coverage

Coverage links detection rules to risks via the detection_threats edge table. Every edge carries a source so you can tell automated coverage from analyst-driven coverage:

SourceWhen it’s written
promoted_from_huntA hunt query graduated into a detection. Confidence = 100.
auto_technique_matchA detection’s MITRE techniques overlap with steps on the risk. Confidence = matched-steps ÷ total-steps × 100.
manualReserved for analyst-driven linking.

Auto-matched edges refresh whenever a detection’s technique list changes. Hunt-promoted and manual edges are preserved across recomputes — analyst intent always wins over the heuristic.


Candidates

The threat feed turns into risks via the Candidates tab at /dashboard/threat-model/candidates. When a brief is highly relevant to your tenant — a relevance score of 75+ or a watchlist match — the platform creates a risk_candidate with proposed severity, likelihood, and a list of MITRE techniques pulled from the brief.

Each candidate shows:

  • The brief title, threat actor (when resolved), and rationale (relevance score, watchlist match, technique overlap).
  • The proposed severity and likelihood, derived from brief severity plus relevance.
  • An existing risk match, when the candidate’s techniques overlap ≥50% with a path you already have.

Three actions:

  • Accept — creates a new risk in accepted state with the proposed fields.
  • Dismiss — drops the candidate without creating a risk.
  • Merge into existing — when an existing risk match is offered, the brief is linked to the existing risk and the candidate is closed.

The bridge runs as a child workflow of the threat-feed sync. Candidates land in the Candidates tab as briefs are ingested; nothing happens to your live risks until an analyst accepts.


The drawer

Click any row on the Risks page to open the drawer. It shows:

  • State pill (color-coded as above) and priority badge (0–100).
  • Severity / likelihood and hunts run count.
  • Evidence summary — populated automatically when a hunt completes against this risk.
  • Lifecycle timeline — every state transition with who fired it and why.
  • Actions (only the ones legal from the current state are shown):
    • Hunt this risk — creates a new hunt anchored to the risk and transitions to hunting.
    • Accept residual — prompts for a note, then transitions to residual_accepted.
    • Mark as active threat — for risks in evidence_gathered, captures escalation context and transitions to active_threat.
    • Schedule re-hunt now — for risks in mitigated, immediately fires a fresh hunt.

Hunting from a risk

When you click Hunt this risk, the platform creates a new hunt with:

  • Title "Hunt: <risk name>" and a hypothesis pointing back to the risk.
  • CompanyAttackPathID set to the risk ID — the hunt is anchored.
  • All active SIEMs selected by default (override on the new-hunt form if needed).

The hunt detail page renders a Covers kill chain card showing every step on the risk, with crosshairs on the steps the hunt is investigating and shields on steps already covered by production rules.

The hunt proposer also sources from accepted risks. Risk-anchored hypotheses are ranked by the underlying risk’s priority, so the suggested hunts at the top of /dashboard/hunts are the ones the model says you should run next.


Re-hunt

When a risk is promoted to mitigated (a hunt graduated into a rule), the platform schedules a re-hunt 90 days out. The clock is stored as cap_next_review_at on the risk; a Temporal cron transitions the risk back to hunting and creates a fresh hunt at the scheduled time.

You can also re-hunt manually from the drawer’s Schedule re-hunt now action — useful when threat intel surfaces a new variant of the same TTP.


Auto-accept

Risks generated with severity critical — or severity high with likelihood high or critical — are auto-accepted on creation. They land in the accepted state with reviewed_by = "auto-accept:severity" so they flow straight into the hunt queue. Less severe risks stay in suggested for analyst review.

This is intentional and not configurable per-tenant: the model already weighs severity heavily, so paths the model considers extreme need to be visible to hunters immediately.


Routes

RoutePurpose
GET /dashboard/threat-model/risksRisks list, filterable by state and coverage view
GET /dashboard/threat-model/risks/{id}/drawerDrawer partial (HTMX)
POST /dashboard/threat-model/risks/{id}/huntCreate hunt + transition to hunting
POST /dashboard/threat-model/risks/{id}/accept-residualTransition to residual_accepted
POST /dashboard/threat-model/risks/{id}/mark-active-threatTransition to active_threat
POST /dashboard/threat-model/risks/{id}/schedule-rehuntRe-hunt a mitigated risk
GET /dashboard/threat-model/candidatesPending risk candidates from the feed
POST /dashboard/threat-model/candidates/{id}/acceptPromote candidate to risk
POST /dashboard/threat-model/candidates/{id}/dismissDismiss candidate

  • Threat Model — how attack paths are declared and weighted.
  • Hunts — the action arm for risks in accepted, hunting, or mitigated.
  • Threat Feed — where candidates originate.
  • Threat Actors — the catalog the bridge enriches briefs against.