---
id: ATS-COM-FUL-020
scope: CAP-COM-FUL-020
product_area: commerce
module: fulfillment
revision: 2
status: proposed
approved_by: null
approved_at: null
source_sha:
  services-commerce: c8b66a98e2490617aec38ba5c8165dd9bd0a8f9b
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
scenarios:
  - id: ATS-COM-FUL-020-01
    title: Collection jobs reject malformed or unauthorized submissions
    level: api
    proves:
      - BR-CAP-COM-FUL-020-02
      - BR-CAP-COM-FUL-020-03
    preconditions: 'Reader-only, portal and bulk-authorized identities are available.'
    steps: Submit invalid payloads and exercise each caller's submission.
    expected: >-
      Field errors identify invalid input, unauthorized callers fail and a valid
      authorized request is accepted.
    negative: true
    data_needs: Fixtures for collection jobs reject malformed or unauthorized submissions.
    bound_to:
      - >-
        services-commerce:modules/data-operations/tests/unit/api/data-jobs-schemas.spec.js#refuses
        a selection with a patch: no Commerce operation changes records in place
        by id
      - >-
        services-commerce:modules/data-operations/tests/unit/api/data-jobs-schemas.spec.js#refuses
        a record naming neither a source key nor an id, and keyed records
        without a source system
      - >-
        services-commerce:modules/data-operations/tests/unit/api/data-jobs-schemas.spec.js#refuses
        an operation outside insert, upsert and update, and a mode outside
        validate and apply
      - >-
        services-commerce:modules/data-operations/tests/e2e/data-jobs.e2e.spec.js#refuses
        a principal holding the read key alone on every data-job route of the
        collection, 403 permission_missing
      - >-
        services-commerce:modules/data-operations/tests/e2e/data-jobs.e2e.spec.js#refuses
        a portal member: the routes are console access
      - >-
        services-commerce:modules/data-operations/tests/unit/operations/data-operations.spec.js#declares,
        for each collection, the bulk key a submission needs and the per-record
        key it re-checks
      - TST-COM-FUL-013
      - TST-COM-FUL-003
      - TST-COM-FUL-014
    provenance: test
    source: >-
      services-commerce:modules/data-operations/tests/unit/api/data-jobs-schemas.spec.js#refuses
      a selection with a patch: no Commerce operation changes records in place
      by id
    category: validation
  - id: ATS-COM-FUL-020-02
    title: Job replay and impact digest protect application
    level: api
    proves:
      - BR-CAP-COM-FUL-020-04
      - BR-CAP-COM-FUL-020-05
    preconditions: A job has completed validation.
    steps: 'Repeat submission and apply with absent, wrong and correct digests.'
    expected: >-
      Replay identifies the same job, invalid digests fail and the correct
      digest permits queued execution.
    negative: true
    data_needs: Fixtures for job replay and impact digest protect application.
    bound_to:
      - >-
        services-commerce:modules/data-operations/tests/e2e/data-jobs.e2e.spec.js#answers
        a second submission of the same body under the same Idempotency-Key with
        the same job, reused
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#answers
        the same job the second time, reused, with one row in the idempotency
        ledger
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#refuses
        an apply that echoes no impact digest, impact_digest_required
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#refuses
        an apply that echoes a digest other than the validation recorded,
        impact_digest_mismatch
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#applies
        the validated job echoing its digest: queued, one batch on the queue
        table for the dispatcher
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#validates
        without writing: the submission validating, its one batch run, the job
        validated with its impact one create
      - TST-COM-FUL-003
      - TST-COM-FUL-004
    provenance: test
    source: >-
      services-commerce:modules/data-operations/tests/e2e/data-jobs.e2e.spec.js#answers
      a second submission of the same body under the same Idempotency-Key with
      the same job, reused
    category: invariant
  - id: ATS-COM-FUL-020-03
    title: Job visibility preserves caller and collection boundaries
    level: api
    proves:
      - BR-CAP-COM-FUL-020-06
    preconditions: Two people submitted jobs in two collections.
    steps: 'List as each, read across collections and submit the wrong record type.'
    expected: >-
      Bulk authority sees its collection's jobs, other callers see their own and
      collection mismatches fail.
    negative: true
    data_needs: Fixtures for job visibility preserves caller and collection boundaries.
    bound_to:
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#lists
        every job of the collection for a caller holding its bulk key, and no
        job of another collection
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#lists
        only the jobs a caller submitted themselves when they lack the
        collection’s bulk key
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#answers
        a job of another collection as not found through this collection’s scope
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#refuses
        a submission naming another collection’s object type
      - TST-COM-FUL-004
    provenance: test
    source: >-
      services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#lists
      every job of the collection for a caller holding its bulk key, and no job
      of another collection
    category: permission
  - id: ATS-COM-FUL-020-04
    title: Initial import requires the loading lifecycle
    level: api
    proves:
      - BR-CAP-COM-FUL-020-07
    preconditions: One workspace is live and another is loading.
    steps: Submit initial imports to both and call an ordinary route while loading.
    expected: >-
      Live import fails, loading import succeeds and ordinary routes remain
      closed.
    negative: true
    data_needs: Fixtures for initial import requires the loading lifecycle.
    bound_to:
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#is
        refused for a tenant that is live
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#is
        accepted for a tenant in implementation that is being loaded
      - >-
        services-commerce:modules/data-operations/tests/e2e/data-jobs.e2e.spec.js#refuses
        the ordinary store routes, 403 TenantUnavailable
      - >-
        services-commerce:modules/data-operations/tests/e2e/data-jobs.e2e.spec.js#keeps
        serving the data-job routes: the engine’s surface is what the load is
        made of
      - TST-COM-FUL-004
      - TST-COM-FUL-003
    provenance: test
    source: >-
      services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#is
      refused for a tenant that is live
    category: boundary
  - id: ATS-COM-FUL-020-05
    title: Worker replay preserves submitter authority and batch identity
    level: api
    proves:
      - BR-CAP-COM-FUL-020-08
    preconditions: A batch is queued and its submitter can lose authority.
    steps: 'Deliver twice, deliver unreadable input and deliver after revocation.'
    expected: >-
      Valid work applies once, unreadable input is dead-lettered and revoked
      authority fails the job.
    negative: true
    data_needs: >-
      Fixtures for worker replay preserves submitter authority and batch
      identity.
    bound_to:
      - >-
        services-commerce:modules/data-operations/tests/integration/services/queue/data-job-worker.integration.spec.js#claims
        the one batch, publishes one message naming the tenant, the job and the
        batch, and deletes the queue row
      - >-
        services-commerce:modules/data-operations/tests/integration/services/queue/data-job-worker.integration.spec.js#runs
        the batch as the submitter, applies its item and acknowledges the
        message
      - >-
        services-commerce:modules/data-operations/tests/integration/services/queue/data-job-worker.integration.spec.js#applies
        nothing on a second delivery of the same message, and acknowledges it
        still
      - >-
        services-commerce:modules/data-operations/tests/integration/services/queue/data-job-worker.integration.spec.js#is
        reported unreadable and left for the dead-letter queue, never retried as
        work
      - >-
        services-commerce:modules/data-operations/tests/integration/services/queue/data-job-worker.integration.spec.js#acknowledges
        the message as access_revoked and fails the job whole with that code,
        nothing left on the queue
      - TST-COM-FUL-011
    provenance: test
    source: >-
      services-commerce:modules/data-operations/tests/integration/services/queue/data-job-worker.integration.spec.js#claims
      the one batch, publishes one message naming the tenant, the job and the
      batch, and deletes the queue row
    category: failure
  - id: ATS-COM-FUL-020-06
    title: Error classification preserves safe dependency information
    level: unit
    proves:
      - BR-CAP-COM-FUL-020-09
    preconditions: Representative writes fail through each supported error type.
    steps: >-
      Classify missing references, typed refusals, invalid values, duplicates
      and reset connections.
    expected: >-
      Classification preserves dependency fields and stable codes, reports only
      constraint names for collisions and treats resets as transient.
    negative: true
    data_needs: Fixtures for error classification preserves safe dependency information.
    bound_to:
      - >-
        services-commerce:modules/data-operations/tests/unit/operations/error-classification.spec.js#blocks
        an item whose reference nobody has loaded, on the engine’s
        dependency_missing, at the field that names it
      - >-
        services-commerce:modules/data-operations/tests/unit/operations/error-classification.spec.js#rejects
        under the stable code a typed refusal carries
      - >-
        services-commerce:modules/data-operations/tests/unit/operations/error-classification.spec.js#names
        a unique violation by its constraint alone, never by the colliding value
      - >-
        services-commerce:modules/data-operations/tests/unit/operations/error-classification.spec.js#reports
        a connection reset as a transient systemic failure, and an unknown error
        as one that is not
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/catalog-import.integration.spec.js#blocks
        a listing whose product nothing has loaded as dependency_missing, naming
        the product source key, and writes nothing
      - TST-COM-FUL-015
      - TST-COM-FUL-005
    provenance: test
    source: >-
      services-commerce:modules/data-operations/tests/unit/operations/error-classification.spec.js#blocks
      an item whose reference nobody has loaded, on the engine’s
      dependency_missing, at the field that names it
    category: failure
  - id: ATS-COM-FUL-020-07
    title: Source-key readback preserves imported shape and scope
    level: api
    proves:
      - BR-CAP-COM-FUL-020-10
    preconditions: Store source keys belong to one workspace.
    steps: Read before and after application and from another workspace.
    expected: >-
      Missing keys are reported before loading, imported shapes appear afterward
      and other workspaces see no match.
    negative: true
    data_needs: Fixtures for source-key readback preserves imported shape and scope.
    bound_to:
      - >-
        services-commerce:modules/data-operations/tests/e2e/data-jobs.e2e.spec.js#answers
        the key missing before the apply, and the store as its load carried it
        once the job is applied and run
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/configuration-imports.integration.spec.js#reads
        a load back by its keys, each store exactly as its GET answers it, the
        keys nothing loaded missing, in the order asked
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/configuration-imports.integration.spec.js#answers
        nothing for the same keys in another tenant: the crosswalk is the
        tenant’s own
      - TST-COM-FUL-003
      - TST-COM-FUL-006
    provenance: test
    source: >-
      services-commerce:modules/data-operations/tests/e2e/data-jobs.e2e.spec.js#answers
      the key missing before the apply, and the store as its load carried it
      once the job is applied and run
    category: boundary
  - id: ATS-COM-FUL-020-08
    title: Historical order opening retains delivered and waiting work
    level: api
    proves:
      - BR-CAP-COM-FUL-020-11
    preconditions: A migrated order has fulfilled and unfulfilled lines.
    steps: 'Import it, repeat insertion and later relink the known invoice source.'
    expected: >-
      The order is accepted, billed and migrated with completed and blocked
      obligations, duplicate insertion fails and relinking uses the existing
      source identity.
    negative: true
    data_needs: Fixtures for historical order opening retains delivered and waiting work.
    bound_to:
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/order-import.integration.spec.js#writes
        the order with its 1.0 number, accepted at its placement, billed, and
        marked migrated
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/order-import.integration.spec.js#creates
        one obligation per item line in its final state: completed and open for
        the fulfilled line, blocked for the other
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/order-import.integration.spec.js#leaves
        the invoice link pending on the order.migrated event rather than
        blocking the order (D-C-04)
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/order-import.integration.spec.js#refuses
        the same key loaded again as that item’s invalid value, writing nothing
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/order-import.integration.spec.js#makes
        the pending link under the idempotency key the first write would have
        used
      - TST-COM-FUL-009
    provenance: test
    source: >-
      services-commerce:modules/data-operations/tests/integration/services/operations/order-import.integration.spec.js#writes
      the order with its 1.0 number, accepted at its placement, billed, and
      marked migrated
    category: transition
  - id: ATS-COM-FUL-020-09
    title: Stock import opens balances through movements
    level: api
    proves:
      - BR-CAP-COM-FUL-020-12
    preconditions: Prepared mug and cap records describe historical stock.
    steps: 'Import them, repeat a key and use an inactive destination.'
    expected: >-
      Ledger opening records count and damage, while repeated identity and
      inactive location fail.
    negative: true
    data_needs: Fixtures for stock import opens balances through movements.
    bound_to:
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/inventory-import.integration.spec.js#opens
        the mug’s item through the ledger: a count correction of twelve and a
        damage of two, so the trigger holds ten available
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/inventory-import.integration.spec.js#opens
        the cap’s item under the product’s own SKU at the default location, with
        no movement for a count of nought
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/inventory-import.integration.spec.js#refuses
        the same key loaded again as that item’s invalid value, moving nothing
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/inventory-import.integration.spec.js#refuses
        an item at an inactive location as that item’s refusal, as the implicit
        creation would
      - TST-COM-FUL-007
    provenance: test
    source: >-
      services-commerce:modules/data-operations/tests/integration/services/operations/inventory-import.integration.spec.js#opens
      the mug’s item through the ledger: a count correction of twelve and a
      damage of two, so the trigger holds ten available
    category: invariant
  - id: ATS-COM-FUL-020-10
    title: Imported opening stock participates in the normal ledger
    category: interaction
    level: api
    proves:
      - BR-CAP-COM-FUL-020-12
      - BR-CAP-COM-FUL-017-03
    exercises:
      - CAP-COM-FUL-020
      - CAP-COM-FUL-017
      - CAP-COM-FUL-016
    relies_on:
      - ATS-COM-FUL-020-09
      - ATS-COM-FUL-017-02
      - ATS-COM-FUL-016-05
    preconditions: >-
      An implementation workspace has a migrated warehouse, location and product
      source identity.
    steps: >-
      Import twelve units with two damaged, read back the source key and inspect
      live balances and movements.
    expected: >-
      The item has ten available units, backed by count and damage entries; an
      inactive destination refuses a new item.
    negative: false
    data_needs: >-
      An isolated workspace with the products, records, authority and quantities
      described in the preconditions.
    bound_to:
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/inventory-import.integration.spec.js#opens
        the mug’s item through the ledger: a count correction of twelve and a
        damage of two, so the trigger holds ten available
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/inventory-import.integration.spec.js#opens
        the cap’s item under the product’s own SKU at the default location, with
        no movement for a count of nought
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/inventory-import.integration.spec.js#refuses
        the same key loaded again as that item’s invalid value, moving nothing
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/inventory-import.integration.spec.js#refuses
        an item at an inactive location as that item’s refusal, as the implicit
        creation would
      - TST-COM-FUL-007
    provenance: test
    source:
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/inventory-import.integration.spec.js#opens
        the mug’s item through the ledger: a count correction of twelve and a
        damage of two, so the trigger holds ten available
      - >-
        services-commerce:modules/inventory/tests/integration/db/inventory-tables.table.integration.spec.js#refuses
        the application role a balance: UPDATE on on_hand is 42501 (the column
        grant), while its settings are its to change
      - >-
        services-commerce:modules/inventory/tests/e2e/inventory.e2e.spec.js#lets
        a reader list and read everything, and refuses it every write 403
        permission_missing
  - id: ATS-COM-FUL-020-11
    title: Migrated delivery remains distinguishable from new waiting work
    category: interaction
    level: api
    proves:
      - BR-CAP-COM-FUL-020-11
      - BR-CAP-COM-FUL-002-02
      - BR-CAP-COM-FUL-004-10
    exercises:
      - CAP-COM-FUL-020
      - CAP-COM-FUL-002
      - CAP-COM-FUL-004
    relies_on:
      - ATS-COM-FUL-020-08
      - ATS-COM-FUL-002-02
      - ATS-COM-FUL-004-07
    preconditions: A historical order contains one delivered item and one undelivered item.
    steps: >-
      Import the order and inspect its two obligations; evaluate the undelivered
      line.
    expected: >-
      Imported delivery remains completed while the undelivered migrated line
      remains blocked for staff.
    negative: false
    data_needs: >-
      An isolated workspace with the products, records, authority and quantities
      described in the preconditions.
    bound_to: []
    provenance: proposed
    source:
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/order-import.integration.spec.js#writes
        the order with its 1.0 number, accepted at its placement, billed, and
        marked migrated
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#blocks
        for a person exactly when the reason is a hold, a migrated line, a
        missing approval or a prerequisite that failed, and never otherwise
      - >-
        services-commerce:modules/fulfillment/tests/integration/db/register-tables.table.integration.spec.js#refuses
        pending to authorized, authorized to pending, failed to completed and
        completed to anything but superseded (RHC02)
evidence:
  - repository: services-commerce
    tests:
      - >-
        services-commerce:modules/data-operations/tests/unit/api/data-jobs-schemas.spec.js#refuses
        a selection with a patch: no Commerce operation changes records in place
        by id
      - >-
        services-commerce:modules/data-operations/tests/unit/api/data-jobs-schemas.spec.js#refuses
        a record naming neither a source key nor an id, and keyed records
        without a source system
      - >-
        services-commerce:modules/data-operations/tests/unit/api/data-jobs-schemas.spec.js#refuses
        an operation outside insert, upsert and update, and a mode outside
        validate and apply
      - >-
        services-commerce:modules/data-operations/tests/e2e/data-jobs.e2e.spec.js#refuses
        a principal holding the read key alone on every data-job route of the
        collection, 403 permission_missing
      - >-
        services-commerce:modules/data-operations/tests/e2e/data-jobs.e2e.spec.js#refuses
        a portal member: the routes are console access
      - >-
        services-commerce:modules/data-operations/tests/unit/operations/data-operations.spec.js#declares,
        for each collection, the bulk key a submission needs and the per-record
        key it re-checks
      - >-
        services-commerce:modules/data-operations/tests/e2e/data-jobs.e2e.spec.js#answers
        a second submission of the same body under the same Idempotency-Key with
        the same job, reused
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#answers
        the same job the second time, reused, with one row in the idempotency
        ledger
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#refuses
        an apply that echoes no impact digest, impact_digest_required
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#refuses
        an apply that echoes a digest other than the validation recorded,
        impact_digest_mismatch
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#applies
        the validated job echoing its digest: queued, one batch on the queue
        table for the dispatcher
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#validates
        without writing: the submission validating, its one batch run, the job
        validated with its impact one create
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#lists
        every job of the collection for a caller holding its bulk key, and no
        job of another collection
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#lists
        only the jobs a caller submitted themselves when they lack the
        collection’s bulk key
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#answers
        a job of another collection as not found through this collection’s scope
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#refuses
        a submission naming another collection’s object type
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#is
        refused for a tenant that is live
      - >-
        services-commerce:modules/data-operations/tests/integration/services/jobs/data-jobs.integration.spec.js#is
        accepted for a tenant in implementation that is being loaded
      - >-
        services-commerce:modules/data-operations/tests/e2e/data-jobs.e2e.spec.js#refuses
        the ordinary store routes, 403 TenantUnavailable
      - >-
        services-commerce:modules/data-operations/tests/e2e/data-jobs.e2e.spec.js#keeps
        serving the data-job routes: the engine’s surface is what the load is
        made of
      - >-
        services-commerce:modules/data-operations/tests/integration/services/queue/data-job-worker.integration.spec.js#claims
        the one batch, publishes one message naming the tenant, the job and the
        batch, and deletes the queue row
      - >-
        services-commerce:modules/data-operations/tests/integration/services/queue/data-job-worker.integration.spec.js#runs
        the batch as the submitter, applies its item and acknowledges the
        message
      - >-
        services-commerce:modules/data-operations/tests/integration/services/queue/data-job-worker.integration.spec.js#applies
        nothing on a second delivery of the same message, and acknowledges it
        still
      - >-
        services-commerce:modules/data-operations/tests/integration/services/queue/data-job-worker.integration.spec.js#is
        reported unreadable and left for the dead-letter queue, never retried as
        work
      - >-
        services-commerce:modules/data-operations/tests/integration/services/queue/data-job-worker.integration.spec.js#acknowledges
        the message as access_revoked and fails the job whole with that code,
        nothing left on the queue
      - >-
        services-commerce:modules/data-operations/tests/unit/operations/error-classification.spec.js#blocks
        an item whose reference nobody has loaded, on the engine’s
        dependency_missing, at the field that names it
      - >-
        services-commerce:modules/data-operations/tests/unit/operations/error-classification.spec.js#rejects
        under the stable code a typed refusal carries
      - >-
        services-commerce:modules/data-operations/tests/unit/operations/error-classification.spec.js#names
        a unique violation by its constraint alone, never by the colliding value
      - >-
        services-commerce:modules/data-operations/tests/unit/operations/error-classification.spec.js#reports
        a connection reset as a transient systemic failure, and an unknown error
        as one that is not
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/catalog-import.integration.spec.js#blocks
        a listing whose product nothing has loaded as dependency_missing, naming
        the product source key, and writes nothing
      - >-
        services-commerce:modules/data-operations/tests/e2e/data-jobs.e2e.spec.js#answers
        the key missing before the apply, and the store as its load carried it
        once the job is applied and run
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/configuration-imports.integration.spec.js#reads
        a load back by its keys, each store exactly as its GET answers it, the
        keys nothing loaded missing, in the order asked
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/configuration-imports.integration.spec.js#answers
        nothing for the same keys in another tenant: the crosswalk is the
        tenant’s own
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/order-import.integration.spec.js#writes
        the order with its 1.0 number, accepted at its placement, billed, and
        marked migrated
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/order-import.integration.spec.js#creates
        one obligation per item line in its final state: completed and open for
        the fulfilled line, blocked for the other
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/order-import.integration.spec.js#leaves
        the invoice link pending on the order.migrated event rather than
        blocking the order (D-C-04)
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/order-import.integration.spec.js#refuses
        the same key loaded again as that item’s invalid value, writing nothing
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/order-import.integration.spec.js#makes
        the pending link under the idempotency key the first write would have
        used
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/inventory-import.integration.spec.js#opens
        the mug’s item through the ledger: a count correction of twelve and a
        damage of two, so the trigger holds ten available
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/inventory-import.integration.spec.js#opens
        the cap’s item under the product’s own SKU at the default location, with
        no movement for a count of nought
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/inventory-import.integration.spec.js#refuses
        the same key loaded again as that item’s invalid value, moving nothing
      - >-
        services-commerce:modules/data-operations/tests/integration/services/operations/inventory-import.integration.spec.js#refuses
        an item at an inactive location as that item’s refusal, as the implicit
        creation would
coverage:
  rule: 'gap: FND-COM-FUL-075'
  transition: covered
  validation: covered
  permission: covered
  edge: 'gap: FND-COM-FUL-075'
  failure: covered
  boundary: covered
  concurrency: 'gap: FND-COM-FUL-075'
  invariant: covered
  interaction: covered
coverage_notes:
  rule: >-
    No scenario specifically isolates this dimension; the coverage finding
    retains the missing proof.
  edge: >-
    No scenario specifically isolates this dimension; the coverage finding
    retains the missing proof.
  concurrency: >-
    No scenario specifically isolates this dimension; the coverage finding
    retains the missing proof.
transition_audit:
  - model: STATE-COM-FUL-001
    from: pending
    to: eligible
    source: >-
      services-commerce:modules/fulfillment/services/persistence/obligations.ts:openGate
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-001
    from: blocked
    to: eligible
    source: 'services-commerce:modules/fulfillment/services/register/gate-evaluation.ts'
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-001
    from: eligible
    to: authorized
    source: >-
      services-commerce:modules/fulfillment/services/persistence/obligations.ts:openGate
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-001
    from: pending
    to: blocked
    source: >-
      services-commerce:modules/fulfillment/services/persistence/obligations.ts:recordGateEvaluation,placeStaffHold
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-001
    from: pending
    to: cancelled
    source: 'services-commerce:docs/migrations/obligation-register/README.md#D-P4-03'
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-001
    from: blocked
    to: cancelled
    source: 'services-commerce:docs/migrations/obligation-register/README.md#D-P4-03'
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-001
    from: eligible
    to: cancelled
    source: >-
      services-commerce:modules/fulfillment/services/persistence/obligations.ts:OBLIGATION_TRANSITIONS
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-001
    from: authorized
    to: in_progress
    source: >-
      services-commerce:modules/fulfillment/services/persistence/obligations.ts:recordObligationOutcome
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-001
    from: authorized
    to: completed
    source: >-
      services-commerce:modules/fulfillment/services/persistence/obligations.ts:recordObligationOutcome,completeObligationManually
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-001
    from: in_progress
    to: completed
    source: >-
      services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#completes
      every unit’s obligation through the register (the allocation as the
      record), and emits one deferred cost relief fact per item
    coverage: covered
    scenarios:
      - ATS-COM-FUL-004-12
      - ATS-COM-FUL-012-10
      - ATS-COM-FUL-013-10
      - ATS-COM-FUL-014-01
      - ATS-COM-FUL-014-06
      - ATS-COM-FUL-014-07
      - ATS-COM-FUL-018-08
  - model: STATE-COM-FUL-001
    from: authorized
    to: failed
    source: >-
      services-commerce:modules/fulfillment/tests/integration/services/register/obligation-worker.integration.spec.js#fails
      the obligation with the participant’s code, raises obligation_failed, and
      acknowledges the item
    coverage: covered
    scenarios:
      - ATS-COM-FUL-004-04
  - model: STATE-COM-FUL-001
    from: in_progress
    to: failed
    source: >-
      services-commerce:modules/fulfillment/services/register/register-sweeper.ts:sweepRegister
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-001
    from: failed
    to: authorized
    source: >-
      services-commerce:modules/fulfillment/tests/e2e/obligation-register.e2e.spec.js#re-authorizes
      the failed obligation at sequence two, which the participant fails again,
      then resolves it with its exceptions
    coverage: covered
    scenarios:
      - ATS-COM-FUL-005-04
  - model: STATE-COM-FUL-001
    from: failed
    to: resolved
    source: >-
      services-commerce:modules/fulfillment/services/register/obligation-interventions.ts:resolveObligationByStaff
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-001
    from: completed
    to: superseded
    source: >-
      services-commerce:modules/fulfillment/services/persistence/obligations.ts:OBLIGATION_TRANSITIONS
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-009
    from: held
    to: committed
    source: >-
      services-commerce:modules/inventory/db/inventory-allocations.table.ts
      (commerce_commit_claims)
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-009
    from: held
    to: released
    source: >-
      services-commerce:modules/inventory/services/persistence/inventory-allocations.ts:expireHolds
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-009
    from: committed
    to: picked
    source: >-
      services-commerce:modules/inventory/services/persistence/inventory-allocations.ts:pickUnitsOfLine
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-009
    from: backordered
    to: committed
    source: >-
      services-commerce:modules/inventory/services/persistence/inventory-allocations.ts:fillBackorders
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-009
    from: picked
    to: shipped
    source: >-
      services-commerce:modules/inventory/services/persistence/inventory-allocations.ts:shipUnits
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-009
    from: committed
    to: released
    source: >-
      services-commerce:modules/inventory/services/persistence/inventory-allocations.ts:releaseFencedUnitsOfLine
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-009
    from: picked
    to: released
    source: >-
      services-commerce:docs/migrations/inventory/README.md (D-P7-24 amendment
      of D-P8I-13)
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
  - model: STATE-COM-FUL-009
    from: backordered
    to: released
    source: >-
      services-commerce:modules/inventory/db/inventory-allocations.table.ts
      (commerce_release_claims)
    coverage: 'gap: FND-COM-FUL-075'
    scenarios: []
permission_audit:
  - key: commerce.inventory.bulk
    where_checked: api
    coverage: 'gap: FND-COM-FUL-075'
    note: >-
      Per-key positive and negative coverage is not separately mapped;
      permission scenarios retain the observed aggregate tests.
  - key: commerce.inventory.update
    where_checked: api
    coverage: 'gap: FND-COM-FUL-075'
    note: >-
      Per-key positive and negative coverage is not separately mapped;
      permission scenarios retain the observed aggregate tests.
related_audit:
  - capability: CAP-COM-FUL-017
    scenarios:
      - ATS-COM-FUL-020-10
invariant_audit:
  - invariant: INV-DOM-COM-FUL-001-01
    scenarios:
      - ATS-COM-FUL-004-07
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/fulfillment/db/obligations.table.ts:obligations_subject_uq
  - invariant: INV-DOM-COM-FUL-001-02
    scenarios:
      - ATS-COM-FUL-004-07
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/fulfillment/services/persistence/obligations.ts:OBLIGATION_TRANSITIONS;
      db/migrations/20261018004016_obligation_register.sql:refuse_obligation_regression
  - invariant: INV-DOM-COM-FUL-001-03
    scenarios:
      - ATS-COM-FUL-004-07
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/fulfillment/db/obligations.table.ts:obligations_authorization_state_check
  - invariant: INV-DOM-COM-FUL-001-04
    scenarios:
      - ATS-COM-FUL-004-03
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/fulfillment/db/obligations.table.ts:obligations_quantity_check
  - invariant: INV-DOM-COM-FUL-001-05
    scenarios:
      - ATS-COM-FUL-002-08
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/fulfillment/services/persistence/obligations.ts:openGate
  - invariant: INV-DOM-COM-FUL-001-06
    scenarios:
      - ATS-COM-FUL-004-02
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/fulfillment/services/persistence/obligations.ts:recordObligationOutcome
  - invariant: INV-DOM-COM-FUL-001-07
    scenarios:
      - ATS-COM-FUL-005-02
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/fulfillment/db/obligation-attempts.table.ts;
      modules/fulfillment/db/intervention-logs.table.ts (UPDATE, DELETE and
      TRUNCATE revoked)
  - invariant: INV-DOM-COM-FUL-001-08
    scenarios:
      - ATS-COM-FUL-005-02
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/fulfillment/services/register/obligation-interventions.ts
  - invariant: INV-DOM-COM-FUL-001-09
    scenarios:
      - ATS-COM-FUL-005-03
    coverage: covered
    provenance: test
    source: >-
      services-commerce:docs/migrations/obligation-register/README.md#D-P4-16
      (obligation-register.e2e five simultaneous approvals)
  - invariant: INV-DOM-COM-FUL-001-10
    scenarios:
      - ATS-COM-FUL-006-03
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/fulfillment/db/enforcements.table.ts:enforcements_cause_uq
  - invariant: INV-DOM-COM-FUL-001-11
    scenarios:
      - ATS-COM-FUL-002-07
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/fulfillment/services/facts/financial-facts-handler.ts
  - invariant: INV-DOM-COM-FUL-001-12
    scenarios: []
    coverage: 'gap: FND-COM-FUL-075'
    provenance: observed
    source: >-
      services-commerce:modules/fulfillment/db/obligations.table.ts (composite
      RESTRICT keys)
  - invariant: INV-DOM-COM-FUL-005-01
    scenarios:
      - ATS-COM-FUL-017-02
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/inventory/db/inventory-items.table.ts (column
      grants, apply_inventory_movement, apply_inventory_allocation)
  - invariant: INV-DOM-COM-FUL-005-02
    scenarios:
      - ATS-COM-FUL-017-02
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/inventory/db/inventory-items.table.ts:inventory_items_balances_check
  - invariant: INV-DOM-COM-FUL-005-03
    scenarios:
      - ATS-COM-FUL-017-01
      - ATS-COM-FUL-017-02
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/inventory/db/inventory-movements.table.ts:inventory_movements_quantity_sign_check
  - invariant: INV-DOM-COM-FUL-005-04
    scenarios:
      - ATS-COM-FUL-017-03
    coverage: covered
    provenance: documented
    source: 'services-commerce:docs/migrations/inventory/README.md#D-P8I-22'
  - invariant: INV-DOM-COM-FUL-005-05
    scenarios:
      - ATS-COM-FUL-018-05
    coverage: covered
    provenance: observed
    source: 'services-commerce:modules/inventory/db/inventory-allocations.table.ts'
  - invariant: INV-DOM-COM-FUL-005-06
    scenarios:
      - ATS-COM-FUL-018-03
    coverage: covered
    provenance: documented
    source: 'services-commerce:docs/migrations/inventory/README.md#D-P8I-21'
  - invariant: INV-DOM-COM-FUL-005-07
    scenarios:
      - ATS-COM-FUL-014-01
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/inventory/services/persistence/inventory-allocations.ts:shipUnits
  - invariant: INV-DOM-COM-FUL-005-08
    scenarios:
      - ATS-COM-FUL-017-05
    coverage: covered
    provenance: observed
    source: 'services-commerce:modules/inventory/services/stock/transfer-stock.ts'
  - invariant: INV-DOM-COM-FUL-005-09
    scenarios:
      - ATS-COM-FUL-017-04
    coverage: covered
    provenance: observed
    source: 'services-commerce:modules/inventory/services/stock/staff-movements.ts'
  - invariant: INV-DOM-COM-FUL-005-10
    scenarios:
      - ATS-COM-FUL-019-01
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/inventory/services/persistence/inventory-counts.ts:completeCount
  - invariant: INV-DOM-COM-FUL-005-11
    scenarios:
      - ATS-COM-FUL-019-02
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/inventory/db/inventory-exceptions.table.ts:inventory_exceptions_open_uidx
  - invariant: INV-DOM-COM-FUL-005-12
    scenarios:
      - ATS-COM-FUL-016-06
      - ATS-COM-FUL-017-09
      - ATS-COM-FUL-018-12
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/inventory/services/persistence/warehouses.ts;
      inventory-locations.ts
---

# Import Commerce history and reconcile source records: Capability Test Specification

## Coverage

The category map distinguishes available cases from missing proof. A covered category has a scenario; the lifecycle and permission audits retain gaps in exhaustive coverage. Proposed cases describe the intended verification and carry no execution result.

| Rule | Scenarios |
|---|---|
| `BR-CAP-COM-FUL-020-02` | `ATS-COM-FUL-020-01` |
| `BR-CAP-COM-FUL-020-03` | `ATS-COM-FUL-020-01` |
| `BR-CAP-COM-FUL-020-04` | `ATS-COM-FUL-020-02` |
| `BR-CAP-COM-FUL-020-05` | `ATS-COM-FUL-020-02` |
| `BR-CAP-COM-FUL-020-06` | `ATS-COM-FUL-020-03` |
| `BR-CAP-COM-FUL-020-07` | `ATS-COM-FUL-020-04` |
| `BR-CAP-COM-FUL-020-08` | `ATS-COM-FUL-020-05` |
| `BR-CAP-COM-FUL-020-09` | `ATS-COM-FUL-020-06` |
| `BR-CAP-COM-FUL-020-10` | `ATS-COM-FUL-020-07` |
| `BR-CAP-COM-FUL-020-11` | `ATS-COM-FUL-020-08`, `ATS-COM-FUL-020-11` |
| `BR-CAP-COM-FUL-020-12` | `ATS-COM-FUL-020-09`, `ATS-COM-FUL-020-10` |

## Interactions With Related Capabilities

The interaction cases exercise keep stock movements and transfers accountable. They vary the upstream record or outcome and inspect the resulting work across the capability boundary. Workflow crossings also include stock, financial or application records when the flow depends on them. Existing test bindings retain their source anchors so a reviewer can distinguish supporting assertions from a complete workflow run.
