# Remediation Workflow Definition / Config Refactor Plan

## Table of Contents

- [Remediation Workflow Definition / Config Refactor Plan](#remediation-workflow-definition--config-refactor-plan)
  - [Table of Contents](#table-of-contents)
  - [Introduction](#introduction)
  - [Motivation or Background](#motivation-or-background)
  - [Current Problems](#current-problems)
  - [Goals](#goals)
  - [Non-Goals](#non-goals)
  - [Detailed Design](#detailed-design)
    - [Design Principles](#design-principles)
    - [Current Hardcoded Areas](#current-hardcoded-areas)
    - [Target Architecture](#target-architecture)
    - [Phase 1: Backend Single Source of Truth](#phase-1-backend-single-source-of-truth)
    - [Phase 2: Externalize Workflow to Config](#phase-2-externalize-workflow-to-config)
    - [Phase 3: Frontend Consumption Cleanup](#phase-3-frontend-consumption-cleanup)
    - [Data Model Proposal](#data-model-proposal)
    - [Config Proposal](#config-proposal)
    - [Backward Compatibility Strategy](#backward-compatibility-strategy)
  - [Implementation Plan](#implementation-plan)
    - [Backend Tasks](#backend-tasks)
    - [Frontend Tasks](#frontend-tasks)
    - [Suggested Delivery Order](#suggested-delivery-order)
  - [Test Design](#test-design)
    - [Functional Tests](#functional-tests)
    - [Scenario Tests](#scenario-tests)
    - [Compatibility Tests](#compatibility-tests)
  - [Impacts & Risks](#impacts--risks)
  - [Unresolved Questions](#unresolved-questions)

## Introduction

This document describes a refactor plan for the remediation approval flow so that phase order and display labels are no longer scattered across frontend and backend hardcoded logic. The immediate trigger is the incident Epic request in `DM-12881`, which changes both role naming and phase ordering. Instead of patching the same flow in multiple files again, this plan proposes introducing a single workflow definition in the backend first, then optionally externalizing it into configuration, and finally reducing frontend duplication.

## Motivation or Background

The current remediation flow can support the existing business process, but phase order and labels are duplicated in many places:

- backend phase transition handlers
- backend approval-flow projection helpers
- frontend phase sequence definitions
- frontend title / label mapping

This design creates three concrete problems:

1. A business change such as "swap Global Deal Desk and Decision Maker" requires editing multiple backend and frontend files.
2. It is easy for frontend display order and backend actual transition order to drift apart.
3. The system is not ready for future remediation workflow changes because the source of truth is split.

The direct example is `DM-12881`:

- rename `RDG SLA Owner` to `EG SLA Owner`
- rename `RDG Decision Maker` to `EG Decision Maker`
- reorder the flow from:
  - `rdg_sla_owner -> rdg_final_decision_maker -> global_deal_desk`
- into:
  - `rdg_sla_owner -> global_deal_desk -> rdg_final_decision_maker`

If only the frontend is changed, page display becomes inconsistent with real backend transition logic. If only the backend is changed, user-facing labels stay outdated. Therefore the root problem is not the single order change itself; the root problem is the absence of a centralized workflow definition.

## Current Problems

The current hardcoded logic is split as follows.

Backend phase transition order:

- `pkg/service/remediationticket/phase/phase_rdgslaowner.go`
- `pkg/service/remediationticket/phase/phase_rdgfinaldecisionmaker.go`
- `pkg/service/remediationticket/phase/phase_globaldealdesk.go`

Backend approval-flow display order and labels:

- `pkg/service/remediationticket/tickets.go`
  - `remediationApprovalFlowPhases()`
  - `remediationApprovalFlowLabel()`

Frontend display order and labels:

- `src/pages/RemediationTickets/RemediationTicketDetail/phases.tsx`
- `src/pages/RemediationTickets/RemediationTicketDetail/utils.tsx`
- `src/pages/RemediationTickets/RemediationTicketDetail/Forms.tsx`

Configuration today only covers responsible persons, not workflow order:

- `pkg/infra/config/config_services.go`
  - `RemediationTicketConfig`

As a result, changing one workflow requires touching:

- backend transition code
- backend flow projection code
- frontend phase-order code
- frontend phase-label code

This is exactly the change pattern we want to eliminate.

## Goals

1. Introduce a single backend source of truth for remediation workflow order and labels.
2. Make backend flow transition and backend approval-flow projection consume the same definition.
3. Prepare the workflow definition to be moved into configuration instead of being permanently hardcoded.
4. Reduce frontend-maintained business ordering logic once backend metadata is reliable enough.
5. Keep current database schema and current phase enum values unchanged in the short term.

## Non-Goals

1. Do not redesign the entire remediation domain into a generic workflow engine in this iteration.
2. Do not rename persisted phase enum keys such as `rdg_sla_owner` or `rdg_final_decision_maker` in the database.
3. Do not remove existing phase handler code paths entirely in the first iteration.
4. Do not attempt to configuration-drive every phase behavior immediately, such as field validation, approval check items, or optional branching business rules.

## Detailed Design

### Design Principles

1. Backend owns the workflow truth.
2. Frontend should render workflow, not infer workflow.
3. Workflow order and labels should be centralized before they are externalized.
4. Configuration should be added only after the backend execution path is already using a single internal definition.
5. Stable enum keys should remain unchanged to avoid unnecessary compatibility risk.

### Current Hardcoded Areas

There are two kinds of hardcoding today.

Behavior hardcoding:

- each phase handler directly chooses the next phase

Projection hardcoding:

- approval flow sequence
- phase display label
- progress title mapping in frontend

Projection-only hardcoding is annoying but survivable. Behavior hardcoding is more serious because it defines the actual approval path. If projection and behavior differ, the product becomes misleading. Therefore the first priority is to make backend execution and backend projection consume the same definition.

### Target Architecture

The target architecture is:

1. A remediation workflow definition is declared once in backend.
2. Backend transition logic asks the definition for the next phase.
3. Backend approval-flow aggregation asks the same definition for ordered phases and labels.
4. Backend returns enough workflow metadata for the frontend.
5. Frontend gradually removes duplicated order and label logic.

This can be done incrementally.

### Phase 1: Backend Single Source of Truth

This is the recommended first implementation step.

Add a backend workflow-definition layer under `pkg/service/remediationticket`, for example:

- `workflow_definition.go`
- `workflow_registry.go`

The exact file split is not critical. The key is to centralize the following:

- ordered phase list
- display labels
- optional phase flags
- default next-phase rules

Recommended interfaces:

```go
type WorkflowDefinition interface {
    OrderedPhases() []entity.RemediationTicketPhase
    Label(phase entity.RemediationTicketPhase) string
    IsOptional(phase entity.RemediationTicketPhase) bool
    NextPhase(current entity.RemediationTicketPhase, ticket *entity.RemediationTicket) (entity.RemediationTicketPhase, error)
}
```

Or a simpler static structure plus helper methods:

```go
type RemediationWorkflowDefinition struct {
    Phases []WorkflowPhaseDefinition
}

type WorkflowPhaseDefinition struct {
    Phase     entity.RemediationTicketPhase
    Label     string
    Optional  bool
    Next      *entity.RemediationTicketPhase
}
```

For conditional branches such as `global_deal_desk -> commercial_operation / regional_gm`, static `Next` is not enough. That branch should still be resolved through a dedicated helper. Therefore a more practical model is:

- static ordered phase list
- static label map
- centralized `NextPhase()` switch / resolver

This is still a meaningful improvement because the flow decision becomes centralized even if not fully declarative yet.

Backend code to migrate onto the definition:

1. `remediationApprovalFlowPhases()`
2. `remediationApprovalFlowLabel()`
3. phase transition handlers that currently hardcode `nextPhase`

Expected outcome of Phase 1:

- changing order no longer requires editing multiple backend files
- backend approval-flow projection and actual transition logic stay aligned
- frontend can safely consume backend order later

### Phase 2: Externalize Workflow to Config

After Phase 1 is stable, move the workflow definition into `RemediationTicketConfig`.

Current config already contains:

- responsible persons
- watcher interval

It can be extended with a workflow block:

```yaml
remediationTicket:
  workflow:
    default:
      phases:
        - created
        - region_tse_leader
        - rdg_sla_owner
        - global_deal_desk
        - rdg_final_decision_maker
        - commercial_operation
        - regional_gm
        - succeed
        - closed
      labels:
        rdg_sla_owner: "EG SLA Owner"
        rdg_final_decision_maker: "EG Decision Maker"
        global_deal_desk: "Global Deal Desk"
      optionalPhases:
        - commercial_operation
```

Recommended validation rules:

1. all phases must be valid enum values
2. `created`, `succeed`, and `closed` must exist
3. `created` must be first
4. `succeed` and `closed` must be tail phases
5. optional phases must be part of the phase list
6. labels may be omitted, but then backend falls back to defaults

This phase should not configuration-drive every business branch yet. It is enough to configuration-drive:

- display order
- display label
- optional phase membership

The conditional next-phase resolution can still remain in code if needed.

### Phase 3: Frontend Consumption Cleanup

Once backend can return reliable workflow order and labels, frontend should stop maintaining a second business workflow model wherever possible.

Frontend should keep:

- field rendering per phase
- page layout
- node card style
- interaction components

Frontend should gradually reduce:

- local hardcoded phase order
- local hardcoded phase display titles when backend can provide them

This means the backend should eventually return enough workflow metadata through the existing remediation endpoints or a workflow-specific endpoint.

### Data Model Proposal

Proposed backend internal structure:

```go
type WorkflowPhaseMeta struct {
    Phase    entity.RemediationTicketPhase
    Label    string
    Optional bool
}

type RemediationWorkflowMeta struct {
    Ordered []WorkflowPhaseMeta
}
```

Proposed helper API:

```go
func GetRemediationWorkflowMeta(conf config.RemediationTicketConfig) (RemediationWorkflowMeta, error)
func GetRemediationPhaseLabel(conf config.RemediationTicketConfig, phase entity.RemediationTicketPhase) string
func GetRemediationPhaseOrder(conf config.RemediationTicketConfig) []entity.RemediationTicketPhase
func ResolveNextRemediationPhase(conf config.RemediationTicketConfig, current entity.RemediationTicketPhase, ticket *entity.RemediationTicket) (entity.RemediationTicketPhase, error)
```

This is not meant to be a reusable generic workflow engine. It is a domain-specific workflow definition for remediation.

### Config Proposal

Suggested addition in `pkg/infra/config/config_services.go`:

```go
type RemediationWorkflowConfig struct {
    Default RemediationWorkflowDefinitionConfig `yaml:"default"`
}

type RemediationWorkflowDefinitionConfig struct {
    Phases         []string          `yaml:"phases"`
    Labels         map[string]string `yaml:"labels"`
    OptionalPhases []string          `yaml:"optionalPhases"`
}
```

Then extend:

```go
type RemediationTicketConfig struct {
    Dummy bool `yaml:"dummy"`

    ResponsiblePersons              RTResponsiblePersonConfig `yaml:"responsiblePersons"`
    WatchRemediationTicketsInterval *time.Duration            `yaml:"watchRemediationTicketsInterval" default:"60s"`
    Workflow                        RemediationWorkflowConfig `yaml:"workflow"`
}
```

The loader should apply defaults if the workflow block is absent.

### Backward Compatibility Strategy

We should not rename persisted enum values in this iteration.

That means:

- `rdg_sla_owner` can still be the phase key
- `rdg_final_decision_maker` can still be the phase key

Only display labels change to:

- `EG SLA Owner`
- `EG Decision Maker`

This keeps compatibility with:

- existing DB records
- existing API enum schema
- existing historical ticket data

The order change only affects:

- next phase resolution
- approval-flow projection
- frontend display order

No schema migration is required for this design.

### Stable Phase Key Constraint

In the current system, phase values such as `rdg_sla_owner` and `rdg_final_decision_maker` are not only display tokens. They are stable identifiers used by:

- persisted ticket phase fields
- persisted approval records such as `from_phase` / `to_phase`
- backend phase-handler registration
- API enum schema in swagger
- frontend-generated client types

Therefore, the current refactor must treat these phase keys as stable IDs instead of business-facing labels.

In practice, this means:

1. `rdg_sla_owner` stays as the stored phase key
2. `rdg_final_decision_maker` stays as the stored phase key
3. only display labels change to `EG SLA Owner` and `EG Decision Maker`
4. workflow sequence can change without renaming stored enum keys

Directly renaming the persisted phase key from `rdg_sla_owner` to `eg_sla_owner` in this iteration is explicitly out of scope because it would require:

- historical data migration
- API compatibility handling
- dual-read or alias compatibility logic
- rollback planning for existing records and clients

If key renaming is ever required in the future, it must be treated as a dedicated compatibility migration project rather than a label/order refactor.

## Implementation Plan

### Backend Tasks

1. Add remediation workflow definition helpers under `pkg/service/remediationticket`.
2. Refactor `tickets.go` approval-flow projection to use the workflow definition.
3. Refactor phase handlers to resolve next phase from the workflow definition instead of local hardcoded transitions.
4. Add default labels into the workflow definition.
5. Add unit tests for sequence, labels, and next-phase resolution.
6. Only after the above is stable, extend `RemediationTicketConfig` with workflow config.
7. Add config validation and default fallback behavior.

### Frontend Tasks

1. Keep current UI rendering as-is during backend refactor.
2. After backend returns stable metadata, reduce duplicated phase label/order definitions.
3. Continue to keep field layout and phase-specific form content in frontend.
4. Prefer backend-returned order for approval flow and progress rendering where possible.

### Suggested Delivery Order

1. Backend internal workflow definition in code only
2. Backend transition/projection refactor
3. Frontend alignment with backend metadata
4. Backend config externalization
5. Frontend cleanup of duplicated hardcoded titles/order

This order minimizes the chance of frontend-backend mismatch during rollout.

## Test Design

### Functional Tests

Backend unit tests should cover:

1. workflow ordered phase list is correct
2. label resolution is correct
3. `rdg_sla_owner` next phase resolves to `global_deal_desk`
4. `global_deal_desk` next phase resolves correctly for both optional and non-optional branches
5. approval-flow projection order matches workflow definition

Frontend verification should cover:

1. approval flow node order matches backend
2. progress titles match backend labels
3. phase detail timeline remains stable after order changes

### Scenario Tests

1. Newly created remediation ticket follows the new order end-to-end
2. Ticket rejected in `global_deal_desk` still returns to the correct previous/current state
3. Ticket with `commercial_operation` skipped still shows correct flow ordering
4. Historical tickets created before the refactor still render correctly

### Compatibility Tests

1. No DB schema migration required
2. Existing enum values remain unchanged
3. Existing APIs remain backward compatible
4. Existing historical remediation records can still be loaded and projected
5. Missing workflow config falls back to backend defaults

## Impacts & Risks

Positive impacts:

1. Order and label changes become much cheaper.
2. Frontend and backend mismatch risk is reduced.
3. Future remediation workflow iterations become incremental instead of scattered patching.
4. This creates a clean path toward a more declarative workflow system later.

Risks:

1. If transition logic and projection logic are only partially migrated, the system may temporarily become more confusing, not less.
2. If workflow config is externalized too early without strong validation, invalid config can break remediation flow at runtime.
3. If frontend cleanup happens before backend metadata is stable, the page may regress in edge cases.
4. Conditional branches such as `commercial_operation` may be oversimplified if we force a fully static phase order too early.

Mitigations:

1. finish backend single-source-of-truth refactor before config externalization
2. add strict validation and default fallback for config
3. keep enum keys unchanged
4. ship backend tests before frontend dependency cleanup

## Unresolved Questions

1. Should workflow config support multiple named workflow variants in the future, or only one default remediation workflow?
2. Should backend expose the workflow definition explicitly to frontend, or only expose already-projected ordered nodes?
3. How far should configuration go in this iteration:
   - order and labels only
   - plus optional phase membership
   - or plus conditional transition rules
4. Is `commercial_operation` optional branching stable enough to remain code-based for now, or should it also be represented declaratively?
