You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
P1 — add after immutable plan versions and explicit provider capabilities are available.
Problem
@croco/membership-core can enforce a local seat limit through SeatLimitChecker, while @croco/billing-core subscriptions do not model or reconcile a licensed quantity. A tenant can therefore have a different active-seat count, entitlement limit, and provider-billed quantity.
Updating the billing provider synchronously inside MembershipManager.addMember() or removeMember() would create a false cross-system transaction: provider failure could either block valid membership changes or leave local state committed with no inspectable repair path.
Desired outcome
Add a provider-neutral licensed-quantity reconciliation contract that derives the desired quantity from application-owned membership state and asynchronously converges the billing provider quantity with idempotent, observable evidence.
Define a SubscriptionQuantitySource contract that returns the desired billable quantity and source version/evidence.
Define an explicit licensed-quantity provider capability rather than adding permissive optional methods to the existing checkout gateway.
Add SubscriptionQuantitySnapshot and reconciliation states such as in_sync, pending, drifted, retryable_failed, terminal_failed, and unsupported.
Make quantity policy explicit per plan version, including minimum quantity, included seats, and which locally active memberships count as billable seats.
Derive a stable reconciliation identity from tenant, external subscription, plan version, desired quantity, and source version.
Execution semantics
Trigger reconciliation only after the local membership transaction commits.
Do not call a remote billing provider from membership request execution.
Support event-driven reconciliation plus a bounded periodic repair scan.
Treat repeated requests for the same desired quantity as idempotent success.
Handle concurrent membership changes by superseding stale desired quantities rather than applying them after a newer source version.
Persist provider-observed quantity, desired quantity, last attempt, last success, retry classification, and actionable Problem evidence.
Composition boundary
billing-core must not depend directly on membership-core.
The source contract lives at the billing boundary; the SaaS composition root or an adapter implements it from membership state.
Related: #1511, #1520, #1524, #1525, #1538
Priority
P1 — add after immutable plan versions and explicit provider capabilities are available.
Problem
@croco/membership-corecan enforce a local seat limit throughSeatLimitChecker, while@croco/billing-coresubscriptions do not model or reconcile a licensed quantity. A tenant can therefore have a different active-seat count, entitlement limit, and provider-billed quantity.Updating the billing provider synchronously inside
MembershipManager.addMember()orremoveMember()would create a false cross-system transaction: provider failure could either block valid membership changes or leave local state committed with no inspectable repair path.Desired outcome
Add a provider-neutral licensed-quantity reconciliation contract that derives the desired quantity from application-owned membership state and asynchronously converges the billing provider quantity with idempotent, observable evidence.
Scope
Core contracts
SubscriptionQuantitySourcecontract that returns the desired billable quantity and source version/evidence.SubscriptionQuantitySnapshotand reconciliation states such asin_sync,pending,drifted,retryable_failed,terminal_failed, andunsupported.Execution semantics
Composition boundary
billing-coremust not depend directly onmembership-core.PlanVersionRefand provider capability metadata introduced by [billing-core] Pin subscriptions to immutable plan versions #1524 and [billing-core] Model explicit usage-billing provider capabilities #1520.Diagnostics and telemetry
Acceptance criteria
in_sync.Verification
pnpm --filter @croco/billing-core testpnpm public-api:checkpnpm docs:api:checkpnpm provider-certification:checkNon-goals
SeatLimitCheckeror entitlement enforcement.