Skip to content

[audit][P1][edge-case] billing: reconcile cron runs without a distributed lock #3728

@PierreBrisorgueil

Description

@PierreBrisorgueil

Finding NODE-BILLING-04
File modules/billing/crons/billing.reconcile.js

runReconciliation() runs with no acquireLock/releaseLock, unlike the 3 sibling crons (dunningSweep, weeklyReset, extrasExpiration). Concurrent pods (rolling restart, overlap) each paginate all active subs and call stripe.subscriptions.retrieve() per sub → doubled Stripe API volume + duplicate billing.reconciliation.divergence alerts.

Fix Wrap in acquireLock({ name: 'billing.reconcile', ttlMs: 20*60*1000, holder })/releaseLock as in billing.dunningSweep.js:58-126.

Devkit Node clean audit 2026-05-29 (rev d42eb12). Verified real by an independent refute-by-default reviewer. Fix flows through /feature #N → /verify-qa → /pull-request-finalize.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions