platform-types 1.10.761 → 1.10.763

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.
@@ -2,8 +2,8 @@
2
2
  // Indexed producers resolve candidates through `getNotificationSubscribers`:
3
3
  // legacy opt-ins and explicit channel maps remain source data on USER rows.
4
4
  // Addressed ERROR / ML_FACTURADOR_COLLISION / ML_SELLER_SWITCHED /
5
- // ML_CONNECTION_BROKEN / MENTION / CUSTOMER_PENDING_APPROVAL do not select a
6
- // producer subscriber audience;
5
+ // ML_CONNECTION_BROKEN / MENTION / CUSTOMER_PENDING_APPROVAL /
6
+ // PAYMENT_ATTEMPT_RESOLUTION do not select a producer subscriber audience;
7
7
  // the consumer still reads the live USER row for each delivery channel.
8
8
  // AFIP_CERT_EXPIRY is seeded on the founding user and uses the subscriber index.
9
9
  // Exported as a real enum consumed by api and app; adding an indexed type
@@ -171,4 +171,29 @@ export var NotificationTypeEnum;
171
171
  * storefront socket), and never the registrant's email address.
172
172
  */
173
173
  NotificationTypeEnum["CUSTOMER_PENDING_APPROVAL"] = "CUSTOMER_PENDING_APPROVAL";
174
+ /**
175
+ * A storefront online payment attempt entered `resolution`: Mercado Pago
176
+ * money landed that did not settle its order (a late capture after the hold
177
+ * ended or the order was cancelled, a second approval, an amount or order
178
+ * mismatch, an order already paid). Names the order (`orderId`) and the
179
+ * cause, in the title and description; the app opens the resolution queue
180
+ * (`GET /payments/attempts?state=resolution`) from it.
181
+ *
182
+ * ⚠️ ADMIN-ONLY, and its own preference key. The producer fans out to every
183
+ * non-disabled ADMIN of the store (`listActiveAdmins`) — the tier that may
184
+ * read and close the queue — and never to a plain USER, so a client offers
185
+ * the `PAYMENT_ATTEMPT_RESOLUTION` toggle to ADMINs only. No legacy opt-in
186
+ * scan, as for `CUSTOMER_PENDING_APPROVAL` (a new key is seeded nowhere): the
187
+ * consumer enforces explicit type/channel preferences
188
+ * (`notificationPreferences.PAYMENT_ATTEMPT_RESOLUTION`), default-on when
189
+ * absent. Additive — no backfill or consumer migration owed.
190
+ *
191
+ * Once per new approval: it rings on the committed move INTO the state, and
192
+ * again on each further APPROVAL recorded on an attempt already there (new
193
+ * money the operator has not seen — a pending decision is then refused
194
+ * `409 PAYMENT_ATTEMPT_CHANGED`). A replayed approval moves nothing and rings
195
+ * nothing. An attempt an operator closed (`resolved`) and a later approval
196
+ * re-opens rings again.
197
+ */
198
+ NotificationTypeEnum["PAYMENT_ATTEMPT_RESOLUTION"] = "PAYMENT_ATTEMPT_RESOLUTION";
174
199
  })(NotificationTypeEnum || (NotificationTypeEnum = {}));
package/dist/order.d.ts CHANGED
@@ -1285,9 +1285,10 @@ declare global {
1285
1285
  * `POST /orders { mode: 'cancel' }`, by ADMIN, SUPERVISOR or MANAGER. All
1286
1286
  * are distinct from a bare `disabled`, which records no cancellation.
1287
1287
  *
1288
- * `system` is written only by the payment-hold expiry, which cancels an
1289
- * order whose online payment attempt lapsed unpaid. No writer emits it yet;
1290
- * it is published first so a client can render it before one does.
1288
+ * `system` is written only by the payment-hold expiry
1289
+ * (`services/orderSystemCancellation.ts`, run by the payment-attempt sweep),
1290
+ * which cancels an order whose online payment attempt lapsed unpaid; its
1291
+ * `cancelledBy` is `'system'`, never a user id.
1291
1292
  */
1292
1293
  type OrderCancellationSource = 'customer' | 'operator' | 'system';
1293
1294
  /**
@@ -2721,14 +2722,14 @@ export declare const orderFulfilmentProgress: (order: OrderFulfilmentProgressInp
2721
2722
  * `data.shiftId`. Logged; reconcile the queued sale by hand.
2722
2723
  * - `ORDER_CURRENCY_NOT_SUBSCRIBED` · 400 — the sale's currency has no
2723
2724
  * subscription in the store's `currencies`. Logged.
2724
- * - `PAYMENT_METHODS_NOT_CONFIGURED` · 409 — `tenders` sent, or storefront/
2725
- * WhatsApp checkout attempted, while the store has no payment methods at
2725
+ * - `PAYMENT_METHODS_NOT_CONFIGURED` · 409 — `tenders` sent, or storefront
2726
+ * checkout attempted, while the store has no payment methods at
2726
2727
  * all. Storefront checkout carries `data: {}` and refuses before the cart read.
2727
2728
  * - `PAYMENT_METHOD_NOT_FOUND` · 400 — a tender leg's `method`, or storefront
2728
2729
  * checkout's `paymentMethod`, names none of the store's payment methods.
2729
2730
  * Storefront checkout carries `data: {}` and refuses before the cart read.
2730
2731
  *
2731
- * Storefront and WhatsApp checkout business refusals. None allocates an order
2732
+ * Storefront checkout business refusals. None allocates an order
2732
2733
  * id, redeems a coupon or writes an order; none is logged as an error:
2733
2734
  * - `DELIVERY_METHOD_NOT_FOUND` · 400 — `deliveryMethod` is not in the store's
2734
2735
  * delivery catalogue, including an absent/empty catalogue. `data: {}`;
@@ -2872,6 +2873,6 @@ export declare const orderFulfilmentProgress: (order: OrderFulfilmentProgressInp
2872
2873
  * `SUBSCRIPTION_READONLY`) sit on the order CREATE leg only: an edit is not a new
2873
2874
  * order, so `bareOrderPostHandler` routes past `requireMetered` entirely.
2874
2875
  */
2875
- export declare const ORDER_ERROR_CODES: readonly ["ORDER_COST_DENOMINATION_UNKNOWN", "SERVICE_ORDER_DELIVERY_MANAGED", "ORDER_NOT_FOUND", "ORDER_LOCKED", "ORDER_NOT_READY", "ORDER_DELIVERED_ANOTHER_DAY", "ORDER_DELIVERY_STATE_UNCHANGED", "ORDER_ILLEGAL_TRANSITION", "ORDER_VERSION_CONFLICT", "CUSTOMER_NOT_FOUND", "CUSTOMER_MERGED", "ORDER_HAS_NO_CUSTOMER", "CUSTOMER_ANONYMIZED", "FX_CONVERSION_UNAVAILABLE", "ROLE_FORBIDDEN", "ORDER_CANCELLED", "PAYMENT_SETTLED_ON_ANOTHER_ORDER", "ORDER_HAS_SHIPMENTS", "ORDER_HAS_RETURNS", "SHIPMENT_QUANTITY_EXCEEDED", "SHIPMENT_LINE_MISMATCH", "SHIPMENT_NOT_FOUND", "SHIPMENT_LIMIT_REACHED", "SHIPMENT_TOO_LARGE", "ORDER_FULFILMENT_EXTERNAL", "SHIPMENT_FAILED", "ADMIN_REQUIRED", "IDEMPOTENCY_KEY_REQUIRED", "INVALID_IDEMPOTENCY_KEY", "IDEMPOTENCY_KEY_REUSE", "IDEMPOTENCY_IN_PROGRESS", "IDEMPOTENCY_LOCK_CONTENTION", "IDEMPOTENCY_KEY_FAILED", "IDEMPOTENT_RESPONSE_NOT_CACHED", "ORDER_CANCELLATION_NOT_PROTECTED", "ORDER_CANCELLATION_COMMITTED", "ORDER_CANCELLATION_LOCKED", "ORDER_CANCELLATION_TOO_LARGE", "ORDER_CANCELLATION_FAILED", "SALE_LEDGER_RETRACTION_REFUSED", "SALE_LEDGER_ROW_NOT_OWNED", "PRODUCT_NOT_FOUND", "PRODUCT_SALE_LIMIT_EXCEEDED", "PRODUCT_SALE_LIMIT_INVALID", "DEPOSIT_SOURCE_NOT_ALLOWED", "DEPOSIT_CURRENCY_MISMATCH", "DEPOSIT_EXCEEDS_TOTAL", "DEPOSIT_FREEZE_REQUIRES_INVOICE", "DEPOSIT_FREEZE_INVOICE_PENDING", "DEPOSIT_CHARACTERIZATION_CONFLICT", "DEPOSIT_FREEZE_INVOICE_NOT_QUALIFYING", "DEPOSIT_INVOICED_ORDER_MUST_FREEZE", "DEPOSIT_FROZEN_ORDER_MUST_FREEZE", "DEPOSIT_REFERENCE_IS_LINKED_PAYMENT", "DEPOSIT_DUPLICATE_REFERENCE", "TILL_TENDER_REQUIRES_DEPOSIT", "PAYMENT_REFERENCED_BY_DEPOSIT", "ORDER_HAS_UNREFUNDED_DEPOSIT", "ORDER_PRICE_FROZEN", "DEPOSIT_NOT_FOUND", "DEPOSIT_ALREADY_REFUNDED", "UNIT_QUANTITY_NOT_WHOLE", "UNIT_REVISION_STALE", "UNIT_QUANTITY_UNREPRESENTABLE", "KIT_RECIPE_CHANGED", "CART_PROMOTION_UNAVAILABLE", "ORDER_HAS_KIT_LINES", "ORDER_TARGET_REQUIRED", "ORDER_SOURCE_CONFLICT", "ORDER_CUSTOMER_REQUIRED", "BASKET_EMPTY", "BASKET_CHANGED_DURING_CHECKOUT", "CART_VERSION_CREATE_ONLY", "CART_VERSION_REQUIRES_CART_ID", "CART_REVISION_STALE", "CART_CUSTOMER_MISMATCH", "COUNTER_SALE_CREATE_ONLY", "SOLD_AT_CREATE_ONLY", "SOLD_AT_IN_FUTURE", "ORDER_TENDER_CREATE_ONLY", "CREDIT_OVERRIDE_CREATE_ONLY", "ON_ACCOUNT_CREATE_ONLY", "ON_ACCOUNT_WITH_TENDERS", "TENDERS_REQUIRE_COUNTER_SALE", "LINES_REQUIRE_COUNTER_SALE", "PRODUCT_COST_UNKNOWN", "PRICE_CHANGE_DISABLED", "LINE_DISCOUNT_EXCEEDS_MAX", "CUSTOMER_DISABLED", "SHIFT_NOT_AVAILABLE", "SOLD_AT_OUTSIDE_SHIFT", "ORDER_CURRENCY_NOT_SUBSCRIBED", "PAYMENT_METHODS_NOT_CONFIGURED", "PAYMENT_METHOD_NOT_FOUND", "DELIVERY_METHOD_NOT_FOUND", "ORDER_BELOW_MINIMUM_PURCHASE", "ORDER_INVALID_CART", "EMAIL_VERIFICATION_REQUIRED", "ACCOUNT_DISABLED", "CUSTOMER_ACCESS_PENDING", "CUSTOMER_ACCESS_REJECTED", "CURRENCY_MISMATCH", "SHIFT_NOT_OPEN", "ORDER_DISCOUNT_AFTER_INVOICE", "ORDER_DISCOUNT_ON_SERVICE_ORDER", "ORDER_DISCOUNT_ON_MARKETPLACE_ORDER", "ORDER_INVOICE_METHOD_OUTSTANDING_FACTURA", "ORDER_SERVICE_PERIOD_AFTER_INVOICE", "ORDER_ATTEMPT_COMMITTED", "ORDER_ATTEMPT_ABANDONED", "ORDER_ATTEMPT_KEY_EXPIRED", "ORDER_ATTEMPT_KEY_SCOPE_MISMATCH", "ORDER_COMPLETION_ATTEMPT_COMMITTED", "ORDER_COMPLETION_ATTEMPT_ABANDONED"];
2876
+ export declare const ORDER_ERROR_CODES: readonly ["ORDER_COST_DENOMINATION_UNKNOWN", "SERVICE_ORDER_DELIVERY_MANAGED", "ORDER_NOT_FOUND", "ORDER_LOCKED", "ORDER_NOT_READY", "ORDER_DELIVERED_ANOTHER_DAY", "ORDER_DELIVERY_STATE_UNCHANGED", "ORDER_ILLEGAL_TRANSITION", "ORDER_VERSION_CONFLICT", "CUSTOMER_NOT_FOUND", "CUSTOMER_MERGED", "ORDER_HAS_NO_CUSTOMER", "CUSTOMER_ANONYMIZED", "FX_CONVERSION_UNAVAILABLE", "ROLE_FORBIDDEN", "ORDER_CANCELLED", "PAYMENT_SETTLED_ON_ANOTHER_ORDER", "ORDER_HAS_SHIPMENTS", "ORDER_HAS_RETURNS", "SHIPMENT_QUANTITY_EXCEEDED", "SHIPMENT_LINE_MISMATCH", "SHIPMENT_NOT_FOUND", "SHIPMENT_LIMIT_REACHED", "SHIPMENT_TOO_LARGE", "ORDER_FULFILMENT_EXTERNAL", "SHIPMENT_FAILED", "ADMIN_REQUIRED", "IDEMPOTENCY_KEY_REQUIRED", "INVALID_IDEMPOTENCY_KEY", "IDEMPOTENCY_KEY_REUSE", "IDEMPOTENCY_IN_PROGRESS", "IDEMPOTENCY_LOCK_CONTENTION", "IDEMPOTENCY_KEY_FAILED", "IDEMPOTENT_RESPONSE_NOT_CACHED", "ORDER_CANCELLATION_NOT_PROTECTED", "ORDER_CANCELLATION_COMMITTED", "ORDER_CANCELLATION_LOCKED", "ORDER_CANCELLATION_TOO_LARGE", "ORDER_CANCELLATION_FAILED", "SALE_LEDGER_RETRACTION_REFUSED", "SALE_LEDGER_ROW_NOT_OWNED", "PRODUCT_NOT_FOUND", "PRODUCT_SALE_LIMIT_EXCEEDED", "PRODUCT_SALE_LIMIT_INVALID", "DEPOSIT_SOURCE_NOT_ALLOWED", "DEPOSIT_CURRENCY_MISMATCH", "DEPOSIT_EXCEEDS_TOTAL", "DEPOSIT_FREEZE_REQUIRES_INVOICE", "DEPOSIT_FREEZE_INVOICE_PENDING", "DEPOSIT_CHARACTERIZATION_CONFLICT", "DEPOSIT_FREEZE_INVOICE_NOT_QUALIFYING", "DEPOSIT_INVOICED_ORDER_MUST_FREEZE", "DEPOSIT_FROZEN_ORDER_MUST_FREEZE", "DEPOSIT_REFERENCE_IS_LINKED_PAYMENT", "DEPOSIT_DUPLICATE_REFERENCE", "TILL_TENDER_REQUIRES_DEPOSIT", "PAYMENT_REFERENCED_BY_DEPOSIT", "ORDER_HAS_UNREFUNDED_DEPOSIT", "ORDER_PRICE_FROZEN", "DEPOSIT_NOT_FOUND", "DEPOSIT_ALREADY_REFUNDED", "UNIT_QUANTITY_NOT_WHOLE", "UNIT_REVISION_STALE", "UNIT_QUANTITY_UNREPRESENTABLE", "KIT_RECIPE_CHANGED", "CART_PROMOTION_UNAVAILABLE", "ORDER_HAS_KIT_LINES", "ORDER_TARGET_REQUIRED", "ORDER_SOURCE_CONFLICT", "ORDER_CUSTOMER_REQUIRED", "BASKET_EMPTY", "BASKET_CHANGED_DURING_CHECKOUT", "CART_VERSION_CREATE_ONLY", "CART_VERSION_REQUIRES_CART_ID", "CART_REVISION_STALE", "CART_CUSTOMER_MISMATCH", "COUNTER_SALE_CREATE_ONLY", "SOLD_AT_CREATE_ONLY", "SOLD_AT_IN_FUTURE", "ORDER_TENDER_CREATE_ONLY", "CREDIT_OVERRIDE_CREATE_ONLY", "ON_ACCOUNT_CREATE_ONLY", "ON_ACCOUNT_WITH_TENDERS", "TENDERS_REQUIRE_COUNTER_SALE", "LINES_REQUIRE_COUNTER_SALE", "PRODUCT_COST_UNKNOWN", "PRICE_CHANGE_DISABLED", "LINE_DISCOUNT_EXCEEDS_MAX", "CUSTOMER_DISABLED", "SHIFT_NOT_AVAILABLE", "SOLD_AT_OUTSIDE_SHIFT", "ORDER_CURRENCY_NOT_SUBSCRIBED", "PAYMENT_METHODS_NOT_CONFIGURED", "PAYMENT_METHOD_NOT_FOUND", "PAYMENT_METHOD_UNAVAILABLE", "CART_PRICES_CHANGED", "ORDER_ID_COLLISION", "DELIVERY_METHOD_NOT_FOUND", "ORDER_BELOW_MINIMUM_PURCHASE", "ORDER_INVALID_CART", "EMAIL_VERIFICATION_REQUIRED", "ACCOUNT_DISABLED", "CUSTOMER_ACCESS_PENDING", "CUSTOMER_ACCESS_REJECTED", "CURRENCY_MISMATCH", "SHIFT_NOT_OPEN", "ORDER_DISCOUNT_AFTER_INVOICE", "ORDER_DISCOUNT_ON_SERVICE_ORDER", "ORDER_DISCOUNT_ON_MARKETPLACE_ORDER", "ORDER_INVOICE_METHOD_OUTSTANDING_FACTURA", "ORDER_SERVICE_PERIOD_AFTER_INVOICE", "ORDER_ATTEMPT_COMMITTED", "ORDER_ATTEMPT_ABANDONED", "ORDER_ATTEMPT_KEY_EXPIRED", "ORDER_ATTEMPT_KEY_SCOPE_MISMATCH", "ORDER_COMPLETION_ATTEMPT_COMMITTED", "ORDER_COMPLETION_ATTEMPT_ABANDONED"];
2876
2877
  export type OrderErrorCode = (typeof ORDER_ERROR_CODES)[number];
2877
2878
  export {};
package/dist/order.js CHANGED
@@ -357,14 +357,14 @@ export const orderFulfilmentProgress = (order) => {
357
357
  * `data.shiftId`. Logged; reconcile the queued sale by hand.
358
358
  * - `ORDER_CURRENCY_NOT_SUBSCRIBED` · 400 — the sale's currency has no
359
359
  * subscription in the store's `currencies`. Logged.
360
- * - `PAYMENT_METHODS_NOT_CONFIGURED` · 409 — `tenders` sent, or storefront/
361
- * WhatsApp checkout attempted, while the store has no payment methods at
360
+ * - `PAYMENT_METHODS_NOT_CONFIGURED` · 409 — `tenders` sent, or storefront
361
+ * checkout attempted, while the store has no payment methods at
362
362
  * all. Storefront checkout carries `data: {}` and refuses before the cart read.
363
363
  * - `PAYMENT_METHOD_NOT_FOUND` · 400 — a tender leg's `method`, or storefront
364
364
  * checkout's `paymentMethod`, names none of the store's payment methods.
365
365
  * Storefront checkout carries `data: {}` and refuses before the cart read.
366
366
  *
367
- * Storefront and WhatsApp checkout business refusals. None allocates an order
367
+ * Storefront checkout business refusals. None allocates an order
368
368
  * id, redeems a coupon or writes an order; none is logged as an error:
369
369
  * - `DELIVERY_METHOD_NOT_FOUND` · 400 — `deliveryMethod` is not in the store's
370
370
  * delivery catalogue, including an absent/empty catalogue. `data: {}`;
@@ -621,6 +621,13 @@ export const ORDER_ERROR_CODES = [
621
621
  'ORDER_CURRENCY_NOT_SUBSCRIBED',
622
622
  'PAYMENT_METHODS_NOT_CONFIGURED',
623
623
  'PAYMENT_METHOD_NOT_FOUND',
624
+ // An online method (`Method.storefront: 'mp-checkout-pro'`) the store cannot
625
+ // take for this cart: Mercado Pago not connected, or a cart not in pesos.
626
+ 'PAYMENT_METHOD_UNAVAILABLE',
627
+ // Storefront checkout: the cart re-priced since the shopper saw it (re-read and
628
+ // confirm), and an allocated order id already taken (retry).
629
+ 'CART_PRICES_CHANGED',
630
+ 'ORDER_ID_COLLISION',
624
631
  'DELIVERY_METHOD_NOT_FOUND',
625
632
  'ORDER_BELOW_MINIMUM_PURCHASE',
626
633
  'ORDER_INVALID_CART',
@@ -33,7 +33,10 @@ declare global {
33
33
  * unless money had already reached it by another route; then the order is
34
34
  * left as it is and the attempt stays `expired` — not `resolution`, since
35
35
  * that money is not this attempt's.
36
- * - `cancelled` — the order was cancelled while the attempt was live.
36
+ * - `cancelled` — the order was cancelled while the attempt was live: by an
37
+ * operator (`POST /orders { mode: 'cancel' }`), in the same transaction as
38
+ * the cancellation. An approval that still lands on its checkout is a late
39
+ * capture and moves it to `resolution`.
37
40
  * - `refunded` — the approved payment was refunded. Only from `approved`: a
38
41
  * refund on a `resolution` attempt is the operator's resolution work and
39
42
  * leaves it `resolution`.
@@ -43,6 +46,13 @@ declare global {
43
46
  * amount other than the order total. The payment is recorded and an
44
47
  * operator decides; the order is neither settled nor re-opened. Show it to
45
48
  * the shopper as under review.
49
+ * - `resolved` — an operator closed the `resolution`
50
+ * ({@link ResolvePaymentAttemptRequest}), recording whether the money was
51
+ * refunded in Mercado Pago or kept. Moves no money and never touches the
52
+ * order. Not quite terminal: a chargeback still moves it to `charged_back`,
53
+ * and a FURTHER approval on the same checkout re-opens it to `resolution`
54
+ * — new money always needs an operator again. Show it to the shopper as
55
+ * reviewed by the store (the outcome and reason are operator-only).
46
56
  */
47
57
  type PaymentAttemptState = (typeof PAYMENT_ATTEMPT_STATES)[number];
48
58
  /** One of {@link PAYMENT_ATTEMPT_ERROR_CODES}. */
@@ -51,6 +61,8 @@ declare global {
51
61
  type OrderNotPayableReason = (typeof ORDER_NOT_PAYABLE_REASONS)[number];
52
62
  /** One of {@link PAYMENT_ATTEMPT_RESOLUTION_CAUSES}. */
53
63
  type PaymentAttemptResolutionCause = (typeof PAYMENT_ATTEMPT_RESOLUTION_CAUSES)[number];
64
+ /** One of {@link PAYMENT_ATTEMPT_RESOLUTION_OUTCOMES}. */
65
+ type PaymentAttemptResolutionOutcome = (typeof PAYMENT_ATTEMPT_RESOLUTION_OUTCOMES)[number];
54
66
  /**
55
67
  * The body that starts (or returns the live) payment attempt for an order.
56
68
  * The caller must be the order's customer; the store is the token's. The
@@ -71,6 +83,18 @@ declare global {
71
83
  interface OrderNotPayableData {
72
84
  reason: OrderNotPayableReason;
73
85
  }
86
+ /**
87
+ * `data` of `409 PAYMENT_ATTEMPT_CHANGED`: the attempt as it stands now. Show
88
+ * it to the operator — a payment they have not seen may be on it — and resend
89
+ * with its `updatedAt` once they have.
90
+ */
91
+ interface PaymentAttemptChangedData {
92
+ attempt: PaymentAttemptOperatorView;
93
+ }
94
+ /** `data` of `409 PAYMENT_ATTEMPT_NOT_IN_RESOLUTION`: the state the attempt is actually in. */
95
+ interface PaymentAttemptNotInResolutionData {
96
+ state: PaymentAttemptState;
97
+ }
74
98
  /**
75
99
  * The minimised attempt the shopper sees on their own order — never the
76
100
  * stored record.
@@ -109,6 +133,12 @@ declare global {
109
133
  state: PaymentAttemptState;
110
134
  /** Why the attempt is in `resolution` — set by the move into it. */
111
135
  resolutionCause?: PaymentAttemptResolutionCause;
136
+ /**
137
+ * How an operator closed the resolution — set by the move to `resolved`
138
+ * and kept after it (a later chargeback, or a re-opening approval, leaves
139
+ * the last closing on record).
140
+ */
141
+ resolution?: PaymentAttemptResolutionRecord;
112
142
  /** The Mercado Pago payments whose approval this attempt processed, oldest first. */
113
143
  approvedPaymentIds: string[];
114
144
  /** The Mercado Pago payment whose notification made the last move. */
@@ -123,9 +153,49 @@ declare global {
123
153
  /** Unix ms. */
124
154
  updatedAt: number;
125
155
  }
156
+ /** How an operator closed a `resolution` — see {@link ResolvePaymentAttemptRequest}. */
157
+ interface PaymentAttemptResolutionRecord {
158
+ outcome: PaymentAttemptResolutionOutcome;
159
+ /** The operator's own words, as sent (trimmed). */
160
+ reason: string;
161
+ /** The store user who closed it. */
162
+ resolvedBy: string;
163
+ /** Unix ms. */
164
+ resolvedAt: number;
165
+ }
166
+ /**
167
+ * `POST /payments/attempts { mode: 'resolve' }` (App host, admin) — an
168
+ * operator closes an attempt in `resolution`, moving it to `resolved`.
169
+ *
170
+ * Records a decision and nothing else: it moves NO money, writes no
171
+ * `PAYMENT#` row and never touches the order. A refund is made in Mercado
172
+ * Pago's own panel (the api has no outbound refund); `outcome: 'refunded'`
173
+ * records that staff did so, `'kept'` that the money stays with the store.
174
+ *
175
+ * ⚠️ The operator closes the attempt AS THEY SAW IT: `expectedUpdatedAt` is
176
+ * the `updatedAt` of the {@link PaymentAttemptOperatorView} they decided on.
177
+ * Anything that moved the attempt since — a further approval recorded on it
178
+ * included — answers `409 PAYMENT_ATTEMPT_CHANGED` with the current view and
179
+ * writes nothing, so a decision is never applied to money it did not cover.
180
+ */
181
+ interface ResolvePaymentAttemptRequest {
182
+ mode: 'resolve';
183
+ attemptId: string;
184
+ /** The attempt's order — must be the one `attemptId` names. */
185
+ orderId: string;
186
+ /** The `updatedAt` (Unix ms) of the operator view the decision was taken on. */
187
+ expectedUpdatedAt: number;
188
+ outcome: PaymentAttemptResolutionOutcome;
189
+ /** Required, 1–{@link PAYMENT_ATTEMPT_RESOLUTION_REASON_MAX} characters after trimming. */
190
+ reason: string;
191
+ }
192
+ /** `data` of a successful resolve: the attempt as it now stands. */
193
+ interface ResolvePaymentAttemptResponse {
194
+ attempt: PaymentAttemptOperatorView;
195
+ }
126
196
  /**
127
- * `data` of `GET /payments/attempts?state=resolution` (App host, admin):
128
- * the store's attempts in that state, newest activity first. Page on
197
+ * `data` of `GET /payments/attempts?state=resolution|resolved` (App host,
198
+ * admin): the store's attempts in that state, newest activity first. Page on
129
199
  * `nextCursor`'s presence, never on the page's length — the state is a
130
200
  * filter, so a page can be short, even empty, with more to come.
131
201
  */
@@ -136,10 +206,10 @@ declare global {
136
206
  }
137
207
  }
138
208
  /** Every {@link PaymentAttemptState}, in lifecycle order. */
139
- export declare const PAYMENT_ATTEMPT_STATES: readonly ["created", "pending", "approved", "rejected", "expired", "cancelled", "refunded", "charged_back", "resolution"];
209
+ export declare const PAYMENT_ATTEMPT_STATES: readonly ["created", "pending", "approved", "rejected", "expired", "cancelled", "refunded", "charged_back", "resolution", "resolved"];
140
210
  /**
141
- * Every refusal code a payment-attempt start, or a checkout choosing an online
142
- * method, answers:
211
+ * Every refusal code a payment-attempt start, a checkout choosing an online
212
+ * method, or an operator closing a resolution answers:
143
213
  *
144
214
  * - `PAYMENT_PROVIDER_NOT_CONNECTED` · 412 — the store has no Mercado Pago
145
215
  * account connected.
@@ -149,11 +219,32 @@ export declare const PAYMENT_ATTEMPT_STATES: readonly ["created", "pending", "ap
149
219
  * {@link OrderNotPayableData}.
150
220
  * - `PAYMENT_ATTEMPT_EXPIRED` · 410 — the attempt's `expiresAt` passed.
151
221
  * - `PAYMENT_METHOD_UNAVAILABLE` · 409 — the checkout chose an online payment
152
- * method the store cannot take right now (its provider is not connected).
222
+ * method the store cannot take for this cart: its provider is not connected,
223
+ * or the cart is not in pesos (Checkout Pro here charges ARS only). `data` is
224
+ * `{}`. Also published in `ORDER_ERROR_CODES` — web `POST /orders` answers it.
153
225
  * - `MP_PREFERENCE_CREATE_FAILED` · 502 — Mercado Pago refused the checkout or
154
226
  * did not answer in time. No attempt was written, so starting again is safe.
227
+ * - `PAYMENT_ATTEMPT_NOT_FOUND` · 404 — the resolve named an attempt the store
228
+ * does not have, or an `orderId` that is not the attempt's.
229
+ * - `PAYMENT_ATTEMPT_NOT_IN_RESOLUTION` · 409 — the resolve's attempt is not in
230
+ * `resolution` (never was, or another operator closed it first). Nothing
231
+ * written; `data.state` is the state it is in.
232
+ * - `PAYMENT_ATTEMPT_CHANGED` · 409 — the attempt is still in `resolution` but
233
+ * is not the one the operator decided on: its `updatedAt` is not the request's
234
+ * `expectedUpdatedAt` (a further payment was recorded on it, for one). Nothing
235
+ * written; `data` is {@link PaymentAttemptChangedData}.
236
+ */
237
+ export declare const PAYMENT_ATTEMPT_ERROR_CODES: readonly ["PAYMENT_PROVIDER_NOT_CONNECTED", "PAYMENT_PROVIDER_TOKEN_EXPIRED", "ORDER_NOT_PAYABLE", "PAYMENT_ATTEMPT_EXPIRED", "PAYMENT_METHOD_UNAVAILABLE", "MP_PREFERENCE_CREATE_FAILED", "PAYMENT_ATTEMPT_NOT_FOUND", "PAYMENT_ATTEMPT_NOT_IN_RESOLUTION", "PAYMENT_ATTEMPT_CHANGED"];
238
+ /**
239
+ * Every `outcome` of {@link ResolvePaymentAttemptRequest}:
240
+ *
241
+ * - `refunded` — staff refunded the payment in Mercado Pago's panel.
242
+ * - `kept` — the money stays with the store (for instance, the order is
243
+ * fulfilled by hand on it).
155
244
  */
156
- export declare const PAYMENT_ATTEMPT_ERROR_CODES: readonly ["PAYMENT_PROVIDER_NOT_CONNECTED", "PAYMENT_PROVIDER_TOKEN_EXPIRED", "ORDER_NOT_PAYABLE", "PAYMENT_ATTEMPT_EXPIRED", "PAYMENT_METHOD_UNAVAILABLE", "MP_PREFERENCE_CREATE_FAILED"];
245
+ export declare const PAYMENT_ATTEMPT_RESOLUTION_OUTCOMES: readonly ["refunded", "kept"];
246
+ /** The longest `reason` a resolve may record, in characters after trimming. */
247
+ export declare const PAYMENT_ATTEMPT_RESOLUTION_REASON_MAX = 500;
157
248
  /**
158
249
  * Every `data.reason` of `409 ORDER_NOT_PAYABLE`:
159
250
  *
@@ -28,10 +28,11 @@ export const PAYMENT_ATTEMPT_STATES = [
28
28
  'refunded',
29
29
  'charged_back',
30
30
  'resolution',
31
+ 'resolved',
31
32
  ];
32
33
  /**
33
- * Every refusal code a payment-attempt start, or a checkout choosing an online
34
- * method, answers:
34
+ * Every refusal code a payment-attempt start, a checkout choosing an online
35
+ * method, or an operator closing a resolution answers:
35
36
  *
36
37
  * - `PAYMENT_PROVIDER_NOT_CONNECTED` · 412 — the store has no Mercado Pago
37
38
  * account connected.
@@ -41,9 +42,20 @@ export const PAYMENT_ATTEMPT_STATES = [
41
42
  * {@link OrderNotPayableData}.
42
43
  * - `PAYMENT_ATTEMPT_EXPIRED` · 410 — the attempt's `expiresAt` passed.
43
44
  * - `PAYMENT_METHOD_UNAVAILABLE` · 409 — the checkout chose an online payment
44
- * method the store cannot take right now (its provider is not connected).
45
+ * method the store cannot take for this cart: its provider is not connected,
46
+ * or the cart is not in pesos (Checkout Pro here charges ARS only). `data` is
47
+ * `{}`. Also published in `ORDER_ERROR_CODES` — web `POST /orders` answers it.
45
48
  * - `MP_PREFERENCE_CREATE_FAILED` · 502 — Mercado Pago refused the checkout or
46
49
  * did not answer in time. No attempt was written, so starting again is safe.
50
+ * - `PAYMENT_ATTEMPT_NOT_FOUND` · 404 — the resolve named an attempt the store
51
+ * does not have, or an `orderId` that is not the attempt's.
52
+ * - `PAYMENT_ATTEMPT_NOT_IN_RESOLUTION` · 409 — the resolve's attempt is not in
53
+ * `resolution` (never was, or another operator closed it first). Nothing
54
+ * written; `data.state` is the state it is in.
55
+ * - `PAYMENT_ATTEMPT_CHANGED` · 409 — the attempt is still in `resolution` but
56
+ * is not the one the operator decided on: its `updatedAt` is not the request's
57
+ * `expectedUpdatedAt` (a further payment was recorded on it, for one). Nothing
58
+ * written; `data` is {@link PaymentAttemptChangedData}.
47
59
  */
48
60
  export const PAYMENT_ATTEMPT_ERROR_CODES = [
49
61
  'PAYMENT_PROVIDER_NOT_CONNECTED',
@@ -52,7 +64,20 @@ export const PAYMENT_ATTEMPT_ERROR_CODES = [
52
64
  'PAYMENT_ATTEMPT_EXPIRED',
53
65
  'PAYMENT_METHOD_UNAVAILABLE',
54
66
  'MP_PREFERENCE_CREATE_FAILED',
67
+ 'PAYMENT_ATTEMPT_NOT_FOUND',
68
+ 'PAYMENT_ATTEMPT_NOT_IN_RESOLUTION',
69
+ 'PAYMENT_ATTEMPT_CHANGED',
55
70
  ];
71
+ /**
72
+ * Every `outcome` of {@link ResolvePaymentAttemptRequest}:
73
+ *
74
+ * - `refunded` — staff refunded the payment in Mercado Pago's panel.
75
+ * - `kept` — the money stays with the store (for instance, the order is
76
+ * fulfilled by hand on it).
77
+ */
78
+ export const PAYMENT_ATTEMPT_RESOLUTION_OUTCOMES = ['refunded', 'kept'];
79
+ /** The longest `reason` a resolve may record, in characters after trimming. */
80
+ export const PAYMENT_ATTEMPT_RESOLUTION_REASON_MAX = 500;
56
81
  /**
57
82
  * Every `data.reason` of `409 ORDER_NOT_PAYABLE`:
58
83
  *
@@ -88,8 +88,8 @@ export interface ReseedConstraintsOpBody extends PlatformOperatorReason {
88
88
  */
89
89
  export interface RotateWebhookKeyOpBody extends PlatformOperatorReason {
90
90
  mode: 'rotate-webhook-key';
91
- provider: 'mercadopago' | 'stripe' | 'whatsapp';
92
- /** Required for `stripe` and `whatsapp` (provider-issued); optional override for `mercadopago`. Never echoed or audited. */
91
+ provider: 'mercadopago' | 'stripe';
92
+ /** Required for `stripe` (provider-issued); optional override for `mercadopago`. Never echoed or audited. */
93
93
  newSecret?: string;
94
94
  /** Must equal `provider`. Required — absent or wrong is `400 CONFIRMATION_MISMATCH`. */
95
95
  confirm: string;
@@ -460,9 +460,6 @@ export interface TenantHealthEnvelope {
460
460
  connected: boolean;
461
461
  oauthExpiresAt: number | null;
462
462
  };
463
- whatsapp: {
464
- enabled: boolean;
465
- };
466
463
  sms: {
467
464
  enabled: boolean;
468
465
  };
package/dist/product.d.ts CHANGED
@@ -774,7 +774,7 @@ declare global {
774
774
  /**
775
775
  * Most units of this product ONE sale may carry, summed across every line of
776
776
  * the operation. Enforced server-side on every local sale entry point
777
- * (order create, storefront and WhatsApp checkout, presupuesto conversion,
777
+ * (order create, storefront checkout, presupuesto conversion,
778
778
  * service delivery, and quantity-increasing edits), which refuse
779
779
  * `409 PRODUCT_SALE_LIMIT_EXCEEDED` — see {@link ProductSaleLimitRefusal}.
780
780
  *
@@ -2,10 +2,11 @@ declare global {
2
2
  /**
3
3
  * Which dispatcher actually delivered. Only the send helper knows this.
4
4
  *
5
- * `'whatsapp'` is the scheduled payment reminder's WhatsApp leg
6
- * (`Store.config.paymentReminders.channels`): a template message sent from the
7
- * store's own connected number. On such a row `to` is the phone number the
8
- * message went to, digits only, not an email address.
5
+ * ⚠️ `'whatsapp'` is HISTORY only. Nothing sends or records it any more, but the
6
+ * automatic payment reminder once had a WhatsApp leg, and the rows it wrote are
7
+ * durable and still read back in a customer's reminder history. On such a row
8
+ * `to` is the phone number the message went to, digits only, not an email
9
+ * address. Handle the member; never expect a new row to carry it.
9
10
  */
10
11
  type ReminderChannel = 'gmail' | 'ses' | 'whatsapp';
11
12
  /**
package/dist/socket.d.ts CHANGED
@@ -26,7 +26,7 @@
26
26
  * A client must ignore actions it does not own rather than assume it
27
27
  * receives all of them.
28
28
  */
29
- export declare const SOCKET_ACTIONS: readonly ["account", "appointments", "appointmentWaitlist", "attendance", "attributes", "automation-rules", "baskets", "cart", "brands", "cash", "catalogOperation", "categories", "campaigns", "customers", "customerNote", "customerAddress", "customerContact", "deliveries", "globals", "inventory", "invoices", "literals", "loyalty", "orders", "presupuestos", "products", "promotions", "segments", "returns", "rma", "templates", "services", "service-templates", "shifts", "stores", "suppliers", "supplier-invoice", "support", "surveys", "users", "warehouses", "zones", "favorites", "webhooks", "account-delete", "baskets-delete", "cart-delete", "log-delete", "notifications", "support-message", "whatsapp-order-draft", "whatsapp-order-confirmation", "payment_received", "mp_payment_status_changed", "payment_linked", "payment_unlinked", "mercadopago", "mercadopago_dynamic_qr_created", "mercadopago_static_qr_created", "mp_hook_log_appended", "mp_ipn_log_appended", "orderPaymentAttempt", "stripe", "subscription", "caea", "print", "print-order", "print-invoice", "print-product", "print-tag", "print_job_failed", "request_printers", "printers_changed", "agent_status_changed", "print_rules_changed", "printers_active", "agent_command", "maintenance", "currency_auto_updated", "drain_progress", "integration_event_appended", "userActivityRecorded", "mercadolibre_settlement_period", "customDomain", "purchaseOrders", "cycleCounts", "stockTransfers", "workItems"];
29
+ export declare const SOCKET_ACTIONS: readonly ["account", "appointments", "appointmentWaitlist", "attendance", "attributes", "automation-rules", "baskets", "cart", "brands", "cash", "catalogOperation", "categories", "campaigns", "customers", "customerNote", "customerAddress", "customerContact", "deliveries", "globals", "inventory", "invoices", "literals", "loyalty", "orders", "presupuestos", "products", "promotions", "segments", "returns", "rma", "templates", "services", "service-templates", "shifts", "stores", "suppliers", "supplier-invoice", "support", "surveys", "users", "warehouses", "zones", "favorites", "webhooks", "account-delete", "baskets-delete", "cart-delete", "log-delete", "notifications", "support-message", "payment_received", "mp_payment_status_changed", "payment_linked", "payment_unlinked", "mercadopago", "mercadopago_dynamic_qr_created", "mercadopago_static_qr_created", "mp_hook_log_appended", "mp_ipn_log_appended", "orderPaymentAttempt", "paymentAttemptChanged", "stripe", "subscription", "caea", "print", "print-order", "print-invoice", "print-product", "print-tag", "print_job_failed", "request_printers", "printers_changed", "agent_status_changed", "print_rules_changed", "printers_active", "agent_command", "maintenance", "currency_auto_updated", "drain_progress", "integration_event_appended", "userActivityRecorded", "mercadolibre_settlement_period", "customDomain", "purchaseOrders", "cycleCounts", "stockTransfers", "workItems"];
30
30
  /** Union of every server→client data-frame action. */
31
31
  export type SocketAction = (typeof SOCKET_ACTIONS)[number];
32
32
  /**
package/dist/socket.js CHANGED
@@ -498,13 +498,6 @@ export const SOCKET_ACTIONS = [
498
498
  // Notifications & messaging.
499
499
  'notifications',
500
500
  'support-message',
501
- /**
502
- * An automatic WhatsApp order draft settled (`ready` or `failed`). The
503
- * operator sockets of the store only; `data` is a `WhatsAppStoredOrderDraft`.
504
- */
505
- 'whatsapp-order-draft',
506
- /** Staff quote confirmation state; operator audience only, data: WhatsAppOrderConfirmation. */
507
- 'whatsapp-order-confirmation',
508
501
  // Payments & providers.
509
502
  'payment_received',
510
503
  // Operator-only observation invalidation; never a receipt or customer frame.
@@ -525,6 +518,18 @@ export const SOCKET_ACTIONS = [
525
518
  * customer broadcast. Sent once per committed state move of the attempt.
526
519
  */
527
520
  'orderPaymentAttempt',
521
+ /**
522
+ * A storefront payment attempt an operator acts on changed: it entered
523
+ * `resolution`, took a further NEW approval while in it, or an operator
524
+ * closed it (`resolved`). `data` is
525
+ * `PaymentAttemptOperatorView` (`paymentAttempt.ts`) — never the checkout
526
+ * URL or the Preference id.
527
+ *
528
+ * ⚠️ OPERATOR sockets of the store only, and ADMIN tier only (`wsPostStore`
529
+ * with `lowTierData: null` — the tier `GET /payments/attempts` admits). Never
530
+ * a customer socket: the shopper's own frame is `orderPaymentAttempt`.
531
+ */
532
+ 'paymentAttemptChanged',
528
533
  'stripe',
529
534
  'subscription',
530
535
  // Fiscal.
package/dist/store.d.ts CHANGED
@@ -270,16 +270,10 @@ declare global {
270
270
  * at send time and failing CLOSED.
271
271
  *
272
272
  * - `channels` — which legs the chase runs on. ABSENT means `['email']`, so a
273
- * store that never set it behaves exactly as before. `'whatsapp'` adds a
274
- * template message from the store's OWN connected WhatsApp number, carrying
275
- * a MercadoPago payment link for the balance, and needs more than the email
276
- * leg: the `whatsappCommerce` entitlement, headroom on the monthly
277
- * `whatsappMessages` meter, a connected MercadoPago account, a ledger in
278
- * ARS, and per customer a `marketing.consent.whatsapp` stamp with
279
- * `marketing.whatsapp === true` and a phone. Both legs share one cooldown
280
- * (`Customer.lastReminderAt`). On a store with both channels the email leg
281
- * wins the period: a customer it can chase gets the email only, and the
282
- * WhatsApp leg covers the customers email cannot reach (no address).
273
+ * store that never set it behaves exactly as before; `'email'` is the only
274
+ * leg. ⚠️ A store saved while a `'whatsapp'` leg still existed can carry that
275
+ * member until its next save: the chase ignores it, and `PATCH /store` accepts
276
+ * it and drops it (a list naming ONLY it saves as `frequency: 'none'`).
283
277
  */
284
278
  interface PaymentRemindersConfig {
285
279
  frequency?: 'none' | 'weekly' | 'monthly';
@@ -288,7 +282,7 @@ declare global {
288
282
  channels?: PaymentReminderChannel[];
289
283
  }
290
284
  /** A leg of the automatic payment reminder — see `PaymentRemindersConfig.channels`. */
291
- type PaymentReminderChannel = 'email' | 'whatsapp';
285
+ type PaymentReminderChannel = 'email';
292
286
  /**
293
287
  * Cut-offs and window for the periodic ABC (Pareto) classification of the
294
288
  * catalogue. Every member is optional and absence falls back to the api's
@@ -879,13 +873,6 @@ declare global {
879
873
  * storefront.
880
874
  */
881
875
  publicContact?: boolean;
882
- /**
883
- * Draft an order automatically from every inbound WhatsApp text message.
884
- * Off unless an admin turns it on. Still needs the `aiFeatures` and
885
- * `whatsappCommerce` entitlements, and `aiOptOut` still wins. Drafts are
886
- * never placed or sent: staff confirm each one.
887
- */
888
- whatsappOrderAutoDraft?: boolean;
889
876
  /**
890
877
  * Per-category × per-channel notification/feedback defaults; absent ⇒
891
878
  * FE falls back to all-on. FE-read only — `PATCH /store` validates shape only.
@@ -1251,7 +1238,6 @@ declare global {
1251
1238
  interface StoreIntegrations {
1252
1239
  afip?: Afip;
1253
1240
  mercadopago?: Mercadopago;
1254
- whatsapp?: WhatsAppConfig;
1255
1241
  sms?: SmsIntegration;
1256
1242
  gmail?: Gmail;
1257
1243
  mercadolibre?: Mercadolibre;
@@ -1754,7 +1740,11 @@ declare global {
1754
1740
  * - `'offline'` — offered, paid on delivery or pickup.
1755
1741
  * - `'mp-checkout-pro'` — offered, paid online through a payment attempt
1756
1742
  * (`StartPaymentAttemptRequest`) on the store's connected Mercado Pago
1757
- * account.
1743
+ * account. ⚠️ PESOS ONLY: Checkout Pro here charges ARS, so the storefront
1744
+ * checkout refuses this method on a cart in any other currency
1745
+ * (`409 PAYMENT_METHOD_UNAVAILABLE`, before the order is created), exactly
1746
+ * as it does when no Mercado Pago account is connected. A client should not
1747
+ * offer it on a non-ARS cart.
1758
1748
  */
1759
1749
  type StorefrontMethodKind = (typeof STOREFRONT_METHOD_KINDS)[number];
1760
1750
  interface Method {
@@ -24,7 +24,7 @@
24
24
  * - Feature keys now match the BE wire format directly (renamed afip→afipInvoicing,
25
25
  * cash→cashManagement, reportsAdvanced→advancedReports as of 2026-04-26). The interim
26
26
  * paymentIntegrations key was split into domesticPayments + stripePayments.
27
- * New keys whatsappCommerce/aiFeatures/mobileApp/customDomain are
27
+ * New keys aiFeatures/mobileApp/customDomain are
28
28
  * declared here even when their epics haven't shipped — the matrix can set
29
29
  * enabled:false until they do.
30
30
  */
@@ -100,7 +100,7 @@ declare global {
100
100
  * exhausts this union (a `switch`, a `Record<FeatureKey, …>`) still has to
101
101
  * handle the new member in the same change.
102
102
  */
103
- type FeatureKey = 'maxOrdersMonth' | 'maxInvoicesMonth' | 'whatsappMessages' | 'maxProducts' | 'maxUsers' | 'maxCustomers' | 'maxWarehouses' | 'priceListsMax' | 'webhooks' | 'afipInvoicing' | 'suppliers' | 'domesticPayments' | 'stripePayments' | 'cashManagement' | 'importExport' | 'advancedReports' | 'customBranding' | 'prioritySupport' | 'whatsappCommerce' | 'aiFeatures' | 'mobileApp' | 'customDomain' | 'advancedPricing' | 'marketplaceChannels' | 'storefront' | 'loyalty' | 'marketing' | 'mandatory2fa';
103
+ type FeatureKey = 'maxOrdersMonth' | 'maxInvoicesMonth' | 'maxProducts' | 'maxUsers' | 'maxCustomers' | 'maxWarehouses' | 'priceListsMax' | 'webhooks' | 'afipInvoicing' | 'suppliers' | 'domesticPayments' | 'stripePayments' | 'cashManagement' | 'importExport' | 'advancedReports' | 'customBranding' | 'prioritySupport' | 'aiFeatures' | 'mobileApp' | 'customDomain' | 'advancedPricing' | 'marketplaceChannels' | 'storefront' | 'loyalty' | 'marketing' | 'mandatory2fa';
104
104
  /** Resolved entitlements for a specific tenant (matrix + overrides applied). */
105
105
  type ResolvedEntitlements = Record<FeatureKey, Entitlement>;
106
106
  /**
@@ -1236,7 +1236,7 @@ export declare const isPaidPlanTier: (value: unknown) => value is PaidPlanTier;
1236
1236
  * metered / lifetime cap PASSES THROUGH — a new cap silently unbounded.
1237
1237
  * Checklist: `docs/PLANS_AND_ENTITLEMENTS.md` in the api repo.
1238
1238
  */
1239
- export declare const FEATURE_KEYS: readonly ["afipInvoicing", "suppliers", "advancedReports", "cashManagement", "importExport", "domesticPayments", "stripePayments", "whatsappCommerce", "aiFeatures", "mobileApp", "customBranding", "customDomain", "prioritySupport", "advancedPricing", "marketplaceChannels", "storefront", "loyalty", "marketing", "mandatory2fa", "maxUsers", "maxProducts", "maxCustomers", "maxWarehouses", "priceListsMax", "webhooks", "maxOrdersMonth", "maxInvoicesMonth", "whatsappMessages"];
1239
+ export declare const FEATURE_KEYS: readonly ["afipInvoicing", "suppliers", "advancedReports", "cashManagement", "importExport", "domesticPayments", "stripePayments", "aiFeatures", "mobileApp", "customBranding", "customDomain", "prioritySupport", "advancedPricing", "marketplaceChannels", "storefront", "loyalty", "marketing", "mandatory2fa", "maxUsers", "maxProducts", "maxCustomers", "maxWarehouses", "priceListsMax", "webhooks", "maxOrdersMonth", "maxInvoicesMonth"];
1240
1240
  type AssertNoUncoveredFeatureKey<T extends never> = T;
1241
1241
  export type UncoveredFeatureKeys = AssertNoUncoveredFeatureKey<Exclude<FeatureKey, (typeof FEATURE_KEYS)[number]>>;
1242
1242
  export {};
@@ -24,7 +24,7 @@
24
24
  * - Feature keys now match the BE wire format directly (renamed afip→afipInvoicing,
25
25
  * cash→cashManagement, reportsAdvanced→advancedReports as of 2026-04-26). The interim
26
26
  * paymentIntegrations key was split into domesticPayments + stripePayments.
27
- * New keys whatsappCommerce/aiFeatures/mobileApp/customDomain are
27
+ * New keys aiFeatures/mobileApp/customDomain are
28
28
  * declared here even when their epics haven't shipped — the matrix can set
29
29
  * enabled:false until they do.
30
30
  */
@@ -109,7 +109,6 @@ export const FEATURE_KEYS = [
109
109
  'importExport',
110
110
  'domesticPayments',
111
111
  'stripePayments',
112
- 'whatsappCommerce',
113
112
  'aiFeatures',
114
113
  'mobileApp',
115
114
  'customBranding',
@@ -129,5 +128,4 @@ export const FEATURE_KEYS = [
129
128
  'webhooks',
130
129
  'maxOrdersMonth',
131
130
  'maxInvoicesMonth',
132
- 'whatsappMessages',
133
131
  ];
package/dist/wire.d.ts CHANGED
@@ -43,8 +43,6 @@ export declare const STORE_MP_SECRET_KEYS: readonly ["accessToken", "code", "ref
43
43
  export declare const STORE_GMAIL_SECRET_KEYS: readonly ["refreshTokenEncrypted", "accessTokenEncrypted"];
44
44
  /** KMS-ciphertext Mercadolibre OAuth credentials + the single-flight refresh marker. */
45
45
  export declare const STORE_MERCADOLIBRE_SECRET_KEYS: readonly ["accessTokenEncrypted", "refreshTokenEncrypted", "refreshAttemptAt"];
46
- /** WhatsApp's only secret field on `Store.integrations.whatsapp`. */
47
- export declare const STORE_WHATSAPP_SECRET_KEYS: readonly ["accessToken"];
48
46
  /**
49
47
  * KMS-ciphertext TiendaNube OAuth credential on `Store.integrations.tiendanube`.
50
48
  * A single `accessTokenEncrypted` — TiendaNube issues no refresh token, so there
@@ -94,8 +92,6 @@ declare global {
94
92
  * because the type has to describe what actually arrives.
95
93
  */
96
94
  type StoreMercadolibreSecretKey = (typeof STORE_MERCADOLIBRE_SECRET_KEYS)[number];
97
- /** The one credential key stripped from `Store.integrations.whatsapp` before it crosses a wire. */
98
- type StoreWhatsappSecretKey = (typeof STORE_WHATSAPP_SECRET_KEYS)[number];
99
95
  /** The one KMS-ciphertext key stripped from `Store.integrations.tiendanube` before it crosses a wire. */
100
96
  type StoreTiendanubeSecretKey = (typeof STORE_TIENDANUBE_SECRET_KEYS)[number];
101
97
  /** A TOTP sub-key stripped from `User.totp` before a USER row crosses a wire. */
package/dist/wire.js CHANGED
@@ -64,8 +64,6 @@ export const STORE_MERCADOLIBRE_SECRET_KEYS = [
64
64
  'refreshTokenEncrypted',
65
65
  'refreshAttemptAt',
66
66
  ];
67
- /** WhatsApp's only secret field on `Store.integrations.whatsapp`. */
68
- export const STORE_WHATSAPP_SECRET_KEYS = ['accessToken'];
69
67
  /**
70
68
  * KMS-ciphertext TiendaNube OAuth credential on `Store.integrations.tiendanube`.
71
69
  * A single `accessTokenEncrypted` — TiendaNube issues no refresh token, so there
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "platform-types",
3
- "version": "1.10.761",
3
+ "version": "1.10.763",
4
4
  "description": "Shared wire and entity contracts for the platform.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",