---
id: ATS-PFM-DJE-009
scope: CAP-PFM-DJE-009
product_area: platform
module: data-job-engine
revision: 2
status: proposed
approved_by: null
approved_at: null
source_sha:
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
scenarios:
  - id: ATS-PFM-DJE-009-01
    title: Selected-field updates remain visible as jobs
    level: browser
    proves:
      - BR-CAP-PFM-DJE-009-02
    preconditions: Prepare selections of twelve and 35 contacts.
    steps:
      - do: 'Preview and apply a field change, then inspect the job list and record history.'
        expect: >-
          Selected records change and the named update job exposes supported rollback and history
          attribution.
        provenance: test
        source: >-
          react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0100.spec.ts#DJE-ACC-0100
    expected: >-
      Selected records change and the named update job exposes supported rollback and history
      attribution.
    negative: false
    data_needs: Prepared contacts.
    bound_to:
      - TST-PFM-DJE-082
      - TST-PFM-DJE-093
    provenance: test
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0100.spec.ts#DJE-ACC-0100
    category: rule
    binding_evidence:
      - >-
        react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0100.spec.ts#DJE-ACC-0100
      - >-
        react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0111.spec.ts#DJE-ACC-0111
  - id: ATS-PFM-DJE-009-02
    title: Large selections transfer to the wizard
    level: browser
    proves:
      - BR-CAP-PFM-DJE-009-01
    preconditions: Select 600 contacts.
    steps:
      - do: Inspect Update Fields and Delete actions.
        expect: Update opens the wizard with the selection; Delete explains that the limit is exceeded.
        provenance: test
        source: >-
          react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0110.spec.ts#DJE-ACC-0110
    expected: Update opens the wizard with the selection; Delete explains that the limit is exceeded.
    negative: true
    data_needs: Six hundred contacts.
    bound_to:
      - TST-PFM-DJE-092
    provenance: test
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0110.spec.ts#DJE-ACC-0110
    category: boundary
    binding_evidence:
      - >-
        react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0110.spec.ts#DJE-ACC-0110
  - id: ATS-PFM-DJE-009-03
    title: Invalid typed input is refused before writes
    level: browser
    proves:
      - BR-CAP-PFM-DJE-009-03
    preconditions: 'Provide number, date and option fields.'
    steps:
      - do: Enter mismatched or unsupported values.
        expect: The refusal names the field and no contact changes.
        provenance: test
        source: >-
          react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0104.spec.ts#DJE-ACC-0104
    expected: The refusal names the field and no contact changes.
    negative: true
    data_needs: Custom-field definitions.
    bound_to:
      - TST-PFM-DJE-086
    provenance: test
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0104.spec.ts#DJE-ACC-0104
    category: validation
    binding_evidence:
      - >-
        react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0104.spec.ts#DJE-ACC-0104
  - id: ATS-PFM-DJE-009-04
    title: Custom values use their proper storage
    level: browser
    proves:
      - BR-CAP-PFM-DJE-009-04
    preconditions: Define a text field for contacts.
    steps:
      - do: Set its value for twelve selected contacts.
        expect: Each contact holds and displays the value under that custom field.
        provenance: test
        source: >-
          react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0102.spec.ts#DJE-ACC-0102
    expected: Each contact holds and displays the value under that custom field.
    negative: false
    data_needs: A contact custom-field definition.
    bound_to:
      - TST-PFM-DJE-084
    provenance: test
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0102.spec.ts#DJE-ACC-0102
    category: invariant
    binding_evidence:
      - >-
        react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0102.spec.ts#DJE-ACC-0102
  - id: ATS-PFM-DJE-009-05
    title: Query selection leaves outside records intact
    level: browser
    proves:
      - BR-CAP-PFM-DJE-009-05
    preconditions: Prepare a 120-contact saved query and a contact excluded from it.
    steps:
      - do: Select all matching records and apply an update.
        expect: The matching records change; the outside contact retains its version.
        provenance: test
        source: >-
          react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0101.spec.ts#DJE-ACC-0101
    expected: The matching records change; the outside contact retains its version.
    negative: false
    data_needs: A saved query and its comparison record.
    bound_to:
      - TST-PFM-DJE-083
    provenance: test
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0101.spec.ts#DJE-ACC-0101
    category: boundary
    binding_evidence:
      - >-
        react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0101.spec.ts#DJE-ACC-0101
  - id: ATS-PFM-DJE-009-06
    title: Joined rows do not multiply job targets
    level: browser
    proves:
      - BR-CAP-PFM-DJE-009-06
    preconditions: Prepare eighteen result rows representing six contacts.
    steps:
      - do: Run an update over those rows.
        expect: The job contains six records with one corresponding revision each.
        provenance: test
        source: >-
          react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0114.spec.ts#DJE-ACC-0114
    expected: The job contains six records with one corresponding revision each.
    negative: false
    data_needs: A joined query.
    bound_to:
      - TST-PFM-DJE-096
    provenance: test
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0114.spec.ts#DJE-ACC-0114
    category: edge
    binding_evidence:
      - >-
        react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0114.spec.ts#DJE-ACC-0114
  - id: ATS-PFM-DJE-009-07
    title: Repeated clicks create one job
    level: browser
    proves:
      - BR-CAP-PFM-DJE-009-07
    preconditions: Select fourteen contacts.
    steps:
      - do: Double-click Apply.
        expect: One job and accepted apply produce one change revision per contact.
        provenance: test
        source: >-
          react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0112.spec.ts#DJE-ACC-0112
    expected: One job and accepted apply produce one change revision per contact.
    negative: false
    data_needs: No additional fixture is needed.
    bound_to:
      - TST-PFM-DJE-094
    provenance: test
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0112.spec.ts#DJE-ACC-0112
    category: concurrency
    binding_evidence:
      - >-
        react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0112.spec.ts#DJE-ACC-0112
  - id: ATS-PFM-DJE-009-08
    title: Closing the dialog preserves submitted work
    level: browser
    proves:
      - BR-CAP-PFM-DJE-009-08
    preconditions: Select 200 contacts.
    steps:
      - do: Apply the update and close its dialog.
        expect: Data Imports shows completion and the 200 selected contacts change.
        provenance: test
        source: >-
          react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0113.spec.ts#DJE-ACC-0113
    expected: Data Imports shows completion and the 200 selected contacts change.
    negative: false
    data_needs: Two hundred contacts.
    bound_to:
      - TST-PFM-DJE-095
    provenance: test
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0113.spec.ts#DJE-ACC-0113
    category: transition
    binding_evidence:
      - >-
        react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0113.spec.ts#DJE-ACC-0113
  - id: ATS-PFM-DJE-009-09
    title: Bulk actions require the relevant key
    level: browser
    proves:
      - BR-CAP-PFM-DJE-009-09
    preconditions: Use a denied-bulk administrator and a read-only user.
    steps:
      - do: Select explorer records and attempt backend submission.
        expect: Bulk actions are absent and the backend responds 403.
        provenance: test
        source: >-
          react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0108.spec.ts#DJE-ACC-0108
    expected: Bulk actions are absent and the backend responds 403.
    negative: true
    data_needs: A role denying bulk permission.
    bound_to:
      - TST-PFM-DJE-090
      - TST-PFM-DJE-099
    provenance: test
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0108.spec.ts#DJE-ACC-0108
    category: permission
    binding_evidence:
      - >-
        react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0108.spec.ts#DJE-ACC-0108
      - >-
        react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0117.spec.ts#DJE-ACC-0117
  - id: ATS-PFM-DJE-009-10
    title: Delete sends approval only for matching text
    level: browser
    proves:
      - BR-CAP-PFM-DJE-009-10
    preconditions: Select 37 contacts with two locks and three organizations with two dependency blocks.
    steps:
      - do: 'Open deletion preview and enter incorrect, then correct, approval text.'
        expect: >-
          The preview explains impact and blocks; incorrect text sends no request; correct approval
          removes only eligible records.
        provenance: test
        source: >-
          react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0105.spec.ts#DJE-ACC-0105
    expected: >-
      The preview explains impact and blocks; incorrect text sends no request; correct approval
      removes only eligible records.
    negative: true
    data_needs: Records with locks and dependants.
    bound_to:
      - TST-PFM-DJE-087
      - TST-PFM-DJE-098
    provenance: test
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0105.spec.ts#DJE-ACC-0105
    category: validation
    binding_evidence:
      - >-
        react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0105.spec.ts#DJE-ACC-0105
      - >-
        react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0116.spec.ts#DJE-ACC-0116
  - id: ATS-PFM-DJE-009-11
    title: Dialog input becomes a durable inspectable job
    category: interaction
    level: browser
    exercises:
      - CAP-PFM-DJE-001
      - CAP-PFM-DJE-009
    proves:
      - BR-CAP-PFM-DJE-001-04
      - BR-CAP-PFM-DJE-009-02
      - BR-CAP-PFM-DJE-009-08
    preconditions: Select contacts on a record list.
    steps:
      - do: >-
          Preview and apply an update from the dialog, close the dialog, and inspect the job after
          completion.
        expect: >-
          Closing the dialog leaves the submitted change active and its recorded job remains
          inspectable.
        provenance: proposed
        source: >-
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#freezes
          the patch on every item, so a later apply writes what was submitted and not what is asked
          for then;
          react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0111.spec.ts#DJE-ACC-0111;
          react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0113.spec.ts#DJE-ACC-0113
    expected: >-
      Closing the dialog leaves the submitted change active and its recorded job remains
      inspectable.
    negative: false
    data_needs: Select contacts on a record list.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#freezes
      the patch on every item, so a later apply writes what was submitted and not what is asked for
      then;
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0111.spec.ts#DJE-ACC-0111;
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0113.spec.ts#DJE-ACC-0113
  - id: ATS-PFM-DJE-009-12
    title: Dialog approval is tied to its saved preview
    category: interaction
    level: browser
    exercises:
      - CAP-PFM-DJE-002
      - CAP-PFM-DJE-009
    proves:
      - BR-CAP-PFM-DJE-002-02
      - BR-CAP-PFM-DJE-009-07
      - BR-CAP-PFM-DJE-009-10
    preconditions: Open a contact deletion dialog with an eligible selection.
    steps:
      - do: >-
          Enter incorrect approval text, verify no apply request, then approve the returned phrase
          and repeat the click.
        expect: Incorrect text sends no approval and the accepted click applies one saved preview.
        provenance: proposed
        source: >-
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#refuses
          an apply of the validated update whose digest is not the one the validation answered;
          react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0112.spec.ts#DJE-ACC-0112;
          react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0105.spec.ts#DJE-ACC-0105
    expected: Incorrect text sends no approval and the accepted click applies one saved preview.
    negative: false
    data_needs: Open a contact deletion dialog with an eligible selection.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#refuses
      an apply of the validated update whose digest is not the one the validation answered;
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0112.spec.ts#DJE-ACC-0112;
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0105.spec.ts#DJE-ACC-0105
  - id: ATS-PFM-DJE-009-13
    title: The delete dialog uses the counted engine approval
    category: interaction
    level: browser
    exercises:
      - CAP-PFM-DJE-007
      - CAP-PFM-DJE-009
    proves:
      - BR-CAP-PFM-DJE-007-02
      - BR-CAP-PFM-DJE-007-03
      - BR-CAP-PFM-DJE-009-10
    preconditions: Select eligible and blocked contacts from a record list.
    steps:
      - do: 'Open Delete, review the preview, enter wrong text, then submit the returned phrase.'
        expect: >-
          The dialog sends approval only for the matching phrase and only preview-eligible records
          are removed.
        provenance: proposed
        source: >-
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-delete.integration.spec.js#counts
          the rows each delete would take with it, per collection, as the contacts hold them;
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-delete.integration.spec.js#refuses
          an apply whose confirmation names another number of contacts;
          react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0105.spec.ts#DJE-ACC-0105
    expected: >-
      The dialog sends approval only for the matching phrase and only preview-eligible records are
      removed.
    negative: false
    data_needs: Select eligible and blocked contacts from a record list.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-delete.integration.spec.js#counts
      the rows each delete would take with it, per collection, as the contacts hold them;
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-delete.integration.spec.js#refuses
      an apply whose confirmation names another number of contacts;
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0105.spec.ts#DJE-ACC-0105
  - id: ATS-PFM-DJE-009-14
    title: Reclassification makes a previously blocked type deletable
    category: interaction
    level: browser
    exercises:
      - CAP-PFM-DJE-009
      - CAP-PFM-DJE-010
    proves:
      - BR-CAP-PFM-DJE-009-02
      - BR-CAP-PFM-DJE-010-01
      - BR-CAP-PFM-DJE-010-03
      - BR-CAP-PFM-DJE-010-07
    preconditions: Create an obsolete type used by three contacts and an unused replacement type.
    steps:
      - do: >-
          Inspect the usage block, change those contacts to the replacement through a
          selected-record job, then preview and approve type deletion.
        expect: >-
          The second preview permits deletion of the obsolete type; the replacement and reclassified
          contacts remain.
        provenance: proposed
        source: >-
          react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0111.spec.ts#DJE-ACC-0111;
          services-crm:modules/data-jobs/tests/integration/services/jobs/configuration-data-jobs.integration.spec.js#says
          both are blocked because they are in use;
          services-crm:modules/data-jobs/tests/integration/services/jobs/configuration-data-jobs.integration.spec.js#asks
          a person to type the number it would delete, not the number submitted;
          react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0106.spec.ts#DJE-ACC-0106
    expected: >-
      The second preview permits deletion of the obsolete type; the replacement and reclassified
      contacts remain.
    negative: false
    data_needs: Create an obsolete type used by three contacts and an unused replacement type.
    bound_to: []
    provenance: proposed
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0111.spec.ts#DJE-ACC-0111;
      services-crm:modules/data-jobs/tests/integration/services/jobs/configuration-data-jobs.integration.spec.js#says
      both are blocked because they are in use;
      services-crm:modules/data-jobs/tests/integration/services/jobs/configuration-data-jobs.integration.spec.js#asks
      a person to type the number it would delete, not the number submitted;
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0106.spec.ts#DJE-ACC-0106
evidence:
  - >-
    Reviewed evidence: react-console (baf6dae3): components/data-management/data-jobs/dialogs/*,
    bulk/*; lib/api/data-jobs/dialogs.ts, selection.ts, handoff.ts, capabilities.ts;
    acceptance/data-jobs/journeys/dialogs/* and playwright specs DJE-ACC-0100 to 0117.
  - >-
    Reviewed evidence: services-crm (a8d1364f): aws/api/data-jobs.routes.ts,
    organization-data-jobs.routes.ts; tests organization-update.e2e.spec.js.
  - >-
    Reviewed evidence: services-platform (ad3f6a65):
    docs/milestones/PLAT-M20-small-bulk-operations.md (D1, D4), plans/PLAT-M20-plan.md.
  - >-
    Testing back-fill: related capability rules, domain invariants, state transitions and crossing
    workflows at the pinned source revisions.
coverage:
  rule: covered
  transition: covered
  validation: covered
  permission: covered
  edge: covered
  failure: 'gap: FND-PFM-DJE-069'
  boundary: covered
  concurrency: covered
  invariant: covered
  interaction: covered
coverage_notes:
  transition: >-
    Selected lifecycle examples do not cover every applicable object and batch transition. The
    linked finding retains the remaining matrix.
  execution: >-
    Covered means a specification scenario exists. Proposed scenarios and registered suites with no
    run result do not establish executed conformance.
related:
  - CAP-PFM-DJE-001
  - CAP-PFM-DJE-002
  - CAP-PFM-DJE-007
  - CAP-PFM-DJE-010
workflows:
  - WF-PFM-DJE-003
  - WF-PFM-DJE-019
coverage_evidence:
  - rule: BR-CAP-PFM-DJE-009-01
    scenarios:
      - ATS-PFM-DJE-009-02
    provenance: proposed
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0110.spec.ts#DJE-ACC-0110
  - rule: BR-CAP-PFM-DJE-009-02
    scenarios:
      - ATS-PFM-DJE-009-01
      - ATS-PFM-DJE-009-11
      - ATS-PFM-DJE-009-14
    provenance: proposed
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0111.spec.ts#DJE-ACC-0111
  - rule: BR-CAP-PFM-DJE-009-03
    scenarios:
      - ATS-PFM-DJE-009-03
    provenance: proposed
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0104.spec.ts#DJE-ACC-0104
  - rule: BR-CAP-PFM-DJE-009-04
    scenarios:
      - ATS-PFM-DJE-009-04
    provenance: proposed
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0102.spec.ts#DJE-ACC-0102
  - rule: BR-CAP-PFM-DJE-009-05
    scenarios:
      - ATS-PFM-DJE-009-05
    provenance: proposed
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0101.spec.ts#DJE-ACC-0101
  - rule: BR-CAP-PFM-DJE-009-06
    scenarios:
      - ATS-PFM-DJE-009-06
    provenance: proposed
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0114.spec.ts#DJE-ACC-0114
  - rule: BR-CAP-PFM-DJE-009-07
    scenarios:
      - ATS-PFM-DJE-009-07
      - ATS-PFM-DJE-009-12
    provenance: proposed
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0112.spec.ts#DJE-ACC-0112
  - rule: BR-CAP-PFM-DJE-009-08
    scenarios:
      - ATS-PFM-DJE-009-08
      - ATS-PFM-DJE-009-11
    provenance: proposed
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0113.spec.ts#DJE-ACC-0113
  - rule: BR-CAP-PFM-DJE-009-09
    scenarios:
      - ATS-PFM-DJE-009-09
    provenance: proposed
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0108.spec.ts#DJE-ACC-0108
  - rule: BR-CAP-PFM-DJE-009-10
    scenarios:
      - ATS-PFM-DJE-009-10
      - ATS-PFM-DJE-009-12
      - ATS-PFM-DJE-009-13
    provenance: proposed
    source: >-
      react-console:acceptance/data-jobs/playwright/journeys/dialogs/DJE-ACC-0105.spec.ts#DJE-ACC-0105
---

# Complete selected-record changes from a list dialog: Capability Test Specification

## Coverage

The structured coverage rows link required rules to their scenarios. A covered category has a defined check; executable coverage and successful execution require separate evidence. The category map keeps incomplete lifecycle matrices and other missing checks visible as findings.

## Interactions With Related Capabilities

Dialog input becomes a durable inspectable job. Dialog approval is tied to its saved preview. The delete dialog uses the counted engine approval. Reclassification makes a previously blocked type deletable. The interaction scenarios use the related capabilities' rule references and identify the shared fixture and observable outcome.
