Skip to content

Commit 99c2bfb

Browse files
docs(billing): fix stale JSDoc + test comment after marker-bump fix
- adminUpdatePlanOnly JSDoc now reflects that lastSubscriptionEvent* markers are bumped (per V8-C3 fix) — the old text said "Never touches … markers" - markUnpaid V8-C3 test comment: was "invoice.payment_failed" but the guard and markers are subscription-family; corrected to "customer.subscription.updated"
1 parent 9c23de3 commit 99c2bfb

2 files changed

Lines changed: 8 additions & 5 deletions

File tree

modules/billing/repositories/billing.subscription.repository.js

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -274,16 +274,19 @@ const updateIfEventNewer = (id, eventCreatedAt, eventId, fields, family = 'subsc
274274

275275
/**
276276
* @function adminUpdatePlanOnly
277-
* @description Restricted admin update — sets ONLY `plan` and `adminUpdatedAt`. Never touches
278-
* `status`, `stripeCustomerId`, `stripeSubscriptionId`, `currentPeriodStart`, or
279-
* the per-family event-ordering markers. Webhook handlers retain exclusive write
280-
* authority on those fields via `updateIfEventNewer`.
277+
* @description Restricted admin update — sets ONLY `plan`, `adminUpdatedAt`, and the
278+
* subscription-family event-ordering markers. Never touches `status`,
279+
* `stripeCustomerId`, `stripeSubscriptionId`, or `currentPeriodStart`.
281280
*
282281
* Why this restriction matters: a free `update()` call with `{ plan, status }` from
283282
* an admin path would overwrite Stripe-driven status (active/past_due/etc.) with
284283
* whatever the admin sent, breaking dunning + access control. Splitting the surface
285284
* forces admin overrides to plan-only territory.
286285
*
286+
* The subscription-family markers (`lastSubscriptionEvent*`) are bumped so a
287+
* subsequent stale Stripe webhook redelivery (customer.subscription.*) cannot
288+
* overwrite the admin plan change via `updateIfEventNewer`.
289+
*
287290
* @param {string} id - Subscription ObjectId (string).
288291
* @param {string} planId - The new plan identifier (must be in config.billing.plans enum).
289292
* @param {string} adminUserId - The admin user ObjectId (string) who triggered the bump (for audit).

modules/billing/tests/billing.subscription.repository.unit.tests.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ describe('BillingSubscriptionRepository unit tests:', () => {
418418
describe('markUnpaid — V8-C3 event-ordering markers', () => {
419419
const threshold = new Date(Date.now() - 14 * 24 * 60 * 60 * 1000);
420420

421-
// V8 audit C3 — markUnpaid must bump markers so a stale invoice.payment_failed
421+
// V8 audit C3 — markUnpaid must bump markers so a stale customer.subscription.updated
422422
// redelivery cannot restore 'past_due' after the dunning sweep set 'unpaid'.
423423
test('V8-C3: bumps lastSubscriptionEventCreatedAt + lastSubscriptionEventId so stale webhook is rejected', async () => {
424424
const updated = { _id: subId, status: 'unpaid', plan: 'free' };

0 commit comments

Comments
 (0)