Bind a repeated refund request to its original merchant and intent
The browser retries an approved 4,500-minor-unit refund after a lost response. The current deduplication key is global, and changing the amount while reusing the key overwrites the queued request.
- Focused work estimate
- 2h 30m + prerequisites
- Priority in the scenario
- High
- Engineering practice
- Command modeling · Idempotency · Intent hashing
Estimated field mix
- Distributed systems50%
- Backend30%
- Database engineering20%
Field percentages are editorial estimates of the ticket's engineering focus. They total 100%; they are not measured time, proficiency scores, or ownership evidence.
Pattern topics
- CommandApply
Capture refund intent as an immutable durable command so retries refer to the same operation and cannot quietly change its merchant, amount, or target.
Review it, then add it to your workspace.
The board opens an editable draft; nothing is saved until you confirm it. Sign-in and workspace permissions apply, and Demo boards remain ephemeral.
Project context
A fictional equipment retailer lets customers choose a refund or replacement after inspection. Its payment and stock providers can time out after accepting an operation, so retrying the whole return is unsafe. Create a local TypeScript application, PostgreSQL state/outbox tables, and synthetic provider doubles with controllable outcomes; no starter code or fixtures are supplied. Use invented orders and integer minor-unit amounts only, with no real payments or external provider calls.
Setup prerequisites
- SQL transactions
- Idempotent commands
- Async failure handling
- State modeling
Preceding work
Complete these dependencies, or supply their agreed outputs before taking this ticket.
Acceptance criteria
- Persist an immutable refund command with merchant, return, amount, currency, and a canonical intent hash scoped to its request key.
- Identical retries return the existing command identity and current status; changed intent under the same scoped key returns a conflict.
- Concurrent identical requests create one accepted command, and command history never rewrites the original amount or target return.
Implementation constraints
- Represent the operation as a durable command rather than relying on an in-memory callback or HTTP response cache; amounts use integer minor units.
Verification to include
- Submit the same intent concurrently and retry after a simulated lost response; compare one command identity and one accepted history entry.
- Reuse the key with a new amount and from another merchant; assert conflict for changed scoped intent and independent authorized identities across merchants.
Deliverables
- Durable refund command contract and scoped idempotency reproduction
Rollout and recovery
Enable durable command intake before dispatching synthetic refunds; disable new intake without deleting accepted command identities.
Value of the work
For the engineer: Practice durable workflow state, ambiguous provider outcomes, compensation, concurrency isolation, and recovery that survives process restarts.
For the team: Inspect whether a proposed workflow preserves refund and inventory invariants, contains provider failures, and gives operators a bounded recovery path.
Evidence boundaries
Outcome Evidence: Tests, patches, and runbooks are requested deliverables. They become Outcome Evidence only through a qualified Mission and immutable Evidence IDs.
Ownership Evidence: Independent adaptation must be observed under a declared verification policy and cite immutable Evidence IDs. Completing a planning ticket establishes no Ownership Evidence.