---
id: TST-ACC-TRX-076
title: Lost answers suite
kind: integration
product_area: accounting
module: transactions
revision: 1
status: draft
source_sha:
  services-accounting: f47cb263875bbc0c5640fba7dae6785ec32695f8
repository: services-accounting
files:
  - >-
    modules/transactions/tests/integration/services/payments/lost-answers.integration.spec.js
implements:
  - ATS-ACC-TRX-007-06
  - ATS-ACC-TRX-007-07
implements_parts:
  - scenario: ATS-ACC-TRX-007-06
    assertion: >-
      it asks at the first step (30 s) and counts it: a not_found changes
      nothing else
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/lost-answers.integration.spec.js#it
      asks at the first step (30 s) and counts it: a not_found changes nothing
      else
  - scenario: ATS-ACC-TRX-007-06
    assertion: 'it hands the intent to a person at the last lookup (180 s), not before'
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/lost-answers.integration.spec.js#it
      hands the intent to a person at the last lookup (180 s), not before
  - scenario: ATS-ACC-TRX-007-06
    assertion: >-
      it hands the intent to a person at the last lookup: needs_review, the item
      published with its facts
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/lost-answers.integration.spec.js#it
      hands the intent to a person at the last lookup: needs_review, the item
      published with its facts
  - scenario: ATS-ACC-TRX-007-06
    assertion: 'it stops looking once it is with a person: further sweeps do not touch it'
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/lost-answers.integration.spec.js#it
      stops looking once it is with a person: further sweeps do not touch it
  - scenario: ATS-ACC-TRX-007-07
    assertion: >-
      it is settled by a person under the processor’s reference: the payment
      recorded, the item resolved settled
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/lost-answers.integration.spec.js#it
      is settled by a person under the processor’s reference: the payment
      recorded, the item resolved settled
  - scenario: ATS-ACC-TRX-007-07
    assertion: >-
      it refuses a second decision once it is settled
      (lost_answer_not_processing)
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/lost-answers.integration.spec.js#it
      refuses a second decision once it is settled (lost_answer_not_processing)
  - scenario: ATS-ACC-TRX-007-07
    assertion: >-
      it refuses both decisions before the last lookup
      (lost_answer_not_in_review)
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/lost-answers.integration.spec.js#it
      refuses both decisions before the last lookup (lost_answer_not_in_review)
  - scenario: ATS-ACC-TRX-007-07
    assertion: >-
      it fails the intent with the person’s reason, frees its key and resolves
      the item failed
    provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/lost-answers.integration.spec.js#it
      fails the intent with the person’s reason, frees its key and resolves the
      item failed
environment: local
implementation_state: implemented
latest_result: not-run
latest_run_at: null
latest_run_ref: null
conformance: not-verified
estimated_minutes: 3
isolation: >-
  Suite-marked records in the prepared local test database; fixture teardown
  removes owned records.
provenance: test
source: >-
  services-accounting:modules/transactions/tests/integration/services/payments/lost-answers.integration.spec.js
evidence:
  - provenance: test
    source: >-
      services-accounting:modules/transactions/tests/integration/services/payments/lost-answers.integration.spec.js
    assertion_titles:
      - 'a lost processor answer: keep checking, then a person (integration)'
      - a charge whose answer was lost and which the key lookup cannot find
      - 'leaves the intent processing, not failed, with each lookup counted'
      - raises no attention item before the last lookup
      - >-
        hands the intent to a person at the last lookup: needs_review, the item
        published with its facts
      - 'stops looking once it is with a person: further sweeps do not touch it'
      - >-
        keeps the key held: a replay of the same request is still uncertain,
        never a second charge
      - >-
        is settled by a person under the processor’s reference: the payment
        recorded, the item resolved settled
      - >-
        refuses a second decision once it is settled
        (lost_answer_not_processing)
      - a charge a person marks failed
      - >-
        refuses both decisions before the last lookup
        (lost_answer_not_in_review)
      - >-
        fails the intent with the person’s reason, frees its key and resolves
        the item failed
      - >-
        frees the invoice and the card for a new attempt under a new key,
        charged once
      - a lookup by the provider’s reference
      - >-
        is asked with the reference, and its not_found is final for a charge
        after the grace: the intent fails processor_unavailable, nothing counted
      - >-
        is used by key only when the intent holds none: the lookup carries no
        reference
      - >-
        the lookup schedule (30s, 60s, 90s: lookups due 30, 90 and 180 seconds
        after the claim), on a stepped clock
      - is the configured schedule in seconds
      - >-
        does not ask by key before the first step is due, and the sweeper does
        not list the intent younger than 30 seconds
      - >-
        asks at the first step (30 s) and counts it: a not_found changes nothing
        else
      - 'does not ask by key between steps (60 s: the second is due at 90 s)'
      - >-
        asks by the reference on every pass: its not_found fails a charge from
        the grace on, between steps, uncounted
      - >-
        settles on a found answer between steps: the reference lookup answers
        captured at 60 s
      - counts the second lookup at 90 s and decides nothing
      - 'hands the intent to a person at the last lookup (180 s), not before'
      - a refund whose answer was lost
      - >-
        keeps both refunds processing and hands both to a person at the last
        lookup, failing neither
      - 'publishes the item for each, about its operation'
      - >-
        completes a refund a person marks settled, under their reference, and
        resolves the item settled
      - >-
        fails a refund a person marks failed, giving the pending money back, and
        resolves the item failed
      - >-
        a refund the provider holds pending, as the Dummy does for a partial
        refund (45 seconds)
      - >-
        is looked up again by its reference and completes without a webhook;
        pending lookups are not lost-answer lookups
      - a void whose answer was lost
      - >-
        stays processing through the lookups, is handed to a person, and
        completes when they settle it
    imports:
      - 'const { stage } = require(''@rhythmsoftware/macroservice-testing/stage'');'
      - >-
        const { manualClock } =
        require('@rhythmsoftware/macroservice-time/clock');
      - >-
        const { TEST_NOW } =
        require('@rhythmsoftware/macroservice-testing/execution-context');
      - 'const { sql } = require(''drizzle-orm'');'
      - >-
        const { dummyPaymentProcessor } =
        require('../../../../services/payments/dummy-processor');
      - >-
        const { sweepProcessingIntents } =
        require('../../../../services/payments/intent-sweeper');
      - >-
        const { failLostAnswer, settleLostAnswer } =
        require('../../../../services/payments/lost-answer-commands');
      - '} = require(''../../../../services/payments/lost-answer-rules'');'
      - >-
        const { receivePayment } =
        require('../../../../services/payments/payment-receive');
      - >-
        const { reversePayment } =
        require('../../../../services/payments/payment-reverse');
      - >-
        const { ProcessorUncertainError, usePaymentProcessorForTests } =
        require('../../../../services/payments/ports/payment-processor');
      - >-
        const { executeRefund, requestRefund } =
        require('../../../../services/refunds/refund-commands');
      - >-
        const { attentionItemsAbout, removeAttentionOf } =
        require('../../../../../batches/tests/integration/support/attention-items');
      - '} = require(''../../payments-fixtures'');'
      - "\t\t\tconst { afterEarly, early } = lost.require();"
      - "\t\t\tconst { intent } = lost.require();"
      - "\t\t\tconst { intent, later } = lost.require();"
      - "\t\t\tconst { intent, later } = lost.require();"
      - "\t\t\texpect(dummyPaymentProcessor().chargesMade(TENANT, lost.require().intent.id)).to.equal(0);"
      - "\t\t\tconst { intent } = lost.require();"
      - "\t\t\tconst { intent } = lost.require();"
      - "\t\t\tconst { intent, later } = lost.require();"
      - "\t\t\tconst { intent, later } = lost.require();"
      - "\t\t\t\t\treturn intentId === lost.require().withReference.id ? answer : { state: 'not_found' };"
      - "\t\t\tconst { intent, withReference } = lost.require();"
      - "\t\t\tconst { intent } = lost.require();"
      - "\t\t\tconst { intent } = lost.require();"
      - "\t\t\tconst { intent } = lost.require();"
      - "\t\t\tconst { notFoundByReference } = lost.require();"
      - "\t\t\tconst { withReference } = lost.require();"
      - "\t\t\tconst { intent } = lost.require();"
      - "\t\t\tconst { intent } = lost.require();"
      - "\t\t\tconst { settled, failed, swept } = lost.require();"
      - "\t\t\tconst { settled } = lost.require();"
      - "\t\t\tconst { settled } = lost.require();"
      - "\t\t\tconst { payment, failed } = lost.require();"
    test_double_declarations:
      - ' * the attention publisher against the local stand-in of Platform''s functions, PostgreSQL. Doubled: the clock (stepped for the'
---

# Lost answers suite

## Verification Boundary

The suite exercises transaction commands and database protections in the local prepared test environment. Registration records the existing executable file; it does not report a run or establish product approval.

## What This Suite Proves

Its cited assertions contribute evidence for lookup exhaustion produces review; human decisions require review eligibility. The structured assertion bindings identify which parts of combined scenarios it executes.

## What It Does Not Prove

Local commands and route invocations do not establish deployed routing, live processor guarantees or the complete staff browser experience. An unbound feature chain remains proposed, and this registration carries no execution result.

## Real Dependencies and Test Doubles

The suite uses the imported commands, route handlers or persistence code against the local test database. Fixture helpers supply accounting context; any stepped clock, dummy processor or substituted external client is retained in the evidence declarations.

## Must Not Be Doubled

The command or persistence behavior under assertion and its relevant database protections must remain real. Substituting the final financial result removes evidence of transactional effects.
