---
id: ATS-COM-FUL-002
scope: CAP-COM-FUL-002
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-002-01
    title: Acceptance is required before every delivery condition
    level: unit
    proves:
      - BR-CAP-COM-FUL-002-01
    preconditions: The order is placed but unaccepted.
    steps: 'Evaluate all six financial conditions, including no condition.'
    expected: No condition permits the gate to open before acceptance.
    negative: true
    data_needs: Fixtures for acceptance is required before every delivery condition.
    bound_to:
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#the
        order must be accepted whatever the policy, even none
      - TST-COM-FUL-052
    provenance: test
    source: >-
      services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#the
      order must be accepted whatever the policy, even none
    category: rule
  - id: ATS-COM-FUL-002-02
    title: Human safeguards precede financial eligibility
    level: unit
    proves:
      - BR-CAP-COM-FUL-002-02
    preconditions: An invoiced line has been paid.
    steps: >-
      Evaluate holds, migration, missing approval and failed readiness, then
      supply approval.
    expected: >-
      Human blocks are retained where applicable; approval permits evaluation of
      the remaining conditions.
    negative: false
    data_needs: Fixtures for human safeguards precede financial eligibility.
    bound_to:
      - >-
        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/unit/policies/evaluate-gate.spec.js#an
        approval is asked before the money is looked at, and an approved
        obligation goes on to the money
      - TST-COM-FUL-052
    provenance: test
    source: >-
      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
    category: edge
  - id: ATS-COM-FUL-002-03
    title: Payment evaluation excludes written-off money
    level: unit
    proves:
      - BR-CAP-COM-FUL-002-03
      - BR-CAP-COM-FUL-002-04
    preconditions: A financial position exists for an invoiced line.
    steps: >-
      Vary credits, refunds, write-offs, pending captures and unsettled bank
      debits.
    expected: >-
      The verdict reflects effective paid money and the configured capture and
      settlement safeguards.
    negative: false
    data_needs: Fixtures for payment evaluation excludes written-off money.
    bound_to:
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#a
        write-off never fulfils: a line written off in full stays closed with
        the balance due (08 row 19, B37)
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#a
        credit application counts as paid
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#a
        refund uncounts what was paid
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#nothing
        may be pending capture for paid in full
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#ACH
        counts when accepted by default, and only once settled when the policy
        says so
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/facts/position-view-gate.integration.spec.js#closes
        paid_in_full on ACH pending when the policy waits for settlement,
        subtracting it from the paid money
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/facts/position-view-gate.integration.spec.js#opens
        paid_in_full on the same ACH line when the policy counts ACH once
        accepted
      - TST-COM-FUL-052
      - TST-COM-FUL-029
    provenance: test
    source: >-
      services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#a
      write-off never fulfils: a line written off in full stays closed with the
      balance due (08 row 19, B37)
    category: rule
  - id: ATS-COM-FUL-002-04
    title: Each financial condition opens at its own boundary
    level: unit
    proves:
      - BR-CAP-COM-FUL-002-05
    preconditions: 'Fixtures cover threshold, immediate and unconditional delivery.'
    steps: Evaluate values either side of thresholds and billing states.
    expected: Only facts satisfying the selected condition open its gate.
    negative: false
    data_needs: Fixtures for each financial condition opens at its own boundary.
    bound_to:
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#a
        minimum amount and a minimum percent are met by what was paid, never by
        the balance
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#immediate
        waits for the order to be billed, and none waits for nothing but
        acceptance
      - >-
        services-commerce:modules/fulfillment/tests/e2e/fulfillment-paid-amount.e2e.spec.js#keeps
        the gate closed while less than the amount is paid
      - >-
        services-commerce:modules/fulfillment/tests/e2e/fulfillment-paid-amount.e2e.spec.js#opens
        the gate
      - TST-COM-FUL-052
      - TST-COM-FUL-019
    provenance: test
    source: >-
      services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#a
      minimum amount and a minimum percent are met by what was paid, never by
      the balance
    category: boundary
  - id: ATS-COM-FUL-002-05
    title: Console billing can supply the terms fact
    level: unit
    proves:
      - BR-CAP-COM-FUL-002-06
    preconditions: 'Fixtures include console terms, portal terms and card orders.'
    steps: Evaluate the billed-on-terms classification of each order.
    expected: The qualifying console terms order alone supplies that approval fact.
    negative: false
    data_needs: Fixtures for console billing can supply the terms fact.
    bound_to:
      - >-
        services-commerce:modules/fulfillment/tests/unit/register/order-billed-on-terms.spec.js#is
        a console order whose profile requires terms
      - >-
        services-commerce:modules/fulfillment/tests/unit/register/order-billed-on-terms.spec.js#is
        a console order with a succeeded terms tender
      - >-
        services-commerce:modules/fulfillment/tests/unit/register/order-billed-on-terms.spec.js#is
        not an order whose terms tender is only submitted or declined
      - >-
        services-commerce:modules/fulfillment/tests/unit/register/order-billed-on-terms.spec.js#is
        not a portal order, even on terms
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#approved
        terms satisfy paid in full when the policy allows it, and not otherwise
      - TST-COM-FUL-056
      - TST-COM-FUL-052
    provenance: test
    source: >-
      services-commerce:modules/fulfillment/tests/unit/register/order-billed-on-terms.spec.js#is
      a console order whose profile requires terms
    category: rule
  - id: ATS-COM-FUL-002-06
    title: Parent and readiness dependencies delay eligibility
    level: unit
    proves:
      - BR-CAP-COM-FUL-002-07
    preconditions: >-
      A child follows its parent and another line requires application
      readiness.
    steps: Evaluate before and after parent opening and prerequisite reporting.
    expected: Each dependent gate waits until its applicable prerequisite is satisfied.
    negative: false
    data_needs: Fixtures for parent and readiness dependencies delay eligibility.
    bound_to:
      - >-
        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
      - TST-COM-FUL-052
    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
    category: edge
  - id: ATS-COM-FUL-002-07
    title: Event replay retains idempotence and permits failed evaluation recovery
    level: api
    proves:
      - BR-CAP-COM-FUL-002-09
      - BR-CAP-COM-FUL-002-10
      - INV-DOM-COM-FUL-001-11
    preconditions: A financial batch includes four valid events and an evaluation failure.
    steps: Deliver the batch again and redeliver the event that failed.
    expected: >-
      Previously applied events do not reopen work; failed evaluation is retried
      and unknown references succeed harmlessly.
    negative: false
    data_needs: >-
      Fixtures for event replay retains idempotence and permits failed
      evaluation recovery.
    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
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/persistence/financial-fact-receipts.queries.integration.spec.js#answers
        claimed: false with the first receipt when the same event id is written
        again, and changes nothing
      - TST-COM-FUL-022
      - TST-COM-FUL-032
    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
    category: failure
  - id: ATS-COM-FUL-002-08
    title: Concurrent evaluation creates one delivery authorization
    level: api
    proves:
      - BR-CAP-COM-FUL-002-11
      - INV-DOM-COM-FUL-001-05
    preconditions: A pending obligation has satisfied its financial condition.
    steps: Evaluate opening concurrently on two database connections.
    expected: Exactly one authorization and its dispatch entry remain.
    negative: false
    data_needs: Fixtures for concurrent evaluation creates one delivery authorization.
    bound_to:
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/persistence/obligation-register.integration.spec.js#answers
        the second not waiting once the first committed, and the register holds
        ONE authorization
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/persistence/obligation-register.integration.spec.js#moves
        it to authorized with the authorization at sequence one, issued by the
        gate, the deadline one SLA on, and a fresh attempt count
      - TST-COM-FUL-040
    provenance: test
    source: >-
      services-commerce:modules/fulfillment/tests/integration/services/persistence/obligation-register.integration.spec.js#answers
      the second not waiting once the first committed, and the register holds
      ONE authorization
    category: concurrency
  - id: ATS-COM-FUL-002-09
    title: The stale-work sweep evaluates eligible page candidates
    level: api
    proves:
      - BR-CAP-COM-FUL-002-12
    preconditions: >-
      The selected page contains paid and unpaid obligations without a recent
      event.
    steps: Sweep five minutes after creation and again after eleven minutes.
    expected: >-
      The early sweep leaves them waiting; the later sweep opens paid candidates
      and retains unpaid candidates.
    negative: false
    data_needs: Fixtures for the stale-work sweep evaluates eligible page candidates.
    bound_to:
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/register-sweeper.integration.spec.js#finds
        no stale pending obligation and no overdue authorization, and nudges
        nothing
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/register-sweeper.integration.spec.js#evaluates
        every stale pending obligation of an accepted order across both tenants,
        opens the paid ones, and nudges once
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/register-sweeper.integration.spec.js#leaves
        the unpaid one pending with why, evaluated, and the placed order’s
        untouched
      - TST-COM-FUL-047
    provenance: test
    source: >-
      services-commerce:modules/fulfillment/tests/integration/services/register/register-sweeper.integration.spec.js#finds
      no stale pending obligation and no overdue authorization, and nudges
      nothing
    category: transition
  - id: ATS-COM-FUL-002-10
    title: Percentage rounding rejects the lower fractional boundary
    level: unit
    proves:
      - BR-CAP-COM-FUL-002-14
    preconditions: >-
      An accepted line is invoiced for 101 minor units with a 50 percent
      condition.
    steps: 'Evaluate payment of 50 minor units, then 51.'
    expected: >-
      The lower amount leaves the gate closed and the rounded-up amount opens
      it.
    negative: false
    data_needs: Fixtures for percentage rounding rejects the lower fractional boundary.
    bound_to: []
    provenance: proposed
    source: >-
      services-commerce:modules/fulfillment/services/policies/evaluate-gate.ts:evaluateGate
    category: boundary
  - id: ATS-COM-FUL-002-11
    title: >-
      A changed payment threshold affects the next sale while the placed sale
      keeps its gate
    category: interaction
    level: api
    proves:
      - BR-CAP-COM-FUL-001-04
      - BR-CAP-COM-FUL-002-05
    exercises:
      - CAP-COM-FUL-001
      - CAP-COM-FUL-002
    relies_on:
      - ATS-COM-FUL-001-04
      - ATS-COM-FUL-002-04
    preconditions: >-
      A product requires payment of 100 minor units. One accepted order already
      exists.
    steps: 'Replace the threshold with 200, place another order and pay 100 on both.'
    expected: >-
      Compare the two gate snapshots and verdicts; only the first order is ready
      for delivery.
    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/fulfillment/tests/e2e/fulfillment-policies.e2e.spec.js#freezes
        the product policy on the obligation with the row’s version and source,
        and the replacement changes nothing on it
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#a
        minimum amount and a minimum percent are met by what was paid, never by
        the balance
  - id: ATS-COM-FUL-002-12
    title: Explicit policy application changes the staff-visible waiting gate
    category: interaction
    level: api
    proves:
      - BR-CAP-COM-FUL-001-08
      - BR-CAP-COM-FUL-005-01
      - BR-CAP-COM-FUL-002-12
    exercises:
      - CAP-COM-FUL-001
      - CAP-COM-FUL-005
      - CAP-COM-FUL-002
    relies_on:
      - ATS-COM-FUL-001-06
      - ATS-COM-FUL-005-01
      - ATS-COM-FUL-002-09
    preconditions: >-
      A waiting order uses the earlier product policy. Staff can apply the
      replacement and inspect delivery.
    steps: >-
      Replace the policy, apply it with a reason, read the obligation, and run
      the eligible pending sweep.
    expected: >-
      The detail shows the replacement gate and intervention; the sweep
      evaluates the new condition. Reapplication adds no gate replacement.
    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/fulfillment/tests/e2e/fulfillment-policies.e2e.spec.js#re-freezes
        the pending obligation to the replaced policy with a receipt, records
        the intervention, and re-freezes nothing on a repeat
      - >-
        services-commerce:modules/fulfillment/tests/e2e/obligation-register.e2e.spec.js#lists
        each order’s one pending obligation with the built-in default gate
        frozen on it, and refuses a portal member the register
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/register-sweeper.integration.spec.js#finds
        no stale pending obligation and no overdue authorization, and nudges
        nothing
  - id: ATS-COM-FUL-002-13
    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-002-14
    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-002-15
    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/unit/policies/evaluate-gate.spec.js#the
        order must be accepted whatever the policy, even none
      - >-
        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/unit/policies/evaluate-gate.spec.js#an
        approval is asked before the money is looked at, and an approved
        obligation goes on to the money
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#a
        write-off never fulfils: a line written off in full stays closed with
        the balance due (08 row 19, B37)
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#a
        credit application counts as paid
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#a
        refund uncounts what was paid
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#nothing
        may be pending capture for paid in full
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#ACH
        counts when accepted by default, and only once settled when the policy
        says so
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/facts/position-view-gate.integration.spec.js#closes
        paid_in_full on ACH pending when the policy waits for settlement,
        subtracting it from the paid money
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/facts/position-view-gate.integration.spec.js#opens
        paid_in_full on the same ACH line when the policy counts ACH once
        accepted
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#a
        minimum amount and a minimum percent are met by what was paid, never by
        the balance
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#immediate
        waits for the order to be billed, and none waits for nothing but
        acceptance
      - >-
        services-commerce:modules/fulfillment/tests/e2e/fulfillment-paid-amount.e2e.spec.js#keeps
        the gate closed while less than the amount is paid
      - >-
        services-commerce:modules/fulfillment/tests/e2e/fulfillment-paid-amount.e2e.spec.js#opens
        the gate
      - >-
        services-commerce:modules/fulfillment/tests/unit/register/order-billed-on-terms.spec.js#is
        a console order whose profile requires terms
      - >-
        services-commerce:modules/fulfillment/tests/unit/register/order-billed-on-terms.spec.js#is
        a console order with a succeeded terms tender
      - >-
        services-commerce:modules/fulfillment/tests/unit/register/order-billed-on-terms.spec.js#is
        not an order whose terms tender is only submitted or declined
      - >-
        services-commerce:modules/fulfillment/tests/unit/register/order-billed-on-terms.spec.js#is
        not a portal order, even on terms
      - >-
        services-commerce:modules/fulfillment/tests/unit/policies/evaluate-gate.spec.js#approved
        terms satisfy paid in full when the policy allows it, and not otherwise
      - >-
        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/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
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/persistence/financial-fact-receipts.queries.integration.spec.js#answers
        claimed: false with the first receipt when the same event id is written
        again, and changes nothing
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/persistence/obligation-register.integration.spec.js#answers
        the second not waiting once the first committed, and the register holds
        ONE authorization
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/persistence/obligation-register.integration.spec.js#moves
        it to authorized with the authorization at sequence one, issued by the
        gate, the deadline one SLA on, and a fresh attempt count
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/register-sweeper.integration.spec.js#finds
        no stale pending obligation and no overdue authorization, and nudges
        nothing
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/register-sweeper.integration.spec.js#evaluates
        every stale pending obligation of an accepted order across both tenants,
        opens the paid ones, and nudges once
      - >-
        services-commerce:modules/fulfillment/tests/integration/services/register/register-sweeper.integration.spec.js#leaves
        the unpaid one pending with why, evaluated, and the placed order’s
        untouched
coverage:
  rule: covered
  transition: covered
  validation: 'gap: FND-COM-FUL-057'
  permission: not-applicable
  edge: covered
  failure: covered
  boundary: covered
  concurrency: covered
  invariant: 'gap: FND-COM-FUL-057'
  interaction: covered
coverage_notes:
  validation: >-
    No scenario specifically isolates this dimension; the coverage finding
    retains the missing proof.
  permission: >-
    The capability declares no independent caller permission; permissions on the
    invoking operation remain with its owner.
  invariant: >-
    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-057'
    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-057'
    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-057'
    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-057'
    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-057'
    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-057'
    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-057'
    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-057'
    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-057'
    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-057'
    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-057'
    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-057'
    scenarios: []
permission_audit: []
related_audit:
  - capability: CAP-COM-FUL-003
    scenarios:
      - ATS-COM-FUL-002-13
  - capability: CAP-COM-FUL-004
    scenarios:
      - ATS-COM-FUL-002-13
      - ATS-COM-FUL-002-14
      - ATS-COM-FUL-002-15
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-057'
    provenance: observed
    source: >-
      services-commerce:modules/fulfillment/db/obligations.table.ts (composite
      RESTRICT keys)
  - invariant: INV-DOM-COM-FUL-002-01
    scenarios:
      - ATS-COM-FUL-001-02
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/fulfillment/db/fulfillment-policies.table.ts:fulfillment_policies_scope_uq,fulfillment_policies_tenant_default_uidx,fulfillment_policies_scope_check
  - invariant: INV-DOM-COM-FUL-002-02
    scenarios:
      - ATS-COM-FUL-001-01
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/fulfillment/services/persistence/fulfillment-policies.ts:storedPolicy
  - invariant: INV-DOM-COM-FUL-002-03
    scenarios:
      - ATS-COM-FUL-001-03
    coverage: covered
    provenance: test
    source: >-
      services-commerce:modules/fulfillment/tests/unit/policies/policy-resolution.spec.js#takes
      the product’s policy over the ordering profile’s and the tenant default’s
  - invariant: INV-DOM-COM-FUL-002-04
    scenarios:
      - ATS-COM-FUL-001-04
    coverage: covered
    provenance: test
    source: >-
      services-commerce:modules/fulfillment/tests/e2e/fulfillment-policies.e2e.spec.js#freezes
      the product policy on the obligation with the row’s version and source,
      and the replacement changes nothing on it
  - invariant: INV-DOM-COM-FUL-002-05
    scenarios:
      - ATS-COM-FUL-001-04
    coverage: covered
    provenance: documented
    source: 'services-commerce:docs/migrations/obligation-register/README.md#D-P4-05'
  - invariant: INV-DOM-COM-FUL-002-06
    scenarios:
      - ATS-COM-FUL-001-05
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/fulfillment/services/persistence/fulfillment-policies.ts:updateFulfillmentPolicy
---

# Authorize delivery from current order facts: 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-002-01` | `ATS-COM-FUL-002-01` |
| `BR-CAP-COM-FUL-002-02` | `ATS-COM-FUL-002-02`, `ATS-COM-FUL-002-15` |
| `BR-CAP-COM-FUL-002-03` | `ATS-COM-FUL-002-03` |
| `BR-CAP-COM-FUL-002-04` | `ATS-COM-FUL-002-03` |
| `BR-CAP-COM-FUL-002-05` | `ATS-COM-FUL-002-04`, `ATS-COM-FUL-002-11` |
| `BR-CAP-COM-FUL-002-06` | `ATS-COM-FUL-002-05` |
| `BR-CAP-COM-FUL-002-07` | `ATS-COM-FUL-002-06`, `ATS-COM-FUL-002-13` |
| `BR-CAP-COM-FUL-002-09` | `ATS-COM-FUL-002-07`, `ATS-COM-FUL-002-14` |
| `BR-CAP-COM-FUL-002-10` | `ATS-COM-FUL-002-07`, `ATS-COM-FUL-002-14` |
| `BR-CAP-COM-FUL-002-11` | `ATS-COM-FUL-002-08` |
| `BR-CAP-COM-FUL-002-12` | `ATS-COM-FUL-002-09`, `ATS-COM-FUL-002-12` |
| `BR-CAP-COM-FUL-002-14` | `ATS-COM-FUL-002-10` |

## Interactions With Related Capabilities

The interaction cases exercise protect a member-priced purchase until its membership arrives; carry authorized work to its delivering application. 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.
