---
id: FAS-PFM-DJE-01
feature: FEAT-PFM-DJE-01
product_area: platform
module: data-job-engine
revision: 1
status: proposed
product_intent: proposed
source_sha:
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  macroservice-libraries: 54536a441935c6e09fdb7f96f0bec71c52ba4e03
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  services-membership: 5994c270e8a37a30f848e99ba5b5ee6b87c08893
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
capabilities:
  - CAP-PFM-DJE-001
  - CAP-PFM-DJE-002
  - CAP-PFM-DJE-003
  - CAP-PFM-DJE-004
  - CAP-PFM-DJE-005
scenarios:
  - id: FAS-PFM-DJE-01-01
    title: 'One job connects approval, partial writes and inspection'
    kind: behaviour
    exercises:
      - CAP-PFM-DJE-001
      - CAP-PFM-DJE-002
      - CAP-PFM-DJE-003
      - CAP-PFM-DJE-005
    relies_on:
      - ATS-PFM-DJE-001-04
      - ATS-PFM-DJE-002-01
      - ATS-PFM-DJE-003-02
      - ATS-PFM-DJE-005-03
    preconditions: 'Prepare ten contacts, one locked and one carrying invalid update input.'
    steps:
      - do: >-
          Submit a validated title change, inspect its preview, approve it, process batches and page
          the outcomes.
        expect: >-
          Eight contacts change; two refusals remain inspectable in the same job and no contact
          changes during preview.
        provenance: proposed
        source: >-
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#freezes
          one item per id, in the order the request named them;
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#changes
          nothing while it is validating;
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#refuses
          the other five, counting each as what refused it;
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#answers
          a page of results in item order, each with its outcome
    expected: >-
      Eight contacts change; two refusals remain inspectable in the same job and no contact changes
      during preview.
    negative: true
    data_needs: 'Prepare ten contacts, one locked and one carrying invalid update input.'
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#freezes
      one item per id, in the order the request named them;
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#changes
      nothing while it is validating;
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#refuses
      the other five, counting each as what refused it;
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#answers
      a page of results in item order, each with its outcome
  - id: FAS-PFM-DJE-01-02
    title: Lost authority changes both processing and its progress account
    kind: interaction
    exercises:
      - CAP-PFM-DJE-001
      - CAP-PFM-DJE-003
      - CAP-PFM-DJE-004
      - CAP-PFM-DJE-005
    relies_on:
      - ATS-PFM-DJE-001-01
      - ATS-PFM-DJE-003-09
      - ATS-PFM-DJE-004-02
      - ATS-PFM-DJE-005-03
    preconditions: Submit a multi-batch job and finish its first batch.
    steps:
      - do: >-
          Withdraw the submitter's bulk authority, deliver the next batch and inspect the job and
          records.
        expect: >-
          The job reports access revoked, earlier commits remain and later positions are
          unattempted.
        provenance: proposed
        source: >-
          services-crm:modules/data-jobs/tests/e2e/data-jobs.e2e.spec.js#refuses a caller who may
          update one contact but holds no bulk key with 403;
          services-crm:modules/data-jobs/tests/integration/services/queue/data-job-worker.integration.spec.js#fails
          the whole job with the code, not just the batch;
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#ends
          the job cancelled, not failed, once the batch it waited for has finished;
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#answers
          a page of results in item order, each with its outcome
    expected: 'The job reports access revoked, earlier commits remain and later positions are unattempted.'
    negative: true
    data_needs: Submit a multi-batch job and finish its first batch.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/data-jobs/tests/e2e/data-jobs.e2e.spec.js#refuses a caller who may update
      one contact but holds no bulk key with 403;
      services-crm:modules/data-jobs/tests/integration/services/queue/data-job-worker.integration.spec.js#fails
      the whole job with the code, not just the batch;
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#ends
      the job cancelled, not failed, once the batch it waited for has finished;
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#answers
      a page of results in item order, each with its outcome
  - id: FAS-PFM-DJE-01-03
    title: Pause and resume finish the saved work once
    kind: lifecycle
    exercises:
      - CAP-PFM-DJE-001
      - CAP-PFM-DJE-003
      - CAP-PFM-DJE-004
      - CAP-PFM-DJE-005
    relies_on:
      - ATS-PFM-DJE-001-04
      - ATS-PFM-DJE-003-01
      - ATS-PFM-DJE-004-02
      - ATS-PFM-DJE-004-03
    preconditions: Submit a two-batch change and finish one batch.
    steps:
      - do: 'Pause, deliver held work, resume, finish and inspect the saved outcomes.'
        expect: Held work makes no change; resumed processing completes each remaining position once.
        provenance: proposed
        source: >-
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#freezes
          one item per id, in the order the request named them;
          services-crm:modules/data-jobs/tests/integration/services/queue/data-job-worker.integration.spec.js#applies
          nothing the second time;
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#ends
          the job cancelled, not failed, once the batch it waited for has finished;
          macroservice-libraries:packages/data-jobs/src/tests/integration/bulk-data-jobs.integration.spec.ts#holds
          a job paused before its source was read, and runs it to the end once resumed
    expected: Held work makes no change; resumed processing completes each remaining position once.
    negative: false
    data_needs: Submit a two-batch change and finish one batch.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#freezes
      one item per id, in the order the request named them;
      services-crm:modules/data-jobs/tests/integration/services/queue/data-job-worker.integration.spec.js#applies
      nothing the second time;
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#ends
      the job cancelled, not failed, once the batch it waited for has finished;
      macroservice-libraries:packages/data-jobs/src/tests/integration/bulk-data-jobs.integration.spec.ts#holds
      a job paused before its source was read, and runs it to the end once resumed
  - id: FAS-PFM-DJE-01-04
    title: A missing bulk key prevents the whole submission chain
    kind: permission
    exercises:
      - CAP-PFM-DJE-001
      - CAP-PFM-DJE-002
      - CAP-PFM-DJE-003
      - CAP-PFM-DJE-005
    relies_on:
      - ATS-PFM-DJE-001-01
    preconditions: Use an updater without contact bulk authority and an authorized positive control.
    steps:
      - do: >-
          Attempt submission with the updater, inspect storage as the owner, then submit the
          control's preview.
        expect: >-
          The refused request creates no job or record change; the authorized preview is available
          for review.
        provenance: proposed
        source: >-
          services-crm:modules/data-jobs/tests/e2e/data-jobs.e2e.spec.js#refuses a caller who may
          update one contact but holds no bulk key with 403
    expected: >-
      The refused request creates no job or record change; the authorized preview is available for
      review.
    negative: true
    data_needs: Use an updater without contact bulk authority and an authorized positive control.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/data-jobs/tests/e2e/data-jobs.e2e.spec.js#refuses a caller who may update
      one contact but holds no bulk key with 403
  - id: FAS-PFM-DJE-01-05
    title: A replayed request cannot multiply its input outcomes
    kind: regression
    exercises:
      - CAP-PFM-DJE-001
      - CAP-PFM-DJE-003
      - CAP-PFM-DJE-005
    relies_on:
      - ATS-PFM-DJE-001-05
      - ATS-PFM-DJE-003-01
      - ATS-PFM-DJE-005-03
    preconditions: Prepare a keyed update of fifty contacts.
    steps:
      - do: >-
          Repeat the request with the same key, deliver each saved batch twice and inspect all
          outcomes.
        expect: Both requests identify one job and each input position has one durable committed outcome.
        provenance: proposed
        source: >-
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#answers
          the second submission with the first job, having written nothing;
          services-crm:modules/data-jobs/tests/integration/services/queue/data-job-worker.integration.spec.js#applies
          nothing the second time;
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#answers
          a page of results in item order, each with its outcome
    expected: Both requests identify one job and each input position has one durable committed outcome.
    negative: false
    data_needs: Prepare a keyed update of fifty contacts.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#answers
      the second submission with the first job, having written nothing;
      services-crm:modules/data-jobs/tests/integration/services/queue/data-job-worker.integration.spec.js#applies
      nothing the second time;
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#answers
      a page of results in item order, each with its outcome
evidence:
  - CAP-PFM-DJE-001
  - CAP-PFM-DJE-002
  - CAP-PFM-DJE-003
  - CAP-PFM-DJE-004
  - CAP-PFM-DJE-005
  - specs/CONVENTIONS.md#5.3 Feature Acceptance Suite
  - specs/CONVENTIONS.md#9.10 Capability Test Specification
---

# Recorded bulk work: Feature Acceptance Suite

## What the Feature Must Do as a Whole

One job connects approval, partial writes and inspection is the feature-level acceptance outcome. The suite follows the work through its participating capabilities and checks the final records, job accounts and refusals together. Permission and regression cases revisit the same feature boundary with changed authority or input.

## Interactions Between Capabilities

Lost authority changes both processing and its progress account. The interaction case changes a shared prerequisite and checks how that change affects the next capability's result. Lifecycle cases retain partial work and distinguish a new attempt from resuming existing work. These feature expectations remain proposed until their complete executable coverage is established.

## Regression Record

| Revision | Change | Scenario | Why |
|---|---|---|---|
| 1 | initial | all | Establish cumulative acceptance across the feature's landed capabilities. |
