---
id: ATS-COM-FUL-004
scope: CAP-COM-FUL-004
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-004-01
    title: Dispatch removes only queue-accepted entries
    level: api
    proves:
      - BR-CAP-COM-FUL-004-01
      - BR-CAP-COM-FUL-004-02
    preconditions: Three authorizations span two workspaces and one publication is rejected.
    steps: Dispatch twice and separately exercise a thrown publish.
    expected: >-
      Accepted entries disappear, rejected work remains for the next run and a
      thrown publish preserves its entries.
    negative: false
    data_needs: Fixtures for dispatch removes only queue-accepted entries.
    bound_to:
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/obligation-dispatcher.integration.spec.js#claims
        the three rows of both tenants, publishes a pointer for each, and
        reports the refused one
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/obligation-dispatcher.integration.spec.js#deletes
        the accepted rows and leaves the refused one
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/obligation-dispatcher.integration.spec.js#leaves
        every row for the next run
      - >-
        services-commerce:modules/fulfillment/tests/unit/register/obligation-queue.spec.js#is
        a pointer: the version, the tenant, the obligation and the
        authorization, and nothing of the row’s content
      - TST-COM-FUL-044
      - TST-COM-FUL-055
    provenance: test
    source: >-
      services-commerce:modules/fulfillment/tests/integration/services/register/obligation-dispatcher.integration.spec.js#claims
      the three rows of both tenants, publishes a pointer for each, and reports
      the refused one
    category: failure
  - id: ATS-COM-FUL-004-02
    title: Old delivery pointers retain the completed result
    level: api
    proves:
      - BR-CAP-COM-FUL-004-03
      - INV-DOM-COM-FUL-001-06
    preconditions: An obligation has completed under its current authorization.
    steps: Replay that pointer and a pointer using an obsolete authorization.
    expected: >-
      Each is acknowledged with a stale attempt while the delivery result
      remains unchanged.
    negative: true
    data_needs: Fixtures for old delivery pointers retain the completed result.
    bound_to:
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/obligation-worker.integration.spec.js#acknowledges
        a redelivery of the same item as stale, writing one stale attempt and
        nothing else (A17)
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/obligation-worker.integration.spec.js#junk,
        and an item whose authorization is not the obligation’s current one
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/persistence/obligation-register.integration.spec.js#answers
        a repeat as not in flight with a stale attempt, changing nothing (A17)
      - TST-COM-FUL-045
      - TST-COM-FUL-040
    provenance: test
    source: >-
      services-commerce:modules/fulfillment/tests/integration/services/register/obligation-worker.integration.spec.js#acknowledges
      a redelivery of the same item as stale, writing one stale attempt and
      nothing else (A17)
    category: edge
  - id: ATS-COM-FUL-004-03
    title: Completion tracks partial quantities and rejects excess
    level: api
    proves:
      - BR-CAP-COM-FUL-004-04
      - INV-DOM-COM-FUL-001-04
    preconditions: One obligation owes three units.
    steps: 'Complete one unit, complete the remainder and attempt excess completion.'
    expected: >-
      Progress advances from one to three units and excess completion is
      rejected.
    negative: false
    data_needs: Fixtures for completion tracks partial quantities and rejects excess.
    bound_to:
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/persistence/obligation-register.integration.spec.js#records
        partial completion as in progress with the units, then completes when
        the rest arrive
      - >-
        services-commerce:modules/fulfillment/tests/integration/db/obligations.table.integration.spec.js#refuses
        more completed than owed, and an operation or state outside the
        contract, by their checks
      - TST-COM-FUL-040
      - TST-COM-FUL-024
    provenance: test
    source: >-
      services-commerce:modules/fulfillment/tests/integration/services/persistence/obligation-register.integration.spec.js#records
      partial completion as in progress with the units, then completes when the
      rest arrive
    category: boundary
  - id: ATS-COM-FUL-004-04
    title: Delivery failures distinguish retry from exhaustion
    level: api
    proves:
      - BR-CAP-COM-FUL-004-05
      - BR-CAP-COM-FUL-004-06
    preconditions: 'Applications permanently refuse, temporarily refuse or cannot be reached.'
    steps: Invoke each path and deliver the retrying work five times.
    expected: >-
      Permanent failure produces an exception; retrying work remains in flight
      until final exhaustion.
    negative: true
    data_needs: Fixtures for delivery failures distinguish retry from exhaustion.
    bound_to:
      - >-
        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
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/obligation-worker.integration.spec.js#reports
        the item failed on receives one to four, leaving the obligation in
        flight with the attempts counted
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/obligation-worker.integration.spec.js#fails
        it attempts_exhausted on the fifth receive, raises the exception, and
        still reports the item failed so the queue dead-letters it
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/obligation-worker.integration.spec.js#logs
        an unavailable attempt and reports the item failed, leaving the
        obligation authorized
      - TST-COM-FUL-045
    provenance: test
    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
    category: failure
  - id: ATS-COM-FUL-004-05
    title: Callbacks finish long-running delivery under current authority
    level: api
    proves:
      - BR-CAP-COM-FUL-004-07
      - BR-CAP-COM-FUL-004-08
    preconditions: The application has returned an in-progress answer.
    steps: >-
      Complete by callback, repeat it and try obsolete authorization and reader
      credentials.
    expected: >-
      Completion occurs once, repetition returns its result and invalid callers
      or authorizations are rejected.
    negative: false
    data_needs: >-
      Fixtures for callbacks finish long-running delivery under current
      authority.
    bound_to:
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-register.e2e.spec.js#completes
        the obligation and answers it as it stands; the repeat answers the same
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-register.e2e.spec.js#refuses
        a callback under an authorization that is not the current one, 409
        authorization_not_current
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-register.e2e.spec.js#refuses
        the callback routes to a console reader (403) and to a portal member,
        and a body outside the contract 400
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/obligation-worker.integration.spec.js#leaves
        the obligation in progress with a deadline, then the callback completes
        it; a repeat of the callback answers the same
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-register.e2e.spec.js#records
        the participant’s prerequisite once and answers the obligation
      - TST-COM-FUL-022
      - TST-COM-FUL-045
    provenance: test
    source: >-
      services-commerce:modules/fulfillment/tests/e2e/obligation-register.e2e.spec.js#completes
      the obligation and answers it as it stands; the repeat answers the same
    category: permission
  - id: ATS-COM-FUL-004-06
    title: Acknowledgement expiry permits one redispatch
    level: api
    proves:
      - BR-CAP-COM-FUL-004-09
    preconditions: Delivery has passed its acknowledgement deadline.
    steps: Sweep after the first expiry and after the extended deadline.
    expected: 'Work is sent again once, then fails for lost acknowledgement.'
    negative: false
    data_needs: Fixtures for acknowledgement expiry permits one redispatch.
    bound_to:
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/register-sweeper.integration.spec.js#re-dispatches
        the overdue authorization once, moving its deadline on, and leaves the
        other
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/register-sweeper.integration.spec.js#fails
        it ack_lost on the next deadline, with the exception raised and the
        history line written
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/persistence/obligation-register.integration.spec.js#re-dispatches
        an in-flight authorization once, extending the deadline, and refuses the
        second time
      - TST-COM-FUL-047
      - TST-COM-FUL-040
    provenance: test
    source: >-
      services-commerce:modules/fulfillment/tests/integration/services/register/register-sweeper.integration.spec.js#re-dispatches
      the overdue authorization once, moving its deadline on, and leaves the
      other
    category: transition
  - id: ATS-COM-FUL-004-07
    title: Database guards preserve legal obligation states
    level: api
    proves:
      - BR-CAP-COM-FUL-004-10
      - BR-CAP-COM-FUL-004-11
      - INV-DOM-COM-FUL-001-01
      - INV-DOM-COM-FUL-001-02
      - INV-DOM-COM-FUL-001-03
    preconditions: The register contains fixtures for each lifecycle state.
    steps: Write invalid transitions and duplicate unit obligations directly.
    expected: The database refuses every invalid transition and duplicate identity.
    negative: true
    data_needs: Fixtures for database guards preserve legal obligation states.
    bound_to:
      - >-
        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)
      - >-
        services-commerce:modules/fulfillment/tests/integration/db/register-tables.table.integration.spec.js#allows
        blocked to cancelled (D-P4-03) and failed to resolved, then nothing out
        of either
      - >-
        services-commerce:modules/fulfillment/tests/integration/db/register-tables.table.integration.spec.js#refuses
        an authorized or in-progress obligation without its authorization
        (obligations_authorization_state_check)
      - >-
        services-commerce:modules/fulfillment/tests/integration/db/obligations.table.integration.spec.js#refuses
        moving a completed obligation anywhere but superseded, SQLSTATE RHC02,
        and lets it be superseded
      - >-
        services-commerce:modules/fulfillment/tests/integration/db/obligations.table.integration.spec.js#refuses
        a second obligation for the same subject, operation and unit, by
        obligations_subject_uq
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/persistence/obligations.integration.spec.js#answers
        the rows that exist to a retry, creating nothing twice
      - TST-COM-FUL-025
      - TST-COM-FUL-024
      - TST-COM-FUL-041
    provenance: test
    source: >-
      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)
    category: invariant
  - id: ATS-COM-FUL-004-08
    title: Membership delivery opens the dependent merchandise gate
    category: interaction
    level: api
    proves:
      - BR-CAP-COM-FUL-002-07
      - BR-CAP-COM-FUL-003-02
      - BR-CAP-COM-FUL-003-03
      - BR-CAP-COM-FUL-004-04
    exercises:
      - CAP-COM-FUL-002
      - CAP-COM-FUL-003
      - CAP-COM-FUL-004
    relies_on:
      - ATS-COM-FUL-002-06
      - ATS-COM-FUL-003-02
      - ATS-COM-FUL-004-03
    preconditions: >-
      A paid cart contains a membership and a member-priced shirt. Both have
      waiting delivery work.
    steps: 'Evaluate payment, deliver the membership and then dispatch the shirt.'
    expected: >-
      The shirt waits before membership completion, records its satisfied
      prerequisite, then completes delivery.
    negative: false
    data_needs: >-
      An isolated workspace with the products, records, authority and quantities
      described in the preconditions.
    bound_to:
      - >-
        services-commerce:modules/fulfillment/tests/e2e/same-cart-grants.e2e.spec.js#delivers
        the membership, meets the T-shirt’s prerequisite with
        order.prerequisite_met on the history, and opens its gate
      - TST-COM-FUL-023
    provenance: test
    source:
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#the
        participant’s prerequisite is waited for, and a child line follows its
        parent unless the policy says not
      - >-
        services-commerce:modules/fulfillment/tests/e2e/same-cart-grants.e2e.spec.js#delivers
        the membership, meets the T-shirt’s prerequisite with
        order.prerequisite_met on the history, and opens its gate
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-register.e2e.spec.js#completes
        the obligation and answers it as it stands; the repeat answers the same
  - id: ATS-COM-FUL-004-09
    title: Authorization reaches its application once despite a replayed pointer
    category: interaction
    level: api
    proves:
      - BR-CAP-COM-FUL-002-09
      - BR-CAP-COM-FUL-004-03
    exercises:
      - CAP-COM-FUL-002
      - CAP-COM-FUL-004
    relies_on:
      - ATS-COM-FUL-002-07
      - ATS-COM-FUL-004-02
    preconditions: An accepted paid order has a waiting obligation.
    steps: >-
      Evaluate payment and replay its event, dispatch the instruction, complete
      it and replay its pointer.
    expected: One authorization remains and replay retains the completed result.
    negative: false
    data_needs: >-
      An isolated workspace with the products, records, authority and quantities
      described in the preconditions.
    bound_to:
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-register.e2e.spec.js#is
        idempotent on the event id: the batch redelivered answers succeeded,
        evaluates nothing and opens nothing
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-register.e2e.spec.js#answers
        failed with the error for an event whose evaluation threw, and leaves no
        receipt, so its redelivery evaluates
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-register.e2e.spec.js#answers
        succeeded for every event, the unknown tenant and the unsold line among
        them, and applies the four
      - TST-COM-FUL-022
    provenance: test
    source:
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-register.e2e.spec.js#is
        idempotent on the event id: the batch redelivered answers succeeded,
        evaluates nothing and opens nothing
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/obligation-worker.integration.spec.js#acknowledges
        a redelivery of the same item as stale, writing one stale attempt and
        nothing else (A17)
  - id: ATS-COM-FUL-004-10
    title: Manual completion closes application delivery before a late callback
    category: interaction
    level: api
    proves:
      - BR-CAP-COM-FUL-004-07
      - BR-CAP-COM-FUL-005-07
    exercises:
      - CAP-COM-FUL-004
      - CAP-COM-FUL-005
    relies_on:
      - ATS-COM-FUL-004-05
      - ATS-COM-FUL-005-06
    preconditions: >-
      An application left the authorized obligation in progress. Staff have
      manual-completion authority.
    steps: >-
      Complete with a reason and evidence, then send the application callback
      using the earlier authorization.
    expected: The recorded manual result remains and the late callback fails.
    negative: true
    data_needs: >-
      An isolated workspace with the products, records, authority and quantities
      described in the preconditions.
    bound_to:
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-holds.e2e.spec.js#refuses
        the manual completion without the evidence (400) and to a reader (403),
        then completes it with the records and the note
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-holds.e2e.spec.js#refuses
        the participant’s late callback as not in flight, leaving the manual
        completion
      - TST-COM-FUL-021
    provenance: test
    source:
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-register.e2e.spec.js#completes
        the obligation and answers it as it stands; the repeat answers the same
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-holds.e2e.spec.js#refuses
        the manual completion without the evidence (400) and to a reader (403),
        then completes it with the records and the note
  - id: ATS-COM-FUL-004-11
    title: >-
      Reversal enforcement completes beside the original delivery and remains
      reviewable
    category: interaction
    level: api
    proves:
      - BR-CAP-COM-FUL-004-04
      - BR-CAP-COM-FUL-006-02
      - BR-CAP-COM-FUL-006-03
      - BR-CAP-COM-FUL-008-01
    exercises:
      - CAP-COM-FUL-004
      - CAP-COM-FUL-006
      - CAP-COM-FUL-008
    relies_on:
      - ATS-COM-FUL-004-03
      - ATS-COM-FUL-006-01
      - ATS-COM-FUL-008-01
    preconditions: >-
      A delivered membership uses suspension on reversal and a delivered seat
      uses staff review.
    steps: >-
      Reverse their payments, dispatch the acting instruction, and inspect the
      review queue.
    expected: >-
      The membership is suspended beside its unchanged delivery result; the seat
      remains a staff review.
    negative: false
    data_needs: >-
      An isolated workspace with the products, records, authority and quantities
      described in the preconditions.
    bound_to:
      - >-
        services-commerce:modules/fulfillment/tests/e2e/enforcement.e2e.spec.js#suspends
        the membership in the participant with the enforcement id stored, the
        original obligation still completed, the enforcement completed
      - TST-COM-FUL-018
    provenance: test
    source:
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-register.e2e.spec.js#completes
        the obligation and answers it as it stands; the repeat answers the same
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/enforcement/enforcement-handler.integration.spec.js#creates
        four enforcements: three dispatched (suspend, cancel_line, notify), one
        for a person (review); the none policy and the pending obligation get
        nothing
      - >-
        services-commerce:modules/operations/tests/e2e/operations.e2e.spec.js#lists
        the finding the reconciler raised about the unbilled order, filtered by
        kind, state and order, and never another tenant’s
  - id: ATS-COM-FUL-004-12
    title: Warehouse departure supplies the physical application outcome
    category: interaction
    level: api
    proves:
      - BR-CAP-COM-FUL-004-04
      - BR-CAP-COM-FUL-014-01
      - BR-CAP-COM-FUL-018-05
    exercises:
      - CAP-COM-FUL-004
      - CAP-COM-FUL-014
      - CAP-COM-FUL-018
    relies_on:
      - ATS-COM-FUL-004-03
      - ATS-COM-FUL-014-01
      - ATS-COM-FUL-018-05
    preconditions: >-
      Three picked units have current delivery authorization and a manifested
      shipment.
    steps: >-
      Hand the shipment to its carrier, then inspect allocation units and
      delivery detail.
    expected: >-
      The three units are shipped and their obligations are completed with the
      allocation references.
    negative: false
    data_needs: >-
      An isolated workspace with the products, records, authority and quantities
      described in the preconditions.
    bound_to:
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#hands
        off: the line handed to the carrier with its whole quantity shipped, the
        units shipped in the ledger, one shipment movement of minus three on the
        item, three fewer on hand
      - >-
        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
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#writes
        the shipped quantity on the order line, the order’s shipping_summary
        complete, and the order’s history
      - TST-COM-FUL-078
    provenance: test
    source:
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/persistence/obligation-register.integration.spec.js#records
        partial completion as in progress with the units, then completes when
        the rest arrive
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#hands
        off: the line handed to the carrier with its whole quantity shipped, the
        units shipped in the ledger, one shipment movement of minus three on the
        item, three fewer on hand
      - >-
        services-commerce:modules/inventory/tests/integration/db/inventory-tables.table.integration.spec.js#counts
        a held row against held, a committed one against allocated and a
        released one against nothing, through the trigger
  - id: ATS-COM-FUL-004-13
    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/fulfillment/tests/integration/services/register/obligation-dispatcher.integration.spec.js#claims
        the three rows of both tenants, publishes a pointer for each, and
        reports the refused one
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/obligation-dispatcher.integration.spec.js#deletes
        the accepted rows and leaves the refused one
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/obligation-dispatcher.integration.spec.js#leaves
        every row for the next run
      - >-
        services-commerce:modules/fulfillment/tests/unit/register/obligation-queue.spec.js#is
        a pointer: the version, the tenant, the obligation and the
        authorization, and nothing of the row’s content
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/obligation-worker.integration.spec.js#acknowledges
        a redelivery of the same item as stale, writing one stale attempt and
        nothing else (A17)
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/obligation-worker.integration.spec.js#junk,
        and an item whose authorization is not the obligation’s current one
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/persistence/obligation-register.integration.spec.js#answers
        a repeat as not in flight with a stale attempt, changing nothing (A17)
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/persistence/obligation-register.integration.spec.js#records
        partial completion as in progress with the units, then completes when
        the rest arrive
      - >-
        services-commerce:modules/fulfillment/tests/integration/db/obligations.table.integration.spec.js#refuses
        more completed than owed, and an operation or state outside the
        contract, by their checks
      - >-
        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
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/obligation-worker.integration.spec.js#reports
        the item failed on receives one to four, leaving the obligation in
        flight with the attempts counted
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/obligation-worker.integration.spec.js#fails
        it attempts_exhausted on the fifth receive, raises the exception, and
        still reports the item failed so the queue dead-letters it
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/obligation-worker.integration.spec.js#logs
        an unavailable attempt and reports the item failed, leaving the
        obligation authorized
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-register.e2e.spec.js#completes
        the obligation and answers it as it stands; the repeat answers the same
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-register.e2e.spec.js#refuses
        a callback under an authorization that is not the current one, 409
        authorization_not_current
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-register.e2e.spec.js#refuses
        the callback routes to a console reader (403) and to a portal member,
        and a body outside the contract 400
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/obligation-worker.integration.spec.js#leaves
        the obligation in progress with a deadline, then the callback completes
        it; a repeat of the callback answers the same
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-register.e2e.spec.js#records
        the participant’s prerequisite once and answers the obligation
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/register-sweeper.integration.spec.js#re-dispatches
        the overdue authorization once, moving its deadline on, and leaves the
        other
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/register-sweeper.integration.spec.js#fails
        it ack_lost on the next deadline, with the exception raised and the
        history line written
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/persistence/obligation-register.integration.spec.js#re-dispatches
        an in-flight authorization once, extending the deadline, and refuses the
        second time
      - >-
        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)
      - >-
        services-commerce:modules/fulfillment/tests/integration/db/register-tables.table.integration.spec.js#allows
        blocked to cancelled (D-P4-03) and failed to resolved, then nothing out
        of either
      - >-
        services-commerce:modules/fulfillment/tests/integration/db/register-tables.table.integration.spec.js#refuses
        an authorized or in-progress obligation without its authorization
        (obligations_authorization_state_check)
      - >-
        services-commerce:modules/fulfillment/tests/integration/db/obligations.table.integration.spec.js#refuses
        moving a completed obligation anywhere but superseded, SQLSTATE RHC02,
        and lets it be superseded
      - >-
        services-commerce:modules/fulfillment/tests/integration/db/obligations.table.integration.spec.js#refuses
        a second obligation for the same subject, operation and unit, by
        obligations_subject_uq
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/persistence/obligations.integration.spec.js#answers
        the rows that exist to a retry, creating nothing twice
coverage:
  rule: 'gap: FND-COM-FUL-059'
  transition: covered
  validation: 'gap: FND-COM-FUL-059'
  permission: covered
  edge: covered
  failure: covered
  boundary: covered
  concurrency: 'gap: FND-COM-FUL-059'
  invariant: covered
  interaction: covered
coverage_notes:
  rule: >-
    No scenario specifically isolates this dimension; the coverage finding
    retains the missing proof.
  validation: >-
    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-059'
    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-059'
    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-059'
    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-059'
    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-059'
    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-059'
    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-059'
    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-059'
    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-059'
    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-059'
    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-059'
    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-059'
    scenarios: []
  - model: STATE-COM-FUL-002
    from: pending
    to: dispatched
    source: >-
      services-commerce:modules/fulfillment/tests/integration/services/enforcement/enforcement-handler.integration.spec.js#leaves
      the review enforcement pending with an enforcement_review exception and no
      obligation, and the cancel_line one dispatched with a review for the
      request
    coverage: covered
    scenarios:
      - ATS-COM-FUL-006-01
  - model: STATE-COM-FUL-002
    from: pending
    to: resolved
    source: >-
      services-commerce:modules/operations/services/interventions/operations-interventions.ts
    coverage: 'gap: FND-COM-FUL-059'
    scenarios: []
  - model: STATE-COM-FUL-002
    from: pending
    to: restored
    source: >-
      services-commerce:modules/fulfillment/services/register/obligation-worker.ts:settleEnforcement
    coverage: 'gap: FND-COM-FUL-059'
    scenarios: []
  - model: STATE-COM-FUL-002
    from: dispatched
    to: completed
    source: >-
      services-commerce:modules/fulfillment/tests/integration/services/persistence/enforcements.queries.integration.spec.js#moves
      an enforcement along its lifecycle (pending -> dispatched -> completed ->
      restored) and refuses a move it does not allow
    coverage: covered
    scenarios:
      - ATS-COM-FUL-006-04
  - model: STATE-COM-FUL-002
    from: dispatched
    to: failed
    source: >-
      services-commerce:modules/fulfillment/services/register/register-sweeper.ts:sweepRegister
    coverage: 'gap: FND-COM-FUL-059'
    scenarios: []
  - model: STATE-COM-FUL-002
    from: dispatched
    to: resolved
    source: >-
      services-commerce:modules/fulfillment/services/persistence/enforcements.ts:ENFORCEMENT_TRANSITIONS
    coverage: 'gap: FND-COM-FUL-059'
    scenarios: []
  - model: STATE-COM-FUL-002
    from: failed
    to: dispatched
    source: >-
      services-commerce:modules/fulfillment/services/persistence/enforcements.ts:ENFORCEMENT_TRANSITIONS
    coverage: 'gap: FND-COM-FUL-059'
    scenarios: []
  - model: STATE-COM-FUL-002
    from: failed
    to: resolved
    source: >-
      services-commerce:modules/fulfillment/services/persistence/enforcements.ts:ENFORCEMENT_TRANSITIONS
    coverage: 'gap: FND-COM-FUL-059'
    scenarios: []
  - model: STATE-COM-FUL-002
    from: completed
    to: restored
    source: >-
      services-commerce:modules/fulfillment/services/register/obligation-worker.ts:settleEnforcement
    coverage: 'gap: FND-COM-FUL-059'
    scenarios: []
  - model: STATE-COM-FUL-002
    from: completed
    to: resolved
    source: >-
      services-commerce:modules/fulfillment/services/persistence/enforcements.ts:ENFORCEMENT_TRANSITIONS
    coverage: 'gap: FND-COM-FUL-059'
    scenarios: []
  - model: STATE-COM-FUL-002
    from: resolved
    to: restored
    source: >-
      services-commerce:modules/fulfillment/services/register/obligation-worker.ts:settleEnforcement
    coverage: 'gap: FND-COM-FUL-059'
    scenarios: []
permission_audit:
  - key: commerce.obligations.callback
    where_checked: api
    coverage: 'gap: FND-COM-FUL-059'
    note: >-
      Per-key positive and negative coverage is not separately mapped;
      permission scenarios retain the observed aggregate tests.
related_audit:
  - capability: CAP-COM-FUL-005
    scenarios:
      - ATS-COM-FUL-004-10
  - capability: CAP-COM-FUL-006
    scenarios:
      - ATS-COM-FUL-004-11
  - capability: CAP-COM-FUL-014
    scenarios:
      - ATS-COM-FUL-004-12
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-059'
    provenance: observed
    source: >-
      services-commerce:modules/fulfillment/db/obligations.table.ts (composite
      RESTRICT keys)
---

# Carry authorized work to its delivering application: 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-004-01` | `ATS-COM-FUL-004-01` |
| `BR-CAP-COM-FUL-004-02` | `ATS-COM-FUL-004-01` |
| `BR-CAP-COM-FUL-004-03` | `ATS-COM-FUL-004-02`, `ATS-COM-FUL-004-09` |
| `BR-CAP-COM-FUL-004-04` | `ATS-COM-FUL-004-03`, `ATS-COM-FUL-004-12` |
| `BR-CAP-COM-FUL-004-05` | `ATS-COM-FUL-004-04` |
| `BR-CAP-COM-FUL-004-06` | `ATS-COM-FUL-004-04` |
| `BR-CAP-COM-FUL-004-07` | `ATS-COM-FUL-004-05`, `ATS-COM-FUL-004-08`, `ATS-COM-FUL-004-10`, `ATS-COM-FUL-004-11` |
| `BR-CAP-COM-FUL-004-08` | `ATS-COM-FUL-004-05`, `ATS-COM-FUL-004-08`, `ATS-COM-FUL-004-10`, `ATS-COM-FUL-004-11` |
| `BR-CAP-COM-FUL-004-09` | `ATS-COM-FUL-004-06` |
| `BR-CAP-COM-FUL-004-10` | `ATS-COM-FUL-004-07`, `ATS-COM-FUL-004-13` |
| `BR-CAP-COM-FUL-004-11` | `ATS-COM-FUL-004-07`, `ATS-COM-FUL-004-13` |

## Interactions With Related Capabilities

The interaction cases exercise understand and intervene in an order's delivery; handle financial reversals after delivery; record goods leaving with a carrier or collector. 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.
