platform-types 1.10.701 → 1.10.703

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/basket.d.ts CHANGED
@@ -63,9 +63,9 @@ declare global {
63
63
  }
64
64
  }
65
65
  /**
66
- * Domain refusals from POST /baskets: legacy replacement, named cart actions,
67
- * and park/resume. Check GATING_ERROR_CODES separately for middleware and role
68
- * refusals. GET /baskets and storefront-only refusals are outside this tuple.
66
+ * Domain refusals from POST /baskets (replacement, named actions and park/resume)
67
+ * and GET /baskets?mode=review. Check GATING_ERROR_CODES separately for middleware
68
+ * and role refusals. Other GET modes and storefront-only refusals remain separate.
69
69
  *
70
70
  * Coupon and promotion reasons are forwarded from evaluateCoupon and
71
71
  * evaluatePromotion (stacks/services/coupons.ts and promotions.ts). Checkout's
@@ -74,6 +74,6 @@ declare global {
74
74
  * priceHandler.resolveLineStamp. The legacy loose body also reaches the shared
75
75
  * foreign-index-key guard; its owned terminalId is validated before that guard.
76
76
  */
77
- export declare const BASKET_ERROR_CODES: readonly ["VALIDATION_FAILED", "FOREIGN_INDEX_KEY_ATTRIBUTE", "CART_TARGET_REQUIRED", "CART_NOT_FOUND", "CART_NOT_PARKED", "CART_ALREADY_PARKED", "TERMINAL_INDEX_UNAVAILABLE", "PRODUCT_NOT_FOUND", "PRODUCT_COST_UNKNOWN", "UNIT_QUANTITY_NOT_WHOLE", "BASKET_VERSION_CONFLICT", "BASKET_LINE_LIMIT", "BASKET_SIZE_LIMIT", "UNKNOWN_LINE", "INVALID_PRICE", "LINE_DISCOUNT_NOT_ALLOWED", "LINE_DISCOUNT_EXCEEDS_MAX", "FX_CONVERSION_UNAVAILABLE", "COUPON_NOT_FOUND", "COUPON_NOT_ACTIVE", "COUPON_EXPIRED", "COUPON_EXHAUSTED", "COUPON_MIN_SUBTOTAL", "COUPON_REQUIRES_CUSTOMER", "COUPON_BUDGET_EXHAUSTED", "COUPON_RATE_LIMITED", "COUPON_CURRENCY_MISMATCH", "PROMOTION_NOT_FOUND", "PROMOTION_NOT_ACTIVE", "PROMOTION_NOT_STARTED", "PROMOTION_EXPIRED", "PROMOTION_NOT_CART_APPLICABLE"];
77
+ export declare const BASKET_ERROR_CODES: readonly ["VALIDATION_FAILED", "FOREIGN_INDEX_KEY_ATTRIBUTE", "CART_TARGET_REQUIRED", "CART_NOT_FOUND", "CART_REVIEW_INCOMPLETE", "CART_REVIEW_UNAVAILABLE", "CART_NOT_PARKED", "CART_ALREADY_PARKED", "TERMINAL_INDEX_UNAVAILABLE", "PRODUCT_NOT_FOUND", "PRODUCT_COST_UNKNOWN", "UNIT_QUANTITY_NOT_WHOLE", "BASKET_VERSION_CONFLICT", "BASKET_LINE_LIMIT", "BASKET_SIZE_LIMIT", "UNKNOWN_LINE", "INVALID_PRICE", "LINE_DISCOUNT_NOT_ALLOWED", "LINE_DISCOUNT_EXCEEDS_MAX", "FX_CONVERSION_UNAVAILABLE", "COUPON_NOT_FOUND", "COUPON_NOT_ACTIVE", "COUPON_EXPIRED", "COUPON_EXHAUSTED", "COUPON_MIN_SUBTOTAL", "COUPON_REQUIRES_CUSTOMER", "COUPON_BUDGET_EXHAUSTED", "COUPON_RATE_LIMITED", "COUPON_CURRENCY_MISMATCH", "PROMOTION_NOT_FOUND", "PROMOTION_NOT_ACTIVE", "PROMOTION_NOT_STARTED", "PROMOTION_EXPIRED", "PROMOTION_NOT_CART_APPLICABLE"];
78
78
  export type BasketErrorCode = (typeof BASKET_ERROR_CODES)[number];
79
79
  export {};
package/dist/basket.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /**
2
- * Domain refusals from POST /baskets: legacy replacement, named cart actions,
3
- * and park/resume. Check GATING_ERROR_CODES separately for middleware and role
4
- * refusals. GET /baskets and storefront-only refusals are outside this tuple.
2
+ * Domain refusals from POST /baskets (replacement, named actions and park/resume)
3
+ * and GET /baskets?mode=review. Check GATING_ERROR_CODES separately for middleware
4
+ * and role refusals. Other GET modes and storefront-only refusals remain separate.
5
5
  *
6
6
  * Coupon and promotion reasons are forwarded from evaluateCoupon and
7
7
  * evaluatePromotion (stacks/services/coupons.ts and promotions.ts). Checkout's
@@ -15,6 +15,8 @@ export const BASKET_ERROR_CODES = [
15
15
  'FOREIGN_INDEX_KEY_ATTRIBUTE',
16
16
  'CART_TARGET_REQUIRED',
17
17
  'CART_NOT_FOUND',
18
+ 'CART_REVIEW_INCOMPLETE',
19
+ 'CART_REVIEW_UNAVAILABLE',
18
20
  'CART_NOT_PARKED',
19
21
  'CART_ALREADY_PARKED',
20
22
  'TERMINAL_INDEX_UNAVAILABLE',
package/dist/cart.d.ts CHANGED
@@ -1,4 +1,24 @@
1
1
  declare global {
2
+ interface OperatorCartReviewRequest {
3
+ mode: 'review';
4
+ customerId: string;
5
+ cartId?: string;
6
+ }
7
+ interface OperatorCartReviewCart extends Omit<Cart, 'customer'> {
8
+ customer?: Partial<Pick<Customer, 'customerId' | 'fullName'>>;
9
+ }
10
+ type OperatorCartReviewData = OperatorCartReviewCart | null;
11
+ /**
12
+ * Completed discovery returns null; an exact missing cart is a refusal.
13
+ * Discovery over several customer carts is never ambiguous: it returns the
14
+ * cart a customer-targeted write resolves (a terminal-less cart before a
15
+ * till's ticket, newest within each group, a new-partition row before a
16
+ * legacy one).
17
+ */
18
+ interface OperatorCartReviewResponse {
19
+ message: string;
20
+ data: OperatorCartReviewData;
21
+ }
2
22
  /**
3
23
  * A cart, keyed by its OWN minted id rather than by the customer.
4
24
  *
@@ -2,9 +2,9 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BASKET_ERROR_CODES = void 0;
4
4
  /**
5
- * Domain refusals from POST /baskets: legacy replacement, named cart actions,
6
- * and park/resume. Check GATING_ERROR_CODES separately for middleware and role
7
- * refusals. GET /baskets and storefront-only refusals are outside this tuple.
5
+ * Domain refusals from POST /baskets (replacement, named actions and park/resume)
6
+ * and GET /baskets?mode=review. Check GATING_ERROR_CODES separately for middleware
7
+ * and role refusals. Other GET modes and storefront-only refusals remain separate.
8
8
  *
9
9
  * Coupon and promotion reasons are forwarded from evaluateCoupon and
10
10
  * evaluatePromotion (stacks/services/coupons.ts and promotions.ts). Checkout's
@@ -18,6 +18,8 @@ exports.BASKET_ERROR_CODES = [
18
18
  'FOREIGN_INDEX_KEY_ATTRIBUTE',
19
19
  'CART_TARGET_REQUIRED',
20
20
  'CART_NOT_FOUND',
21
+ 'CART_REVIEW_INCOMPLETE',
22
+ 'CART_REVIEW_UNAVAILABLE',
21
23
  'CART_NOT_PARKED',
22
24
  'CART_ALREADY_PARKED',
23
25
  'TERMINAL_INDEX_UNAVAILABLE',
@@ -8,8 +8,11 @@
8
8
  *
9
9
  * Notes:
10
10
  * - Tier names are the 4 locked Spanish tiers (per SUBSCRIPTION_TIERS_BEST_PRACTICES §0):
11
- * BÁSICO, EMPRENDEDOR, PROFESIONAL, AVANZADO. The launch policy
12
- * (ADR-0010) gives every new paid subscription a 30-day Stripe trial; courtesy
11
+ * BÁSICO, EMPRENDEDOR, PROFESIONAL, AVANZADO. A new store starts trialing on
12
+ * the `trialTier` platform global, with `trialEndsAt` set `trialDays` days out
13
+ * (see `PlanCatalogue.trial`); that date is not yet enforced for a store
14
+ * without a payment provider. A Stripe checkout adds its own fixed 30-day
15
+ * trial, which does not follow those globals (ADR-0010). Courtesy
13
16
  * gifts (formerly the Founders cohort) are now a one-off ops action via
14
17
  * `gift-subscription` that sets `freeUntil` on the SUBSCRIPTION row.
15
18
  * - `freeUntil` lives on every Subscription independent of status. It is the
@@ -24,7 +27,7 @@
24
27
  * enabled:false until they do.
25
28
  */
26
29
  Object.defineProperty(exports, "__esModule", { value: true });
27
- exports.FEATURE_KEYS = exports.PLAN_TIERS = void 0;
30
+ exports.FEATURE_KEYS = exports.isPaidPlanTier = exports.PAID_PLAN_TIERS = exports.PLAN_TIERS = void 0;
28
31
  /*
29
32
  * Runtime tuples for the unions above.
30
33
  *
@@ -44,6 +47,15 @@ exports.FEATURE_KEYS = exports.PLAN_TIERS = void 0;
44
47
  const exhaustiveTuple = () => (tuple) => tuple;
45
48
  /** Every plan tier, in rank order (lowest first). */
46
49
  exports.PLAN_TIERS = exhaustiveTuple()(['basico', 'emprendedor', 'profesional', 'avanzado']);
50
+ /**
51
+ * Every paid tier, in rank order (lowest first) — `PLAN_TIERS` without the free
52
+ * `basico`. The one list of "tiers that bill": the trial-tier vocabulary, the
53
+ * grace sweep's tier fan-out and the provider plan seeders all read it.
54
+ */
55
+ exports.PAID_PLAN_TIERS = exhaustiveTuple()(['emprendedor', 'profesional', 'avanzado']);
56
+ /** Whether `value` names a paid tier — narrows an untyped read (a stored row, a global) to `PaidPlanTier`. */
57
+ const isPaidPlanTier = (value) => typeof value === 'string' && exports.PAID_PLAN_TIERS.includes(value);
58
+ exports.isPaidPlanTier = isPaidPlanTier;
47
59
  /**
48
60
  * Every gated feature key.
49
61
  *
@@ -7,8 +7,11 @@
7
7
  *
8
8
  * Notes:
9
9
  * - Tier names are the 4 locked Spanish tiers (per SUBSCRIPTION_TIERS_BEST_PRACTICES §0):
10
- * BÁSICO, EMPRENDEDOR, PROFESIONAL, AVANZADO. The launch policy
11
- * (ADR-0010) gives every new paid subscription a 30-day Stripe trial; courtesy
10
+ * BÁSICO, EMPRENDEDOR, PROFESIONAL, AVANZADO. A new store starts trialing on
11
+ * the `trialTier` platform global, with `trialEndsAt` set `trialDays` days out
12
+ * (see `PlanCatalogue.trial`); that date is not yet enforced for a store
13
+ * without a payment provider. A Stripe checkout adds its own fixed 30-day
14
+ * trial, which does not follow those globals (ADR-0010). Courtesy
12
15
  * gifts (formerly the Founders cohort) are now a one-off ops action via
13
16
  * `gift-subscription` that sets `freeUntil` on the SUBSCRIPTION row.
14
17
  * - `freeUntil` lives on every Subscription independent of status. It is the
@@ -24,10 +27,15 @@
24
27
  */
25
28
  declare global {
26
29
  type PlanTier = 'basico' | 'emprendedor' | 'profesional' | 'avanzado';
30
+ /** A tier that bills — every `PlanTier` but the free `basico`. Enumerated by `PAID_PLAN_TIERS`. */
31
+ type PaidPlanTier = Exclude<PlanTier, 'basico'>;
27
32
  /**
28
33
  * Lifecycle status of a tenant's subscription.
29
34
  *
30
- * - `trialing` — new paid-tier signup in their 30-day Stripe trial.
35
+ * - `trialing` — a trial on a paid tier: a new store trials on the
36
+ * `trialTier` platform global with `trialEndsAt` set `trialDays` days out
37
+ * (`PlanCatalogue.trial`) — a date not yet enforced for a store without a
38
+ * payment provider — and a Stripe checkout adds its own fixed 30-day trial.
31
39
  * - `active` — paid subscription, period current.
32
40
  * - `past_due` — payment failed, in the 7-day grace window.
33
41
  * - `readonly` — grace elapsed, writes blocked, tenant can still read.
@@ -319,13 +327,24 @@ declare global {
319
327
  }
320
328
  /**
321
329
  * `data` of `GET /public/plans` and `GET /subscription/plans` — both return
322
- * the same `{ plans, groups }`: the plans plus the feature groups their rows
323
- * render under.
330
+ * the same `{ plans, groups, trial }`: the plans, the feature groups their
331
+ * rows render under, and the trial a new store starts on.
324
332
  */
325
333
  interface PlanCatalogue {
326
334
  plans: Plan[];
327
335
  /** Every group a `features[].group` can name, with its label and sort position. */
328
336
  groups: PlanFeatureGroup[];
337
+ /**
338
+ * What a store registered now starts on: `tier` — a paid tier — in status
339
+ * `trialing`, with `trialEndsAt` set `days` days out. That date is not yet
340
+ * enforced for a store without a payment provider. Resolved from the platform globals
341
+ * `trialTier` / `trialDays` — `profesional` / `30` when unset or invalid —
342
+ * so it is always present.
343
+ */
344
+ trial: {
345
+ tier: PaidPlanTier;
346
+ days: number;
347
+ };
329
348
  }
330
349
  /**
331
350
  * One audit row per MANAGER-driven plan mutation (`POST` / `PATCH
@@ -422,17 +441,35 @@ declare global {
422
441
  /** A single usage entry as returned by GET /subscription. */
423
442
  interface SubscriptionUsageEntry {
424
443
  key: FeatureKey;
425
- /** Period in YYYYMM format; `null` for lifetime caps (maxProducts/maxCustomers/maxUsers). */
444
+ /**
445
+ * Period in YYYYMM format for a monthly counter; `null` for a cap that never
446
+ * resets — the lifetime caps (maxProducts/maxCustomers/maxUsers) and the
447
+ * row-counted ones (webhooks, maxWarehouses: active rows, as their caps count).
448
+ */
426
449
  period: string | null;
427
450
  current: number;
428
- /** `null` for unlimited tiers (no cap). */
451
+ /**
452
+ * The resolved ceiling: `-1` is the unlimited sentinel, and `null` means
453
+ * the plan declares no ceiling for this key.
454
+ */
429
455
  limit: number | null;
430
- /** `null` when `limit` is unlimited/uncapped. */
456
+ /** `limit - current`, floored at zero; `null` whenever `limit` is `-1` or `null`. */
431
457
  remaining: number | null;
432
458
  }
433
459
  /**
434
- * Full subscription snapshot pushed to the frontend on subscription/entitlement
435
- * changes. Flat shape — matches GET /subscription wire format directly.
460
+ * Full subscription snapshot. Three producers emit it:
461
+ *
462
+ * - `GET /subscription` — the full `usage[]`, including the row-counted
463
+ * `webhooks` / `maxWarehouses` meters. The two are present together or
464
+ * absent together: both are absent when the row count failed in this pass,
465
+ * and absent is not zero;
466
+ * - the `GET /store` subscription embed — WITHOUT those two meters (monthly
467
+ * and lifetime only) and without `provider`;
468
+ * - the reply of the MANAGER `PUT /platform/stores/{storeId}/subscription` —
469
+ * built by the same assembly as `GET /subscription`, meters included.
470
+ *
471
+ * The WebSocket only nudges a refetch on subscription/entitlement changes; it
472
+ * never carries this payload.
436
473
  */
437
474
  interface SubscriptionSyncPayload {
438
475
  planTier: PlanTier;
@@ -738,6 +775,14 @@ export type BillingProviderName = SubscriptionProvider;
738
775
  export type InvoiceSummary = globalThis.InvoiceSummary;
739
776
  /** Every plan tier, in rank order (lowest first). */
740
777
  export declare const PLAN_TIERS: readonly ["basico", "emprendedor", "profesional", "avanzado"];
778
+ /**
779
+ * Every paid tier, in rank order (lowest first) — `PLAN_TIERS` without the free
780
+ * `basico`. The one list of "tiers that bill": the trial-tier vocabulary, the
781
+ * grace sweep's tier fan-out and the provider plan seeders all read it.
782
+ */
783
+ export declare const PAID_PLAN_TIERS: readonly ["emprendedor", "profesional", "avanzado"];
784
+ /** Whether `value` names a paid tier — narrows an untyped read (a stored row, a global) to `PaidPlanTier`. */
785
+ export declare const isPaidPlanTier: (value: unknown) => value is PaidPlanTier;
741
786
  /**
742
787
  * Every gated feature key.
743
788
  *
@@ -7,8 +7,11 @@
7
7
  *
8
8
  * Notes:
9
9
  * - Tier names are the 4 locked Spanish tiers (per SUBSCRIPTION_TIERS_BEST_PRACTICES §0):
10
- * BÁSICO, EMPRENDEDOR, PROFESIONAL, AVANZADO. The launch policy
11
- * (ADR-0010) gives every new paid subscription a 30-day Stripe trial; courtesy
10
+ * BÁSICO, EMPRENDEDOR, PROFESIONAL, AVANZADO. A new store starts trialing on
11
+ * the `trialTier` platform global, with `trialEndsAt` set `trialDays` days out
12
+ * (see `PlanCatalogue.trial`); that date is not yet enforced for a store
13
+ * without a payment provider. A Stripe checkout adds its own fixed 30-day
14
+ * trial, which does not follow those globals (ADR-0010). Courtesy
12
15
  * gifts (formerly the Founders cohort) are now a one-off ops action via
13
16
  * `gift-subscription` that sets `freeUntil` on the SUBSCRIPTION row.
14
17
  * - `freeUntil` lives on every Subscription independent of status. It is the
@@ -41,6 +44,14 @@
41
44
  const exhaustiveTuple = () => (tuple) => tuple;
42
45
  /** Every plan tier, in rank order (lowest first). */
43
46
  export const PLAN_TIERS = exhaustiveTuple()(['basico', 'emprendedor', 'profesional', 'avanzado']);
47
+ /**
48
+ * Every paid tier, in rank order (lowest first) — `PLAN_TIERS` without the free
49
+ * `basico`. The one list of "tiers that bill": the trial-tier vocabulary, the
50
+ * grace sweep's tier fan-out and the provider plan seeders all read it.
51
+ */
52
+ export const PAID_PLAN_TIERS = exhaustiveTuple()(['emprendedor', 'profesional', 'avanzado']);
53
+ /** Whether `value` names a paid tier — narrows an untyped read (a stored row, a global) to `PaidPlanTier`. */
54
+ export const isPaidPlanTier = (value) => typeof value === 'string' && PAID_PLAN_TIERS.includes(value);
44
55
  /**
45
56
  * Every gated feature key.
46
57
  *
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "platform-types",
3
- "version": "1.10.701",
3
+ "version": "1.10.703",
4
4
  "description": "Shared wire and entity contracts for the platform.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",