platform-types 1.10.734 → 1.10.735

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/cjs/store.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.STORE_MODULE_ERROR_CODES = exports.isStoreModuleOn = exports.isStoreModuleKey = exports.STORE_MODULE_KEYS = exports.CUSTOM_DOMAIN_ROW_LIMIT = exports.CUSTOM_DOMAIN_SLOT_LIMIT = void 0;
3
+ exports.STORE_PATCH_ERROR_CODES = exports.STORE_MODULE_ERROR_CODES = exports.isStoreModuleOn = exports.isStoreModuleKey = exports.STORE_MODULE_KEYS = exports.CUSTOM_DOMAIN_ROW_LIMIT = exports.CUSTOM_DOMAIN_SLOT_LIMIT = void 0;
4
4
  /**
5
5
  * How many custom-domain rows a store may hold that count: one active domain
6
6
  * and one spare, so a replacement can be verified and provisioned before the
@@ -52,9 +52,11 @@ exports.isStoreModuleKey = isStoreModuleKey;
52
52
  const isStoreModuleOn = (modules, module) => modules?.[module] !== false;
53
53
  exports.isStoreModuleOn = isStoreModuleOn;
54
54
  /**
55
- * Every refusal code the store-module switches put on the wire, beyond the
56
- * platform-wide set (`VALIDATION_FAILED`, and `STORE_CONFIG_FORBIDDEN` for a
57
- * plain USER writing the privileged leaf):
55
+ * Every refusal code the store-module switches put on the wire. Not listed
56
+ * here: `VALIDATION_FAILED` (a malformed body), and `STORE_CONFIG_FORBIDDEN` —
57
+ * the `PATCH /store` role refusal a plain USER gets for ANY privileged `config`
58
+ * leaf, `modules` included, judged before this module code runs. That one is in
59
+ * {@link STORE_PATCH_ERROR_CODES}:
58
60
  *
59
61
  * - `STORE_MODULE_UNKNOWN` (400) — `PATCH /store` named a key outside
60
62
  * `STORE_MODULE_KEYS`; `data.module` carries it.
@@ -91,3 +93,69 @@ exports.STORE_MODULE_ERROR_CODES = [
91
93
  'STORE_MODULE_SHIFTS_OPEN',
92
94
  'STORE_MODULE_DISABLED',
93
95
  ];
96
+ /**
97
+ * The bare refusal codes `PATCH /store` (`stacks/lambdas/store/_patch.ts`, and
98
+ * the route's own sibling modules it calls) answers itself — `{ error, message }`
99
+ * with no `data`, unless noted:
100
+ *
101
+ * Role refusals, `403` — a plain USER writing a privileged section. Each is
102
+ * judged before any other check on that section:
103
+ * - `STORE_CONFIG_FORBIDDEN` — any privileged `config` leaf (`modules`,
104
+ * `stock`, `priceDecimals`, `changePrice`, `mandatory2fa`, …).
105
+ * - `STORE_ECOMMERCE_FORBIDDEN` — any `ecommerce` block.
106
+ * - `STORE_FISCAL_FIELD_FORBIDDEN` — a fiscal field of the store.
107
+ * - `STORE_JURISDICTION_FORBIDDEN` — `jurisdiction`.
108
+ * - `AFIP_RELACION_FLAG_FORBIDDEN` — `afip.wscdcEnabled` / `afip.fceEnabled`.
109
+ * - `FX_TABLE_FORBIDDEN` — the `currencies` exchange-rate table.
110
+ * - `FX_AUTO_UPDATE_FORBIDDEN` — `fxAutoUpdate`.
111
+ *
112
+ * Request refusals, `400`:
113
+ * - `FIELD_NOT_WRITABLE_HERE` — a field written through `POST /store`, not
114
+ * this route; a top-level `fields` array names them.
115
+ * - `AFIP_POINT_OF_SALE_NOT_CLEARABLE` — `null` sent for the punto de venta.
116
+ * - `CURRENCY_CATALOG_ID_UNKNOWN` — a `currencies` entry names an unknown or
117
+ * disabled catalog id.
118
+ * - `ARS_RATE_MUST_BE_ONE` — the peso entry's value is not exactly `1`.
119
+ * - `CURRENCY_RATE_ABOVE_CEILING` — a `currencies` value is above its ceiling.
120
+ * - `FX_CATALOG_ID_UNKNOWN` / `FX_SOURCE_ID_UNKNOWN` — an `fxAutoUpdate`
121
+ * binding names an unknown catalog id or rate source.
122
+ * - `DISPLAY_CURRENCY_NOT_INVOICEABLE` / `PRODUCT_CURRENCY_NOT_INVOICEABLE` — a
123
+ * store carrying an AFIP CUIT set `config.displayCurrency` /
124
+ * `config.defaultProductCurrency` to a non-oficial USD variant.
125
+ * - `PRICE_LIST_NOT_FOUND` — an `ecommerce` save names a
126
+ * `newCustomerPriceList` that does not exist (`store/_ecommercePatch.ts`).
127
+ *
128
+ * Maintenance mode (`{ mode: 'maintenance', level }`, `store/_patchMaintenance.ts`):
129
+ * - `FORBIDDEN` (403) — the caller is neither an ADMIN nor a MANAGER.
130
+ * - `STORE_NOT_FOUND` (404) — the store row is gone.
131
+ *
132
+ * ⚠️ Not repeated here because another tuple already publishes them:
133
+ * `VALIDATION_FAILED`, `PRODUCT_CURRENCY_NOT_SUBSCRIBED`
134
+ * (`PRODUCT_POST_ERROR_CODES`), `WAREHOUSE_NOT_FOUND` /
135
+ * `WAREHOUSE_INACTIVE` (a `channelWarehouses` target), and every
136
+ * `STORE_MODULE_*` code ({@link STORE_MODULE_ERROR_CODES}). Codes the route
137
+ * forwards from shared helpers (the write conflict, the CAEA punto-de-venta
138
+ * checks, the display-currency lock, the storefront fence) are not listed
139
+ * either. Cross-cutting refusals: check `GATING_ERROR_CODES` as well.
140
+ */
141
+ exports.STORE_PATCH_ERROR_CODES = [
142
+ 'STORE_CONFIG_FORBIDDEN',
143
+ 'STORE_ECOMMERCE_FORBIDDEN',
144
+ 'STORE_FISCAL_FIELD_FORBIDDEN',
145
+ 'STORE_JURISDICTION_FORBIDDEN',
146
+ 'AFIP_RELACION_FLAG_FORBIDDEN',
147
+ 'FX_TABLE_FORBIDDEN',
148
+ 'FX_AUTO_UPDATE_FORBIDDEN',
149
+ 'FIELD_NOT_WRITABLE_HERE',
150
+ 'AFIP_POINT_OF_SALE_NOT_CLEARABLE',
151
+ 'CURRENCY_CATALOG_ID_UNKNOWN',
152
+ 'ARS_RATE_MUST_BE_ONE',
153
+ 'CURRENCY_RATE_ABOVE_CEILING',
154
+ 'FX_CATALOG_ID_UNKNOWN',
155
+ 'FX_SOURCE_ID_UNKNOWN',
156
+ 'DISPLAY_CURRENCY_NOT_INVOICEABLE',
157
+ 'PRODUCT_CURRENCY_NOT_INVOICEABLE',
158
+ 'PRICE_LIST_NOT_FOUND',
159
+ 'FORBIDDEN',
160
+ 'STORE_NOT_FOUND',
161
+ ];
@@ -30,7 +30,7 @@
30
30
  * enabled:false until they do.
31
31
  */
32
32
  Object.defineProperty(exports, "__esModule", { value: true });
33
- exports.FEATURE_KEYS = exports.isPaidPlanTier = exports.PLAN_CATALOGUE_ERROR_CODES = exports.PLAN_CATALOGUE_TEMPLATE_FIELDS = exports.PAID_PLAN_TIERS = exports.PLAN_TIERS = void 0;
33
+ exports.FEATURE_KEYS = exports.isPaidPlanTier = exports.PLAN_PRICE_SYNC_ERROR_CODES = exports.PLAN_CATALOGUE_ERROR_CODES = exports.PLAN_CATALOGUE_TEMPLATE_FIELDS = exports.PAID_PLAN_TIERS = exports.PLAN_TIERS = void 0;
34
34
  /*
35
35
  * Runtime tuples for the unions above.
36
36
  *
@@ -79,6 +79,10 @@ exports.PLAN_CATALOGUE_ERROR_CODES = exhaustiveTuple()([
79
79
  'PLAN_CATALOGUE_DRAFT_STALE',
80
80
  'IDEMPOTENCY_CONFLICT',
81
81
  ]);
82
+ /** Every `error` code `POST /subscription/checkout` adds for a price the provider has not caught up with. */
83
+ exports.PLAN_PRICE_SYNC_ERROR_CODES = exhaustiveTuple()([
84
+ 'PLAN_STRIPE_PRICE_STALE',
85
+ ]);
82
86
  /** Whether `value` names a paid tier — narrows an untyped read (a stored row, a global) to `PaidPlanTier`. */
83
87
  const isPaidPlanTier = (value) => typeof value === 'string' && exports.PAID_PLAN_TIERS.includes(value);
84
88
  exports.isPaidPlanTier = isPaidPlanTier;
package/dist/store.d.ts CHANGED
@@ -918,7 +918,7 @@ declare global {
918
918
  * not finish); `cash` while any cash shift is still open
919
919
  * (`409 STORE_MODULE_SHIFTS_OPEN` — `StoreModuleShiftsOpenData`).
920
920
  *
921
- * Enforced on the server for seven modules only:
921
+ * Enforced on the server for nine modules only:
922
922
  * - `promotions` — applying one is refused `PROMOTION_NOT_ACTIVE` (the
923
923
  * existing promotion refusal, not `STORE_MODULE_DISABLED`), a grant already
924
924
  * frozen on a cart stays on the row but derives no money (its
@@ -945,8 +945,22 @@ declare global {
945
945
  * settled `'skipped'` with reason `MODULE_OFF` at its send worker.
946
946
  * - `cash` — a POS terminal activates WITHOUT a shift (no `shiftId`,
947
947
  * living until its own expiry), and opening a shift (`POST /shifts`) is
948
- * refused `403 STORE_MODULE_DISABLED`; every other `/shifts` endpoint
949
- * (close, movements, reconcile, reads) stays reachable.
948
+ * refused `403 STORE_MODULE_DISABLED` — re-checked at commit, so an
949
+ * open that commits after the turn-off is refused (one committing
950
+ * inside the turn-off's own check-then-write window is accepted — see
951
+ * `docs/STORE.md` § Store module switches); every other `/shifts`
952
+ * endpoint (close, movements, reconcile, reads) stays reachable.
953
+ * - `customerAccounts` — the scheduled payment-reminder cron sends
954
+ * nothing for the store, and a scheduled reminder email already queued
955
+ * is dropped; the operator's per-customer send-reminder stays reachable.
956
+ * - `fiscalInvoicing` — "stop new, finish old": the CAEA request cron
957
+ * requests no new CAEA for the store and `AFIP_CERT_EXPIRY` is muted
958
+ * for it; a price-freezing seña over an order with no live factura
959
+ * freezes with no `invoiceId` (re-checked at commit) instead of being
960
+ * refused `DEPOSIT_FREEZE_REQUIRES_INVOICE`, and while that seña is held
961
+ * a re-price that moves the charged total is `409 ORDER_PRICE_FROZEN`,
962
+ * even after the module is back on. The CAEA inform cron, the return
963
+ * credit-note reconciler and operator-initiated invoicing are unchanged.
950
964
  * Every other module is hide-only: its endpoints stay reachable. Public
951
965
  * reads carry only `appointments`, `surveys`, `promotions` and
952
966
  * `customerAccounts`. `PUT /platform/stores/{storeId}` refuses the leaf.
@@ -2032,9 +2046,11 @@ export declare const isStoreModuleKey: (value: unknown) => value is StoreModuleK
2032
2046
  */
2033
2047
  export declare const isStoreModuleOn: (modules: StoreModules | null | undefined, module: StoreModuleKey) => boolean;
2034
2048
  /**
2035
- * Every refusal code the store-module switches put on the wire, beyond the
2036
- * platform-wide set (`VALIDATION_FAILED`, and `STORE_CONFIG_FORBIDDEN` for a
2037
- * plain USER writing the privileged leaf):
2049
+ * Every refusal code the store-module switches put on the wire. Not listed
2050
+ * here: `VALIDATION_FAILED` (a malformed body), and `STORE_CONFIG_FORBIDDEN` —
2051
+ * the `PATCH /store` role refusal a plain USER gets for ANY privileged `config`
2052
+ * leaf, `modules` included, judged before this module code runs. That one is in
2053
+ * {@link STORE_PATCH_ERROR_CODES}:
2038
2054
  *
2039
2055
  * - `STORE_MODULE_UNKNOWN` (400) — `PATCH /store` named a key outside
2040
2056
  * `STORE_MODULE_KEYS`; `data.module` carries it.
@@ -2147,3 +2163,50 @@ export type StoreModuleRefusalBody = {
2147
2163
  data: StoreModuleRefusalDataByCode[Code];
2148
2164
  };
2149
2165
  }[StoreModuleErrorCode];
2166
+ /**
2167
+ * The bare refusal codes `PATCH /store` (`stacks/lambdas/store/_patch.ts`, and
2168
+ * the route's own sibling modules it calls) answers itself — `{ error, message }`
2169
+ * with no `data`, unless noted:
2170
+ *
2171
+ * Role refusals, `403` — a plain USER writing a privileged section. Each is
2172
+ * judged before any other check on that section:
2173
+ * - `STORE_CONFIG_FORBIDDEN` — any privileged `config` leaf (`modules`,
2174
+ * `stock`, `priceDecimals`, `changePrice`, `mandatory2fa`, …).
2175
+ * - `STORE_ECOMMERCE_FORBIDDEN` — any `ecommerce` block.
2176
+ * - `STORE_FISCAL_FIELD_FORBIDDEN` — a fiscal field of the store.
2177
+ * - `STORE_JURISDICTION_FORBIDDEN` — `jurisdiction`.
2178
+ * - `AFIP_RELACION_FLAG_FORBIDDEN` — `afip.wscdcEnabled` / `afip.fceEnabled`.
2179
+ * - `FX_TABLE_FORBIDDEN` — the `currencies` exchange-rate table.
2180
+ * - `FX_AUTO_UPDATE_FORBIDDEN` — `fxAutoUpdate`.
2181
+ *
2182
+ * Request refusals, `400`:
2183
+ * - `FIELD_NOT_WRITABLE_HERE` — a field written through `POST /store`, not
2184
+ * this route; a top-level `fields` array names them.
2185
+ * - `AFIP_POINT_OF_SALE_NOT_CLEARABLE` — `null` sent for the punto de venta.
2186
+ * - `CURRENCY_CATALOG_ID_UNKNOWN` — a `currencies` entry names an unknown or
2187
+ * disabled catalog id.
2188
+ * - `ARS_RATE_MUST_BE_ONE` — the peso entry's value is not exactly `1`.
2189
+ * - `CURRENCY_RATE_ABOVE_CEILING` — a `currencies` value is above its ceiling.
2190
+ * - `FX_CATALOG_ID_UNKNOWN` / `FX_SOURCE_ID_UNKNOWN` — an `fxAutoUpdate`
2191
+ * binding names an unknown catalog id or rate source.
2192
+ * - `DISPLAY_CURRENCY_NOT_INVOICEABLE` / `PRODUCT_CURRENCY_NOT_INVOICEABLE` — a
2193
+ * store carrying an AFIP CUIT set `config.displayCurrency` /
2194
+ * `config.defaultProductCurrency` to a non-oficial USD variant.
2195
+ * - `PRICE_LIST_NOT_FOUND` — an `ecommerce` save names a
2196
+ * `newCustomerPriceList` that does not exist (`store/_ecommercePatch.ts`).
2197
+ *
2198
+ * Maintenance mode (`{ mode: 'maintenance', level }`, `store/_patchMaintenance.ts`):
2199
+ * - `FORBIDDEN` (403) — the caller is neither an ADMIN nor a MANAGER.
2200
+ * - `STORE_NOT_FOUND` (404) — the store row is gone.
2201
+ *
2202
+ * ⚠️ Not repeated here because another tuple already publishes them:
2203
+ * `VALIDATION_FAILED`, `PRODUCT_CURRENCY_NOT_SUBSCRIBED`
2204
+ * (`PRODUCT_POST_ERROR_CODES`), `WAREHOUSE_NOT_FOUND` /
2205
+ * `WAREHOUSE_INACTIVE` (a `channelWarehouses` target), and every
2206
+ * `STORE_MODULE_*` code ({@link STORE_MODULE_ERROR_CODES}). Codes the route
2207
+ * forwards from shared helpers (the write conflict, the CAEA punto-de-venta
2208
+ * checks, the display-currency lock, the storefront fence) are not listed
2209
+ * either. Cross-cutting refusals: check `GATING_ERROR_CODES` as well.
2210
+ */
2211
+ export declare const STORE_PATCH_ERROR_CODES: readonly ["STORE_CONFIG_FORBIDDEN", "STORE_ECOMMERCE_FORBIDDEN", "STORE_FISCAL_FIELD_FORBIDDEN", "STORE_JURISDICTION_FORBIDDEN", "AFIP_RELACION_FLAG_FORBIDDEN", "FX_TABLE_FORBIDDEN", "FX_AUTO_UPDATE_FORBIDDEN", "FIELD_NOT_WRITABLE_HERE", "AFIP_POINT_OF_SALE_NOT_CLEARABLE", "CURRENCY_CATALOG_ID_UNKNOWN", "ARS_RATE_MUST_BE_ONE", "CURRENCY_RATE_ABOVE_CEILING", "FX_CATALOG_ID_UNKNOWN", "FX_SOURCE_ID_UNKNOWN", "DISPLAY_CURRENCY_NOT_INVOICEABLE", "PRODUCT_CURRENCY_NOT_INVOICEABLE", "PRICE_LIST_NOT_FOUND", "FORBIDDEN", "STORE_NOT_FOUND"];
2212
+ export type StorePatchErrorCode = (typeof STORE_PATCH_ERROR_CODES)[number];
package/dist/store.js CHANGED
@@ -47,9 +47,11 @@ export const isStoreModuleKey = (value) => typeof value === 'string' && STORE_MO
47
47
  */
48
48
  export const isStoreModuleOn = (modules, module) => modules?.[module] !== false;
49
49
  /**
50
- * Every refusal code the store-module switches put on the wire, beyond the
51
- * platform-wide set (`VALIDATION_FAILED`, and `STORE_CONFIG_FORBIDDEN` for a
52
- * plain USER writing the privileged leaf):
50
+ * Every refusal code the store-module switches put on the wire. Not listed
51
+ * here: `VALIDATION_FAILED` (a malformed body), and `STORE_CONFIG_FORBIDDEN` —
52
+ * the `PATCH /store` role refusal a plain USER gets for ANY privileged `config`
53
+ * leaf, `modules` included, judged before this module code runs. That one is in
54
+ * {@link STORE_PATCH_ERROR_CODES}:
53
55
  *
54
56
  * - `STORE_MODULE_UNKNOWN` (400) — `PATCH /store` named a key outside
55
57
  * `STORE_MODULE_KEYS`; `data.module` carries it.
@@ -86,3 +88,69 @@ export const STORE_MODULE_ERROR_CODES = [
86
88
  'STORE_MODULE_SHIFTS_OPEN',
87
89
  'STORE_MODULE_DISABLED',
88
90
  ];
91
+ /**
92
+ * The bare refusal codes `PATCH /store` (`stacks/lambdas/store/_patch.ts`, and
93
+ * the route's own sibling modules it calls) answers itself — `{ error, message }`
94
+ * with no `data`, unless noted:
95
+ *
96
+ * Role refusals, `403` — a plain USER writing a privileged section. Each is
97
+ * judged before any other check on that section:
98
+ * - `STORE_CONFIG_FORBIDDEN` — any privileged `config` leaf (`modules`,
99
+ * `stock`, `priceDecimals`, `changePrice`, `mandatory2fa`, …).
100
+ * - `STORE_ECOMMERCE_FORBIDDEN` — any `ecommerce` block.
101
+ * - `STORE_FISCAL_FIELD_FORBIDDEN` — a fiscal field of the store.
102
+ * - `STORE_JURISDICTION_FORBIDDEN` — `jurisdiction`.
103
+ * - `AFIP_RELACION_FLAG_FORBIDDEN` — `afip.wscdcEnabled` / `afip.fceEnabled`.
104
+ * - `FX_TABLE_FORBIDDEN` — the `currencies` exchange-rate table.
105
+ * - `FX_AUTO_UPDATE_FORBIDDEN` — `fxAutoUpdate`.
106
+ *
107
+ * Request refusals, `400`:
108
+ * - `FIELD_NOT_WRITABLE_HERE` — a field written through `POST /store`, not
109
+ * this route; a top-level `fields` array names them.
110
+ * - `AFIP_POINT_OF_SALE_NOT_CLEARABLE` — `null` sent for the punto de venta.
111
+ * - `CURRENCY_CATALOG_ID_UNKNOWN` — a `currencies` entry names an unknown or
112
+ * disabled catalog id.
113
+ * - `ARS_RATE_MUST_BE_ONE` — the peso entry's value is not exactly `1`.
114
+ * - `CURRENCY_RATE_ABOVE_CEILING` — a `currencies` value is above its ceiling.
115
+ * - `FX_CATALOG_ID_UNKNOWN` / `FX_SOURCE_ID_UNKNOWN` — an `fxAutoUpdate`
116
+ * binding names an unknown catalog id or rate source.
117
+ * - `DISPLAY_CURRENCY_NOT_INVOICEABLE` / `PRODUCT_CURRENCY_NOT_INVOICEABLE` — a
118
+ * store carrying an AFIP CUIT set `config.displayCurrency` /
119
+ * `config.defaultProductCurrency` to a non-oficial USD variant.
120
+ * - `PRICE_LIST_NOT_FOUND` — an `ecommerce` save names a
121
+ * `newCustomerPriceList` that does not exist (`store/_ecommercePatch.ts`).
122
+ *
123
+ * Maintenance mode (`{ mode: 'maintenance', level }`, `store/_patchMaintenance.ts`):
124
+ * - `FORBIDDEN` (403) — the caller is neither an ADMIN nor a MANAGER.
125
+ * - `STORE_NOT_FOUND` (404) — the store row is gone.
126
+ *
127
+ * ⚠️ Not repeated here because another tuple already publishes them:
128
+ * `VALIDATION_FAILED`, `PRODUCT_CURRENCY_NOT_SUBSCRIBED`
129
+ * (`PRODUCT_POST_ERROR_CODES`), `WAREHOUSE_NOT_FOUND` /
130
+ * `WAREHOUSE_INACTIVE` (a `channelWarehouses` target), and every
131
+ * `STORE_MODULE_*` code ({@link STORE_MODULE_ERROR_CODES}). Codes the route
132
+ * forwards from shared helpers (the write conflict, the CAEA punto-de-venta
133
+ * checks, the display-currency lock, the storefront fence) are not listed
134
+ * either. Cross-cutting refusals: check `GATING_ERROR_CODES` as well.
135
+ */
136
+ export const STORE_PATCH_ERROR_CODES = [
137
+ 'STORE_CONFIG_FORBIDDEN',
138
+ 'STORE_ECOMMERCE_FORBIDDEN',
139
+ 'STORE_FISCAL_FIELD_FORBIDDEN',
140
+ 'STORE_JURISDICTION_FORBIDDEN',
141
+ 'AFIP_RELACION_FLAG_FORBIDDEN',
142
+ 'FX_TABLE_FORBIDDEN',
143
+ 'FX_AUTO_UPDATE_FORBIDDEN',
144
+ 'FIELD_NOT_WRITABLE_HERE',
145
+ 'AFIP_POINT_OF_SALE_NOT_CLEARABLE',
146
+ 'CURRENCY_CATALOG_ID_UNKNOWN',
147
+ 'ARS_RATE_MUST_BE_ONE',
148
+ 'CURRENCY_RATE_ABOVE_CEILING',
149
+ 'FX_CATALOG_ID_UNKNOWN',
150
+ 'FX_SOURCE_ID_UNKNOWN',
151
+ 'DISPLAY_CURRENCY_NOT_INVOICEABLE',
152
+ 'PRODUCT_CURRENCY_NOT_INVOICEABLE',
153
+ 'PRICE_LIST_NOT_FOUND',
154
+ 'FORBIDDEN',
155
+ 'STORE_NOT_FOUND',
156
+ ];
@@ -780,11 +780,20 @@ declare global {
780
780
  * place to echo a catalogue's payment-provider IDs.
781
781
  */
782
782
  missingProviderIds: string[];
783
+ /**
784
+ * The charged billing cycles whose Stripe Price was minted at a different amount or currency
785
+ * than the row now publishes (its `stripePrice*Cents` / `stripePriceCurrency` stamp differs):
786
+ * Stripe checkout refuses them (`409 PLAN_STRIPE_PRICE_STALE`) until `seed-stripe-products`
787
+ * re-mints. A cycle with no stamp (a row seeded before the stamp existed) is never listed.
788
+ */
789
+ staleStripePriceCycles: ('monthly' | 'annual')[];
783
790
  /**
784
791
  * Keys in the template row's `grants` overlay that the api does not
785
792
  * declare (retired or misspelt), sorted. Inert — every reader ignores them
786
793
  * and the code default applies — but stored, so they are drift: a `null`
787
- * for that key on `PATCH /platform/billing/plans/grants` removes them.
794
+ * for that key on `PATCH /platform/billing/plans/grants`, then
795
+ * `POST /platform/billing/plans/publish`, removes them (the PATCH alone
796
+ * writes only the draft).
788
797
  */
789
798
  undeclaredGrantKeys: string[];
790
799
  /**
@@ -1093,10 +1102,24 @@ declare global {
1093
1102
  reconciledStores?: number;
1094
1103
  /**
1095
1104
  * A paid tier whose price, currency or name changed, with a currency set on the draft being
1096
- * published (never `basico`, never when that currency is absent): run the provider seeders
1097
- * to mint its new prices.
1105
+ * published (never `basico`, never when that currency is absent). A live publish mints the
1106
+ * new Stripe Prices itself when Stripe already bills the tier (see `stripePriceMinted`), and
1107
+ * that mint also converges the Stripe Product's name on the published `name`. The MercadoPago
1108
+ * PreApproval plans, and a Product rename after a `name`-only publish (which mints nothing),
1109
+ * stay the seeders'.
1098
1110
  */
1099
1111
  stripeSyncRequired: boolean;
1112
+ /**
1113
+ * Live publish only, and only on a tier whose price or currency moved while Stripe bills it
1114
+ * (its row carries a `stripeProductId`): `true` when the publish minted the new Stripe Prices
1115
+ * and stamped them on the row. `false` means this publish did NOT stamp the row, for one of
1116
+ * two reasons: the mint failed (an operator ERROR row `STRIPE_PLAN_PRICE_MINT_FAILED` is
1117
+ * written, and Stripe checkout refuses the tier with `409 PLAN_STRIPE_PRICE_STALE` until
1118
+ * `seed-stripe-products` re-mints), or a LATER publish moved the price before this mint's
1119
+ * stamp landed — superseded, so no ERROR row: that later publish mints its own. Absent
1120
+ * otherwise.
1121
+ */
1122
+ stripePriceMinted?: boolean;
1100
1123
  }
1101
1124
  /** `data` of `POST /platform/billing/plans/publish`. */
1102
1125
  interface PlanCataloguePublishResult {
@@ -1161,6 +1184,20 @@ declare global {
1161
1184
  * revision moved: send the same request again.
1162
1185
  */
1163
1186
  | 'PLAN_CATALOGUE_BUSY' | 'PLAN_CATALOGUE_NO_CHANGES' | 'PLAN_CATALOGUE_PUBLICATION_NOT_FOUND' | 'PLAN_CATALOGUE_REQUEST_EXPIRED' | 'PLAN_CATALOGUE_INVALID_CURSOR' | 'PLAN_CATALOGUE_DRAFT_STALE' | 'IDEMPOTENCY_CONFLICT';
1187
+ /**
1188
+ * The `error` codes `POST /subscription/checkout` adds when a published price
1189
+ * has not reached the provider that would bill it.
1190
+ */
1191
+ type PlanPriceSyncErrorCode =
1192
+ /**
1193
+ * 409 · the store checks out through Stripe, and the Stripe Price on that
1194
+ * plan cycle was minted at a different amount or currency than the plan
1195
+ * now publishes (its stamp, `stripePrice*Cents` / `stripePriceCurrency`,
1196
+ * differs) — a checkout would bill the old price. Nothing was created; the
1197
+ * operator re-mints (`seed-stripe-products`). Carries `planTier` and
1198
+ * `billingCycle` like `PLAN_NOT_PURCHASABLE`.
1199
+ */
1200
+ 'PLAN_STRIPE_PRICE_STALE';
1164
1201
  }
1165
1202
  export type BillingProviderName = SubscriptionProvider;
1166
1203
  export type InvoiceSummary = globalThis.InvoiceSummary;
@@ -1176,6 +1213,8 @@ export declare const PAID_PLAN_TIERS: readonly ["emprendedor", "profesional", "a
1176
1213
  export declare const PLAN_CATALOGUE_TEMPLATE_FIELDS: readonly ["name", "description", "displayOrder", "isActive", "isPopular", "color", "priceMonthlyCents", "priceAnnualCents", "currency"];
1177
1214
  /** Every `error` code the plan catalogue draft / publish routes add — the coverage test holds the handlers to it. */
1178
1215
  export declare const PLAN_CATALOGUE_ERROR_CODES: readonly ["PLAN_CATALOGUE_REVISION_CONFLICT", "PLAN_CATALOGUE_BUSY", "PLAN_CATALOGUE_NO_CHANGES", "PLAN_CATALOGUE_PUBLICATION_NOT_FOUND", "PLAN_CATALOGUE_REQUEST_EXPIRED", "PLAN_CATALOGUE_INVALID_CURSOR", "PLAN_CATALOGUE_DRAFT_STALE", "IDEMPOTENCY_CONFLICT"];
1216
+ /** Every `error` code `POST /subscription/checkout` adds for a price the provider has not caught up with. */
1217
+ export declare const PLAN_PRICE_SYNC_ERROR_CODES: readonly ["PLAN_STRIPE_PRICE_STALE"];
1179
1218
  /** Whether `value` names a paid tier — narrows an untyped read (a stored row, a global) to `PaidPlanTier`. */
1180
1219
  export declare const isPaidPlanTier: (value: unknown) => value is PaidPlanTier;
1181
1220
  /**
@@ -76,6 +76,10 @@ export const PLAN_CATALOGUE_ERROR_CODES = exhaustiveTuple()([
76
76
  'PLAN_CATALOGUE_DRAFT_STALE',
77
77
  'IDEMPOTENCY_CONFLICT',
78
78
  ]);
79
+ /** Every `error` code `POST /subscription/checkout` adds for a price the provider has not caught up with. */
80
+ export const PLAN_PRICE_SYNC_ERROR_CODES = exhaustiveTuple()([
81
+ 'PLAN_STRIPE_PRICE_STALE',
82
+ ]);
79
83
  /** Whether `value` names a paid tier — narrows an untyped read (a stored row, a global) to `PaidPlanTier`. */
80
84
  export const isPaidPlanTier = (value) => typeof value === 'string' && PAID_PLAN_TIERS.includes(value);
81
85
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "platform-types",
3
- "version": "1.10.734",
3
+ "version": "1.10.735",
4
4
  "description": "Shared wire and entity contracts for the platform.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",