sinfactura-types 1.1.2 → 1.3.0
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/dist/subscription.d.ts +125 -59
- package/dist/subscription.js +9 -7
- package/package.json +1 -1
package/dist/subscription.d.ts
CHANGED
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
* Subscription types — plan tiers, entitlements, feature matrix, subscription state.
|
|
3
3
|
*
|
|
4
4
|
* Ships app#710 (Chunk 1). Canonical decisions live in
|
|
5
|
-
* sinfactura/app/docs/plans/SUBSCRIPTION_BUSINESS_DECISIONS.md
|
|
5
|
+
* sinfactura/app/docs/plans/SUBSCRIPTION_BUSINESS_DECISIONS.md and
|
|
6
|
+
* sinfactura/app/docs/adr/0010-launch-trial-policy.md.
|
|
6
7
|
*
|
|
7
8
|
* Notes:
|
|
8
|
-
* - Tier names are the
|
|
9
|
-
* and api#802
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
9
|
+
* - Tier names are the 4 locked Spanish tiers (per SUBSCRIPTION_TIERS_BEST_PRACTICES §0
|
|
10
|
+
* and api#802): BÁSICO, EMPRENDEDOR, PROFESIONAL, AVANZADO. The launch policy
|
|
11
|
+
* (ADR-0010) gives every new paid subscription a 30-day Stripe trial; courtesy
|
|
12
|
+
* gifts (formerly the Founders cohort) are now a one-off ops action via
|
|
13
|
+
* `gift-subscription` that sets `freeUntil` on the SUBSCRIPTION row.
|
|
14
|
+
* - `freeUntil` lives on every Subscription independent of status. It is the
|
|
15
|
+
* courtesy-gift cutoff; while `freeUntil > now` the BE suppresses billing.
|
|
14
16
|
* - `FeatureKey` uses flat camelCase (not the dotted `reports.advanced` from the design kit).
|
|
15
17
|
* - Monetary amounts are integers in minor units (ARS cents) to avoid float issues.
|
|
16
18
|
* - Feature keys now match the BE wire format directly (renamed afip→afipInvoicing,
|
|
@@ -20,19 +22,21 @@
|
|
|
20
22
|
* enabled:false until they do.
|
|
21
23
|
*/
|
|
22
24
|
declare global {
|
|
23
|
-
type PlanTier = 'basico' | 'emprendedor' | 'profesional' | 'avanzado'
|
|
25
|
+
type PlanTier = 'basico' | 'emprendedor' | 'profesional' | 'avanzado';
|
|
24
26
|
/**
|
|
25
27
|
* Lifecycle status of a tenant's subscription.
|
|
26
28
|
*
|
|
27
|
-
* - `trialing` — new signup in
|
|
29
|
+
* - `trialing` — new paid-tier signup in their 30-day Stripe trial.
|
|
28
30
|
* - `active` — paid subscription, period current.
|
|
29
31
|
* - `past_due` — payment failed, in the 7-day grace window.
|
|
30
32
|
* - `readonly` — grace elapsed, writes blocked, tenant can still read.
|
|
31
33
|
* - `canceled` — tenant ended subscription; data retained per grace policy.
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
+
*
|
|
35
|
+
* Courtesy gifts (formerly the Founders cohort, ADR-0009) are no longer a
|
|
36
|
+
* status — they are represented by `Subscription.freeUntil` on top of any
|
|
37
|
+
* normal status. See ADR-0010.
|
|
34
38
|
*/
|
|
35
|
-
type SubscriptionStatus = 'trialing' | 'active' | 'past_due' | 'readonly' | 'canceled'
|
|
39
|
+
type SubscriptionStatus = 'trialing' | 'active' | 'past_due' | 'readonly' | 'canceled';
|
|
36
40
|
type BillingCycle = 'monthly' | 'annual';
|
|
37
41
|
/**
|
|
38
42
|
* Shape of a single entitlement on a (tier, feature) cell.
|
|
@@ -65,57 +69,122 @@ declare global {
|
|
|
65
69
|
/** Resolved entitlements for a specific tenant (matrix + overrides applied). */
|
|
66
70
|
type ResolvedEntitlements = Record<FeatureKey, Entitlement>;
|
|
67
71
|
/**
|
|
68
|
-
*
|
|
69
|
-
*
|
|
72
|
+
* Implementation status of a feature on a plan row. Informational —
|
|
73
|
+
* gating still happens via `enabled` / `limit`. `'service'` rows
|
|
74
|
+
* (e.g. prioritySupport) are human-delivered but still gated like
|
|
75
|
+
* booleans.
|
|
76
|
+
*/
|
|
77
|
+
type PlanFeatureStatus = 'live' | 'planned' | 'future' | 'service';
|
|
78
|
+
/**
|
|
79
|
+
* A single feature row in a Plan's `features[]` array. Matches the
|
|
80
|
+
* BE wire format from `GET /subscription/plans` exactly — boolean
|
|
81
|
+
* features carry `enabled`, numeric/metered carry `limit` (-1 =
|
|
82
|
+
* unlimited).
|
|
83
|
+
*/
|
|
84
|
+
interface PlanFeature {
|
|
85
|
+
key: FeatureKey;
|
|
86
|
+
type: EntitlementType;
|
|
87
|
+
status: PlanFeatureStatus;
|
|
88
|
+
/** User-facing Spanish description. */
|
|
89
|
+
description: string;
|
|
90
|
+
/** Set on `boolean` features; `null` on numeric/metered. */
|
|
91
|
+
enabled: boolean | null;
|
|
92
|
+
/** Set on `numeric`/`metered` features; `null` on boolean. -1 = unlimited. */
|
|
93
|
+
limit: number | null;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* A sellable plan in the catalog. Aligned with the BE wire format from
|
|
97
|
+
* `GET /subscription/plans` (api#859). Source of truth lives in
|
|
98
|
+
* DynamoDB (`PLAN#{tier}` partition), administered via `POST /sa/plans`
|
|
99
|
+
* + `PATCH /sa/plans/{tier}` (api#859).
|
|
100
|
+
*
|
|
101
|
+
* Prices are integers in the `currency` smallest unit (centavos for ARS,
|
|
102
|
+
* cents for USD). `null` = "Contactar ventas" (AVANZADO annual at launch
|
|
103
|
+
* is sales-led; basico/fundador are free) per spec §6.4.
|
|
104
|
+
*
|
|
105
|
+
* **Breaking change vs 1.1.x:** the catalog Plan interface was reshaped
|
|
106
|
+
* to match the BE wire format. Renames & removals:
|
|
107
|
+
* - `label` → `name`
|
|
108
|
+
* - `blurb` → `description`
|
|
109
|
+
* - `priceMonthly` → `priceMonthlyCents` (number | null)
|
|
110
|
+
* - `priceAnnual` → `priceAnnualCents` (number | null)
|
|
111
|
+
* - `currency` widened to `'ARS' | 'USD' | null`
|
|
112
|
+
* - `entitlements: Record<FeatureKey, Entitlement>` → `features: PlanFeature[]`
|
|
113
|
+
* - `isPublic` removed (use `isActive` for visibility gating)
|
|
114
|
+
* - `stripeMonthlyPriceId` / `stripeAnnualPriceId` /
|
|
115
|
+
* `mpPreApprovalPlanIdMonthly` / `mpPreApprovalPlanIdAnnual` removed
|
|
116
|
+
* (BE-internal — not on the public wire format)
|
|
117
|
+
* - `createdAt` / `updatedAt` removed (not on the public wire format)
|
|
70
118
|
*
|
|
71
|
-
*
|
|
72
|
-
* `
|
|
119
|
+
* Added per api#859:
|
|
120
|
+
* - `displayOrder` (number)
|
|
121
|
+
* - `color` (single hex string, FE derives `soft`/`border` shades)
|
|
122
|
+
* - `isPopular` (now required, was optional)
|
|
73
123
|
*/
|
|
74
124
|
interface Plan {
|
|
75
125
|
tier: PlanTier;
|
|
76
|
-
/** Display
|
|
77
|
-
|
|
78
|
-
/** Short marketing
|
|
79
|
-
|
|
80
|
-
/** Price in the plan's `currency` smallest unit for monthly billing. `null` = contactar. */
|
|
81
|
-
priceMonthly: number | null;
|
|
82
|
-
/** Price in the plan's `currency` smallest unit for annual billing (total / 12; ~20% discount). `null` = contactar. */
|
|
83
|
-
priceAnnual: number | null;
|
|
126
|
+
/** Display name in Spanish (e.g. "Profesional"). */
|
|
127
|
+
name: string;
|
|
128
|
+
/** Short marketing one-liner in Spanish. */
|
|
129
|
+
description: string;
|
|
84
130
|
/**
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
* without a type change once the platform flips.
|
|
131
|
+
* Whether the plan is shown on the pricing page and accepting new
|
|
132
|
+
* subscribers. Pre-launch / sales-led tiers (e.g. AVANZADO until ≥2
|
|
133
|
+
* Planned features ship) set this to `false` without deleting the row.
|
|
89
134
|
*/
|
|
90
|
-
|
|
135
|
+
isActive: boolean;
|
|
91
136
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
137
|
+
* Anchor / recommended tier on the pricing page. The FE typically
|
|
138
|
+
* renders the "Más elegido" pill on the plan(s) flagged here. The
|
|
139
|
+
* BE does not enforce uniqueness — admins can flag any number of
|
|
140
|
+
* plans, but the canonical convention is exactly one.
|
|
95
141
|
*/
|
|
96
|
-
|
|
97
|
-
/**
|
|
98
|
-
|
|
142
|
+
isPopular: boolean;
|
|
143
|
+
/** Sort order on the pricing page (ascending). Ties allowed. */
|
|
144
|
+
displayOrder: number;
|
|
145
|
+
/** Monthly price in `currency` smallest units. `null` = sales-led / free. */
|
|
146
|
+
priceMonthlyCents: number | null;
|
|
147
|
+
/** Annual price in `currency` smallest units. `null` = sales-led / free. */
|
|
148
|
+
priceAnnualCents: number | null;
|
|
149
|
+
/**
|
|
150
|
+
* Currency the prices are denominated in. `'ARS'` at launch; `'USD'`
|
|
151
|
+
* is the migration target (api#841). `null` on free / off-billing
|
|
152
|
+
* tiers (basico).
|
|
153
|
+
*/
|
|
154
|
+
currency: 'ARS' | 'USD' | null;
|
|
99
155
|
/**
|
|
100
|
-
*
|
|
101
|
-
*
|
|
156
|
+
* Single brand hex color (e.g. '#590d82'). The FE derives `soft`
|
|
157
|
+
* (light tint) and `border` shades via MUI's `alpha()` helper.
|
|
158
|
+
* `null` on plans created/seeded before the api#859 backfill.
|
|
102
159
|
*/
|
|
103
|
-
|
|
104
|
-
/** Stripe Price IDs once the plan is wired to Stripe Products (api#627). */
|
|
105
|
-
stripeMonthlyPriceId?: string;
|
|
106
|
-
stripeAnnualPriceId?: string;
|
|
160
|
+
color: string | null;
|
|
107
161
|
/**
|
|
108
|
-
*
|
|
109
|
-
*
|
|
110
|
-
* IDs above on the same Plan row so both providers' state can live
|
|
111
|
-
* in one place; unused fields stay dormant.
|
|
162
|
+
* Per-feature configuration. Every `FeatureKey` appears exactly once.
|
|
163
|
+
* Boolean features carry `enabled`; numeric/metered carry `limit`.
|
|
112
164
|
*/
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
165
|
+
features: PlanFeature[];
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* One audit row per SUPER_ADMIN-driven plan mutation. Returned by
|
|
169
|
+
* `GET /sa/plans/{tier}/audit` (api#859). The same row shape is used
|
|
170
|
+
* for the sibling `STORE` audit partition (api#827).
|
|
171
|
+
*
|
|
172
|
+
* `before` and `after` carry only the fields that changed (diff slice),
|
|
173
|
+
* not the full row blob.
|
|
174
|
+
*/
|
|
175
|
+
interface PlanAuditEntry {
|
|
176
|
+
entity: 'PLAN';
|
|
177
|
+
entityId: string;
|
|
178
|
+
timestamp: number;
|
|
179
|
+
actor: {
|
|
180
|
+
userId: string;
|
|
181
|
+
fullName: string;
|
|
182
|
+
};
|
|
183
|
+
action: string;
|
|
184
|
+
before: Record<string, unknown>;
|
|
185
|
+
after: Record<string, unknown>;
|
|
186
|
+
reason: string;
|
|
117
187
|
createdAt: number;
|
|
118
|
-
updatedAt: number;
|
|
119
188
|
}
|
|
120
189
|
/**
|
|
121
190
|
* A tenant's current subscription row. One per `tenantId`.
|
|
@@ -141,17 +210,13 @@ declare global {
|
|
|
141
210
|
/** Set while `status === 'trialing'`. Unix ms. */
|
|
142
211
|
trialEndsAt?: number;
|
|
143
212
|
/**
|
|
144
|
-
*
|
|
145
|
-
*
|
|
146
|
-
*
|
|
147
|
-
*
|
|
213
|
+
* Courtesy-gift cutoff (ADR-0010) — YYYY-MM-DD up to which billing is
|
|
214
|
+
* suppressed regardless of `status`. String (not numeric ms) so it's
|
|
215
|
+
* human-readable in the DynamoDB console. Set/cleared via the
|
|
216
|
+
* `gift-subscription` super endpoint with an audit-logged reason.
|
|
148
217
|
*/
|
|
149
218
|
freeUntil?: string;
|
|
150
|
-
/**
|
|
151
|
-
graceUntil?: string;
|
|
152
|
-
/** Founders cohort only — eligible for the perpetual founder discount after cutoff. */
|
|
153
|
-
founderDiscountEligible?: boolean;
|
|
154
|
-
/** Stripe identifiers (absent for trialing/fundador before checkout). */
|
|
219
|
+
/** Stripe identifiers (absent before first checkout). */
|
|
155
220
|
stripeCustomerId?: string;
|
|
156
221
|
stripeSubscriptionId?: string;
|
|
157
222
|
/**
|
|
@@ -204,6 +269,7 @@ declare global {
|
|
|
204
269
|
currentPeriodStart: number | null;
|
|
205
270
|
currentPeriodEnd: number | null;
|
|
206
271
|
trialEndsAt: number | null;
|
|
272
|
+
/** Courtesy-gift cutoff (ADR-0010). YYYY-MM-DD or omitted. */
|
|
207
273
|
freeUntil?: string;
|
|
208
274
|
cancelAt: number | null;
|
|
209
275
|
canceledAt: number | null;
|
package/dist/subscription.js
CHANGED
|
@@ -2,15 +2,17 @@
|
|
|
2
2
|
* Subscription types — plan tiers, entitlements, feature matrix, subscription state.
|
|
3
3
|
*
|
|
4
4
|
* Ships app#710 (Chunk 1). Canonical decisions live in
|
|
5
|
-
* sinfactura/app/docs/plans/SUBSCRIPTION_BUSINESS_DECISIONS.md
|
|
5
|
+
* sinfactura/app/docs/plans/SUBSCRIPTION_BUSINESS_DECISIONS.md and
|
|
6
|
+
* sinfactura/app/docs/adr/0010-launch-trial-policy.md.
|
|
6
7
|
*
|
|
7
8
|
* Notes:
|
|
8
|
-
* - Tier names are the
|
|
9
|
-
* and api#802
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
9
|
+
* - Tier names are the 4 locked Spanish tiers (per SUBSCRIPTION_TIERS_BEST_PRACTICES §0
|
|
10
|
+
* and api#802): BÁSICO, EMPRENDEDOR, PROFESIONAL, AVANZADO. The launch policy
|
|
11
|
+
* (ADR-0010) gives every new paid subscription a 30-day Stripe trial; courtesy
|
|
12
|
+
* gifts (formerly the Founders cohort) are now a one-off ops action via
|
|
13
|
+
* `gift-subscription` that sets `freeUntil` on the SUBSCRIPTION row.
|
|
14
|
+
* - `freeUntil` lives on every Subscription independent of status. It is the
|
|
15
|
+
* courtesy-gift cutoff; while `freeUntil > now` the BE suppresses billing.
|
|
14
16
|
* - `FeatureKey` uses flat camelCase (not the dotted `reports.advanced` from the design kit).
|
|
15
17
|
* - Monetary amounts are integers in minor units (ARS cents) to avoid float issues.
|
|
16
18
|
* - Feature keys now match the BE wire format directly (renamed afip→afipInvoicing,
|