platform-types 1.10.737 → 1.10.739

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
@@ -64,9 +64,12 @@ declare global {
64
64
  * optionality.
65
65
  *
66
66
  * ⚠️ NOT interchangeable with {@link CustomerRegisterInput}. The two
67
- * registration endpoints differ in four places — `name` and `acquisition`
68
- * exist only here, `fullName` is OPTIONAL here and REQUIRED there, and the
69
- * address/`afip` block exists only there.
67
+ * registration endpoints differ in key set AND in rules: `name`,
68
+ * `acknowledgedSharedCuit`, `acquisition`, `consentTimestamp`,
69
+ * `consentVersion` and `storeContact` exist only here, and the address block
70
+ * and `afip` only there; `fullName` is OPTIONAL here and REQUIRED there,
71
+ * `email` has an 8-character floor here and 5 there, and `cuit` is a bare
72
+ * length check here and a mod-11 check there.
70
73
  *
71
74
  * ⚠️ Bounds are stated per field below and are what the server ENFORCES;
72
75
  * a violation is `400` and creates nothing at all, not a partial tenant.
@@ -75,13 +78,17 @@ declare global {
75
78
  * keys and ignores them. This type deliberately does not declare an index
76
79
  * signature: an unknown key buys a client nothing and losing the
77
80
  * excess-property check is how a misspelled `fullname` ships silently. The
78
- * nested `acquisition` object is the opposite — `.strict()`, so an unknown key
79
- * inside it refuses the WHOLE registration.
81
+ * nested `acquisition` and `storeContact` objects are the opposite —
82
+ * `.strict()`, so an unknown key inside either refuses the WHOLE
83
+ * registration.
80
84
  */
81
85
  interface TenantRegisterInput {
82
86
  /** Store name. Trimmed, then 4–40 characters. Required — tenants are never created nameless. */
83
87
  name: string;
84
- /** Must parse as an email address, and at least 8 characters. Lower-cased server-side. */
88
+ /**
89
+ * Must parse as an email address, 8–254 characters. The local part must be
90
+ * ASCII (`z.email()`), so `dueño@…` is refused. Lower-cased server-side.
91
+ */
85
92
  email: string;
86
93
  /** At least 8 characters — the one creation-time floor every password-accepting surface shares. */
87
94
  password: string;
@@ -136,6 +143,57 @@ declare global {
136
143
  * Its presence is what makes a consent record exist at all.
137
144
  */
138
145
  consentVersion?: string;
146
+ /**
147
+ * The STORE's own contact leaves, prefilled from the signup form.
148
+ *
149
+ * ⚠️ Send it ONLY after the merchant has confirmed that each value is a
150
+ * BUSINESS contact, never by copying the founder's own `phone`/`email`
151
+ * across silently: both land on the STORE row as `phone`/`email`, which
152
+ * are printed on every transactional mail to the store's customers
153
+ * (`storeContactFooter`), and `phone` also on the emisor block of every
154
+ * invoice PDF.
155
+ *
156
+ * ⚠️ A STORE `email` becomes a DESTINATION once its inbox confirms it, so
157
+ * the client must confirm it is a MONITORED business address, not just a
158
+ * public one. Registering with it mails a single-use confirmation link
159
+ * there (platform-branded, valid 48 h), and until that link is followed:
160
+ * - customer-facing store-branded mail sent under the platform envelope
161
+ * carries NO `Reply-To`; once confirmed, the address is that `Reply-To`,
162
+ * so a customer's answer goes there. Customer mail never falls back to
163
+ * the founder's address;
164
+ * - the storefront's survey responses (suppressed for a demo store) and
165
+ * the scheduled sales digest (once the store opts in and is entitled
166
+ * to it) go to the founding admin's verified login email instead, and
167
+ * to no one when that account is disabled or its email unverified;
168
+ * once confirmed, they go to this address. Without a store `email`
169
+ * neither is sent at all;
170
+ * - an integration re-authorisation mail that names no address goes to
171
+ * the founding admin's verified login email, and to this address only
172
+ * when that one is unusable AND this one is confirmed.
173
+ *
174
+ * STRICT, like `acquisition`: an unknown key refuses the WHOLE
175
+ * registration, and so does an empty object — send at least one key or
176
+ * omit the object. `storeContact: null` is refused too: to send no
177
+ * contact, leave the key ABSENT. `phone` is EXACTLY 10 characters (the founder `phone`
178
+ * rule); `email` is the founder `email` rule — an email address, 8–254
179
+ * characters, ASCII local part — and is lower-cased server-side exactly as
180
+ * the founder `email` is. A violation is a `400` and creates no tenant.
181
+ *
182
+ * The api records which keys were sent as the server-owned
183
+ * {@link Store.registrationPrefill}; a client never sends that.
184
+ */
185
+ storeContact?: TenantRegisterStoreContactInput;
186
+ }
187
+ /** {@link TenantRegisterInput.storeContact} — at least one key. */
188
+ interface TenantRegisterStoreContactInput {
189
+ /** EXACTLY 10 characters. */
190
+ phone?: string;
191
+ /**
192
+ * A valid email address, 8–254 characters — the founder `email` rule. The
193
+ * local part must be ASCII (the same `z.email()` rule), so `dueño@…` is
194
+ * refused. Lower-cased server-side.
195
+ */
196
+ email?: string;
139
197
  }
140
198
  /**
141
199
  * One `afip` entry as the CUSTOMER registration ACCEPTS it — {@link CustomerAfip}
@@ -159,7 +217,7 @@ declare global {
159
217
  * that schema.
160
218
  *
161
219
  * ⚠️ NOT interchangeable with {@link TenantRegisterInput} — see that type for
162
- * the five differences. In particular there is no `acquisition` here: campaign
220
+ * the differences. In particular there is no `acquisition` here: campaign
163
221
  * attribution is a TENANT property, and a value sent on this leg is dropped.
164
222
  *
165
223
  * ⚠️ Unlike the tenant schema this object is NOT `.loose()`, so an unknown
package/dist/store.d.ts CHANGED
@@ -388,6 +388,55 @@ declare global {
388
388
  */
389
389
  userId: string;
390
390
  }
391
+ /** A STORE contact leaf that tenant self-registration may prefill. */
392
+ type StoreRegistrationPrefillField = 'phone' | 'email';
393
+ /**
394
+ * Which top-level contact leaves tenant self-registration wrote onto this
395
+ * STORE row, and when — the record that `phone` / `email` came from the
396
+ * signup form (`TenantRegisterInput.storeContact`) rather than from the
397
+ * store settings.
398
+ *
399
+ * ⚠️ Server-owned and forward-only, like {@link StoreAcquisition}: the api
400
+ * assembles it from the keys `storeContact` actually carried, and no body
401
+ * may set it — the register body ignores a top-level `registrationPrefill`,
402
+ * and `POST /store` / `POST /tenants` refuse it `FIELD_SERVER_OWNED`. No
403
+ * route rewrites or clears it, so it keeps describing the SIGNUP even after
404
+ * an operator edits the contact leaves it names.
405
+ */
406
+ interface StoreRegistrationPrefill {
407
+ /** The leaves the registration wrote, in `['phone', 'email']` order; never empty. */
408
+ fields: StoreRegistrationPrefillField[];
409
+ /** Unix ms — the registration's own `createdAt`, the instant the STORE item is stamped with. */
410
+ capturedAt: number;
411
+ }
412
+ /**
413
+ * The ownership check on the STORE row's `email`: whether whoever reads that
414
+ * inbox has confirmed it, by following a single-use link the api mailed to it.
415
+ *
416
+ * ⚠️ Server-owned: no request body may set it. Every write that puts a NEW
417
+ * `email` on the row stamps it `pending` for that exact address; the
418
+ * confirmation link flips it to `verified` only while the row still holds
419
+ * that address. Clearing `email` KEEPS the record: it names the address it
420
+ * is about, so it can only vouch for a later `email` that really is that
421
+ * verified address.
422
+ *
423
+ * ABSENT means verified (rows that predate it are grandfathered); a PRESENT
424
+ * record that is `null` or malformed counts as unverified. The one reader of
425
+ * "verified" is `isStoreEmailVerified` (`stacks/helpers/storeEmailVerified.ts`).
426
+ */
427
+ interface StoreEmailVerification {
428
+ /** `pending` until the link mailed to `address` is followed, then `verified`. */
429
+ status: 'pending' | 'verified';
430
+ /**
431
+ * The normalised address the record is about. A record whose `address` is
432
+ * not the row's current `email` says nothing about that email.
433
+ */
434
+ address: string;
435
+ /** Unix ms — when the api stamped it `pending`. */
436
+ requestedAt: number;
437
+ /** Unix ms — when the link was followed. Present only once `verified`. */
438
+ verifiedAt?: number;
439
+ }
391
440
  /**
392
441
  * The shop's public address, as every link minter and every client reads it.
393
442
  * Computed by the api from server-owned row fields that never reach a client
@@ -501,6 +550,23 @@ declare global {
501
550
  * permanently absent by construction.
502
551
  */
503
552
  termsConsent?: StoreTermsConsent;
553
+ /**
554
+ * Which contact leaves tenant self-registration prefilled, and when.
555
+ * Admin-only; absent on every row the signup did not prefill — including
556
+ * every row written before this shipped (forward-only, never backfilled)
557
+ * and every operator-created tenant.
558
+ */
559
+ registrationPrefill?: StoreRegistrationPrefill;
560
+ /**
561
+ * Whether `email` has been confirmed by its inbox. Admin-only; written only
562
+ * by the server.
563
+ *
564
+ * ⚠️ **Absent means verified.** A row whose `email` predates verification
565
+ * carries no record, and that address is grandfathered as verified — it is
566
+ * never backfilled. Only a record that is `pending`, or `verified` for an
567
+ * address other than the current `email`, makes the email unverified.
568
+ */
569
+ emailVerification?: StoreEmailVerification;
504
570
  /**
505
571
  * Response-time join, not a persisted Store attribute — and TWO different
506
572
  * shapes depending on the endpoint: `GET /tenants` (SUPERVISOR) attaches the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "platform-types",
3
- "version": "1.10.737",
3
+ "version": "1.10.739",
4
4
  "description": "Shared wire and entity contracts for the platform.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",