mirror of
https://github.com/affaan-m/ECC.git
synced 2026-09-29 13:05:18 +02:00
1.5 KiB
1.5 KiB
Runbook: idempotency for money-moving operations
The incident class
INC-201, INC-214, INC-227 (refunds) and the payout double-pay risk flagged by finance are one class of bug: a caller retries a money-moving request that carries no idempotency key, and the service executes it again. Asking clients to retry less has failed three times; prevention must live in the service.
The pattern
Every money-moving entry point routes through the shared helper in
src/idempotency.js:
deriveKey(scope, parts)builds a stable key from the request payload when the caller did not supply one.once(store, key, produce)claims the key synchronously (concurrent retries share one execution) and persists the receipt (retries after a restart get the stored receipt back).
src/refunds.js and src/payouts.js both use it. Do not add a second inline
implementation of key derivation or seen-tracking in another module.
Prevention procedure
For any new operation that moves money (charges, refunds, payouts, credits, adjustments):
- Route the side effect through
once()fromsrc/idempotency.js— never call the gateway directly from the entry point. - Add a regression test that retries the operation without a key (including a concurrent retry storm) and asserts the ledger shows exactly one effect.
- Run
npm testbefore merging. - If this class of bug recurs anywhere, log it in
docs/incidents.mdand extend this runbook instead of fixing silently.