---
id: ATS-COM-FUL-013
scope: CAP-COM-FUL-013
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-013-01
    title: Label attempts distinguish purchased and unavailable outcomes
    level: api
    proves:
      - BR-CAP-COM-FUL-013-01
      - BR-CAP-COM-FUL-013-04
    preconditions: A packed UPS parcel and a denied integration binding exist.
    steps: Purchase a label through each binding.
    expected: >-
      Successful work stores tracking and cost; denied work stores failure and a
      later purchase uses attempt two.
    negative: false
    data_needs: >-
      Fixtures for label attempts distinguish purchased and unavailable
      outcomes.
    bound_to:
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#buys
        the first label through UPS under package:<id>:1 (the intent then the
        outcome), the tracking number and the cost on the label, the package
        labelled
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#records
        the refused purchase failed (carrier_unavailable), not in flight, so the
        next purchase buys on attempt 2
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#answers
        a purchase the platform refused before anything ran 503
        carrier_unavailable with the reason, sent once
      - >-
        services-commerce:modules/shipping/tests/integration/db/shipping-tables.table.integration.spec.js#writes
        a label intent once under its key (premise), refuses the same key twice,
        by carrier_labels_idempotency_key_uq, and holds a purchased label to its
        tracking number and instant, by carrier_labels_purchased_check
      - TST-COM-FUL-078
      - TST-COM-FUL-077
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#buys
      the first label through UPS under package:<id>:1 (the intent then the
      outcome), the tracking number and the cost on the label, the package
      labelled
    category: transition
  - id: ATS-COM-FUL-013-02
    title: Uncertain carrier purchases retain their original key
    level: api
    proves:
      - BR-CAP-COM-FUL-013-02
      - INV-DOM-COM-FUL-004-06
    preconditions: UPS accepted a purchase but its response was lost.
    steps: Repeat the purchase while its result remains uncertain.
    expected: >-
      Recovery queries and resends the original key, reports in-flight
      uncertainty and records the found label without another purchase.
    negative: true
    data_needs: Fixtures for uncertain carrier purchases retain their original key.
    bound_to:
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#leaves
        an unknown purchase in flight: the label requested under package:<id>:1,
        the package packed, the uncertainty on the history
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#asks
        the carrier by the key before buying again, then the same purchase under
        the same key, and refuses label_purchase_in_flight while neither settles
        it, buying under no new key
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#settles
        the purchase in flight by the lookup: the label the carrier holds
        recorded on attempt 1, the package labelled, never bought twice
      - >-
        services-commerce:modules/shipping/tests/e2e/shipping.e2e.spec.js#answers
        an unknown purchase 200 with the label still requested, and the next
        purchase 409 label_purchase_in_flight while the carrier cannot say
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#answers
        an unknown purchase as uncertain with the execution, never bought again
      - TST-COM-FUL-078
      - TST-COM-FUL-075
      - TST-COM-FUL-084
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#leaves
      an unknown purchase in flight: the label requested under package:<id>:1,
      the package packed, the uncertainty on the history
    category: failure
  - id: ATS-COM-FUL-013-03
    title: Staff can record a carrier-confirmed in-flight purchase
    level: api
    proves:
      - BR-CAP-COM-FUL-013-03
    preconditions: A manual-carrier label attempt remains in flight.
    steps: Resolve the attempt with the carrier-visible result.
    expected: The attempt becomes purchased and its parcel becomes labelled.
    negative: false
    data_needs: Fixtures for staff can record a carrier-confirmed in-flight purchase.
    bound_to: []
    provenance: proposed
    source: >-
      services-commerce:modules/shipping/services/fulfillment/labels.ts:resolveLabelPurchase
    category: transition
  - id: ATS-COM-FUL-013-04
    title: Manual labels require clerk-supplied information
    level: unit
    proves:
      - BR-CAP-COM-FUL-013-05
    preconditions: A manual carrier account is configured.
    steps: >-
      Try valid details, absent details and fractional cost, then rating, void
      and tracking.
    expected: >-
      Valid details are accepted, invalid purchases fail, rating supplies no
      option and void succeeds without automatic tracking.
    negative: true
    data_needs: Fixtures for manual labels require clerk-supplied information.
    bound_to:
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#answers
        the clerk’s details as the purchased label, under the request’s key
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#fails
        a purchase with no details, not retryable, and one with a cost that is
        not a whole non-negative number
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#rates
        nothing, with the warning that says so
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#voids
        every label and tracks nothing
      - TST-COM-FUL-084
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#answers
      the clerk’s details as the purchased label, under the request’s key
    category: validation
  - id: ATS-COM-FUL-013-05
    title: UPS invocation checks the connection and grant
    level: unit
    proves:
      - BR-CAP-COM-FUL-013-06
      - BR-CAP-COM-FUL-013-07
    preconditions: UPS fixtures include missing connections and invocation authority.
    steps: Exercise granted and ungranted calls and each response class.
    expected: >-
      Only the connected authorized request is sent and each failure retains its
      mapped classification.
    negative: true
    data_needs: Fixtures for uPS invocation checks the connection and grant.
    bound_to:
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#buys
        a label through shipping.label.purchase@1 under the label’s key, the
        shipment as the subject
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#refuses
        an account with no connection as 503 carrier_unavailable, sending
        nothing
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#refuses
        every call 503 carrier_unavailable in a function without the
        integrations_invoke grant, sending nothing
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#answers
        a timeout and a rate limit as failed and retryable
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#answers
        an invalid request as failed and not retryable, the contract’s code as
        it is (never ups_<code>)
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#answers
        a purchase the gateway gave no answer to (IntegrationInvokeFailed) as
        uncertain, so it stays in flight
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#refuses
        a purchase on a disconnected connection (IntegrationInvokeRefused) as
        503 carrier_unavailable, not in flight
      - TST-COM-FUL-084
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#buys
      a label through shipping.label.purchase@1 under the label’s key, the
      shipment as the subject
    category: permission
  - id: ATS-COM-FUL-013-06
    title: Void retries retain distinct attempt outcomes
    level: api
    proves:
      - BR-CAP-COM-FUL-013-09
    preconditions: Purchased labels receive refused and uncertain void responses.
    steps: Void both labels and retry the uncertain result.
    expected: >-
      Refusal retains label cost and a finding, and uncertain recovery uses
      another void key before returning the parcel to packing.
    negative: false
    data_needs: Fixtures for void retries retain distinct attempt outcomes.
    bound_to:
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#keeps
        a void the carrier refused (refused.void_window_closed): the label
        void_failed with its cost, the void_failed finding
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#voids
        the second label through the platform: the label voided, the package
        back to packed
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#voids
        again under the next attempt’s key (void:<label id>:2), each attempt’s
        intent on the history
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#names
        each void attempt by its label and its number (void:<label
        id>:<attempt>), a new key for each attempt
      - TST-COM-FUL-078
      - TST-COM-FUL-084
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#keeps
      a void the carrier refused (refused.void_window_closed): the label
      void_failed with its cost, the void_failed finding
    category: failure
  - id: ATS-COM-FUL-013-07
    title: Tracking completion can finish the shipment
    level: api
    proves:
      - BR-CAP-COM-FUL-013-10
    preconditions: A handed-over shipment contains UPS and manual parcels.
    steps: Request UPS history and enter the manual delivery result.
    expected: Both parcels become delivered and the shipment follows them.
    negative: false
    data_needs: Fixtures for tracking completion can finish the shipment.
    bound_to:
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#tracks
        the UPS package to delivery from the platform’s history, records the
        counter package delivered by hand, and the shipment is delivered once
        both are
      - TST-COM-FUL-078
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#tracks
      the UPS package to delivery from the platform’s history, records the
      counter package delivered by hand, and the shipment is delivered once both
      are
    category: transition
  - id: ATS-COM-FUL-013-08
    title: Pickup rejects carrier-only operations
    level: api
    proves:
      - BR-CAP-COM-FUL-013-11
    preconditions: A pickup shipment has been packed.
    steps: 'Try label purchase, label void, manifest and carrier handoff.'
    expected: Every carrier-only action reports unsupported operation.
    negative: true
    data_needs: Fixtures for pickup rejects carrier-only operations.
    bound_to:
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#refuses
        the carrier’s label purchase, void, manifest and handoff
        operation_not_supported
      - >-
        services-commerce:modules/shipping/tests/e2e/shipping.e2e.spec.js#makes
        a pickup shipment of the paid order, on no carrier, and refuses its
        label 409 operation_not_supported
      - TST-COM-FUL-078
      - TST-COM-FUL-075
    provenance: test
    source: >-
      services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#refuses
      the carrier’s label purchase, void, manifest and handoff
      operation_not_supported
    category: edge
  - id: ATS-COM-FUL-013-09
    title: The account selected by shipping configuration supplies label invocation
    category: interaction
    level: api
    proves:
      - BR-CAP-COM-FUL-010-07
      - BR-CAP-COM-FUL-013-06
    exercises:
      - CAP-COM-FUL-010
      - CAP-COM-FUL-013
    relies_on:
      - ATS-COM-FUL-010-04
      - ATS-COM-FUL-013-05
    preconditions: >-
      A packed carrier shipment references a UPS account connected through the
      integration service.
    steps: >-
      Purchase a label with the invocation grant, then use an account without a
      valid connection or grant.
    expected: >-
      The connected purchase records a label; the invalid configuration makes no
      carrier request.
    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/shipping/tests/integration/db/shipping-tables.table.integration.spec.js#refuses
        a carrier outside the six and a markup above 100 %, by
        carrier_accounts_carrier_check and carrier_accounts_markup_check
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#buys
        a label through shipping.label.purchase@1 under the label’s key, the
        shipment as the subject
  - id: ATS-COM-FUL-013-10
    title: Packing permits label purchase and manifestation before departure
    category: interaction
    level: api
    proves:
      - BR-CAP-COM-FUL-012-04
      - BR-CAP-COM-FUL-012-06
      - BR-CAP-COM-FUL-012-07
      - BR-CAP-COM-FUL-013-01
      - BR-CAP-COM-FUL-014-01
    exercises:
      - CAP-COM-FUL-012
      - CAP-COM-FUL-013
      - CAP-COM-FUL-014
    relies_on:
      - ATS-COM-FUL-012-04
      - ATS-COM-FUL-013-01
      - ATS-COM-FUL-014-01
    preconditions: An authorized merchandise order has released warehouse work.
    steps: 'Pick, pack, purchase labels for every parcel, manifest and hand off.'
    expected: >-
      Parcel preparation reaches labelled and manifested states before the
      shipment leaves; departure completes its units.
    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#releases
        the shipment to the floor and lists its line for picking at the bin the
        ledger names, the shipment picking
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#records
        the pick: the list line picked, the shipment line picked with its
        quantity, the shipment picked
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#packs
        the three units into two parcels, the second weighed from nothing (the
        shirt has no weight), the line packed, the shipment packed with two
        packages
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#buys
        the first label through UPS under package:<id>:1 (the intent then the
        outcome), the tracking number and the cost on the label, the package
        labelled
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#records
        the refused purchase failed (carrier_unavailable), not in flight, so the
        next purchase buys on attempt 2
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#answers
        a purchase the platform refused before anything ran 503
        carrier_unavailable with the reason, sent once
      - >-
        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/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#releases
        the shipment to the floor and lists its line for picking at the bin the
        ledger names, the shipment picking
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#buys
        the first label through UPS under package:<id>:1 (the intent then the
        outcome), the tracking number and the cost on the label, the package
        labelled
      - >-
        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
  - id: ATS-COM-FUL-013-11
    title: Return-label preparation uses the outbound carrier choice
    category: interaction
    level: api
    proves:
      - BR-CAP-COM-FUL-015-09
      - BR-CAP-COM-FUL-013-01
    exercises:
      - CAP-COM-FUL-015
      - CAP-COM-FUL-013
    relies_on:
      - ATS-COM-FUL-015-06
      - ATS-COM-FUL-013-01
    preconditions: >-
      An issued return permits a label and identifies an outbound carrier
      account.
    steps: >-
      Prepare the incoming shipment and purchase its label, then withdraw an
      unreceived return.
    expected: >-
      The incoming parcel uses the selected account and warehouse destination;
      withdrawal pulls its parcel.
    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/shipping/tests/integration/services/returns/return-receiving.integration.spec.js#makes
        the return_label shipment of the three shipped units, packed in one
        parcel, addressed to the warehouse, labelled through UPS from the
        customer’s address
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#buys
        the first label through UPS under package:<id>:1 (the intent then the
        outcome), the tracking number and the cost on the label, the package
        labelled
evidence:
  - repository: services-commerce
    tests:
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#buys
        the first label through UPS under package:<id>:1 (the intent then the
        outcome), the tracking number and the cost on the label, the package
        labelled
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#records
        the refused purchase failed (carrier_unavailable), not in flight, so the
        next purchase buys on attempt 2
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#answers
        a purchase the platform refused before anything ran 503
        carrier_unavailable with the reason, sent once
      - >-
        services-commerce:modules/shipping/tests/integration/db/shipping-tables.table.integration.spec.js#writes
        a label intent once under its key (premise), refuses the same key twice,
        by carrier_labels_idempotency_key_uq, and holds a purchased label to its
        tracking number and instant, by carrier_labels_purchased_check
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#leaves
        an unknown purchase in flight: the label requested under package:<id>:1,
        the package packed, the uncertainty on the history
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#asks
        the carrier by the key before buying again, then the same purchase under
        the same key, and refuses label_purchase_in_flight while neither settles
        it, buying under no new key
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#settles
        the purchase in flight by the lookup: the label the carrier holds
        recorded on attempt 1, the package labelled, never bought twice
      - >-
        services-commerce:modules/shipping/tests/e2e/shipping.e2e.spec.js#answers
        an unknown purchase 200 with the label still requested, and the next
        purchase 409 label_purchase_in_flight while the carrier cannot say
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#answers
        an unknown purchase as uncertain with the execution, never bought again
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#answers
        the clerk’s details as the purchased label, under the request’s key
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#fails
        a purchase with no details, not retryable, and one with a cost that is
        not a whole non-negative number
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#rates
        nothing, with the warning that says so
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#voids
        every label and tracks nothing
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#buys
        a label through shipping.label.purchase@1 under the label’s key, the
        shipment as the subject
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#refuses
        an account with no connection as 503 carrier_unavailable, sending
        nothing
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#refuses
        every call 503 carrier_unavailable in a function without the
        integrations_invoke grant, sending nothing
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#answers
        a timeout and a rate limit as failed and retryable
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#answers
        an invalid request as failed and not retryable, the contract’s code as
        it is (never ups_<code>)
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#answers
        a purchase the gateway gave no answer to (IntegrationInvokeFailed) as
        uncertain, so it stays in flight
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#refuses
        a purchase on a disconnected connection (IntegrationInvokeRefused) as
        503 carrier_unavailable, not in flight
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#keeps
        a void the carrier refused (refused.void_window_closed): the label
        void_failed with its cost, the void_failed finding
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#voids
        the second label through the platform: the label voided, the package
        back to packed
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#voids
        again under the next attempt’s key (void:<label id>:2), each attempt’s
        intent on the history
      - >-
        services-commerce:modules/shipping/tests/unit/carriers/carrier-adapters.spec.js#names
        each void attempt by its label and its number (void:<label
        id>:<attempt>), a new key for each attempt
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#tracks
        the UPS package to delivery from the platform’s history, records the
        counter package delivered by hand, and the shipment is delivered once
        both are
      - >-
        services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#refuses
        the carrier’s label purchase, void, manifest and handoff
        operation_not_supported
      - >-
        services-commerce:modules/shipping/tests/e2e/shipping.e2e.spec.js#makes
        a pickup shipment of the paid order, on no carrier, and refuses its
        label 409 operation_not_supported
  - repository: react-console
    tests: []
coverage:
  rule: 'gap: FND-COM-FUL-068'
  transition: covered
  validation: covered
  permission: covered
  edge: covered
  failure: covered
  boundary: 'gap: FND-COM-FUL-068'
  concurrency: 'gap: FND-COM-FUL-068'
  invariant: 'gap: FND-COM-FUL-068'
  interaction: covered
coverage_notes:
  rule: >-
    No scenario specifically isolates this dimension; the coverage finding
    retains the missing proof.
  boundary: >-
    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.
  invariant: >-
    No scenario specifically isolates this dimension; the coverage finding
    retains the missing proof.
transition_audit:
  - model: STATE-COM-FUL-005
    from: open
    to: released
    source: >-
      services-commerce:modules/shipping/services/fulfillment/shipment-creation.ts:releaseShipment
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: released
    to: picking
    source: >-
      services-commerce:modules/shipping/services/fulfillment/picking.ts:createPickListForWarehouse
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: picking
    to: picked
    source: >-
      services-commerce:modules/shipping/services/fulfillment/picking.ts:recordPickOnList
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: picked
    to: packing
    source: >-
      services-commerce:modules/shipping/services/fulfillment/packing.ts:packShipment
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: picked
    to: packed
    source: >-
      services-commerce:modules/shipping/services/fulfillment/packing.ts:packShipment
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: packing
    to: packed
    source: >-
      services-commerce:modules/shipping/services/fulfillment/packing.ts:packShipment
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: packed
    to: labelled
    source: >-
      services-commerce:modules/shipping/services/fulfillment/labels.ts:purchaseLabelForPackage
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: labelled
    to: packed
    source: >-
      services-commerce:modules/shipping/services/fulfillment/labels.ts:voidLabelOfPackage
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: labelled
    to: manifested
    source: >-
      services-commerce:modules/shipping/services/fulfillment/handoff.ts:manifestShipment
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: manifested
    to: handed_to_carrier
    source: >-
      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
    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-005
    from: packed
    to: collected
    source: 'services-commerce:docs/migrations/shipping/README.md#D-P8S-14'
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: handed_to_carrier
    to: delivered
    source: >-
      services-commerce:modules/shipping/services/fulfillment/labels.ts:trackPackage
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: handed_to_carrier
    to: exception
    source: >-
      services-commerce:modules/shipping/services/fulfillment/labels.ts:trackPackage
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: handed_to_carrier
    to: returned_to_sender
    source: >-
      services-commerce:modules/shipping/services/fulfillment/labels.ts:trackPackage
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: open
    to: cancelled
    source: >-
      services-commerce:modules/shipping/services/fulfillment/shipment-creation.ts:cancelShipment
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: manifested
    to: cancelled
    source: >-
      services-commerce:modules/shipping/services/fulfillment/cancellation-fence.ts:cancelFencedShipmentLines
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: allocated
    to: released_to_warehouse
    source: >-
      services-commerce:modules/shipping/services/fulfillment/shipment-creation.ts:releaseShipment
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: released_to_warehouse
    to: picking
    source: >-
      services-commerce:modules/shipping/services/fulfillment/picking.ts:createPickListForWarehouse
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: picking
    to: picked
    source: >-
      services-commerce:modules/shipping/services/fulfillment/picking.ts:recordPickOnList
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: picking
    to: short
    source: >-
      services-commerce:modules/shipping/services/fulfillment/picking.ts:recordPickOnList
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: picking
    to: released_to_warehouse
    source: >-
      services-commerce:modules/shipping/services/fulfillment/picking.ts:cancelPickList
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: allocated
    to: cancellation_pending
    source: >-
      services-commerce:modules/shipping/services/persistence/shipments.ts:fenceLinesForCancellation
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: released_to_warehouse
    to: cancellation_pending
    source: >-
      services-commerce:modules/shipping/services/persistence/shipments.ts:fenceLinesForCancellation
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: picking
    to: cancellation_pending
    source: >-
      services-commerce:modules/shipping/services/persistence/shipments.ts:fenceLinesForCancellation
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: picked
    to: cancellation_pending
    source: >-
      services-commerce:modules/shipping/services/persistence/shipments.ts:fenceLinesForCancellation
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: packing
    to: cancellation_pending
    source: >-
      services-commerce:modules/shipping/services/persistence/shipments.ts:fenceLinesForCancellation
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: packed
    to: cancellation_pending
    source: >-
      services-commerce:modules/shipping/services/persistence/shipments.ts:fenceLinesForCancellation
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: labelled
    to: cancellation_pending
    source: >-
      services-commerce:modules/shipping/services/persistence/shipments.ts:fenceLinesForCancellation
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: manifested
    to: cancellation_pending
    source: >-
      services-commerce:modules/shipping/services/persistence/shipments.ts:fenceLinesForCancellation
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: short
    to: cancellation_pending
    source: >-
      services-commerce:modules/shipping/services/persistence/shipments.ts:fenceLinesForCancellation
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-005
    from: cancellation_pending
    to: cancelled
    source: >-
      services-commerce:modules/shipping/services/persistence/shipments.ts:cancelFencedLines
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-006
    from: packed
    to: packed
    source: >-
      services-commerce:modules/shipping/tests/integration/services/fulfillment/shipping-flow.integration.spec.js#buys
      the first label through UPS under package:<id>:1 (the intent then the
      outcome), the tracking number and the cost on the label, the package
      labelled
    coverage: covered
    scenarios:
      - ATS-COM-FUL-012-10
      - ATS-COM-FUL-013-01
      - ATS-COM-FUL-013-10
      - ATS-COM-FUL-014-07
  - model: STATE-COM-FUL-006
    from: packed
    to: labelled
    source: >-
      services-commerce:modules/shipping/services/fulfillment/labels.ts:recordPurchaseOutcome,resolveLabelPurchase
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-006
    from: packed
    to: packed
    source: >-
      services-commerce:modules/shipping/services/fulfillment/labels.ts:purchaseLabelForPackage
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-006
    from: labelled
    to: packed
    source: >-
      services-commerce:modules/shipping/services/fulfillment/labels.ts:voidLabelOfPackage
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-006
    from: labelled
    to: voided
    source: >-
      services-commerce:modules/shipping/services/fulfillment/labels.ts:voidLabelsOfShipment
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-006
    from: labelled
    to: manifested
    source: >-
      services-commerce:modules/shipping/services/fulfillment/handoff.ts:manifestShipment
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-006
    from: manifested
    to: handed_to_carrier
    source: >-
      services-commerce:modules/shipping/services/fulfillment/handoff.ts:handoffShipment
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-006
    from: handed_to_carrier
    to: in_transit
    source: >-
      services-commerce:modules/shipping/services/fulfillment/labels.ts:trackPackage
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-006
    from: in_transit
    to: delivered
    source: >-
      services-commerce:modules/shipping/services/fulfillment/labels.ts:trackPackage
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-006
    from: in_transit
    to: exception
    source: >-
      services-commerce:modules/shipping/services/fulfillment/labels.ts:trackPackage
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-006
    from: in_transit
    to: returned_to_sender
    source: >-
      services-commerce:modules/shipping/services/fulfillment/labels.ts:trackPackage
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-006
    from: packed
    to: collected
    source: >-
      services-commerce:modules/shipping/services/fulfillment/handoff.ts:handoverShipment
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-006
    from: packed
    to: voided
    source: >-
      services-commerce:modules/shipping/services/fulfillment/cancellation-fence.ts:cancelFencedShipmentLines
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-006
    from: requested
    to: purchased
    source: >-
      services-commerce:modules/shipping/services/persistence/carrier-labels.ts:recordLabelOutcome
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-006
    from: requested
    to: failed
    source: >-
      services-commerce:modules/shipping/services/persistence/carrier-labels.ts:recordLabelOutcome
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-006
    from: purchased
    to: voided
    source: >-
      services-commerce:modules/shipping/services/persistence/carrier-labels.ts:recordLabelVoid
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-006
    from: purchased
    to: void_failed
    source: >-
      services-commerce:modules/shipping/services/persistence/carrier-labels.ts:recordLabelVoid
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-006
    from: void_failed
    to: voided
    source: >-
      services-commerce:modules/shipping/services/persistence/carrier-labels.ts:recordLabelVoid
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
  - model: STATE-COM-FUL-006
    from: void_failed
    to: void_failed
    source: >-
      services-commerce:modules/shipping/services/persistence/carrier-labels.ts:recordLabelVoid
    coverage: 'gap: FND-COM-FUL-068'
    scenarios: []
permission_audit:
  - key: commerce.shipments.update
    where_checked: api
    coverage: 'gap: FND-COM-FUL-068'
    note: >-
      Per-key positive and negative coverage is not separately mapped;
      permission scenarios retain the observed aggregate tests.
  - key: orders.shipments.printLabel
    where_checked: console
    coverage: 'gap: FND-COM-FUL-068'
    note: >-
      Per-key positive and negative coverage is not separately mapped;
      permission scenarios retain the observed aggregate tests.
  - key: orders.shipments.voidLabel
    where_checked: console
    coverage: 'gap: FND-COM-FUL-068'
    note: >-
      Per-key positive and negative coverage is not separately mapped;
      permission scenarios retain the observed aggregate tests.
related_audit:
  - capability: CAP-COM-FUL-014
    scenarios:
      - ATS-COM-FUL-013-10
  - capability: CAP-COM-FUL-015
    scenarios:
      - ATS-COM-FUL-013-11
invariant_audit:
  - invariant: INV-DOM-COM-FUL-004-01
    scenarios: []
    coverage: 'gap: FND-COM-FUL-068'
    provenance: observed
    source: >-
      services-commerce:modules/shipping/db/shipments.table.ts;
      packages.table.ts; pick-lists.table.ts; return-receipts.table.ts
  - invariant: INV-DOM-COM-FUL-004-02
    scenarios: []
    coverage: 'gap: FND-COM-FUL-068'
    provenance: observed
    source: 'services-commerce:modules/shipping/db/shipment-lines.table.ts'
  - invariant: INV-DOM-COM-FUL-004-03
    scenarios:
      - ATS-COM-FUL-014-01
    coverage: covered
    provenance: test
    source: >-
      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
  - invariant: INV-DOM-COM-FUL-004-04
    scenarios:
      - ATS-COM-FUL-014-02
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/shipping/services/fulfillment/handoff.ts:obligationsOfUnits
  - invariant: INV-DOM-COM-FUL-004-05
    scenarios:
      - ATS-COM-FUL-014-03
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/shipping/services/persistence/shipments.ts:fenceLinesForCancellation,handoffLinesOfShipment
  - invariant: INV-DOM-COM-FUL-004-06
    scenarios:
      - ATS-COM-FUL-013-02
    coverage: covered
    provenance: documented
    source: 'services-commerce:docs/migrations/shipping/README.md#D-P8S-08'
  - invariant: INV-DOM-COM-FUL-004-07
    scenarios: []
    coverage: 'gap: FND-COM-FUL-068'
    provenance: observed
    source: >-
      services-commerce:modules/shipping/db/shipments.table.ts:shipments_pickup_check
  - invariant: INV-DOM-COM-FUL-004-08
    scenarios:
      - ATS-COM-FUL-012-07
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/shipping/db/shipment-events.table.ts (UPDATE,
      DELETE and TRUNCATE revoked)
  - invariant: INV-DOM-COM-FUL-004-09
    scenarios: []
    coverage: 'gap: FND-COM-FUL-068'
    provenance: observed
    source: >-
      services-commerce:modules/shipping/db/return-receipts.table.ts;
      return-receipt-lines.table.ts:return_receipt_lines_quantities_check
  - invariant: INV-DOM-COM-FUL-004-10
    scenarios:
      - ATS-COM-FUL-010-04
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/shipping/services/persistence/carrier-accounts.ts
  - invariant: INV-DOM-COM-FUL-004-11
    scenarios:
      - ATS-COM-FUL-010-02
      - ATS-COM-FUL-010-03
      - ATS-COM-FUL-010-04
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/shipping/db/shipping-strategies.table.ts;
      modules/shipping/db/shipments.table.ts;
      modules/shipping/db/carrier-labels.table.ts
  - invariant: INV-DOM-COM-FUL-004-12
    scenarios:
      - ATS-COM-FUL-010-03
    coverage: covered
    provenance: observed
    source: >-
      services-commerce:modules/shipping/services/persistence/shipping-strategies.ts:validateStrategyInput
---

# Purchase and follow carrier labels safely: 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-013-01` | `ATS-COM-FUL-013-01`, `ATS-COM-FUL-013-10`, `ATS-COM-FUL-013-11` |
| `BR-CAP-COM-FUL-013-02` | `ATS-COM-FUL-013-02` |
| `BR-CAP-COM-FUL-013-03` | `ATS-COM-FUL-013-03` |
| `BR-CAP-COM-FUL-013-04` | `ATS-COM-FUL-013-01`, `ATS-COM-FUL-013-10`, `ATS-COM-FUL-013-11` |
| `BR-CAP-COM-FUL-013-05` | `ATS-COM-FUL-013-04` |
| `BR-CAP-COM-FUL-013-06` | `ATS-COM-FUL-013-05`, `ATS-COM-FUL-013-09` |
| `BR-CAP-COM-FUL-013-07` | `ATS-COM-FUL-013-05`, `ATS-COM-FUL-013-09` |
| `BR-CAP-COM-FUL-013-09` | `ATS-COM-FUL-013-06` |
| `BR-CAP-COM-FUL-013-10` | `ATS-COM-FUL-013-07` |
| `BR-CAP-COM-FUL-013-11` | `ATS-COM-FUL-013-08` |

## Interactions With Related Capabilities

The interaction cases exercise record goods leaving with a carrier or collector; process returned goods through inspection and disposition. 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.
