feat(billing): queue verified Stripe reconciliation triggers - #570
Conversation
|
Important Review skippedDraft detected. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
Caution Review failedAn error occurred during the review process. Please try again later. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Buyer/reliability objective
Refs #488. Stripe may retry, duplicate, and deliver webhook events out of order, so a verified delivery must become durable reconciliation work, never inline lifecycle or entitlement authority. This stacked Draft turns already-verified Subscription/Invoice webhook evidence into one normalized pending trigger that #569 can later consume by re-reading current provider state.
Exact current stack
develop:2dcbdc06d3a9e2f87eac42447338e7fcc523dd54;feat/stripe-billing-authoritative-reconciliation-488@21e6a4acc8fd06ddebb0b2c35e45b504f417cc18;8604c661eba3b5a5b97bea32eaa54bac4dcd2972;The effective semantic delta is limited to
package.json,server/db.mjs,server/stripe_webhook_reconciliation_queue.mjs,tests/unit/coverage-script-contract.test.mjs,tests/unit/stripe-webhook-reconciliation-queue.test.mjs, andtests/unit/stripe-webhook-reconciliation-queue-integration.test.mjs. No auth/session, Clearfolio, general application route, dependency lockfile, workflow, scanner suppression, or branch-protection artifact is changed.Any parent, contributor-head, protected-base, review, or check movement invalidates ancestry- and head-sensitive evidence until freshly revalidated.
Implemented reconciliation-trigger contract
customer.subscription.*events map only to the exact boundedsub_...provider identity;parent.subscription_details.subscriptionprovenance and the legacy top-levelsubscriptionrepresentation, while contradictory representations fail closed;billing_stripe_reconciliation_triggersstores one pending trigger per already-verified Stripe Event and references the immutable verified-event ledger by foreign key;orgs.planmutation, capability grant, or entitlement decision.TDD and causal repairs
The original registered queue contract was intentionally RED while the production module was absent. Production implementation then established extraction, normalized schema, durable enqueue, bootstrap composition, and canonical c8/unit registration.
Fresh current-source verification exposed two additional causal defects and both were repaired test-first on this existing branch:
now()before checking the existing trigger, so a later bad wall-clock seam could fail an otherwise idempotent replay. The regression at predecessor171a75cbe12590d492b03448ad41b1e83f390cdfmade the second clock read invalid;081f2a90211719af0f8c993f93d61f1c9ff267eemoved time acquisition to the first-insert path only.0bc93b447464ec9e3c4260fc715bf64f597cf2b1injects a real SQLiteBEFORE INSERT ... RAISE(ABORT)failure and requires zero surviving Event, delivery, and trigger rows. Current head8604c661eba3b5a5b97bea32eaa54bac4dcd2972wraps the existing nested repositories in one outer SQLite savepoint and releases only after both evidence recording and trigger creation succeed. Failed rollback remains fail-closed and cleanup errors cannot replace the causal failure.The exact parent→child comparison remains bounded to the six intended queue/integration/evidence paths after both repairs.
Current exact-head evidence
Fresh repository-native workflows for exact contributor head
8604c661eba3b5a5b97bea32eaa54bac4dcd2972exist but are still queued and therefore non-passing:32375891058;32375891060; and32375891523.No submitted review or inline review thread exists on this exact head and no qualifying independent current-head approval exists. Queued, pending, skipped-required, cancelled, absent, neutral-required, failed, stale, predecessor, synthetic, status-only, author-only, or model-only evidence is non-passing.
Standards and scope boundary
The design follows Stripe's documented duplicate/retry and non-guaranteed-ordering webhook model: delivery creates bounded work; #569 remains responsible for authoritative Subscription/Invoice re-fetch and claim evaluation. Event arrival time and embedded snapshots are not lifecycle authority.
This PR does not yet implement worker claiming/completion state, retry/backoff/dead-letter policy, operator recovery, or the final end-to-end out-of-order convergence acceptance for #488. Remain Draft and do not integrate independently of #569/#568 and their prerequisite billing stack.
Merge gate
After prerequisite integration, reconcile this exact bounded semantic delta to the resulting protected head and regenerate every then-applicable exact-head deterministic/browser/statement/branch/function/line coverage/docstring/CodeQL/SAST/security/dependency/supply-chain/package/provenance/migration/recovery/resolved-thread and qualifying independent-review gate required by live policy. No predecessor-head, author-only, skipped, neutral, status-only, synthetic, or model-only evidence transfers.