platform-types 1.10.764 → 1.10.765

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/auth.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { EmailSuppressionReason } from './emailSuppression.ts';
1
2
  declare global {
2
3
  interface Login {
3
4
  email: string;
@@ -1079,6 +1080,56 @@ declare global {
1079
1080
  /** Unix ms after which the code no longer redeems (mint + 60 s). */
1080
1081
  expiresAt: number;
1081
1082
  }
1083
+ /**
1084
+ * `POST /auth` (Web API) body for `send-otp`: mail a 6-digit code to the
1085
+ * address STORED on the caller's customer row. Needs a Bearer customer ACCESS
1086
+ * token (`Authorization: Bearer …`); the method has no API Gateway authorizer,
1087
+ * so the handler verifies it. The body carries no address — one supplied is
1088
+ * ignored.
1089
+ *
1090
+ * `200 { message }` with no `data` when a code was queued. Refusals: see
1091
+ * {@link CUSTOMER_OTP_ERROR_CODES}. Timing: see {@link CUSTOMER_OTP_LIMITS}.
1092
+ * Nothing is mailed automatically after the customer changes their address —
1093
+ * call this.
1094
+ */
1095
+ interface CustomerSendOtpRequest {
1096
+ mode: 'send-otp';
1097
+ }
1098
+ /**
1099
+ * `POST /auth` (Web API) body for `verify-otp`, with the same Bearer customer
1100
+ * ACCESS token as `send-otp`.
1101
+ */
1102
+ interface CustomerVerifyOtpRequest {
1103
+ mode: 'verify-otp';
1104
+ /** Exactly six ASCII digits; anything else is `400 VALIDATION_FAILED`. */
1105
+ code: string;
1106
+ }
1107
+ /**
1108
+ * `verify-otp` 200 `data`. Merge it into the cached `AuthCustomer`; the same
1109
+ * pair also arrives as a `customers` socket frame (`data: { customerId,
1110
+ * emailVerified, emailVerifiedAt }`) on every socket of this customer, so other
1111
+ * open tabs update without a refresh.
1112
+ */
1113
+ interface CustomerVerifyOtpResponse {
1114
+ emailVerified: true;
1115
+ /** ms-epoch of the verification. */
1116
+ emailVerifiedAt: number;
1117
+ }
1118
+ /**
1119
+ * `verify-otp` `400 OTP_WRONG_CODE` body.
1120
+ *
1121
+ * ⚠️ `attemptsLeft` is TOP-LEVEL, beside `error`, not under `data`. `0` means
1122
+ * the next guess answers `429 OTP_LOCKED`.
1123
+ */
1124
+ interface CustomerOtpWrongCodeBody {
1125
+ error: 'OTP_WRONG_CODE';
1126
+ message: string;
1127
+ attemptsLeft: number;
1128
+ }
1129
+ /** `send-otp` `409 EMAIL_ADDRESS_SUPPRESSED` `data`: why the stored address cannot receive mail. */
1130
+ interface CustomerOtpSuppressedData {
1131
+ reason: EmailSuppressionReason;
1132
+ }
1082
1133
  /**
1083
1134
  * `POST /auth` body for `social-bridge-redeem`. Public, captcha-exempt.
1084
1135
  *
@@ -1854,4 +1905,52 @@ export type PasskeyErrorCode = (typeof PASSKEY_ERROR_CODES)[number];
1854
1905
  */
1855
1906
  export declare const SESSION_ACTION_ERROR_CODES: readonly ["SESSION_LOOKUP_INCOMPLETE", "SESSION_UNKNOWN", "REVOKE_INCOMPLETE"];
1856
1907
  export type SessionActionErrorCode = (typeof SESSION_ACTION_ERROR_CODES)[number];
1908
+ /**
1909
+ * `body.error` codes the two customer email-OTP modes (Web API `POST /auth`
1910
+ * `send-otp` / `verify-otp`) refuse with. Match on `body.error`.
1911
+ *
1912
+ * NOT members, and answered by both modes before any of these: the shared
1913
+ * customer-identity refusals — `MISSING_TOKEN`, `INVALID_TOKEN`,
1914
+ * `REFRESH_TOKEN_NOT_ALLOWED` (401), `ROLE_NOT_ALLOWED`,
1915
+ * `CUSTOMER_ACCESS_PENDING`, `CUSTOMER_ACCESS_REJECTED` (403),
1916
+ * `CUSTOMER_NOT_FOUND` (404), `ACCOUNT_DISABLED` (400) — and, on `verify-otp`,
1917
+ * `VALIDATION_FAILED` (400) for a `code` that is not six digits.
1918
+ *
1919
+ * - `OTP_COOLDOWN` · 429 — `send-otp` inside 60 s of the last live code.
1920
+ * - `EMAIL_ADDRESS_SUPPRESSED` · 409 — `send-otp`; the address bounced.
1921
+ * `data` is {@link CustomerOtpSuppressedData}.
1922
+ * - `EMAIL_ALREADY_VERIFIED` · 409 — `send-otp`; the stored address is already
1923
+ * verified, so nothing was mailed. Hide the resend action.
1924
+ * - `OTP_INVALID` · 400 — `verify-otp`; no code outstanding for the CURRENT
1925
+ * address: none was sent, or the one sent went to an address the account no
1926
+ * longer holds. Ask for a new code.
1927
+ * - `OTP_ALREADY_USED` · 400 — `verify-otp`; the code was consumed, or lost a
1928
+ * race (including a concurrent address change). Ask for a new code.
1929
+ * - `OTP_EXPIRED` · 400 — `verify-otp`; past its 10-minute TTL.
1930
+ * - `OTP_LOCKED` · 429 — `verify-otp`; 5 wrong guesses. Only a new `send-otp`
1931
+ * unlocks.
1932
+ * - `OTP_WRONG_CODE` · 400 — `verify-otp`; {@link CustomerOtpWrongCodeBody},
1933
+ * `attemptsLeft` at the TOP level.
1934
+ *
1935
+ * ⚠️ Deliberately not the operator tree's vocabulary (`OTP_INVALID_OR_EXPIRED`,
1936
+ * `OTP_TOO_MANY_ATTEMPTS`, `OTP_RESEND_TOO_SOON`); the two are not unified.
1937
+ */
1938
+ export declare const CUSTOMER_OTP_ERROR_CODES: readonly ["OTP_COOLDOWN", "EMAIL_ADDRESS_SUPPRESSED", "EMAIL_ALREADY_VERIFIED", "OTP_INVALID", "OTP_ALREADY_USED", "OTP_EXPIRED", "OTP_LOCKED", "OTP_WRONG_CODE"];
1939
+ export type CustomerOtpErrorCode = (typeof CUSTOMER_OTP_ERROR_CODES)[number];
1940
+ /**
1941
+ * The numbers the customer email OTP enforces, so a client countdown matches
1942
+ * the server. The api's own OTP service reads them from here, for operators and
1943
+ * customers alike.
1944
+ *
1945
+ * - `ttlSeconds` — a code expires this long after it was sent.
1946
+ * - `resendCooldownSeconds` — `send-otp` answers `429 OTP_COOLDOWN` until this
1947
+ * long after the last live code.
1948
+ * - `maxAttempts` — wrong guesses per code before `429 OTP_LOCKED`; a new code
1949
+ * starts the count again.
1950
+ */
1951
+ export declare const CUSTOMER_OTP_LIMITS: {
1952
+ readonly ttlSeconds: 600;
1953
+ readonly resendCooldownSeconds: 60;
1954
+ readonly maxAttempts: 5;
1955
+ };
1857
1956
  export {};
package/dist/auth.js CHANGED
@@ -502,3 +502,55 @@ export const SESSION_ACTION_ERROR_CODES = [
502
502
  'SESSION_UNKNOWN',
503
503
  'REVOKE_INCOMPLETE',
504
504
  ];
505
+ /**
506
+ * `body.error` codes the two customer email-OTP modes (Web API `POST /auth`
507
+ * `send-otp` / `verify-otp`) refuse with. Match on `body.error`.
508
+ *
509
+ * NOT members, and answered by both modes before any of these: the shared
510
+ * customer-identity refusals — `MISSING_TOKEN`, `INVALID_TOKEN`,
511
+ * `REFRESH_TOKEN_NOT_ALLOWED` (401), `ROLE_NOT_ALLOWED`,
512
+ * `CUSTOMER_ACCESS_PENDING`, `CUSTOMER_ACCESS_REJECTED` (403),
513
+ * `CUSTOMER_NOT_FOUND` (404), `ACCOUNT_DISABLED` (400) — and, on `verify-otp`,
514
+ * `VALIDATION_FAILED` (400) for a `code` that is not six digits.
515
+ *
516
+ * - `OTP_COOLDOWN` · 429 — `send-otp` inside 60 s of the last live code.
517
+ * - `EMAIL_ADDRESS_SUPPRESSED` · 409 — `send-otp`; the address bounced.
518
+ * `data` is {@link CustomerOtpSuppressedData}.
519
+ * - `EMAIL_ALREADY_VERIFIED` · 409 — `send-otp`; the stored address is already
520
+ * verified, so nothing was mailed. Hide the resend action.
521
+ * - `OTP_INVALID` · 400 — `verify-otp`; no code outstanding for the CURRENT
522
+ * address: none was sent, or the one sent went to an address the account no
523
+ * longer holds. Ask for a new code.
524
+ * - `OTP_ALREADY_USED` · 400 — `verify-otp`; the code was consumed, or lost a
525
+ * race (including a concurrent address change). Ask for a new code.
526
+ * - `OTP_EXPIRED` · 400 — `verify-otp`; past its 10-minute TTL.
527
+ * - `OTP_LOCKED` · 429 — `verify-otp`; 5 wrong guesses. Only a new `send-otp`
528
+ * unlocks.
529
+ * - `OTP_WRONG_CODE` · 400 — `verify-otp`; {@link CustomerOtpWrongCodeBody},
530
+ * `attemptsLeft` at the TOP level.
531
+ *
532
+ * ⚠️ Deliberately not the operator tree's vocabulary (`OTP_INVALID_OR_EXPIRED`,
533
+ * `OTP_TOO_MANY_ATTEMPTS`, `OTP_RESEND_TOO_SOON`); the two are not unified.
534
+ */
535
+ export const CUSTOMER_OTP_ERROR_CODES = [
536
+ 'OTP_COOLDOWN',
537
+ 'EMAIL_ADDRESS_SUPPRESSED',
538
+ 'EMAIL_ALREADY_VERIFIED',
539
+ 'OTP_INVALID',
540
+ 'OTP_ALREADY_USED',
541
+ 'OTP_EXPIRED',
542
+ 'OTP_LOCKED',
543
+ 'OTP_WRONG_CODE',
544
+ ];
545
+ /**
546
+ * The numbers the customer email OTP enforces, so a client countdown matches
547
+ * the server. The api's own OTP service reads them from here, for operators and
548
+ * customers alike.
549
+ *
550
+ * - `ttlSeconds` — a code expires this long after it was sent.
551
+ * - `resendCooldownSeconds` — `send-otp` answers `429 OTP_COOLDOWN` until this
552
+ * long after the last live code.
553
+ * - `maxAttempts` — wrong guesses per code before `429 OTP_LOCKED`; a new code
554
+ * starts the count again.
555
+ */
556
+ export const CUSTOMER_OTP_LIMITS = { ttlSeconds: 600, resendCooldownSeconds: 60, maxAttempts: 5 };
package/dist/cjs/auth.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.SESSION_ACTION_ERROR_CODES = exports.PASSKEY_ERROR_CODES = exports.TWO_FACTOR_MANAGEMENT_ERROR_CODES = exports.LOGIN_2FA_ERROR_CODES = exports.LOGIN_ERROR_CODES = exports.STEP_UP_ERROR_CODES = exports.REFRESH_ERROR_CODES = exports.CUSTOMER_SOCIAL_REGISTER_ERROR_CODES = exports.SOCIAL_BRIDGE_ERROR_CODES = exports.SIGN_IN_METHOD_ERROR_CODES = void 0;
3
+ exports.CUSTOMER_OTP_LIMITS = exports.CUSTOMER_OTP_ERROR_CODES = exports.SESSION_ACTION_ERROR_CODES = exports.PASSKEY_ERROR_CODES = exports.TWO_FACTOR_MANAGEMENT_ERROR_CODES = exports.LOGIN_2FA_ERROR_CODES = exports.LOGIN_ERROR_CODES = exports.STEP_UP_ERROR_CODES = exports.REFRESH_ERROR_CODES = exports.CUSTOMER_SOCIAL_REGISTER_ERROR_CODES = exports.SOCIAL_BRIDGE_ERROR_CODES = exports.SIGN_IN_METHOD_ERROR_CODES = void 0;
4
4
  /**
5
5
  * `body.error` codes the sign-in-method paths can refuse with.
6
6
  *
@@ -505,3 +505,55 @@ exports.SESSION_ACTION_ERROR_CODES = [
505
505
  'SESSION_UNKNOWN',
506
506
  'REVOKE_INCOMPLETE',
507
507
  ];
508
+ /**
509
+ * `body.error` codes the two customer email-OTP modes (Web API `POST /auth`
510
+ * `send-otp` / `verify-otp`) refuse with. Match on `body.error`.
511
+ *
512
+ * NOT members, and answered by both modes before any of these: the shared
513
+ * customer-identity refusals — `MISSING_TOKEN`, `INVALID_TOKEN`,
514
+ * `REFRESH_TOKEN_NOT_ALLOWED` (401), `ROLE_NOT_ALLOWED`,
515
+ * `CUSTOMER_ACCESS_PENDING`, `CUSTOMER_ACCESS_REJECTED` (403),
516
+ * `CUSTOMER_NOT_FOUND` (404), `ACCOUNT_DISABLED` (400) — and, on `verify-otp`,
517
+ * `VALIDATION_FAILED` (400) for a `code` that is not six digits.
518
+ *
519
+ * - `OTP_COOLDOWN` · 429 — `send-otp` inside 60 s of the last live code.
520
+ * - `EMAIL_ADDRESS_SUPPRESSED` · 409 — `send-otp`; the address bounced.
521
+ * `data` is {@link CustomerOtpSuppressedData}.
522
+ * - `EMAIL_ALREADY_VERIFIED` · 409 — `send-otp`; the stored address is already
523
+ * verified, so nothing was mailed. Hide the resend action.
524
+ * - `OTP_INVALID` · 400 — `verify-otp`; no code outstanding for the CURRENT
525
+ * address: none was sent, or the one sent went to an address the account no
526
+ * longer holds. Ask for a new code.
527
+ * - `OTP_ALREADY_USED` · 400 — `verify-otp`; the code was consumed, or lost a
528
+ * race (including a concurrent address change). Ask for a new code.
529
+ * - `OTP_EXPIRED` · 400 — `verify-otp`; past its 10-minute TTL.
530
+ * - `OTP_LOCKED` · 429 — `verify-otp`; 5 wrong guesses. Only a new `send-otp`
531
+ * unlocks.
532
+ * - `OTP_WRONG_CODE` · 400 — `verify-otp`; {@link CustomerOtpWrongCodeBody},
533
+ * `attemptsLeft` at the TOP level.
534
+ *
535
+ * ⚠️ Deliberately not the operator tree's vocabulary (`OTP_INVALID_OR_EXPIRED`,
536
+ * `OTP_TOO_MANY_ATTEMPTS`, `OTP_RESEND_TOO_SOON`); the two are not unified.
537
+ */
538
+ exports.CUSTOMER_OTP_ERROR_CODES = [
539
+ 'OTP_COOLDOWN',
540
+ 'EMAIL_ADDRESS_SUPPRESSED',
541
+ 'EMAIL_ALREADY_VERIFIED',
542
+ 'OTP_INVALID',
543
+ 'OTP_ALREADY_USED',
544
+ 'OTP_EXPIRED',
545
+ 'OTP_LOCKED',
546
+ 'OTP_WRONG_CODE',
547
+ ];
548
+ /**
549
+ * The numbers the customer email OTP enforces, so a client countdown matches
550
+ * the server. The api's own OTP service reads them from here, for operators and
551
+ * customers alike.
552
+ *
553
+ * - `ttlSeconds` — a code expires this long after it was sent.
554
+ * - `resendCooldownSeconds` — `send-otp` answers `429 OTP_COOLDOWN` until this
555
+ * long after the last live code.
556
+ * - `maxAttempts` — wrong guesses per code before `429 OTP_LOCKED`; a new code
557
+ * starts the count again.
558
+ */
559
+ exports.CUSTOMER_OTP_LIMITS = { ttlSeconds: 600, resendCooldownSeconds: 60, maxAttempts: 5 };
@@ -302,8 +302,16 @@ declare global {
302
302
  email?: string;
303
303
  /**
304
304
  * Set `true` ONLY where the address is proven: by the customer OTP verify
305
- * transaction, or at creation by a storefront `register-social`, whose
306
- * provider verified the email (an unverified identity creates nothing).
305
+ * transaction; at creation by a storefront `register-social`, whose
306
+ * provider verified the email (an unverified identity creates nothing); or
307
+ * by a storefront social sign-in (`social`, `social-bridge-redeem`) or
308
+ * `link-sign-in-method` whose provider asserts a verified email equal,
309
+ * case-insensitively, to the stored one — never through an Apple Hide My
310
+ * Email relay, which is not the stored address. A sign-in then answers
311
+ * `true` in its body and the customer's own sockets get a `customers` frame.
312
+ * When that sign-in is the provider's FIRST on a row that held an unproven
313
+ * password, the password is removed and every earlier session revoked.
314
+ * Any move or clear of the address resets it to `false`.
307
315
  *
308
316
  * ⚠️ UNDEFINED MEANS **NOT** VERIFIED — deliberately the INVERSE of
309
317
  * `User.emailVerified`, which carries a grandfather clause telling apps to
@@ -314,8 +322,10 @@ declare global {
314
322
  */
315
323
  emailVerified?: boolean;
316
324
  /**
317
- * ms-epoch of the proof: the OTP verification, or — for a `register-social`
318
- * account — the row's `createdAt`. Absent whenever `emailVerified` is not `true`.
325
+ * ms-epoch of the proof: the OTP verification, the social sign-in or link
326
+ * that proved it, or — for a `register-social` account — the row's
327
+ * `createdAt`. Kept from the FIRST proof; a later social sign-in does not
328
+ * move it. Absent or `null` whenever `emailVerified` is not `true`.
319
329
  */
320
330
  emailVerifiedAt?: number;
321
331
  /**
package/dist/store.d.ts CHANGED
@@ -1222,6 +1222,14 @@ declare global {
1222
1222
  * until they verify. That is the tenant's decision to make, but a
1223
1223
  * settings UI should say so rather than presenting it as a neutral
1224
1224
  * switch.
1225
+ *
1226
+ * Web `GET /store` (and the storefront preview's store frame) ALWAYS
1227
+ * carries it as a boolean, `true` only when the stored value is exactly
1228
+ * `true` — absent, `false` or any other stored value reads `false`, the
1229
+ * same test checkout applies. A storefront reads it to prompt for
1230
+ * verification before checkout rather than after the
1231
+ * `403 EMAIL_VERIFICATION_REQUIRED`. It is not on the customer `stores`
1232
+ * socket frame; the next `GET /store` picks up a change.
1225
1233
  */
1226
1234
  requireEmailVerification?: boolean;
1227
1235
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "platform-types",
3
- "version": "1.10.764",
3
+ "version": "1.10.765",
4
4
  "description": "Shared wire and entity contracts for the platform.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",