---
id: TST-PFM-DJE-119
title: Contact update rollback
kind: integration
product_area: platform
module: data-job-engine
revision: 1
status: draft
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  macroservice-libraries: 54536a441935c6e09fdb7f96f0bec71c52ba4e03
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  services-membership: 5994c270e8a37a30f848e99ba5b5ee6b87c08893
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
repository: services-crm
files:
  - modules/data-jobs/tests/integration/services/jobs/contact-update-rollback.integration.spec.js
implements:
  - ATS-PFM-DJE-007-08
  - ATS-PFM-DJE-008-01
  - ATS-PFM-DJE-008-02
environment: local
implementation_state: implemented
latest_result: not-run
latest_run_at: null
latest_run_ref: null
conformance: not-verified
estimated_minutes: 5
isolation: >-
  Suite-owned fixture records, job identifiers and workspace contexts; teardown removes the fixture
  data.
evidence:
  - >-
    services-crm:modules/data-jobs/tests/integration/services/jobs/contact-update-rollback.integration.spec.js
assertion_inventory:
  - rolling a bulk contact update back
  - had written the new nickname to all ten contacts (premise)
  - 'plans a rollback of the eight nobody touched, and refuses the two somebody did'
  - 'says why the two cannot be put back, by code'
  - 'answers a rollback job of its own, linked to the job it compensates'
  - 'plans it already validated, because planning a rollback IS validating it'
  - 'names the job it rolls back on the rollback job, so a reader of either finds the other'
  - 'freezes one item per contact it will put back, each carrying the value the job overwrote'
  - 'records the two refusals as the rollback job’s own rejections, at the positions after its items'
  - 'names in each refusal the contact it left alone, which the rejection itself has no column for'
  - 'says which field changed since the job and when, without saying what it was changed to'
  - puts the eight contacts back to what they held before the job
  - leaves the two contacts somebody edited as that person left them
  - 'writes a receipt for each contact it put back, so its own redelivery is safe'
  - 'finishes the rollback as completed with rejections, which is what eight and two is'
  - 'pages the rollback’s rejections like any other job’s, so a person can see what was left alone'
  - rolling a hard delete back
  - deleted the contact (premise)
  - 'refuses the rollback, because there is no undo for a hard delete'
  - 'creates no job while refusing it, so nothing is left half planned'
registration_note: Registration describes existing source; the suite is not executed by this documentation job.
---

# Contact update rollback

## Verification Boundary

The suite checks the production service or shared engine against its database fixture. The structured assertion inventory records the checks present at the pinned revision.

## What This Suite Proves

The existing checks exercise contact update rollback. The specification bindings identify the narrower outcomes supported by those assertions.

## What It Does Not Prove

Local execution does not establish deployed queue, storage or service behavior. Independent test cases do not establish a complete cross-feature process.

## Real Dependencies and Test Doubles

The owning service exercises production persistence and domain behavior against real Postgres. The fixture supplies caller contexts; queue delivery, storage and external calls are doubled where the file installs a test port.

## Must Not Be Doubled

The database effects, security context and production operation under examination remain real. Their outcomes cannot be replaced with canned success responses.
