---
id: WF-PFM-DJE-005
title: Plan and apply a rollback
trigger: >-
  A caller requests compensation for a finished CRM job with a declared
  rollback.
product_area: platform
module: data-job-engine
revision: 1
status: draft
design_intent: confirmed
origin: >-
  services-platform:docs/proposals/rhythm-data-job-engine-plan.md §13.1
  compensating rollback (approved 2026-10-12);
  services-crm:docs/milestones/CRM-M7-data-operations.md D-39; PLAT-M19 D6 (the
  90-day rollback window)
implementation_evidence: observed
inference: []
source_sha:
  macroservice-libraries: 54536a441935c6e09fdb7f96f0bec71c52ba4e03
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
implements:
  - CAP-PFM-DJE-008
moves:
  - STATE-PFM-DJE-001
crosses:
  - SVC-PFM-DJE-crm-data-jobs
  - SVC-PFM-DJE-engine
hops:
  - 'n': 1
    actor_or_service: Rollback route (contacts or organizations)
    action: Check collection authority and require the original job’s record category.
    anchor: 'services-crm:modules/data-jobs/aws/api/data-jobs.routes.ts:dataJobsRoutes'
    seam: sync
    on_failure: Return an access or missing-job refusal.
    left_inconsistent: No compensation preview exists.
    observer: The request response exposes the result.
    provenance: documented
    source: >-
      macroservice-libraries:packages/data-jobs/README.md#What a rollback
      promises, and what Retry does beside it
  - 'n': 2
    actor_or_service: Engine rollback planner
    action: >-
      Check reversibility, final state, retained receipts and existing applied
      rollbacks, then read all receipts.
    anchor: >-
      macroservice-libraries:packages/data-jobs/src/plan-data-job-rollback.ts:planDataJobRollback
    seam: sync
    on_failure: Return the applicable reversal refusal code.
    left_inconsistent: The original job and records remain unchanged.
    observer: The response exposes the applicable refusal reason.
    provenance: test
    source: >-
      macroservice-libraries:packages/data-jobs/src/data-job-actions.spec.ts#does
      not offer Rollback once a rollback has been applied, by the code the route
      answers, and still does while one is only planned
  - 'n': 3
    actor_or_service: Owning record's rollback plan (CRM)
    action: >-
      Use record history to prepare versioned before-value updates and enumerate
      excluded records.
    anchor: 'services-crm:modules/data-jobs/services/operations/record-rollback-plan.ts'
    seam: sync
    on_failure: Refuse an unversioned plan before saving it.
    left_inconsistent: Excluded records retain their current state.
    observer: The request response displays the failure.
    provenance: test
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-rollback.integration.spec.js#says
      which field changed since the job and when, without saying what it was
      changed to
  - 'n': 4
    actor_or_service: Engine rollback planner
    action: >-
      Commit a linked validated compensation job with impact, digest and
      exclusion refusals.
    anchor: >-
      macroservice-libraries:packages/data-jobs/src/plan-data-job-rollback.ts:planDataJobRollback
    seam: sync
    on_failure: Roll back failed plan persistence.
    left_inconsistent: No partial compensation job remains.
    observer: Original-job inspection links its compensation jobs and current states.
    provenance: test
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-rollback.integration.spec.js#plans
      it already validated, because planning a rollback IS validating it
  - 'n': 5
    actor_or_service: Approver and batches
    action: Approve and apply eligible compensation items with expected versions.
    anchor: 'macroservice-libraries:packages/data-jobs/src/version-capture.ts'
    seam: queue
    on_failure: Report intervening edits as conflicts.
    left_inconsistent: Excluded and conflicted records retain the original change.
    observer: The rollback job's refusals page.
    provenance: documented
    source: >-
      macroservice-libraries:packages/data-jobs/README.md#What a rollback
      promises, and what Retry does beside it
idempotency: >-
  Repeated planning can create multiple previews. A qualifying applied rollback
  blocks another plan, while approval of each preview follows ordinary digest
  checks.
concurrency: >-
  Planning does not hold the original job lock across every domain read. Each
  compensation item’s expected version protects later edits. A merely planned
  rollback does not prevent retry of the original.
branches:
  - >-
    Imports, configuration, activity and Platform operations provide no rollback
    declaration.
  - Hard deletion has no compensation operation.
  - >-
    Rollback conflicts require another planning decision rather than ordinary
    conflict revalidation.
waits:
  - A compensation preview uses the ordinary 24-hour approval window.
evidence:
  - >-
    macroservice-libraries at 54536a44: src/plan-data-job-rollback.ts,
    data-job-rollback.ts, data-job-actions.ts, define-data-operation.ts
    (rollback declaration); README.md#Rolling a job back.
  - >-
    services-crm at a8d1364f: services/operations/contact-update-rollback.ts,
    organization-update-rollback.ts, record-rollback-plan.ts;
    docs/data-jobs.md#Putting a bulk change back.
  - >-
    react-console at baf6dae3:
    components/data-management/data-jobs/job-rollback-panel.tsx;
    lib/api/data-jobs/rules.ts (ROLLBACK_SUPPORTED).
controls: [TC-AVL-004, TC-AVL-005, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-DAT-004, TC-IAM-001, TC-IAM-002, TC-IAM-004, TC-IAM-005, TC-IAM-006, TC-LOG-002, TC-LOG-003, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-PI-001, TC-PI-002, TC-PI-003, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-TEN-001, TC-TEN-002, TC-TEN-003, TC-VEN-001, TC-VEN-002, TC-VEN-003]
---

# Plan And Apply A Rollback

## What It Does

The owning domain turns receipts and record history into a separate compensation job. Eligible records retain expected versions, and excluded records are listed before the operator approves the plan.

## The Flow

```mermaid
flowchart TD
  H1["Rollback route (contacts or organizations)"] --> H2
  H2["Engine rollback planner"] --> H3
  H3["Owning record's rollback plan (CRM)"] --> H4
  H4["Engine rollback planner"] --> H5
  H5["Approver and batches"]
```

## When Something Fails

Planning can exclude individual records or refuse the whole request. Applying a plan restores only still-eligible records; it preserves later edits and reports what remains uncompensated.

## Open Design Questions

The recorded findings identify the remaining limits; this examination does not authorize stronger behavior or change the planning rules.
