@happyvertical/smrt-subscriptions 0.57.1 → 0.57.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -41,9 +41,28 @@ subscription and plan.
41
41
 
42
42
  ## Core model
43
43
 
44
- - `SubscriptionPlan` stores versioned feature grants and thresholds.
44
+ - `SubscriptionPlan` is tenant-scoped by `(tenantId, planKey)` and stores
45
+ feature grants, thresholds, and a `free`, `fixed`, or `pay_what_you_can`
46
+ pricing mode. Amounts (`priceAmount`, `minimumAmount`, and
47
+ `suggestedAmount`) are integer minor units. Provider bindings are optional
48
+ metadata (`externalProvider`, `providerProductId`, `providerPriceId`).
45
49
  - `TenantSubscription` binds a tenant or external subscriber to a plan over an
46
- effective period.
50
+ effective period and records its chosen `agreedAmount` in integer minor
51
+ units for pay-what-you-can plans. Such subscriptions require an amount at
52
+ least the plan minimum; free/fixed subscriptions must leave it null.
53
+ Free and pay-what-you-can plans require `priceAmount: 0`; fixed plans use
54
+ `priceAmount`. Monthly commerce period-close bills tenant subscribers using
55
+ their agreed amount for pay-what-you-can, never the suggested amount, and
56
+ skips free plans. External subscriber invoice routing remains host-owned. Pricing
57
+ mode and minimum are immutable after the plan is saved; create a
58
+ new plan instead (effective-dated transitions are tracked in #4032).
59
+ Invalid legacy pricing fails only its payer group at period close and reports
60
+ the subscription ID while other payer groups continue. Ordinary subscription
61
+ writes resolve only their own tenant's plans or legacy global plans; trusted
62
+ system-context billing can link a seller's plan to its child tenant.
63
+ Entitlement resolution validates plan ownership on both reader and supplied
64
+ context paths; trusted seller-to-child resolution requires explicit system
65
+ context too.
47
66
  - `TenantUsageMetric` is immutable, idempotent usage evidence.
48
67
  - `SubscriptionResolver` combines current subscription, plan, and batched usage
49
68
  summaries into one entitlement decision.
@@ -61,6 +80,31 @@ subscribers add a stable external discriminator. Utilities such as
61
80
  `normalizeSubscriber()` and `assertSubscriberInvariant()` keep that identity
62
81
  coherent.
63
82
 
83
+ ## Upgrade note
84
+
85
+ `SubscriptionPlanCollection.findByPlanKey` now requires `(tenantId, planKey)`;
86
+ pass `null` explicitly for legacy global plans. Update callers from the old
87
+ single-argument signature. Pricing mode and minimum cannot be edited after
88
+ persistence, even before the first subscriber, so a concurrent signup cannot
89
+ observe terms that change mode underneath it. Existing fixed-price edits and
90
+ current-period entitlement versioning remain separate work in #4032; this
91
+ foundation does not provide immutable period snapshots. Concurrent first creates
92
+ for one `(tenantId, planKey)` use a strict insert: one succeeds and a collision
93
+ fails without changing the winner. Retry by reading the existing plan; a
94
+ sequential create with matching mode/minimum retains natural-key upsert behavior.
95
+ Retrying different pricing mode/minimum is rejected. The provider-neutral price
96
+ lookup falls back to legacy Stripe IDs when the binding is Stripe or unspecified;
97
+ explicit bindings to other providers do not use that fallback. PlanPicker accepts
98
+ optional pricing mode, minimum and suggested amounts, labeling free plans and
99
+ PWYC terms explicitly instead of displaying them as zero fixed-price plans.
100
+
101
+ Existing databases created before #3829 may retain the global
102
+ `_smrt_subscription_plans_plan_key_idx` on older migration runners. Run
103
+ `scripts/migrate-3829-drop-legacy-plan-key-index.ts` after the ordinary manifest
104
+ migration so different tenants can reuse a plan key. The script supports SQLite
105
+ and PostgreSQL and refuses DuckDB, whose inline unique constraint needs a
106
+ reviewed table rebuild.
107
+
64
108
  ## Thresholds and spending
65
109
 
66
110
  Thresholds define a metric key, time window, limit, and enforcement behavior.
@@ -2,8 +2,10 @@ import { SmrtCollection } from '@happyvertical/smrt-core';
2
2
  import { SubscriptionPlan } from '../models/SubscriptionPlan.js';
3
3
  export declare class SubscriptionPlanCollection extends SmrtCollection<SubscriptionPlan> {
4
4
  static readonly _itemClass: typeof SubscriptionPlan;
5
- findByPlanKey(planKey: string): Promise<SubscriptionPlan | null>;
5
+ findByPlanKey(tenantId: string | null, planKey: string): Promise<SubscriptionPlan | null>;
6
6
  findActive(): Promise<SubscriptionPlan[]>;
7
+ findByProviderPriceId(providerPriceId: string): Promise<SubscriptionPlan | null>;
8
+ /** @deprecated Provider-neutral integrations should use findByProviderPriceId. */
7
9
  findByStripePriceId(stripePriceId: string): Promise<SubscriptionPlan | null>;
8
10
  }
9
11
  //# sourceMappingURL=SubscriptionPlanCollection.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"SubscriptionPlanCollection.d.ts","sourceRoot":"","sources":["../../src/collections/SubscriptionPlanCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEjE,qBAAa,0BAA2B,SAAQ,cAAc,CAAC,gBAAgB,CAAC;IAC9E,MAAM,CAAC,QAAQ,CAAC,UAAU,0BAAoB;IAExC,aAAa,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAKhE,UAAU,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAOzC,mBAAmB,CACvB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;CAIpC"}
1
+ {"version":3,"file":"SubscriptionPlanCollection.d.ts","sourceRoot":"","sources":["../../src/collections/SubscriptionPlanCollection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEjE,qBAAa,0BAA2B,SAAQ,cAAc,CAAC,gBAAgB,CAAC;IAC9E,MAAM,CAAC,QAAQ,CAAC,UAAU,0BAAoB;IAExC,aAAa,CACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,EACvB,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAK7B,UAAU,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAOzC,qBAAqB,CACzB,eAAe,EAAE,MAAM,GACtB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAanC,kFAAkF;IAC5E,mBAAmB,CACvB,aAAa,EAAE,MAAM,GACpB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;CAIpC"}
package/dist/index.d.ts CHANGED
@@ -13,6 +13,6 @@ export type { PriceBookKind, PricingStrategy, SpendingBasis, SpendingPeriod, Spe
13
13
  export { BillingAdjustment, BillingAdjustmentCollection, ClientCharge, ClientChargeCollection, CreditGrant, CreditGrantCollection, isCurrencyCode, isPriceBookKind, PriceBook, PriceBookAssignment, PriceBookCollection, PricingRule, PricingRuleCollection, RetailCharge, RetailChargeCollection, SpendingPolicy, SpendingPolicyCollection, SubscriptionPlan, TenantSubscription, TenantUsageMetric, } from './models/index.js';
14
14
  export type { AssignPriceBooksInput, AutoTopUpGrant, AutoTopUpHook, AutoTopUpRequest, BillingRelationshipReader, CommercialBillingStorage, CommercialUsageServiceOptions, CustomPricingContext, CustomPricingStrategy, DefinePriceBookPriceInput, DelegatedSpendingPolicyInput, GrantChildCreditInput, GrantCreditInput, PriceBookAssignmentView, PriceBookLeg, PriceUsageOptions, RateUsageOptions, ResellerBillingAction, ResellerBillingErrorCode, ResellerBillingServiceOptions, SpendingDecision, SpendingEvaluationInput, SpendingPolicyEvaluatorExtensions, SpendingPolicyEvaluatorOptions, UsageRating, } from './services/index.js';
15
15
  export { assertCommercialBillingStorageSupported, CommercialBillingStorageConfigurationError, CommercialUsageService, evaluateThreshold, evaluateThresholds, ResellerBillingError, ResellerBillingService, SpendingPolicyEvaluator, type SubscriptionPlanReader, SubscriptionResolver, type SubscriptionResolverReaders, type TenantSubscriptionReader, TenantUsageMeter, UnsupportedCommercialBillingStorageError, type UsageSummaryReader, } from './services/index.js';
16
- export type { AiUsageSummary, BillingInterval, EntitlementResolution, EntitlementResolutionContext, JsonObject, PlanFeatureGrant, PlanThreshold, RecordUsageOptions, Subscriber, SubscriberKind, SubscriptionPlanStatus, SubscriptionResolverOptions, SubscriptionStatus, SummarizeAiUsageOptions, SummarizeUsageBatchOptions, SummarizeUsageOptions, ThresholdEnforcement, ThresholdEvaluation, ThresholdWindow, UsageMeterOptions, UsageMetricRecord, UsageSummary, UsageWindow, } from './types.js';
16
+ export type { AiUsageSummary, BillingInterval, EntitlementResolution, EntitlementResolutionContext, JsonObject, PlanFeatureGrant, PlanThreshold, PricingMode, RecordUsageOptions, Subscriber, SubscriberKind, SubscriptionPlanStatus, SubscriptionResolverOptions, SubscriptionStatus, SummarizeAiUsageOptions, SummarizeUsageBatchOptions, SummarizeUsageOptions, ThresholdEnforcement, ThresholdEvaluation, ThresholdWindow, UsageMeterOptions, UsageMetricRecord, UsageSummary, UsageWindow, } from './types.js';
17
17
  export { assertSubscriberInvariant, getWindowForThreshold, getWindowKey, isValidThreshold, normalizeFeatureGrants, normalizeSubscriber, subscriberToColumns, } from './utils.js';
18
18
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,wBAAwB,CAAC;AAEhC,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,EAC5B,2BAA2B,GAC5B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,qCAAqC,EACrC,qCAAqC,EACrC,2BAA2B,EAC3B,wCAAwC,GACzC,MAAM,iCAAiC,CAAC;AACzC,YAAY,EACV,aAAa,EACb,eAAe,EACf,aAAa,EACb,cAAc,EACd,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,iBAAiB,EACjB,2BAA2B,EAC3B,YAAY,EACZ,sBAAsB,EACtB,WAAW,EACX,qBAAqB,EACrB,cAAc,EACd,eAAe,EACf,SAAS,EACT,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,qBAAqB,EACrB,YAAY,EACZ,sBAAsB,EACtB,cAAc,EACd,wBAAwB,EACxB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,yBAAyB,EACzB,wBAAwB,EACxB,6BAA6B,EAC7B,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,4BAA4B,EAC5B,qBAAqB,EACrB,gBAAgB,EAChB,uBAAuB,EACvB,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,EACxB,6BAA6B,EAC7B,gBAAgB,EAChB,uBAAuB,EACvB,iCAAiC,EACjC,8BAA8B,EAC9B,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,uCAAuC,EACvC,0CAA0C,EAC1C,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,KAAK,sBAAsB,EAC3B,oBAAoB,EACpB,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC7B,gBAAgB,EAChB,wCAAwC,EACxC,KAAK,kBAAkB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,4BAA4B,EAC5B,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,UAAU,EACV,cAAc,EACd,sBAAsB,EACtB,2BAA2B,EAC3B,kBAAkB,EAClB,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,YAAY,EACZ,gBAAgB,EAChB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,wBAAwB,CAAC;AAEhC,OAAO,EACL,0BAA0B,EAC1B,4BAA4B,EAC5B,2BAA2B,GAC5B,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,qCAAqC,EACrC,qCAAqC,EACrC,2BAA2B,EAC3B,wCAAwC,GACzC,MAAM,iCAAiC,CAAC;AACzC,YAAY,EACV,aAAa,EACb,eAAe,EACf,aAAa,EACb,cAAc,EACd,sBAAsB,GACvB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,iBAAiB,EACjB,2BAA2B,EAC3B,YAAY,EACZ,sBAAsB,EACtB,WAAW,EACX,qBAAqB,EACrB,cAAc,EACd,eAAe,EACf,SAAS,EACT,mBAAmB,EACnB,mBAAmB,EACnB,WAAW,EACX,qBAAqB,EACrB,YAAY,EACZ,sBAAsB,EACtB,cAAc,EACd,wBAAwB,EACxB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,mBAAmB,CAAC;AAC3B,YAAY,EACV,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,gBAAgB,EAChB,yBAAyB,EACzB,wBAAwB,EACxB,6BAA6B,EAC7B,oBAAoB,EACpB,qBAAqB,EACrB,yBAAyB,EACzB,4BAA4B,EAC5B,qBAAqB,EACrB,gBAAgB,EAChB,uBAAuB,EACvB,YAAY,EACZ,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,wBAAwB,EACxB,6BAA6B,EAC7B,gBAAgB,EAChB,uBAAuB,EACvB,iCAAiC,EACjC,8BAA8B,EAC9B,WAAW,GACZ,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,uCAAuC,EACvC,0CAA0C,EAC1C,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,sBAAsB,EACtB,uBAAuB,EACvB,KAAK,sBAAsB,EAC3B,oBAAoB,EACpB,KAAK,2BAA2B,EAChC,KAAK,wBAAwB,EAC7B,gBAAgB,EAChB,wCAAwC,EACxC,KAAK,kBAAkB,GACxB,MAAM,qBAAqB,CAAC;AAC7B,YAAY,EACV,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,4BAA4B,EAC5B,UAAU,EACV,gBAAgB,EAChB,aAAa,EACb,WAAW,EACX,kBAAkB,EAClB,UAAU,EACV,cAAc,EACd,sBAAsB,EACtB,2BAA2B,EAC3B,kBAAkB,EAClB,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,EACrB,oBAAoB,EACpB,mBAAmB,EACnB,eAAe,EACf,iBAAiB,EACjB,iBAAiB,EACjB,YAAY,EACZ,WAAW,GACZ,MAAM,YAAY,CAAC;AACpB,OAAO,EACL,yBAAyB,EACzB,qBAAqB,EACrB,YAAY,EACZ,gBAAgB,EAChB,sBAAsB,EACtB,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,YAAY,CAAC"}