Files
member-console/openspec/changes
cgalo5758 fa614d0fb7 Ask for a subscription reconcile from every act that changes who holds a ladder
Fourth section of #269's change. Every act that can change who holds a
ladder now writes one reconcile_subscription outbox entry per live
subscription of the organization (active, trialing, past_due or unpaid,
in id order), in the act's own transaction, so each subscription's
collection pause is decided again after the act commits. The entry is
an insert and takes no lock.

The acts: issuing a grant (entitlements.IssueGrant, which the issue
handler now calls in place of ConferGrant), managing, revoking and
expiring one, the legacy grant a default change confers, and removing a
tier from a ladder. ConferGrantTx itself requests nothing, because the
conferral and provisioning paths that call it run before the
subscription exists or reconcile it themselves. In the reconcile, the
ended branch and the surplus end request the organization's other
subscriptions, excepting the one being reconciled.

The screens utility waits until the application database holds no
pending or failed outbox row before its first capture, because the demo
seed's revocation and expiry now leave two entries the running app's
relay completes on its own schedule.

docs/stripe.md rewrites the grant over a paid plan: the console pauses
the subscription's collection while the grant holds, and the costs that
pause accepts are listed. docs/models/plan-ladders-transitions.md,
docs/plan-management.md, docs/models/payments-billing.md and
docs/database-locks.md say the same.

Tests: TestActsRequestSubscriptionReconciles (six acts, two live
subscriptions and a canceled one, ids and creation order differing),
TestConferGrantTxRequestsNothing,
TestReconcileEndedRequestsTheOtherSubscriptions,
TestSurplusEndRequestsTheOtherSubscriptions,
TestIssueGrantHandlerRequestsAReconcile, and the demo seed's entries.
Seven trace goldens gain the ListLiveSubscriptionsOfPool read.

Review: no blocker or major; six minors and six nits applied (a step
name for the tier removal's request error, the fixture's id order, doc
comments and the docs that still said a grant over a paid plan keeps
billing).

Breaks: 17 of 17 caught. Ignoring the exception is caught only through
the surplus end: in the ended branch the excepted subscription is
already canceled, so the live read never lists it. Full suite on reset
databases: 4768 pass, 14 skip. make screens: no change beyond the three
captures every run since section 2 redraws.
2026-10-28 02:18:02 -05:00
..