---
id: CAP-CRM-REG-012
title: Monitor recalculation and recover from failure
feature: FEAT-CRM-REG-04
product_area: crm
module: regions
revision: 2
status: draft
product_intent: proposed
implementation_evidence: partially-observed
supersedes:
  - CAP-CRM-CFG-017
source_sha:
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
intent_sources:
  - >-
    services-crm:docs/migrations/crm-regions/README.md#Assignment and recalculation triggers in Rolodex 2.0
    (Andrew, 2026-10-10: the failure reason is redacted)
purpose: Staff inspect a recalculation’s progress and identify whether more processing or a new run is needed.
outcomes:
  - Run status and accumulated counts remain inspectable.
  - Database failures reveal a redacted explanation.
  - Later queue delivery can recover unfinished work.
concepts:
  - CON-CRM-REG-004
actors:
  - ACT-CRM-003
  - ACT-CRM-002
  - ACT-CRM-005
surfaces:
  - console
  - api
  - job
preconditions: []
postconditions: []
permissions:
  - key: crm.regions.read
    where_checked: api
    scope: tenant
rules:
  - id: BR-CAP-CRM-REG-012-01
    proved_by: [ATS-CRM-REG-010-08, ATS-CRM-REG-011-10, ATS-CRM-REG-012-01, TST-CRM-REG-047, TST-CRM-REG-053]
    statement: >-
      Staff can list recent workspace recalculations newest first, with a default limit of twenty-five and
      maximum of one hundred, and inspect their status, phase, counts and failure reason.
    kind: policy
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/persistence/region-recalculations.queries.integration.spec.js#listRegionRecalculations
      › answers the whole record of every run of the tenant, the newest first
    origin: none
  - id: BR-CAP-CRM-REG-012-02
    proved_by: [ATS-CRM-REG-012-02, TST-CRM-REG-052]
    statement: >-
      Runs have running, completed or failed status; completion requires both record phases to finish, and
      changed never exceeds examined.
    kind: invariant
    enforced_at:
      - database
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/persistence/region-recalculations.integration.spec.js#refuses
      completed before the run is done
    origin: none
  - id: BR-CAP-CRM-REG-012-03
    proved_by: [ATS-CRM-REG-012-03, ATS-CRM-REG-012-07, TST-CRM-REG-059]
    statement: >-
      A failed database batch records only the redacted error kind and database code, then resumes from its
      committed position on another delivery.
    kind: policy
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/region-assignment/region-recalculation-errors.integration.spec.js#the
      reason it records › records no value of the batch that failed: not the contact, the tenant, the
      statement or its parameters
    origin: >-
      services-crm:docs/migrations/crm-regions/README.md#Assignment and recalculation triggers in Rolodex 2.0
      (Andrew, 2026-10-10: the failure reason is redacted)
  - id: BR-CAP-CRM-REG-012-04
    proved_by: [ATS-CRM-REG-012-04, TST-CRM-REG-059]
    statement: 'A failed final delivery marks the run failed, while earlier failures leave it running.'
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/region-assignment/region-recalculation-errors.integration.spec.js#the
      last delivery of a run’s event › fails the run, because nothing will deliver its event again
    origin: >-
      services-crm:docs/migrations/crm-regions/README.md#Assignment and recalculation triggers in Rolodex 2.0
      (Andrew, 2026-10-10: the failure reason is redacted)
  - id: BR-CAP-CRM-REG-012-05
    proved_by: [ATS-CRM-REG-012-05, ATS-CRM-REG-012-07, TST-CRM-REG-059]
    statement: 'Successful progress clears an earlier failure reason, leaving a completed run without that reason.'
    kind: lifecycle
    enforced_at:
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/region-assignment/region-recalculation-errors.integration.spec.js#a
      run that gets past what stopped it › answers the whole record of the completed run, with no reason left
      on it
    origin: none
  - id: BR-CAP-CRM-REG-012-06
    proved_by: [ATS-CRM-REG-012-06, TST-CRM-REG-047, TST-CRM-REG-053]
    statement: Recalculation reads remain workspace-specific and return not found for unknown runs.
    kind: invariant
    enforced_at:
      - api
      - service
    must_prove: true
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/persistence/region-recalculations.queries.integration.spec.js#getRegionRecalculation
      › answers undefined in another tenant for the first tenant's run
    origin: none
  - id: BR-CAP-CRM-REG-012-07
    proved_by: []
    statement: The API provides no cancellation action for a running recalculation.
    kind: policy
    enforced_at:
      - api
    must_prove: false
    provenance: observed
    source: 'services-crm:modules/regions/aws/api/regions.routes.ts:regionsRoutes'
    origin: none
  - id: BR-CAP-CRM-REG-012-08
    proved_by: []
    statement: A failed recalculation does not restart automatically; an authorized user must request a new run.
    kind: lifecycle
    enforced_at:
      - service
    must_prove: false
    provenance: observed
    source: 'services-crm:modules/regions/services/region-assignment/region-recalculation.ts:startRegionRecalculation'
    origin: none
  - id: BR-CAP-CRM-REG-012-09
    proved_by: []
    statement: >-
      The console polls an active run every one and a half seconds, adopts an existing running run on page
      load, replaces the needed banner with progress and shows failure with the accumulated counts.
    kind: policy
    enforced_at:
      - console
    must_prove: false
    provenance: observed
    source: >-
      react-console:components/regions/__tests__/recalculation.test.tsx#the banner › reports a failure, with
      what it got through before it stopped;
      react-console:components/regions/recalculation.tsx:useRecalculation
    origin: >-
      services-crm:docs/migrations/crm-regions/README.md#2026-10-15 — Final acceptance (console follow-ups)
      (Andrew approved 2026-10-15: two tabs, Test an Address dialog, drawers, a read-only Assignment Rules tab
      with its own editor screen and the banner)
scenarios:
  - id: SC-CAP-CRM-REG-012-01
    given: A transient database error interrupts the next batch.
    when: Staff inspect the run and processing is delivered again.
    then: 'The run retains a redacted reason while running, then clears it after successful progress.'
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/region-assignment/region-recalculation-errors.integration.spec.js#a
      run that gets past what stopped it › answers the whole record of the completed run, with no reason left
      on it
edge_cases:
  - id: SC-CAP-CRM-REG-012-02
    given: All deliveries fail to process the unfinished batch.
    when: The queue makes its final delivery.
    then: The run becomes failed with its reason and staff can request a new run.
    provenance: test
    source: >-
      services-crm:modules/regions/tests/integration/services/region-assignment/region-recalculation-errors.integration.spec.js#the
      last delivery of a run’s event › fails the run, because nothing will deliver its event again
constraints: []
depends_on:
  - CAP-CRM-REG-011
related:
  - CAP-CRM-REG-011
journeys:
  - JNY-CRM-REG-002
open_questions: []
evidence:
  - >-
    services-crm: Examined the pinned regional implementation, its declared constraints and the supporting
    records.
  - 'react-console: Examined the pinned regional configuration surfaces and their available test evidence.'
  - 'services-crm:docs/migrations/crm-regions/README.md'
  - >-
    services-crm:modules/regions/tests/integration/services/persistence/region-recalculations.queries.integration.spec.js
  - >-
    services-crm:modules/regions/tests/integration/services/persistence/region-recalculations.integration.spec.js
  - >-
    services-crm:modules/regions/tests/integration/services/region-assignment/region-recalculation-errors.integration.spec.js
  - 'services-crm:modules/regions/aws/api/regions.routes.ts'
  - 'services-crm:modules/regions/services/region-assignment/region-recalculation.ts'
  - 'react-console:components/regions/__tests__/recalculation.test.tsx'
  - 'react-console:components/regions/recalculation.tsx'
controls: [TC-AVL-004, TC-AZ-001, TC-AZ-002, TC-AZ-003, TC-AZ-004, TC-AZ-006, TC-DAT-001, TC-DAT-002, TC-DAT-003, TC-IAM-001, TC-IAM-005, TC-IAM-006, TC-LOG-004, TC-LOG-005, TC-MON-001, TC-MON-002, TC-PI-001, TC-PI-004, TC-PI-005, TC-PRV-001, TC-PRV-002, TC-TEN-001, TC-TEN-002, TC-TEN-003]
exercised_by: [FAS-CRM-REG-04-01, FAS-CRM-REG-04-02, FAS-CRM-REG-04-03, FAS-CRM-REG-04-04]
suites: [TST-CRM-REG-047, TST-CRM-REG-052, TST-CRM-REG-053, TST-CRM-REG-059]
---

# Monitor recalculation and recover from failure

## Purpose

Staff inspect a recalculation’s progress and identify whether more processing or a new run is needed.

## How It Works

Staff inspect recent recalculations or a particular run. The record identifies its status, processing phase and examined and changed counts. The console polls active work and can resume watching a run found when the page opens. A failing batch stores a redacted database reason while leaving the run eligible for later delivery. Successful progress clears the reason. Only a failing final delivery marks the run failed. The console reports the failure and the work completed beforehand. There is no cancellation operation. Recovery from a failed final run requires a new recalculation rather than restarting that record.

## Relationships

- Apply the current policy across existing records applies policy changes to existing records.
