TenantAtlas/specs/111-findings-workflow-sla/data-model.md
2026-02-25 02:45:20 +01:00

4.0 KiB

Data Model: 111 — Findings Workflow V2 + SLA

Date: 2026-02-24
Branch: 111-findings-workflow-sla


Modified Entities

1. findings Table (Lifecycle + SLA + Recurrence)

This feature evolves findings from v1 (new|acknowledged|resolved) to a v2 workflow and adds lifecycle metadata and SLA fields.

New Columns

Column Type Constraints Notes
first_seen_at timestampTz nullable initially; NOT NULL after backfill Set on first observation; backfill from created_at where possible
last_seen_at timestampTz nullable initially; NOT NULL after backfill Updated on every observation (including terminal findings)
times_seen integer default 0, NOT NULL (after backfill enforce) Incremented on every observation
sla_days smallint nullable SLA policy value applied when due_at was set/reset
due_at timestampTz nullable Only “open” findings participate in SLA due evaluation
owner_user_id bigint FK → users, nullable Retained even if user is no longer a tenant member
assignee_user_id bigint FK → users, nullable Retained even if user is no longer a tenant member
triaged_at timestampTz nullable Set on `new
in_progress_at timestampTz nullable Set on triaged → in_progress
reopened_at timestampTz nullable Set when transitioning into reopened (manual or automatic)
closed_at timestampTz nullable Used for both closed and risk_accepted terminal outcomes
closed_by_user_id bigint FK → users, nullable Actor for closed / risk_accepted
closed_reason string nullable Reason required for closed and risk_accepted
recurrence_key string(64) nullable; indexed Stable identity for drift recurrence (v2)

Existing Columns Used/Extended

Column Notes
status Extended v2 statuses (see below). Legacy acknowledged is mapped to v2 triaged in the UI and migrated during backfill.
resolved_at / resolved_reason Remains the terminal “resolved” record with reason.
acknowledged_at / acknowledged_by_user_id Retained for historical reference; acknowledged status is legacy.
fingerprint Remains unique per tenant. For canonical drift rows going forward, the fingerprint is stable (aligned to recurrence identity).

Status Values (Canonical)

Open statuses:

  • new
  • triaged
  • in_progress
  • reopened

Terminal statuses:

  • resolved
  • closed
  • risk_accepted

Legacy status (migration window):

  • acknowledged (treated as triaged in v2 surfaces)

Indexes

New/updated indexes to support list filters and alert evaluation:

Index Type Purpose
(tenant_id, status, due_at) btree Open/overdue filtering in tenant UI
(tenant_id, assignee_user_id) btree “My assigned” filter
(tenant_id, recurrence_key) btree Drift recurrence lookups and consolidation
(workspace_id, status, due_at) btree Workspace-scoped SLA due producer query

Existing index (tenant_id, status) remains valid.


Configuration Keys (No Schema Change)

Settings: Findings SLA policy

Add a SettingsRegistry entry (workspace-resolvable):

  • findings.sla_days (JSON object): severity → days
  • Default:
    • critical: 3
    • high: 7
    • medium: 14
    • low: 30

Stored in existing workspace_settings / tenant_settings tables; no new tables required.


State Machine (High-Level)

new ──triage──> triaged ──start──> in_progress ──resolve──> resolved
  └───────────────────────────────close/risk_accept──────────────> closed|risk_accepted

resolved ──(auto or manual)──> reopened ──triage──> triaged ...
closed|risk_accepted ──(manual only)──> reopened