fix(finance): preserve per-movement stock accounting and retry failures #37
Copy link
Copy link
Open
Description
Source-reviewed risk (not an executed exploit)
At baseline acf623e, InventoryService queues inventory.stock_depleted per immutable transaction with idempotency key stock_depleted:{transaction.id}. Multiple allocations/partial shipments share business reference SALE-SHIP-{orderNo}. FinanceBridgeListener.onStockDepleted instead skips when any INV journal exists with that business reference; later legitimate movement events can be discarded. Its catch records Finance DLQ then returns, unlike corrected supplier handlers; outer event delivery may interpret the failure as success.
Scope for a separate focused fix
- Keep business reference readable while deduplicating by durable movement/event identity.
- Prove same-reference distinct movements each account exactly once, replay/concurrent delivery cannot duplicate, and posting failure remains retryable without queue-ownership ambiguity.
- Tenant/cost/account mapping and period enforcement must remain intact; no invented finance policy or blanket historical replay.
- Inspect AccountingService transaction-level journal dedupe and outbox dispatch semantics before implementation; use real PostgreSQL regressions.
- Audit existing historical gaps separately; do NOT automatically backfill production.
This is not solved by shipment quantity safety, Chromium UI regression, or passing the 13-step stocked-trade HTTP journey. Track as a blocker for claiming complete shipment-to-accounting maturity.
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
No labels
Activity
cb8010d6 commentedon Sep 26, 2026
Implemented in draft PR#41, exact head1b01849. Real CI run36254241302 ALL GREEN: additive movement-receipt migration applied, new18 PostgreSQL cases passed (77total),793 regular tests,13HTTP steps,6Chromium regressions. Per-movement receipt prevents same-ref allocations being discarded; original event retries are preserved; tx-aware helpers also passed low-pool concurrency. No production rollout, old-event replay/backfill or merge. Existing historical NULL-source journal ambiguity remains fail-closed for authorized reconciliation; drain old consumers before new activation.