# Incident DM Follow-Ups Plan

## Background

This note records the current code-level assessment for incident-related child items under `DM-11220`, and proposes an execution order.

The immediate focus is the first three infrastructure-level items:

- `DM-12749` Incident component config and severity helper
- `DM-12750` Unify incident time model in UTC
- `DM-12751` Fix incident Jira link persistence and retrieval

These three items sit below most of the later incident improvements. Until they are cleaned up, the incident detail model remains unstable and later work will continue to build on weak foundations.

## Scope

This document covers:

- code-level findings for incident-related DMs
- whether each Jira item is already reflected in the current codebase
- the suggested implementation sequence
- a short delivery plan for the first three DMs

This document does not yet contain the final implementation design for each item. It is meant to align priority and execution shape first.

## Summary Table

| Jira | Current code evidence | Assessment | Suggested direction |
| --- | --- | --- | --- |
| `DM-12089` update incident alert rule | No clear implementation point found in current incident module. This likely belongs to alerting or automation integration rather than the current incident CRUD flow. | Not yet confirmed from code | Check O11Y / automation / incident creation trigger path separately. |
| `DM-12749` Incident component config and severity helper | Incident `components` is still a space-joined string in backend API and model. Frontend keeps a hardcoded `knownComponents` list and explicitly notes it should be replaced by backend requests. | Confirmed | Move component options to backend-managed metadata and stop using frontend hardcoded options. |
| `DM-12750` Unify incident time model in UTC | Time fields are stored and transported as generic `time.Time`, but frontend edit/display path mixes raw strings and `moment.utc(...)` conversion without a single normalization path. Validation does not enforce UTC or precision rules. | Confirmed | Define a canonical UTC time contract for create/edit/display and normalize all API paths to it. |
| `DM-12751` Fix incident Jira link persistence and retrieval | `jira_issues` is a single joined string in backend and frontend. Update request is not patch-style; omitted string fields can collapse to empty strings and be written back. | Confirmed | Replace joined-string storage with structured Jira link data and patch-safe update semantics. |
| `DM-12752` Postmortem snapshot archival and preview | Postmortem is still hyperlink-driven in UI. Model has `postmortem_doc_url`, but entity/API/converter path does not expose a stable archived artifact model. | Confirmed | Add managed postmortem artifact model with immutable snapshot metadata and preview/download entry. |
| `DM-12753` Repair incident todo action workflow | API and routes carry `postmortem_id`, but todo action persistence only stores `incident_id`. Filtering and sync are incident-scoped. Update path ignores `Persons`. Frontend also passes placeholder postmortem id `1`. | Strongly confirmed | Fix relation model first, then repair CRUD, filtering, and status workflow. |
| `DM-12754` Feishu incident lifecycle sync and warning workflow | Current Feishu support is mostly one-time message generation plus todo status sync from Feishu task. No warning record workflow or incident lifecycle card-update flow is present. | Confirmed | Split into lifecycle sync and warning workflow tracks. Persist message/card id and update the same artifact on milestones. |
| `DM-12755` Implement incident scoring algorithm in system | No incident scoring model, API field, or UI display exists in current incident implementation. | Confirmed | Add a persisted scoring result model with calculation version and recalculation path. |
| `DM-12761` Record postmortem meeting recording reference | No recording-related field exists in incident postmortem entity/model/API/UI. | Confirmed | Add lightweight recording reference fields on postmortem. |

## Detailed Notes

### DM-12749

Problem shown by code today:

- backend `incident` model still uses `components string`
- frontend incident pages keep a hardcoded component list
- frontend create/edit/list all do string join or split for component values

Why it matters:

- component options cannot evolve safely without frontend edits
- severity guidance cannot be cleanly tied to a stable component key
- validation is weak because components are not structured

Implementation target:

- backend provides component options and metadata
- incident stores stable component keys
- frontend renders backend-provided labels and helper text

### DM-12750

Problem shown by code today:

- frontend edit form converts incoming values with `moment.utc(...)`
- frontend update adaptor still treats incident times as raw strings
- display path prints backend time strings directly
- backend validation does not enforce UTC normalization or minute precision

Why it matters:

- create, edit, and display are not guaranteed to round-trip consistently
- timezone intent remains implicit
- timeline and reporting fields can drift subtly

Implementation target:

- incident API always accepts and returns UTC timestamps in one agreed format
- backend normalizes stored values to UTC
- frontend only converts at UI boundaries and uses one serializer path
- minute precision rules are explicit

### DM-12751

Problem shown by code today:

- Jira links are modeled as one string field
- frontend turns list input into a joined string
- update request uses plain strings rather than optional patch fields
- backend update path can write empty strings back for omitted fields

Why it matters:

- Jira links are fragile under edit and later reads
- data loss risk exists even when user intent is partial update
- the model cannot express stable `issue_key` plus `issue_url`

Implementation target:

- Jira links become structured data
- update semantics become patch-safe
- detail and list APIs return stable link objects rather than joined strings

## Suggested Delivery Order

### Phase 1: Foundation cleanup

Do first:

1. `DM-12751`
2. `DM-12749`
3. `DM-12750`

Reason:

- `DM-12751` fixes a direct data-loss and persistence problem
- `DM-12749` removes hardcoded workflow-adjacent metadata from frontend
- `DM-12750` makes time semantics stable before later lifecycle work

### Phase 2: Follow-up model repairs

Then:

1. `DM-12753`
2. `DM-12752`
3. `DM-12761`

Reason:

- todo action relation repair is the most broken postmortem workflow today
- postmortem archival should build on a cleaner incident/postmortem model
- recording reference is a lightweight extension once postmortem shape is cleaner

## Detailed Implementation Checklist

### DM-12753 Repair incident todo action workflow

Goal:

- make todo actions belong to the real postmortem record rather than a loosely incident-scoped placeholder flow
- repair CRUD, filtering, and Feishu sync on top of the corrected relation model

Checklist:

1. Clarify data ownership
- define todo actions as children of `postmortem`
- verify whether the current database table already has `postmortem_id`
- if not, add a migration
- if the column exists but is unused, move all reads and writes to it

2. Normalize backend model shape
- update `models.IncidentPostMortemToDoAction`
- update `entity.IncidentPostMortemToDoAction`
- keep a consistent field set:
  - `id`
  - `postmortem_id`
  - optional `incident_id` only if still needed as redundant context
  - `title`
  - `description`
  - `persons`
  - `deadline`
  - `status`
  - `feishu_task_id`
- define one canonical status enum, recommended:
  - `open`
  - `in_progress`
  - `done`
  - `canceled`

3. Fix service semantics
- change `ListIncidentPostMortemToDoActions()` to query by `postmortem_id`
- ensure `CreateIncidentPostMortemToDoActionItem()` persists the true `postmortem_id`
- ensure `UpdateIncidentPostMortemToDoActionItem()` correctly updates `persons`
- change `SyncToDoActionStatusFromFeishu()` to use the corrected relation model

4. Fix controller and API contract
- make route semantics match implementation semantics for `postmortem_id`
- return real `postmortem_id` in response payloads
- remove misleading field or route naming if it conflicts with actual ownership
- regenerate swagger after the API shape is updated

5. Fix frontend usage
- stop passing placeholder postmortem id `1` from `IncidentPostMortem/index.tsx`
- bind create, update, and list actions to the real postmortem id
- align status display with the normalized enum
- verify `persons` edit and replay behavior

6. Prepare migration and backfill
- audit existing todo action rows
- determine whether historical rows can map from `incident_id` to one concrete `postmortem_id`
- add a backfill strategy
- define a fallback policy for rows that cannot be mapped cleanly

7. Add regression coverage
- backend tests for create, list, update, and sync paths
- backend tests for invalid or missing `postmortem_id`
- frontend smoke validation for action create and edit in the postmortem page

Suggested landing sequence:

1. relation model and database migration
2. service and controller cleanup
3. frontend real-id wiring
4. status and sync cleanup
5. backfill and compatibility cleanup

### DM-12752 Postmortem snapshot archival and preview

Goal:

- stop treating postmortem content as an incidental hyperlink
- make postmortem artifacts a stable part of the incident/postmortem model
- land a minimal artifact contract first, then expand into snapshot and preview behavior

Checklist:

1. Audit current field usage
- verify `models.IncidentPostMortem.postmortem_doc_url`
- compare `model`, `entity`, `api`, and repo converter coverage
- confirm where the frontend still relies on `incident.feishu_url` instead of postmortem fields

2. Land the minimal artifact model
- expose `postmortem_doc_url` end to end first
- if scope allows, prepare future fields such as:
  - `snapshot_url`
  - `preview_url`
  - `archive_status`
- avoid building a large archival subsystem in the first step

3. Fix repository converters
- update `model_to_entity`
- update `entity_to_model`
- ensure `postmortem_doc_url` no longer disappears across conversions

4. Fix API and controller paths
- allow create postmortem to set `postmortem_doc_url`
- allow update postmortem to modify `postmortem_doc_url`
- return `postmortem_doc_url` from get and list responses
- regenerate swagger after the API shape is updated

5. Fix frontend postmortem page
- stop treating `incident.feishu_url` as the only postmortem document reference
- render postmortem artifact data inside `IncidentPostMortem/index.tsx`
- at minimum, show the source doc link from the postmortem model
- if `snapshot_url` or `preview_url` exists later, add explicit preview and download entry points

6. Plan snapshot expansion as phase 2
- define how snapshot creation is triggered:
  - manual archive
  - automatic archive
- define artifact persistence fields:
  - `snapshot_url` or `archive_ref`
- define frontend presentation:
  - source doc
  - archived snapshot
  - preview status

7. Add regression coverage
- backend tests for create, get, and update of postmortem document URL
- converter tests for `postmortem_doc_url`
- frontend verification for postmortem form replay and save behavior

Suggested landing sequence:

1. expose `postmortem_doc_url` through model, converter, API, and UI
2. switch frontend postmortem view away from incidental incident-level link usage
3. add snapshot metadata fields
4. add preview and download behavior

### Phase 3: Lifecycle and governance features

Then:

1. `DM-12754`
2. `DM-12755`
3. `DM-12089`

Reason:

- lifecycle sync should consume a more stable incident model
- scoring should be added after the core incident fields are trustworthy
- alert-rule work still needs separate discovery

## Proposed Plan For The First Three DMs

### Track A: DM-12751 Jira link model

Backend:

- introduce structured Jira link fields in incident DTO and persistence path
- make update behavior patch-safe
- keep temporary backward compatibility for old string payload if needed

Frontend:

- stop serializing Jira links with string join or split
- use structured form state
- preserve link key and url separately where possible

Suggested landing sequence:

1. backend DTO and service patch semantics
2. backend read-path compatibility
3. frontend type regeneration and form update
4. optional migration of historical joined-string records

### Track B: DM-12749 component config

Backend:

- add component options endpoint or extend existing incident metadata endpoint
- define stable component key plus display label
- prepare severity helper metadata shape

Frontend:

- replace `knownComponents`
- render backend-provided option list
- keep local fallback only during transition if required

Suggested landing sequence:

1. backend component metadata
2. frontend option consumption
3. backend validation against allowed keys
4. optional helper text integration

### Track C: DM-12750 UTC time contract

Backend:

- define accepted timestamp format
- normalize to UTC on write
- keep response format consistent

Frontend:

- unify create/edit serializer
- keep UI labels aligned with actual UTC behavior
- avoid mixing direct string reuse with implicit timezone conversion

Suggested landing sequence:

1. backend time contract and validation
2. frontend request serialization cleanup
3. frontend display formatting cleanup
4. regression coverage for create -> edit -> read round trip

## Expected File Touch Areas

Likely backend files for the first three DMs:

- `api/incident/incident_api.go`
- `entity/incident.go`
- `entity/validation/incident.go`
- `models/incident.go`
- `pkg/service/incident/incident_service.go`
- `pkg/controller/incident/incident_controller.go`
- incident-related tests

Likely frontend files for the first three DMs:

- `src/pages/Incidents/Util.tsx`
- `src/pages/Incidents/index.tsx`
- `src/pages/Incidents/IncidentView/index.tsx`
- generated API types

## Risks

- `DM-12751` may need compatibility handling for existing joined-string records
- `DM-12750` may expose hidden timezone assumptions in existing data
- `DM-12749` may depend on product agreement for component key set and severity helper text
- frontend generated types may lag backend DTO changes if not regenerated early

## Recommendation

Treat the first three DMs as one short foundation batch rather than three isolated tickets.

Recommended execution:

1. land backend patch-safe incident update semantics and structured Jira link path
2. add backend incident metadata for component options
3. define and enforce UTC time contract
4. regenerate frontend types
5. update incident create/edit/detail pages together

This keeps the incident detail model from drifting further while preparing the codebase for the later postmortem, Feishu, and scoring work.
