---
id: ATS-PFM-DJE-001
scope: CAP-PFM-DJE-001
product_area: platform
module: data-job-engine
revision: 2
status: proposed
approved_by: null
approved_at: null
source_sha:
  macroservice-libraries: 54536a441935c6e09fdb7f96f0bec71c52ba4e03
  services-crm: a8d1364f1dd44b723bb5f9acba12f983e9ec8d69
  services-platform: ad3f6a6582843008ed0f5a17b131878d15829af1
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-PFM-DJE-001-01
    title: Both operation and bulk access are required
    level: api
    proves:
      - BR-CAP-PFM-DJE-001-01
    preconditions: Prepare callers with each permission alone and with both.
    steps:
      - do: Submit the contact change under each identity.
        expect: The single-permission callers receive 403; the fully authorized caller succeeds.
        provenance: test
        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 single-permission callers receive 403; the fully authorized caller succeeds.
    negative: true
    data_needs: Signed caller contexts with distinct grants.
    bound_to:
      - TST-PFM-DJE-109
      - TST-PFM-DJE-108
    provenance: test
    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
    category: permission
    binding_evidence:
      - >-
        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/e2e/data-jobs.e2e.spec.js#refuses a caller who may
        change contacts in bulk but may not update one with 403
      - >-
        services-crm:modules/data-jobs/tests/e2e/configuration-data-jobs.e2e.spec.js#refuses a
        caller who holds the bulk key but may not change a contact type with 403
  - id: ATS-PFM-DJE-001-02
    title: Interactive requests obey size and shape limits
    level: api
    proves:
      - BR-CAP-PFM-DJE-001-02
    preconditions: Use an authorized organization updater.
    steps:
      - do: 'Send 501 identifiers, then both input forms, then no input form.'
        expect: Each request receives 400 before work is submitted.
        provenance: test
        source: >-
          services-crm:modules/data-jobs/tests/e2e/organization-update.e2e.spec.js#refuses a
          selection past the interactive lane’s 500 with 400
    expected: Each request receives 400 before work is submitted.
    negative: true
    data_needs: No additional fixture is needed.
    bound_to:
      - TST-PFM-DJE-110
      - TST-PFM-DJE-109
    provenance: test
    source: >-
      services-crm:modules/data-jobs/tests/e2e/organization-update.e2e.spec.js#refuses a selection
      past the interactive lane’s 500 with 400
    category: boundary
    binding_evidence:
      - >-
        services-crm:modules/data-jobs/tests/e2e/organization-update.e2e.spec.js#refuses a selection
        past the interactive lane’s 500 with 400
      - >-
        services-crm:modules/data-jobs/tests/e2e/data-jobs.e2e.spec.js#refuses a submission carrying
        both a selection and prepared records with 400
      - >-
        services-crm:modules/data-jobs/tests/e2e/data-jobs.e2e.spec.js#refuses a submission carrying
        neither with 400
  - id: ATS-PFM-DJE-001-03
    title: Undeclared fields are named in the refusal
    level: api
    proves:
      - BR-CAP-PFM-DJE-001-03
    preconditions: >-
      Prepare a contact update with an undeclared collection and an organization update with a
      system column.
    steps:
      - do: Submit each disallowed change.
        expect: Each refusal names the disallowed field.
        provenance: test
        source: >-
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#refuses
          a field the bulk update may not set, naming it, before any contact is touched
    expected: Each refusal names the disallowed field.
    negative: true
    data_needs: No additional fixture is needed.
    bound_to:
      - TST-PFM-DJE-117
      - TST-PFM-DJE-110
    provenance: test
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#refuses
      a field the bulk update may not set, naming it, before any contact is touched
    category: validation
    binding_evidence:
      - >-
        services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#refuses
        a field the bulk update may not set, naming it, before any contact is touched
      - >-
        services-crm:modules/data-jobs/tests/e2e/organization-update.e2e.spec.js#refuses a patch of
        a system column with 400, naming it
  - id: ATS-PFM-DJE-001-04
    title: Saved input retains order and values
    level: api
    proves:
      - BR-CAP-PFM-DJE-001-04
    preconditions: Submit a multi-contact change.
    steps:
      - do: Inspect the job input and process it.
        expect: Input order and submitted field values are retained.
        provenance: test
        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
    expected: Input order and submitted field values are retained.
    negative: false
    data_needs: No additional fixture is needed.
    bound_to:
      - TST-PFM-DJE-117
    provenance: test
    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
    category: invariant
    binding_evidence:
      - >-
        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#freezes
        the patch on every item, so a later apply writes what was submitted and not what is asked
        for then
  - id: ATS-PFM-DJE-001-05
    title: A keyed retry retrieves existing work
    level: browser
    proves:
      - BR-CAP-PFM-DJE-001-05
    preconditions: Submit a request with an idempotency key.
    steps:
      - do: >-
          Repeat it, reuse its key with a different body, and exercise the console double-click
          path.
        expect: >-
          The retry returns the same job; the changed request is refused; the console sends one
          apply request.
        provenance: test
        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
    expected: >-
      The retry returns the same job; the changed request is refused; the console sends one apply
      request.
    negative: false
    data_needs: No additional fixture is needed.
    bound_to:
      - TST-PFM-DJE-117
      - TST-PFM-DJE-053
    provenance: test
    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
    category: edge
    binding_evidence:
      - >-
        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/jobs/contact-data-jobs.integration.spec.js#holds
        one submission row for the key, so the ledger is what answered the second
      - >-
        react-console:acceptance/crm/playwright/journeys/data-operations/CRM-ACC-0654.spec.ts#CRM-ACC-0654
  - id: ATS-PFM-DJE-001-06
    title: Unsupported record kinds identify supported operations
    level: api
    proves:
      - BR-CAP-PFM-DJE-001-06
    preconditions: No setup beyond an authorized caller is necessary.
    steps:
      - do: Request an operation for an unsupported record kind.
        expect: The refusal describes the supported choices.
        provenance: test
        source: >-
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#refuses
          an object type CRM performs no bulk operation on, naming what it does perform
    expected: The refusal describes the supported choices.
    negative: true
    data_needs: No additional fixture is needed.
    bound_to:
      - TST-PFM-DJE-117
    provenance: test
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#refuses
      an object type CRM performs no bulk operation on, naming what it does perform
    category: validation
    binding_evidence:
      - >-
        services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#refuses
        an object type CRM performs no bulk operation on, naming what it does perform
  - id: ATS-PFM-DJE-001-07
    title: CRM refuses imports on the interactive route
    level: api
    proves:
      - BR-CAP-PFM-DJE-001-07
    preconditions: Use a caller authorized to change contacts.
    steps:
      - do: Submit inline input for an insert with a producer key.
        expect: The schema refuses the import without changing a contact.
        provenance: test
        source: >-
          react-console:acceptance/crm/playwright/journeys/data-operations/CRM-ACC-0653.spec.ts#CRM-ACC-0653
    expected: The schema refuses the import without changing a contact.
    negative: true
    data_needs: No additional fixture is needed.
    bound_to:
      - TST-PFM-DJE-052
    provenance: test
    source: >-
      react-console:acceptance/crm/playwright/journeys/data-operations/CRM-ACC-0653.spec.ts#CRM-ACC-0653
    category: validation
    binding_evidence:
      - >-
        react-console:acceptance/crm/playwright/journeys/data-operations/CRM-ACC-0653.spec.ts#CRM-ACC-0653
  - id: ATS-PFM-DJE-001-08
    title: Collection boundaries conceal mismatched jobs
    level: api
    proves:
      - BR-CAP-PFM-DJE-001-08
    preconditions: Prepare a validated contact job.
    steps:
      - do: 'Attempt its reads, apply and controls through contact-type routes.'
        expect: Every mismatched call reports not found and preserves the job.
        provenance: test
        source: >-
          services-crm:modules/data-jobs/tests/integration/services/jobs/configuration-data-jobs.integration.spec.js#is
          not found by the apply, so a validated job of contacts cannot be started from here
    expected: Every mismatched call reports not found and preserves the job.
    negative: true
    data_needs: No additional fixture is needed.
    bound_to:
      - TST-PFM-DJE-116
      - TST-PFM-DJE-108
    provenance: test
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/configuration-data-jobs.integration.spec.js#is
      not found by the apply, so a validated job of contacts cannot be started from here
    category: boundary
    binding_evidence:
      - >-
        services-crm:modules/data-jobs/tests/integration/services/jobs/configuration-data-jobs.integration.spec.js#is
        not found by the apply, so a validated job of contacts cannot be started from here
      - >-
        services-crm:modules/data-jobs/tests/integration/services/jobs/configuration-data-jobs.integration.spec.js#is
        left exactly as it was by all nine refusals, still validating and still waiting for its own
        routes
      - >-
        services-crm:modules/data-jobs/tests/e2e/configuration-data-jobs.e2e.spec.js#is refused by
        the apply at the contacts path as not found, a job of another object type, with 404
  - id: ATS-PFM-DJE-001-09
    title: Workspace boundaries conceal jobs
    level: api
    proves:
      - BR-CAP-PFM-DJE-001-09
    preconditions: Create a job in the first of two workspaces.
    steps:
      - do: Attempt to inspect and process it from the second.
        expect: The job is not found and records in both workspaces remain intact.
        provenance: test
        source: >-
          macroservice-libraries:packages/data-jobs/src/tests/integration/tenant-isolation.integration.spec.ts#does
          not let another tenant see a job, or learn that it exists
    expected: The job is not found and records in both workspaces remain intact.
    negative: true
    data_needs: Two independent workspaces.
    bound_to:
      - TST-PFM-DJE-035
      - TST-PFM-DJE-117
    provenance: test
    source: >-
      macroservice-libraries:packages/data-jobs/src/tests/integration/tenant-isolation.integration.spec.ts#does
      not let another tenant see a job, or learn that it exists
    category: boundary
    binding_evidence:
      - >-
        macroservice-libraries:packages/data-jobs/src/tests/integration/tenant-isolation.integration.spec.ts#does
        not let another tenant see a job, or learn that it exists
      - >-
        macroservice-libraries:packages/data-jobs/src/tests/integration/tenant-isolation.integration.spec.ts#does
        not let another tenant run a job's batch, and changes no record of either tenant
      - >-
        services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#tells
        another tenant the job does not exist, rather than anything about it
  - id: ATS-PFM-DJE-001-10
    title: A failed submission leaves no durable work
    category: invariant
    level: api
    proves:
      - BR-CAP-PFM-DJE-001-10
    preconditions: Prepare a keyed two-batch request and inject an exception before its transaction commits.
    steps:
      - do: 'Submit in the failing transaction, inspect all engine records, then retry successfully.'
        expect: >-
          The failed request leaves no job, input, batches, queue entries or ledger key; the retry
          records one complete submission.
        provenance: proposed
        source: >-
          macroservice-libraries:packages/data-jobs/README.md#A worked example: updating contacts in
          bulk
    expected: >-
      The failed request leaves no job, input, batches, queue entries or ledger key; the retry
      records one complete submission.
    negative: true
    data_needs: Prepare a keyed two-batch request and inject an exception before its transaction commits.
    bound_to: []
    provenance: proposed
    source: >-
      macroservice-libraries:packages/data-jobs/README.md#A worked example: updating contacts in
      bulk
  - id: ATS-PFM-DJE-001-11
    title: Saved submission reaches approval unchanged
    category: interaction
    level: api
    exercises:
      - CAP-PFM-DJE-001
      - CAP-PFM-DJE-002
    proves:
      - BR-CAP-PFM-DJE-001-04
      - BR-CAP-PFM-DJE-002-01
      - BR-CAP-PFM-DJE-002-02
    preconditions: Create two contacts with distinct starting values.
    steps:
      - do: >-
          Submit a common change for validation, alter the caller's local request, and approve the
          saved preview.
        expect: >-
          The contacts receive the saved change; the altered local request supplies no replacement
          input.
        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;
          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
          an apply of the validated update whose digest is not the one the validation answered
    expected: >-
      The contacts receive the saved change; the altered local request supplies no replacement
      input.
    negative: false
    data_needs: Create two contacts with distinct starting values.
    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;
      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
      an apply of the validated update whose digest is not the one the validation answered
  - id: ATS-PFM-DJE-001-12
    title: Submission commits before processing can account for it
    category: interaction
    level: api
    exercises:
      - CAP-PFM-DJE-001
      - CAP-PFM-DJE-003
    proves:
      - BR-CAP-PFM-DJE-001-10
      - BR-CAP-PFM-DJE-003-01
    preconditions: Prepare a submission and a transaction failure immediately before commit.
    steps:
      - do: >-
          Refuse the first transaction, inspect job storage, then submit successfully and process
          the saved batches twice.
        expect: >-
          The refused submission leaves no job or queued work; the successful job has one committed
          outcome per position.
        provenance: proposed
        source: >-
          macroservice-libraries:packages/data-jobs/README.md#A worked example: updating contacts in
          bulk;
          services-crm:modules/data-jobs/tests/integration/services/queue/data-job-worker.integration.spec.js#changes
          each contact once between them, whichever delivery got there first
    expected: >-
      The refused submission leaves no job or queued work; the successful job has one committed
      outcome per position.
    negative: true
    data_needs: Prepare a submission and a transaction failure immediately before commit.
    bound_to: []
    provenance: proposed
    source: >-
      macroservice-libraries:packages/data-jobs/README.md#A worked example: updating contacts in
      bulk;
      services-crm:modules/data-jobs/tests/integration/services/queue/data-job-worker.integration.spec.js#changes
      each contact once between them, whichever delivery got there first
  - id: ATS-PFM-DJE-001-13
    title: Keyed submission remains identifiable in inspection
    category: interaction
    level: api
    exercises:
      - CAP-PFM-DJE-001
      - CAP-PFM-DJE-005
    proves:
      - BR-CAP-PFM-DJE-001-05
      - BR-CAP-PFM-DJE-005-03
    preconditions: Create an authorized caller and two selected contacts.
    steps:
      - do: 'Submit a keyed update, repeat it, process it, and read its job and result pages.'
        expect: Both submissions identify the same job and inspection contains each input position once.
        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/jobs/contact-data-jobs.integration.spec.js#answers
          the next page from the cursor the last one gave, so no item is read twice
    expected: Both submissions identify the same job and inspection contains each input position once.
    negative: false
    data_needs: Create an authorized caller and two selected 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/jobs/contact-data-jobs.integration.spec.js#answers
      the next page from the cursor the last one gave, so no item is read twice
  - id: ATS-PFM-DJE-001-14
    title: Dialog input becomes a durable inspectable job
    category: interaction
    level: api
    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-001-15
    title: Operation declarations constrain submitted work
    category: interaction
    level: api
    exercises:
      - CAP-PFM-DJE-001
      - CAP-PFM-DJE-018
    proves:
      - BR-CAP-PFM-DJE-001-06
      - BR-CAP-PFM-DJE-018-01
      - BR-CAP-PFM-DJE-018-07
    preconditions: >-
      Prepare a supported Platform field-definition operation and authorized and unauthorized
      callers.
    steps:
      - do: >-
          Submit a supported definition, an unsupported operation, and the supported input without
          bulk authority.
        expect: >-
          Only the permitted declared operation creates work; the refused requests leave no
          definition or job.
        provenance: proposed
        source: >-
          services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#refuses
          an object type CRM performs no bulk operation on, naming what it does perform;
          macroservice-libraries:packages/data-jobs/src/validate-data-job-request.spec.ts#refuses a
          delete that declares patchable fields, which a delete never sets;
          services-platform:modules/data-jobs/tests/integration/services/jobs/custom-field-data-jobs.integration.spec.js#refuses
          a caller who may create a definition but holds no bulk right
    expected: >-
      Only the permitted declared operation creates work; the refused requests leave no definition
      or job.
    negative: true
    data_needs: >-
      Prepare a supported Platform field-definition operation and authorized and unauthorized
      callers.
    bound_to: []
    provenance: proposed
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#refuses
      an object type CRM performs no bulk operation on, naming what it does perform;
      macroservice-libraries:packages/data-jobs/src/validate-data-job-request.spec.ts#refuses a
      delete that declares patchable fields, which a delete never sets;
      services-platform:modules/data-jobs/tests/integration/services/jobs/custom-field-data-jobs.integration.spec.js#refuses
      a caller who may create a definition but holds no bulk right
evidence:
  - >-
    Reviewed evidence: macroservice-libraries (54536a44): README.md (The operation contract; A
    worked example); src/validate-data-job-request.ts, submit-data-job.ts, row-level-security.ts;
    tests tenant-isolation.integration.spec.ts, data-job-engine.integration.spec.ts.
  - >-
    Reviewed evidence: services-crm (a8d1364f): aws/api/data-jobs.routes.ts,
    organization-data-jobs.routes.ts, bulk-data-jobs.routes.ts, data-jobs.schemas.ts;
    services/operations/data-operations.ts; tests contact-data-jobs.integration.spec.js,
    configuration-data-jobs.integration.spec.js, data-jobs.e2e.spec.js,
    organization-update.e2e.spec.js.
  - >-
    Reviewed evidence: services-platform (ad3f6a65): aws/api/custom-field-data-jobs.routes.ts,
    custom-object-record-data-jobs.routes.ts; services/jobs/data-job-surfaces.ts.
  - >-
    Reviewed evidence: react-console (baf6dae3): lib/api/data-jobs/capabilities.ts, submit.ts;
    acceptance/crm/journeys/data-operations/CRM-ACC-0653, 0654.
  - >-
    Testing back-fill: related capability rules, domain invariants, state transitions and crossing
    workflows at the pinned source revisions.
coverage:
  rule: 'gap: FND-PFM-DJE-061'
  transition: 'gap: FND-PFM-DJE-061'
  validation: covered
  permission: covered
  edge: covered
  failure: 'gap: FND-PFM-DJE-061'
  boundary: covered
  concurrency: 'gap: FND-PFM-DJE-061'
  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-002
  - CAP-PFM-DJE-003
  - CAP-PFM-DJE-005
workflows:
  - WF-PFM-DJE-001
  - WF-PFM-DJE-009
  - WF-PFM-DJE-018
  - WF-PFM-DJE-020
coverage_evidence:
  - rule: BR-CAP-PFM-DJE-001-01
    scenarios:
      - ATS-PFM-DJE-001-01
    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
  - rule: BR-CAP-PFM-DJE-001-02
    scenarios:
      - ATS-PFM-DJE-001-02
    provenance: proposed
    source: >-
      services-crm:modules/data-jobs/tests/e2e/organization-update.e2e.spec.js#refuses a selection
      past the interactive lane’s 500 with 400
  - rule: BR-CAP-PFM-DJE-001-03
    scenarios:
      - ATS-PFM-DJE-001-03
    provenance: proposed
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#refuses
      a field the bulk update may not set, naming it, before any contact is touched
  - rule: BR-CAP-PFM-DJE-001-04
    scenarios:
      - ATS-PFM-DJE-001-04
      - ATS-PFM-DJE-001-11
      - ATS-PFM-DJE-001-14
    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
  - rule: BR-CAP-PFM-DJE-001-05
    scenarios:
      - ATS-PFM-DJE-001-05
      - ATS-PFM-DJE-001-13
    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
  - rule: BR-CAP-PFM-DJE-001-06
    scenarios:
      - ATS-PFM-DJE-001-06
      - ATS-PFM-DJE-001-15
    provenance: proposed
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/contact-data-jobs.integration.spec.js#refuses
      an object type CRM performs no bulk operation on, naming what it does perform
  - rule: BR-CAP-PFM-DJE-001-07
    scenarios:
      - ATS-PFM-DJE-001-07
    provenance: proposed
    source: 'services-crm:modules/data-jobs/aws/api/data-jobs.schemas.ts:dataJobRequestSchema'
  - rule: BR-CAP-PFM-DJE-001-08
    scenarios:
      - ATS-PFM-DJE-001-08
    provenance: proposed
    source: >-
      services-crm:modules/data-jobs/tests/integration/services/jobs/configuration-data-jobs.integration.spec.js#is
      not found by the apply, so a validated job of contacts cannot be started from here
  - rule: BR-CAP-PFM-DJE-001-09
    scenarios:
      - ATS-PFM-DJE-001-09
    provenance: proposed
    source: >-
      macroservice-libraries:packages/data-jobs/src/tests/integration/tenant-isolation.integration.spec.ts#does
      not let another tenant see a job, or learn that it exists
---

# Submit an accountable change across many records: 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

Saved submission reaches approval unchanged. Submission commits before processing can account for it. Keyed submission remains identifiable in inspection. Dialog input becomes a durable inspectable job. Operation declarations constrain submitted work. The interaction scenarios use the related capabilities' rule references and identify the shared fixture and observable outcome.
