founder-schema 0.3.0 → 0.4.0

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.
Files changed (102) hide show
  1. package/README.md +18 -15
  2. package/dist/access/access.d.ts +76 -0
  3. package/dist/access/access.d.ts.map +1 -0
  4. package/dist/access/access.js +66 -0
  5. package/dist/access/access.js.map +1 -0
  6. package/dist/access/permissions.d.ts +153 -0
  7. package/dist/access/permissions.d.ts.map +1 -0
  8. package/dist/access/permissions.js +80 -0
  9. package/dist/access/permissions.js.map +1 -0
  10. package/dist/access/roles.d.ts +71 -0
  11. package/dist/access/roles.d.ts.map +1 -0
  12. package/dist/access/roles.js +72 -0
  13. package/dist/access/roles.js.map +1 -0
  14. package/dist/chat.d.ts +4 -4
  15. package/dist/chat.d.ts.map +1 -1
  16. package/dist/chat.js +7 -2
  17. package/dist/chat.js.map +1 -1
  18. package/dist/core/common.d.ts +304 -0
  19. package/dist/core/common.d.ts.map +1 -0
  20. package/dist/core/common.js +340 -0
  21. package/dist/core/common.js.map +1 -0
  22. package/dist/core/errors.d.ts +105 -0
  23. package/dist/core/errors.d.ts.map +1 -0
  24. package/dist/core/errors.js +115 -0
  25. package/dist/core/errors.js.map +1 -0
  26. package/dist/core/limits.d.ts +99 -0
  27. package/dist/core/limits.d.ts.map +1 -0
  28. package/dist/core/limits.js +109 -0
  29. package/dist/core/limits.js.map +1 -0
  30. package/dist/core/responses.d.ts +195 -0
  31. package/dist/core/responses.d.ts.map +1 -0
  32. package/dist/core/responses.js +73 -0
  33. package/dist/core/responses.js.map +1 -0
  34. package/dist/core/validation.d.ts +144 -0
  35. package/dist/core/validation.d.ts.map +1 -0
  36. package/dist/core/validation.js +150 -0
  37. package/dist/core/validation.js.map +1 -0
  38. package/dist/domains/account/account.d.ts +40 -0
  39. package/dist/domains/account/account.d.ts.map +1 -0
  40. package/dist/domains/account/account.js +39 -0
  41. package/dist/domains/account/account.js.map +1 -0
  42. package/dist/domains/audit/audit.d.ts +169 -0
  43. package/dist/domains/audit/audit.d.ts.map +1 -0
  44. package/dist/domains/audit/audit.js +84 -0
  45. package/dist/domains/audit/audit.js.map +1 -0
  46. package/dist/domains/chat/chat.d.ts +187 -0
  47. package/dist/domains/chat/chat.d.ts.map +1 -0
  48. package/dist/domains/chat/chat.js +189 -0
  49. package/dist/domains/chat/chat.js.map +1 -0
  50. package/dist/domains/dashboard/dashboard.d.ts +48 -0
  51. package/dist/domains/dashboard/dashboard.d.ts.map +1 -0
  52. package/dist/domains/dashboard/dashboard.js +58 -0
  53. package/dist/domains/dashboard/dashboard.js.map +1 -0
  54. package/dist/domains/discover/discover.d.ts +245 -0
  55. package/dist/domains/discover/discover.d.ts.map +1 -0
  56. package/dist/domains/discover/discover.js +68 -0
  57. package/dist/domains/discover/discover.js.map +1 -0
  58. package/dist/domains/feed/feed.d.ts +1658 -0
  59. package/dist/domains/feed/feed.d.ts.map +1 -0
  60. package/dist/domains/feed/feed.js +623 -0
  61. package/dist/domains/feed/feed.js.map +1 -0
  62. package/dist/domains/members/members.d.ts +175 -0
  63. package/dist/domains/members/members.d.ts.map +1 -0
  64. package/dist/domains/members/members.js +106 -0
  65. package/dist/domains/members/members.js.map +1 -0
  66. package/dist/domains/moderation/moderation.d.ts +184 -0
  67. package/dist/domains/moderation/moderation.d.ts.map +1 -0
  68. package/dist/domains/moderation/moderation.js +90 -0
  69. package/dist/domains/moderation/moderation.js.map +1 -0
  70. package/dist/domains/onboarding/onboarding.d.ts +1018 -0
  71. package/dist/domains/onboarding/onboarding.d.ts.map +1 -0
  72. package/dist/domains/onboarding/onboarding.js +717 -0
  73. package/dist/domains/onboarding/onboarding.js.map +1 -0
  74. package/dist/domains/profile/founder-profile.d.ts +387 -0
  75. package/dist/domains/profile/founder-profile.d.ts.map +1 -0
  76. package/dist/domains/profile/founder-profile.js +180 -0
  77. package/dist/domains/profile/founder-profile.js.map +1 -0
  78. package/dist/domains/support/support.d.ts +305 -0
  79. package/dist/domains/support/support.d.ts.map +1 -0
  80. package/dist/domains/support/support.js +129 -0
  81. package/dist/domains/support/support.js.map +1 -0
  82. package/dist/domains/team/team.d.ts +79 -0
  83. package/dist/domains/team/team.d.ts.map +1 -0
  84. package/dist/domains/team/team.js +54 -0
  85. package/dist/domains/team/team.js.map +1 -0
  86. package/dist/domains/uploads/uploads.d.ts +113 -0
  87. package/dist/domains/uploads/uploads.d.ts.map +1 -0
  88. package/dist/domains/uploads/uploads.js +106 -0
  89. package/dist/domains/uploads/uploads.js.map +1 -0
  90. package/dist/env.d.ts +85 -0
  91. package/dist/env.d.ts.map +1 -0
  92. package/dist/env.js +150 -0
  93. package/dist/env.js.map +1 -0
  94. package/dist/index.d.ts +21 -12
  95. package/dist/index.d.ts.map +1 -1
  96. package/dist/index.js +29 -18
  97. package/dist/index.js.map +1 -1
  98. package/dist/onboarding.d.ts +58 -32
  99. package/dist/onboarding.d.ts.map +1 -1
  100. package/dist/onboarding.js +155 -32
  101. package/dist/onboarding.js.map +1 -1
  102. package/package.json +14 -2
@@ -0,0 +1,1018 @@
1
+ /**
2
+ * founder-schema — Onboarding: steps, enums, and the two shapes of the answers
3
+ *
4
+ * ONE LIST DEFINES THE FLOW, AND IT IS DERIVED. Each step's fields are a pick
5
+ * of the finish body (`ONBOARDING_STEP_SCHEMAS`), and `FOUNDER_ONBOARDING_STEPS`
6
+ * is built FROM those picks: its `fields`, and even whether a step may be
7
+ * skipped, come from the schema rather than from a second hand-written list.
8
+ * GymMonk arrived at one list after keeping two in sync by hand, where a step
9
+ * could exist with no title or, worse, no validation gate at all; until 0.2.0
10
+ * this file still wrote the field lists twice.
11
+ *
12
+ * TWO SHAPES, ONE SET OF RULES. A half-filled form legitimately holds `null`
13
+ * for a choice nobody has made yet; the finalize body only ever sees completed
14
+ * answers. So the rules are written once and expressed over both shapes:
15
+ * `onboardingFormSchema` for work in progress and `completeOnboardingBodySchema`
16
+ * for the end. Letting those two drift is how a wizard says a step is optional
17
+ * and then answers 422 at Finish.
18
+ *
19
+ * NO COPY IN HERE. Step titles, help lines and topic category names are
20
+ * translation KEYS (`titleKey`, `helpKey`, `labelKey`), Jansathi's rule for
21
+ * every config string: an English sentence in a shared package is a sentence
22
+ * every other language has to match by wording.
23
+ *
24
+ * @module founder-schema/domains/onboarding
25
+ */
26
+ import { z } from 'zod';
27
+ /**
28
+ * 18, ruled by the user 2026-09-21. Under-18 would pull in parental-consent
29
+ * duties under the DPDP Act, which is a different and larger problem than a
30
+ * validation rule.
31
+ *
32
+ * ⚠️ The SERVER refuses at finalize. This schema exists so the member sees a
33
+ * useful message; it is not the gate.
34
+ */
35
+ export declare const MIN_AGE_YEARS = 18;
36
+ /** A sanity ceiling, not a product rule. Catches a mistyped year. */
37
+ export declare const MAX_AGE_YEARS = 120;
38
+ /**
39
+ * Whole years completed, by the calendar.
40
+ *
41
+ * ⚠️ NOT `elapsedMs / (365.25 * day)`, which is what the sibling product uses.
42
+ * That approximation reads 17.9986 at the start of somebody's eighteenth
43
+ * birthday and only crosses 18 about halfway through the day, so it refuses
44
+ * them for the half of their birthday they are most likely to be signing up on.
45
+ * Measured: it disagrees with the calendar on all 400 of the next 400 days.
46
+ * An age gate is exactly the place an approximation is not good enough.
47
+ */
48
+ export declare function ageInYears(isoDate: string, now?: Date): number;
49
+ /** A calendar date with no time component, `YYYY-MM-DD`. */
50
+ export declare const isoDateSchema: z.ZodString;
51
+ export type IsoDate = z.infer<typeof isoDateSchema>;
52
+ /**
53
+ * Date of birth, with the age gate applied per parse.
54
+ *
55
+ * ⚠️ THE CLIENT IS NOT THE GATE. This schema exists so the member sees a useful
56
+ * message, and the server must refuse the same dates at finalize regardless.
57
+ * The sibling dating product validates the identical rule on its client and
58
+ * still shipped a defect where an under-age date of birth produced a live,
59
+ * discoverable profile, because the client was the only thing checking.
60
+ */
61
+ export declare const dateOfBirthSchema: z.ZodString;
62
+ export type DateOfBirth = z.infer<typeof dateOfBirthSchema>;
63
+ export declare const BUSINESS_TYPE_VALUES: readonly ["startup", "sme", "enterprise"];
64
+ export declare const businessTypeSchema: z.ZodEnum<{
65
+ startup: "startup";
66
+ sme: "sme";
67
+ enterprise: "enterprise";
68
+ }>;
69
+ export type BusinessType = z.infer<typeof businessTypeSchema>;
70
+ /**
71
+ * ONE vocabulary, used TWICE: a member picks these as their `interests`, and a
72
+ * post carries them as its `topics`. That is what makes relevance an index
73
+ * lookup rather than a guess, and it is why this list is not called "interests"
74
+ * - naming it for one of its two jobs would have invited a second list for the
75
+ * other, which is the mistake this package has already made once with goals.
76
+ * (User's ruling via hary, 2026-09-21.)
77
+ *
78
+ * Deliberately DISTINCT from two neighbours that will otherwise collect the
79
+ * same words:
80
+ *
81
+ * industry what your company does
82
+ * skills what you can do
83
+ * interests what you want to read about
84
+ *
85
+ * If the copy does not keep them apart, members fill all three identically and
86
+ * every one of them stops telling us anything.
87
+ *
88
+ * A closed list, consistent with industry, skill and stage, for the reason
89
+ * already written beside those: free text means two people typing "growth" and
90
+ * "Growth Marketing" never match, and matching is the entire point. The cost is
91
+ * that adding an interest needs a publish.
92
+ *
93
+ * Tuned down from the dating product's 246, which is mostly dating material.
94
+ * Values reuse its exact strings wherever one existed, so its Hindi
95
+ * translations can be lifted across.
96
+ *
97
+ * ⚠️ Stored per member. Append only; removing a value orphans data.
98
+ */
99
+ export declare const TOPIC_VALUES: readonly ["mentoring", "leadership", "networking", "public_speaking", "teaching", "hiring_talent", "personal_branding", "career_transition", "remote_work", "ai_ml", "blockchain", "crypto_web3", "robotics", "data_science", "cybersecurity", "game_dev", "ux_design", "app_development", "open_source", "electronics", "space_exploration", "green_tech", "deeptech", "no_code", "entrepreneurship", "investing", "stock_trading", "personal_finance", "fundraising", "marketing", "sales", "consulting", "ecommerce", "retail", "real_estate", "supply_chain", "product_management", "growth", "b2b_saas", "d2c", "meditation", "journaling", "self_improvement", "productivity", "reading", "online_courses", "philosophy", "psychology", "therapy", "sleep_optimization", "gym", "yoga", "photography", "writing", "graphic_design", "filmmaking", "digital_art", "content_creation", "blogging", "vlogging", "podcasts", "animation", "music_production", "volunteering", "ngo_work", "environmental", "women_empowerment", "community_service", "social_enterprise", "education_access"];
100
+ export declare const topicSchema: z.ZodEnum<{
101
+ ai_ml: "ai_ml";
102
+ b2b_saas: "b2b_saas";
103
+ d2c: "d2c";
104
+ deeptech: "deeptech";
105
+ robotics: "robotics";
106
+ growth: "growth";
107
+ sales: "sales";
108
+ marketing: "marketing";
109
+ supply_chain: "supply_chain";
110
+ fundraising: "fundraising";
111
+ mentoring: "mentoring";
112
+ leadership: "leadership";
113
+ networking: "networking";
114
+ public_speaking: "public_speaking";
115
+ teaching: "teaching";
116
+ hiring_talent: "hiring_talent";
117
+ personal_branding: "personal_branding";
118
+ career_transition: "career_transition";
119
+ remote_work: "remote_work";
120
+ blockchain: "blockchain";
121
+ crypto_web3: "crypto_web3";
122
+ data_science: "data_science";
123
+ cybersecurity: "cybersecurity";
124
+ game_dev: "game_dev";
125
+ ux_design: "ux_design";
126
+ app_development: "app_development";
127
+ open_source: "open_source";
128
+ electronics: "electronics";
129
+ space_exploration: "space_exploration";
130
+ green_tech: "green_tech";
131
+ no_code: "no_code";
132
+ entrepreneurship: "entrepreneurship";
133
+ investing: "investing";
134
+ stock_trading: "stock_trading";
135
+ personal_finance: "personal_finance";
136
+ consulting: "consulting";
137
+ ecommerce: "ecommerce";
138
+ retail: "retail";
139
+ real_estate: "real_estate";
140
+ product_management: "product_management";
141
+ meditation: "meditation";
142
+ journaling: "journaling";
143
+ self_improvement: "self_improvement";
144
+ productivity: "productivity";
145
+ reading: "reading";
146
+ online_courses: "online_courses";
147
+ philosophy: "philosophy";
148
+ psychology: "psychology";
149
+ therapy: "therapy";
150
+ sleep_optimization: "sleep_optimization";
151
+ gym: "gym";
152
+ yoga: "yoga";
153
+ photography: "photography";
154
+ writing: "writing";
155
+ graphic_design: "graphic_design";
156
+ filmmaking: "filmmaking";
157
+ digital_art: "digital_art";
158
+ content_creation: "content_creation";
159
+ blogging: "blogging";
160
+ vlogging: "vlogging";
161
+ podcasts: "podcasts";
162
+ animation: "animation";
163
+ music_production: "music_production";
164
+ volunteering: "volunteering";
165
+ ngo_work: "ngo_work";
166
+ environmental: "environmental";
167
+ women_empowerment: "women_empowerment";
168
+ community_service: "community_service";
169
+ social_enterprise: "social_enterprise";
170
+ education_access: "education_access";
171
+ }>;
172
+ export type Topic = z.infer<typeof topicSchema>;
173
+ /**
174
+ * The grouping the picker renders.
175
+ *
176
+ * ⚠️ `TOPIC_VALUES` above is the single source of truth and this is typed
177
+ * against it, so a typo here is a compile error rather than a chip that renders
178
+ * and can never be selected. The dating product keeps a categorised list and a
179
+ * flat list side by side and they have already drifted apart by two values;
180
+ * a test in this package asserts these two agree exactly, in both directions.
181
+ */
182
+ export declare const TOPIC_CATEGORY_KEYS: readonly ["career", "tech", "business", "growth", "creative", "impact"];
183
+ export type TopicCategoryKey = (typeof TOPIC_CATEGORY_KEYS)[number];
184
+ /**
185
+ * ⚠ TRANSLATION KEY SHAPE, for whoever builds the picker: `topics.category.<key>`
186
+ * for a category and `topics.value.<topic>` for a topic. The dating product's
187
+ * interests JSON is keyed by CATEGORY NAME instead, so all five of its label
188
+ * lookups miss and every chip renders its raw English in every locale, with a
189
+ * fully translated Hindi file sitting unreachable.
190
+ */
191
+ export interface TopicCategory {
192
+ key: TopicCategoryKey;
193
+ /** A translation key. The English lives in the client's message files, not here. */
194
+ labelKey: `topics.category.${TopicCategoryKey}`;
195
+ values: readonly Topic[];
196
+ }
197
+ export declare const TOPIC_CATEGORIES: readonly TopicCategory[];
198
+ /**
199
+ * How many a member must pick. A minimum exists because these drive feed
200
+ * relevance and zero of them means no relevance at all.
201
+ *
202
+ * ⚠️ If 3 turns out to be hard to reach against this list, that is a signal
203
+ * about the LIST, not about the minimum. The sibling product enforces no
204
+ * minimum at all, and its own field config says "pick up to 10" while every
205
+ * screen and schema enforces 20.
206
+ */
207
+ export declare const INTERESTS_MIN = 3;
208
+ export declare const INTERESTS_MAX = 10;
209
+ /**
210
+ * The step keys, in order, as a literal union, so a consumer can key a table by
211
+ * step and have TypeScript insist on every one. Before 0.2.0 `key` was a plain
212
+ * string and the web client kept its own copy of this list to get the same
213
+ * check; a test there held the two together. Now there is one list.
214
+ */
215
+ export declare const ONBOARDING_STEP_KEYS: readonly ["identity", "contact", "location", "goals", "interests", "business", "guidelines"];
216
+ export type OnboardingStepKey = (typeof ONBOARDING_STEP_KEYS)[number];
217
+ /**
218
+ * The community guidelines a member agrees to at the last step, by version.
219
+ *
220
+ * The finish body accepts THIS version and no other: an old tab still showing
221
+ * last month's text cannot record agreement to text it never displayed, and
222
+ * `'whatever'` is not a version. Until 0.2.0 any non-empty string passed, and
223
+ * the web client held this constant on its own.
224
+ *
225
+ * ⚠ Changing the guidelines text means bumping this, in the same publish.
226
+ * Every member who agreed to an earlier version keeps that version on their
227
+ * profile; that record is the point.
228
+ */
229
+ export declare const GUIDELINES_VERSION: "2026-10-03";
230
+ export declare const guidelinesVersionSchema: z.ZodLiteral<"2026-10-03">;
231
+ /**
232
+ * The links the contact step collects, picked from the profile's own links so
233
+ * the two cannot disagree on what a link is. The phone is `phoneSchema`: ten
234
+ * digits, stored raw with no country code, on the account rather than here.
235
+ */
236
+ export declare const contactLinksSchema: z.ZodObject<{
237
+ linkedin: z.ZodOptional<z.ZodURL>;
238
+ x: z.ZodOptional<z.ZodURL>;
239
+ instagram: z.ZodOptional<z.ZodURL>;
240
+ }, z.core.$strip>;
241
+ export type ContactLinks = z.infer<typeof contactLinksSchema>;
242
+ /** A team size has at most this many digits: `TEAM_SIZE_MAX` written out. */
243
+ export declare const TEAM_SIZE_DIGITS_MAX: number;
244
+ /**
245
+ * The answers so far, keyed by the finish body's own field names: what each
246
+ * step SAVES (`PATCH /onboarding`, merged per field), what `GET` hands back
247
+ * to resume, and so the only keys a draft may hold
248
+ * (`ONBOARDING_DRAFT_KEYS`).
249
+ *
250
+ * RAW, on purpose: a draft is what the member TYPED, not what Finish will send.
251
+ * A half-typed link is ordinary text, a team size is digits as typed, and every
252
+ * choice is `null` until made ("not answered" is not "answered with nothing").
253
+ * Nothing here is required; whether a member may FINISH is
254
+ * `completeOnboardingBodySchema`'s decision, and the client builds that body
255
+ * from these answers.
256
+ *
257
+ * Screens may hold a different shape on top of this one (the web draws first
258
+ * and last name as two fields and joins them into `displayName`). Derive that
259
+ * type from `OnboardingForm` rather than writing it out, so a field added here
260
+ * reaches every screen.
261
+ *
262
+ * A stored draft is UNTRUSTED when it comes back: an older client, or another
263
+ * one, wrote it, and the server stores values opaquely. Read it with
264
+ * `readOnboardingDraft`, never by casting.
265
+ */
266
+ export declare const onboardingFormSchema: z.ZodObject<{
267
+ displayName: z.ZodString;
268
+ gender: z.ZodNullable<z.ZodEnum<{
269
+ other: "other";
270
+ male: "male";
271
+ female: "female";
272
+ prefer_not_to_say: "prefer_not_to_say";
273
+ }>>;
274
+ dateOfBirth: z.ZodString;
275
+ headline: z.ZodString;
276
+ about: z.ZodString;
277
+ avatarUploadKey: z.ZodNullable<z.ZodString>;
278
+ skills: z.ZodArray<z.ZodEnum<{
279
+ engineering: "engineering";
280
+ product: "product";
281
+ design: "design";
282
+ data: "data";
283
+ growth: "growth";
284
+ sales: "sales";
285
+ marketing: "marketing";
286
+ operations: "operations";
287
+ finance: "finance";
288
+ legal: "legal";
289
+ hr_people: "hr_people";
290
+ supply_chain: "supply_chain";
291
+ research: "research";
292
+ fundraising: "fundraising";
293
+ community: "community";
294
+ }>>;
295
+ phone: z.ZodString;
296
+ links: z.ZodObject<{
297
+ linkedin: z.ZodString;
298
+ x: z.ZodString;
299
+ instagram: z.ZodString;
300
+ }, z.core.$strip>;
301
+ location: z.ZodNullable<z.ZodObject<{
302
+ city: z.ZodString;
303
+ state: z.ZodString;
304
+ country: z.ZodString;
305
+ }, z.core.$strip>>;
306
+ goals: z.ZodArray<z.ZodEnum<{
307
+ find_cofounder: "find_cofounder";
308
+ find_investors: "find_investors";
309
+ find_customers: "find_customers";
310
+ hiring: "hiring";
311
+ partnerships: "partnerships";
312
+ mentorship: "mentorship";
313
+ grow_network: "grow_network";
314
+ business_ideas: "business_ideas";
315
+ market_insights: "market_insights";
316
+ learn_startup: "learn_startup";
317
+ start_company: "start_company";
318
+ }>>;
319
+ interests: z.ZodArray<z.ZodEnum<{
320
+ ai_ml: "ai_ml";
321
+ b2b_saas: "b2b_saas";
322
+ d2c: "d2c";
323
+ deeptech: "deeptech";
324
+ robotics: "robotics";
325
+ growth: "growth";
326
+ sales: "sales";
327
+ marketing: "marketing";
328
+ supply_chain: "supply_chain";
329
+ fundraising: "fundraising";
330
+ mentoring: "mentoring";
331
+ leadership: "leadership";
332
+ networking: "networking";
333
+ public_speaking: "public_speaking";
334
+ teaching: "teaching";
335
+ hiring_talent: "hiring_talent";
336
+ personal_branding: "personal_branding";
337
+ career_transition: "career_transition";
338
+ remote_work: "remote_work";
339
+ blockchain: "blockchain";
340
+ crypto_web3: "crypto_web3";
341
+ data_science: "data_science";
342
+ cybersecurity: "cybersecurity";
343
+ game_dev: "game_dev";
344
+ ux_design: "ux_design";
345
+ app_development: "app_development";
346
+ open_source: "open_source";
347
+ electronics: "electronics";
348
+ space_exploration: "space_exploration";
349
+ green_tech: "green_tech";
350
+ no_code: "no_code";
351
+ entrepreneurship: "entrepreneurship";
352
+ investing: "investing";
353
+ stock_trading: "stock_trading";
354
+ personal_finance: "personal_finance";
355
+ consulting: "consulting";
356
+ ecommerce: "ecommerce";
357
+ retail: "retail";
358
+ real_estate: "real_estate";
359
+ product_management: "product_management";
360
+ meditation: "meditation";
361
+ journaling: "journaling";
362
+ self_improvement: "self_improvement";
363
+ productivity: "productivity";
364
+ reading: "reading";
365
+ online_courses: "online_courses";
366
+ philosophy: "philosophy";
367
+ psychology: "psychology";
368
+ therapy: "therapy";
369
+ sleep_optimization: "sleep_optimization";
370
+ gym: "gym";
371
+ yoga: "yoga";
372
+ photography: "photography";
373
+ writing: "writing";
374
+ graphic_design: "graphic_design";
375
+ filmmaking: "filmmaking";
376
+ digital_art: "digital_art";
377
+ content_creation: "content_creation";
378
+ blogging: "blogging";
379
+ vlogging: "vlogging";
380
+ podcasts: "podcasts";
381
+ animation: "animation";
382
+ music_production: "music_production";
383
+ volunteering: "volunteering";
384
+ ngo_work: "ngo_work";
385
+ environmental: "environmental";
386
+ women_empowerment: "women_empowerment";
387
+ community_service: "community_service";
388
+ social_enterprise: "social_enterprise";
389
+ education_access: "education_access";
390
+ }>>;
391
+ venture: z.ZodObject<{
392
+ name: z.ZodString;
393
+ website: z.ZodString;
394
+ industry: z.ZodNullable<z.ZodEnum<{
395
+ agritech: "agritech";
396
+ ai_ml: "ai_ml";
397
+ b2b_saas: "b2b_saas";
398
+ consumer: "consumer";
399
+ climate: "climate";
400
+ d2c: "d2c";
401
+ deeptech: "deeptech";
402
+ edtech: "edtech";
403
+ fintech: "fintech";
404
+ gaming: "gaming";
405
+ healthtech: "healthtech";
406
+ logistics: "logistics";
407
+ manufacturing: "manufacturing";
408
+ marketplace: "marketplace";
409
+ media: "media";
410
+ mobility: "mobility";
411
+ proptech: "proptech";
412
+ robotics: "robotics";
413
+ services: "services";
414
+ space: "space";
415
+ other: "other";
416
+ }>>;
417
+ stage: z.ZodNullable<z.ZodEnum<{
418
+ idea: "idea";
419
+ validation: "validation";
420
+ mvp: "mvp";
421
+ pre_seed: "pre_seed";
422
+ seed: "seed";
423
+ series_a_plus: "series_a_plus";
424
+ profitable: "profitable";
425
+ exited: "exited";
426
+ }>>;
427
+ teamSize: z.ZodString;
428
+ }, z.core.$strip>;
429
+ businessType: z.ZodNullable<z.ZodEnum<{
430
+ startup: "startup";
431
+ sme: "sme";
432
+ enterprise: "enterprise";
433
+ }>>;
434
+ guidelinesVersion: z.ZodNullable<z.ZodString>;
435
+ }, z.core.$strip>;
436
+ export type OnboardingForm = z.infer<typeof onboardingFormSchema>;
437
+ /** The business step before anything is chosen. */
438
+ export declare const EMPTY_ONBOARDING_VENTURE: OnboardingForm['venture'];
439
+ /**
440
+ * A stored draft as an `OnboardingForm`, FIELD BY FIELD.
441
+ *
442
+ * Every field is checked against its own vocabulary and cut to its own limit;
443
+ * one that does not fit becomes "not answered" (`''`, `null`, `[]`) and the
444
+ * rest of the draft survives. Never coerced into a different answer: a value
445
+ * outside a vocabulary is dropped, not mapped to the nearest one. A photo key
446
+ * is never restored (see `avatarUploadKey`), and agreement only counts for the
447
+ * CURRENT guidelines.
448
+ *
449
+ * It fills in no answer the member did not give: a blank country stays blank.
450
+ * Whatever a screen shows by default is that screen's choice.
451
+ */
452
+ export declare function readOnboardingDraft(draft: unknown): OnboardingForm;
453
+ /**
454
+ * What the client sends to finish. Completed answers only.
455
+ *
456
+ * ⚠️ EVERY OPTIONAL FIELD HERE MUST BE ABSENT WHEN UNANSWERED, never a default
457
+ * standing in for one. The sibling gym product sent `bloodGroup ?? 'O+'`, so
458
+ * every member who skipped the question was recorded as O-positive: a real
459
+ * answer, indistinguishable from one somebody gave, sitting on a screen staff
460
+ * would read in an emergency. Absent has to stay absent.
461
+ *
462
+ * ⚠️ AND THIS IS NOT THE GATE EITHER. The server re-checks the age and refuses
463
+ * at finalize. `isOnboarded` may be set here and nowhere else: four of the
464
+ * profile's partial indexes are gated on it, so a half-built profile carrying
465
+ * it true appears in Discover half-built.
466
+ *
467
+ * Location, venture and links are the profile's own shapes, not copies: the
468
+ * copies are how the profile model came to lack Instagram.
469
+ */
470
+ export declare const completeOnboardingBodySchema: z.ZodObject<{
471
+ displayName: z.ZodString;
472
+ gender: z.ZodEnum<{
473
+ other: "other";
474
+ male: "male";
475
+ female: "female";
476
+ prefer_not_to_say: "prefer_not_to_say";
477
+ }>;
478
+ dateOfBirth: z.ZodString;
479
+ headline: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
480
+ about: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
481
+ avatarUploadKey: z.ZodOptional<z.ZodString>;
482
+ phone: z.ZodString;
483
+ links: z.ZodOptional<z.ZodObject<{
484
+ linkedin: z.ZodOptional<z.ZodURL>;
485
+ x: z.ZodOptional<z.ZodURL>;
486
+ instagram: z.ZodOptional<z.ZodURL>;
487
+ }, z.core.$strip>>;
488
+ location: z.ZodOptional<z.ZodObject<{
489
+ city: z.ZodString;
490
+ state: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
491
+ country: z.ZodString;
492
+ }, z.core.$strip>>;
493
+ goals: z.ZodArray<z.ZodEnum<{
494
+ find_cofounder: "find_cofounder";
495
+ find_investors: "find_investors";
496
+ find_customers: "find_customers";
497
+ hiring: "hiring";
498
+ partnerships: "partnerships";
499
+ mentorship: "mentorship";
500
+ grow_network: "grow_network";
501
+ business_ideas: "business_ideas";
502
+ market_insights: "market_insights";
503
+ learn_startup: "learn_startup";
504
+ start_company: "start_company";
505
+ }>>;
506
+ interests: z.ZodArray<z.ZodEnum<{
507
+ ai_ml: "ai_ml";
508
+ b2b_saas: "b2b_saas";
509
+ d2c: "d2c";
510
+ deeptech: "deeptech";
511
+ robotics: "robotics";
512
+ growth: "growth";
513
+ sales: "sales";
514
+ marketing: "marketing";
515
+ supply_chain: "supply_chain";
516
+ fundraising: "fundraising";
517
+ mentoring: "mentoring";
518
+ leadership: "leadership";
519
+ networking: "networking";
520
+ public_speaking: "public_speaking";
521
+ teaching: "teaching";
522
+ hiring_talent: "hiring_talent";
523
+ personal_branding: "personal_branding";
524
+ career_transition: "career_transition";
525
+ remote_work: "remote_work";
526
+ blockchain: "blockchain";
527
+ crypto_web3: "crypto_web3";
528
+ data_science: "data_science";
529
+ cybersecurity: "cybersecurity";
530
+ game_dev: "game_dev";
531
+ ux_design: "ux_design";
532
+ app_development: "app_development";
533
+ open_source: "open_source";
534
+ electronics: "electronics";
535
+ space_exploration: "space_exploration";
536
+ green_tech: "green_tech";
537
+ no_code: "no_code";
538
+ entrepreneurship: "entrepreneurship";
539
+ investing: "investing";
540
+ stock_trading: "stock_trading";
541
+ personal_finance: "personal_finance";
542
+ consulting: "consulting";
543
+ ecommerce: "ecommerce";
544
+ retail: "retail";
545
+ real_estate: "real_estate";
546
+ product_management: "product_management";
547
+ meditation: "meditation";
548
+ journaling: "journaling";
549
+ self_improvement: "self_improvement";
550
+ productivity: "productivity";
551
+ reading: "reading";
552
+ online_courses: "online_courses";
553
+ philosophy: "philosophy";
554
+ psychology: "psychology";
555
+ therapy: "therapy";
556
+ sleep_optimization: "sleep_optimization";
557
+ gym: "gym";
558
+ yoga: "yoga";
559
+ photography: "photography";
560
+ writing: "writing";
561
+ graphic_design: "graphic_design";
562
+ filmmaking: "filmmaking";
563
+ digital_art: "digital_art";
564
+ content_creation: "content_creation";
565
+ blogging: "blogging";
566
+ vlogging: "vlogging";
567
+ podcasts: "podcasts";
568
+ animation: "animation";
569
+ music_production: "music_production";
570
+ volunteering: "volunteering";
571
+ ngo_work: "ngo_work";
572
+ environmental: "environmental";
573
+ women_empowerment: "women_empowerment";
574
+ community_service: "community_service";
575
+ social_enterprise: "social_enterprise";
576
+ education_access: "education_access";
577
+ }>>;
578
+ skills: z.ZodOptional<z.ZodArray<z.ZodEnum<{
579
+ engineering: "engineering";
580
+ product: "product";
581
+ design: "design";
582
+ data: "data";
583
+ growth: "growth";
584
+ sales: "sales";
585
+ marketing: "marketing";
586
+ operations: "operations";
587
+ finance: "finance";
588
+ legal: "legal";
589
+ hr_people: "hr_people";
590
+ supply_chain: "supply_chain";
591
+ research: "research";
592
+ fundraising: "fundraising";
593
+ community: "community";
594
+ }>>>;
595
+ venture: z.ZodOptional<z.ZodObject<{
596
+ name: z.ZodString;
597
+ industry: z.ZodEnum<{
598
+ agritech: "agritech";
599
+ ai_ml: "ai_ml";
600
+ b2b_saas: "b2b_saas";
601
+ consumer: "consumer";
602
+ climate: "climate";
603
+ d2c: "d2c";
604
+ deeptech: "deeptech";
605
+ edtech: "edtech";
606
+ fintech: "fintech";
607
+ gaming: "gaming";
608
+ healthtech: "healthtech";
609
+ logistics: "logistics";
610
+ manufacturing: "manufacturing";
611
+ marketplace: "marketplace";
612
+ media: "media";
613
+ mobility: "mobility";
614
+ proptech: "proptech";
615
+ robotics: "robotics";
616
+ services: "services";
617
+ space: "space";
618
+ other: "other";
619
+ }>;
620
+ stage: z.ZodEnum<{
621
+ idea: "idea";
622
+ validation: "validation";
623
+ mvp: "mvp";
624
+ pre_seed: "pre_seed";
625
+ seed: "seed";
626
+ series_a_plus: "series_a_plus";
627
+ profitable: "profitable";
628
+ exited: "exited";
629
+ }>;
630
+ tagline: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
631
+ website: z.ZodOptional<z.ZodURL>;
632
+ teamSize: z.ZodOptional<z.ZodNumber>;
633
+ }, z.core.$strip>>;
634
+ businessType: z.ZodOptional<z.ZodEnum<{
635
+ startup: "startup";
636
+ sme: "sme";
637
+ enterprise: "enterprise";
638
+ }>>;
639
+ guidelinesVersion: z.ZodLiteral<"2026-10-03">;
640
+ }, z.core.$strip>;
641
+ export type CompleteOnboardingBody = z.infer<typeof completeOnboardingBodySchema>;
642
+ /** What a form may hand to the finish body before parsing. */
643
+ export type CompleteOnboardingBodyInput = z.input<typeof completeOnboardingBodySchema>;
644
+ /**
645
+ * Each step's slice of the finish body, picked FROM it, so a client validating
646
+ * "may I leave this step" and the server validating the finish apply the very
647
+ * same rules. A copy would drift, and the drift shows up as a wizard that lets
648
+ * a step pass and a finish that refuses it, on the last screen.
649
+ *
650
+ * THIS IS THE ONE PLACE A STEP'S FIELDS ARE WRITTEN. `FOUNDER_ONBOARDING_STEPS`
651
+ * below reads them from here. A test asserts that every finish field belongs to
652
+ * exactly one step.
653
+ *
654
+ * These validate the FINISH shape (skipped = absent), not the in-progress form:
655
+ * a client maps its form state to the slice first. The server does not run them
656
+ * on a draft save, because a half-answered step must be storable.
657
+ */
658
+ export declare const ONBOARDING_STEP_SCHEMAS: {
659
+ readonly identity: z.ZodObject<{
660
+ about: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
661
+ displayName: z.ZodString;
662
+ headline: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
663
+ skills: z.ZodOptional<z.ZodArray<z.ZodEnum<{
664
+ engineering: "engineering";
665
+ product: "product";
666
+ design: "design";
667
+ data: "data";
668
+ growth: "growth";
669
+ sales: "sales";
670
+ marketing: "marketing";
671
+ operations: "operations";
672
+ finance: "finance";
673
+ legal: "legal";
674
+ hr_people: "hr_people";
675
+ supply_chain: "supply_chain";
676
+ research: "research";
677
+ fundraising: "fundraising";
678
+ community: "community";
679
+ }>>>;
680
+ gender: z.ZodEnum<{
681
+ other: "other";
682
+ male: "male";
683
+ female: "female";
684
+ prefer_not_to_say: "prefer_not_to_say";
685
+ }>;
686
+ dateOfBirth: z.ZodString;
687
+ avatarUploadKey: z.ZodOptional<z.ZodString>;
688
+ }, z.core.$strip>;
689
+ readonly contact: z.ZodObject<{
690
+ links: z.ZodOptional<z.ZodObject<{
691
+ linkedin: z.ZodOptional<z.ZodURL>;
692
+ x: z.ZodOptional<z.ZodURL>;
693
+ instagram: z.ZodOptional<z.ZodURL>;
694
+ }, z.core.$strip>>;
695
+ phone: z.ZodString;
696
+ }, z.core.$strip>;
697
+ readonly location: z.ZodObject<{
698
+ location: z.ZodOptional<z.ZodObject<{
699
+ city: z.ZodString;
700
+ state: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
701
+ country: z.ZodString;
702
+ }, z.core.$strip>>;
703
+ }, z.core.$strip>;
704
+ readonly goals: z.ZodObject<{
705
+ goals: z.ZodArray<z.ZodEnum<{
706
+ find_cofounder: "find_cofounder";
707
+ find_investors: "find_investors";
708
+ find_customers: "find_customers";
709
+ hiring: "hiring";
710
+ partnerships: "partnerships";
711
+ mentorship: "mentorship";
712
+ grow_network: "grow_network";
713
+ business_ideas: "business_ideas";
714
+ market_insights: "market_insights";
715
+ learn_startup: "learn_startup";
716
+ start_company: "start_company";
717
+ }>>;
718
+ }, z.core.$strip>;
719
+ readonly interests: z.ZodObject<{
720
+ interests: z.ZodArray<z.ZodEnum<{
721
+ ai_ml: "ai_ml";
722
+ b2b_saas: "b2b_saas";
723
+ d2c: "d2c";
724
+ deeptech: "deeptech";
725
+ robotics: "robotics";
726
+ growth: "growth";
727
+ sales: "sales";
728
+ marketing: "marketing";
729
+ supply_chain: "supply_chain";
730
+ fundraising: "fundraising";
731
+ mentoring: "mentoring";
732
+ leadership: "leadership";
733
+ networking: "networking";
734
+ public_speaking: "public_speaking";
735
+ teaching: "teaching";
736
+ hiring_talent: "hiring_talent";
737
+ personal_branding: "personal_branding";
738
+ career_transition: "career_transition";
739
+ remote_work: "remote_work";
740
+ blockchain: "blockchain";
741
+ crypto_web3: "crypto_web3";
742
+ data_science: "data_science";
743
+ cybersecurity: "cybersecurity";
744
+ game_dev: "game_dev";
745
+ ux_design: "ux_design";
746
+ app_development: "app_development";
747
+ open_source: "open_source";
748
+ electronics: "electronics";
749
+ space_exploration: "space_exploration";
750
+ green_tech: "green_tech";
751
+ no_code: "no_code";
752
+ entrepreneurship: "entrepreneurship";
753
+ investing: "investing";
754
+ stock_trading: "stock_trading";
755
+ personal_finance: "personal_finance";
756
+ consulting: "consulting";
757
+ ecommerce: "ecommerce";
758
+ retail: "retail";
759
+ real_estate: "real_estate";
760
+ product_management: "product_management";
761
+ meditation: "meditation";
762
+ journaling: "journaling";
763
+ self_improvement: "self_improvement";
764
+ productivity: "productivity";
765
+ reading: "reading";
766
+ online_courses: "online_courses";
767
+ philosophy: "philosophy";
768
+ psychology: "psychology";
769
+ therapy: "therapy";
770
+ sleep_optimization: "sleep_optimization";
771
+ gym: "gym";
772
+ yoga: "yoga";
773
+ photography: "photography";
774
+ writing: "writing";
775
+ graphic_design: "graphic_design";
776
+ filmmaking: "filmmaking";
777
+ digital_art: "digital_art";
778
+ content_creation: "content_creation";
779
+ blogging: "blogging";
780
+ vlogging: "vlogging";
781
+ podcasts: "podcasts";
782
+ animation: "animation";
783
+ music_production: "music_production";
784
+ volunteering: "volunteering";
785
+ ngo_work: "ngo_work";
786
+ environmental: "environmental";
787
+ women_empowerment: "women_empowerment";
788
+ community_service: "community_service";
789
+ social_enterprise: "social_enterprise";
790
+ education_access: "education_access";
791
+ }>>;
792
+ }, z.core.$strip>;
793
+ readonly business: z.ZodObject<{
794
+ venture: z.ZodOptional<z.ZodObject<{
795
+ name: z.ZodString;
796
+ industry: z.ZodEnum<{
797
+ agritech: "agritech";
798
+ ai_ml: "ai_ml";
799
+ b2b_saas: "b2b_saas";
800
+ consumer: "consumer";
801
+ climate: "climate";
802
+ d2c: "d2c";
803
+ deeptech: "deeptech";
804
+ edtech: "edtech";
805
+ fintech: "fintech";
806
+ gaming: "gaming";
807
+ healthtech: "healthtech";
808
+ logistics: "logistics";
809
+ manufacturing: "manufacturing";
810
+ marketplace: "marketplace";
811
+ media: "media";
812
+ mobility: "mobility";
813
+ proptech: "proptech";
814
+ robotics: "robotics";
815
+ services: "services";
816
+ space: "space";
817
+ other: "other";
818
+ }>;
819
+ stage: z.ZodEnum<{
820
+ idea: "idea";
821
+ validation: "validation";
822
+ mvp: "mvp";
823
+ pre_seed: "pre_seed";
824
+ seed: "seed";
825
+ series_a_plus: "series_a_plus";
826
+ profitable: "profitable";
827
+ exited: "exited";
828
+ }>;
829
+ tagline: z.ZodPreprocess<z.ZodOptional<z.ZodString>, unknown>;
830
+ website: z.ZodOptional<z.ZodURL>;
831
+ teamSize: z.ZodOptional<z.ZodNumber>;
832
+ }, z.core.$strip>>;
833
+ businessType: z.ZodOptional<z.ZodEnum<{
834
+ startup: "startup";
835
+ sme: "sme";
836
+ enterprise: "enterprise";
837
+ }>>;
838
+ }, z.core.$strip>;
839
+ readonly guidelines: z.ZodObject<{
840
+ guidelinesVersion: z.ZodLiteral<"2026-10-03">;
841
+ }, z.core.$strip>;
842
+ };
843
+ /** One step's slice, parsed: `OnboardingStepBody<'contact'>` is `{ phone, links? }`. */
844
+ export type OnboardingStepBody<K extends OnboardingStepKey> = z.infer<(typeof ONBOARDING_STEP_SCHEMAS)[K]>;
845
+ /** A finish-body field name. */
846
+ export type OnboardingField = keyof CompleteOnboardingBody;
847
+ /**
848
+ * One step of the wizard, as a client renders it.
849
+ *
850
+ * `fields` is what gates leaving this step: a field that appears in no step is
851
+ * unreachable twice over, because Continue will not surface its error and the
852
+ * final submit's jump-to-the-bad-step finds no step to jump to and leaves the
853
+ * last screen dead.
854
+ */
855
+ export interface OnboardingStepConfig {
856
+ /** Stable identifier. Safe for analytics and for a resume cursor, unlike an index. */
857
+ key: OnboardingStepKey;
858
+ /** Translation keys. The words live in the client's message files. */
859
+ titleKey: `onboarding.steps.${OnboardingStepKey}.title`;
860
+ helpKey: `onboarding.steps.${OnboardingStepKey}.help`;
861
+ /** The step's slice of the finish body, in schema order. */
862
+ fields: readonly OnboardingField[];
863
+ /**
864
+ * False when the whole step may be passed without answering anything.
865
+ * DERIVED: a step is optional exactly when its slice accepts an empty
866
+ * object, so "skippable" can never disagree with what the finish accepts.
867
+ */
868
+ required: boolean;
869
+ }
870
+ export declare const FOUNDER_ONBOARDING_STEPS: readonly OnboardingStepConfig[];
871
+ export declare const ONBOARDING_TOTAL_STEPS: number;
872
+ /** Fields gating each step, in step order. Read from the same picks. */
873
+ export declare const ONBOARDING_STEP_FIELDS: readonly (readonly OnboardingField[])[];
874
+ /** What finishing answers: the new profile's id and the handle derived for it. */
875
+ export declare const completeOnboardingResponseSchema: z.ZodObject<{
876
+ id: z.ZodString;
877
+ username: z.ZodString;
878
+ }, z.core.$strip>;
879
+ export type CompleteOnboardingResponse = z.infer<typeof completeOnboardingResponseSchema>;
880
+ /**
881
+ * The keys a draft may hold: exactly the in-progress form's fields.
882
+ *
883
+ * ⚠ The server writes each key as a dot path (`draft.<key>`). Unchecked, a key
884
+ * holding a dot writes somewhere nested the form never asked for, and the
885
+ * collection fills with whatever a client invents. Until 0.2.0 the backend
886
+ * kept its own copy of this list and DROPPED unknown keys without a word; now a
887
+ * draft carrying one is refused, with the key in the issue's path.
888
+ */
889
+ export declare const onboardingDraftKeySchema: z.ZodEnum<{
890
+ location: "location";
891
+ about: "about";
892
+ displayName: "displayName";
893
+ headline: "headline";
894
+ venture: "venture";
895
+ skills: "skills";
896
+ goals: "goals";
897
+ links: "links";
898
+ interests: "interests";
899
+ gender: "gender";
900
+ dateOfBirth: "dateOfBirth";
901
+ avatarUploadKey: "avatarUploadKey";
902
+ phone: "phone";
903
+ businessType: "businessType";
904
+ guidelinesVersion: "guidelinesVersion";
905
+ }>;
906
+ export declare const ONBOARDING_DRAFT_KEYS: ("location" | "about" | "displayName" | "headline" | "venture" | "skills" | "goals" | "links" | "interests" | "gender" | "dateOfBirth" | "avatarUploadKey" | "phone" | "businessType" | "guidelinesVersion")[];
907
+ export type OnboardingDraftKey = z.infer<typeof onboardingDraftKeySchema>;
908
+ /**
909
+ * Where the member got to, kept in its own collection, separate from the
910
+ * profile.
911
+ *
912
+ * `step` is a flat index into `FOUNDER_ONBOARDING_STEPS`, not a `(step, sub)`
913
+ * pair: one number is what lets a member start on the web and resume elsewhere,
914
+ * provided both ends agree on the encoding.
915
+ *
916
+ * The draft's KEYS come from the form; its VALUES are opaque on purpose. A
917
+ * half-answered step must be storable even though it would fail the finish,
918
+ * and everything in it is re-validated strictly at finalize.
919
+ *
920
+ * `partialRecord`, not `record`: in Zod 4 an enum-keyed `z.record` demands
921
+ * every key, and a draft holds whichever steps the member has reached.
922
+ */
923
+ export declare const onboardingDraftSchema: z.ZodRecord<z.ZodEnum<{
924
+ location: "location";
925
+ about: "about";
926
+ displayName: "displayName";
927
+ headline: "headline";
928
+ venture: "venture";
929
+ skills: "skills";
930
+ goals: "goals";
931
+ links: "links";
932
+ interests: "interests";
933
+ gender: "gender";
934
+ dateOfBirth: "dateOfBirth";
935
+ avatarUploadKey: "avatarUploadKey";
936
+ phone: "phone";
937
+ businessType: "businessType";
938
+ guidelinesVersion: "guidelinesVersion";
939
+ }> & z.core.$partial, z.ZodUnknown>;
940
+ export type OnboardingDraft = z.infer<typeof onboardingDraftSchema>;
941
+ export declare const onboardingProgressSchema: z.ZodObject<{
942
+ step: z.ZodNumber;
943
+ draft: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
944
+ location: "location";
945
+ about: "about";
946
+ displayName: "displayName";
947
+ headline: "headline";
948
+ venture: "venture";
949
+ skills: "skills";
950
+ goals: "goals";
951
+ links: "links";
952
+ interests: "interests";
953
+ gender: "gender";
954
+ dateOfBirth: "dateOfBirth";
955
+ avatarUploadKey: "avatarUploadKey";
956
+ phone: "phone";
957
+ businessType: "businessType";
958
+ guidelinesVersion: "guidelinesVersion";
959
+ }> & z.core.$partial, z.ZodUnknown>>;
960
+ }, z.core.$strip>;
961
+ export type OnboardingProgress = z.infer<typeof onboardingProgressSchema>;
962
+ /**
963
+ * `PATCH` body: any subset of the cursor, merged server-side. No defaults.
964
+ * `step` may equal `ONBOARDING_TOTAL_STEPS`: "past the last step", which the
965
+ * client sends on its way to finish.
966
+ */
967
+ export declare const onboardingProgressUpdateSchema: z.ZodObject<{
968
+ step: z.ZodOptional<z.ZodNumber>;
969
+ draft: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
970
+ location: "location";
971
+ about: "about";
972
+ displayName: "displayName";
973
+ headline: "headline";
974
+ venture: "venture";
975
+ skills: "skills";
976
+ goals: "goals";
977
+ links: "links";
978
+ interests: "interests";
979
+ gender: "gender";
980
+ dateOfBirth: "dateOfBirth";
981
+ avatarUploadKey: "avatarUploadKey";
982
+ phone: "phone";
983
+ businessType: "businessType";
984
+ guidelinesVersion: "guidelinesVersion";
985
+ }> & z.core.$partial, z.ZodUnknown>>;
986
+ }, z.core.$strip>;
987
+ export type OnboardingProgressUpdate = z.infer<typeof onboardingProgressUpdateSchema>;
988
+ /**
989
+ * What the client reads on return, from `GET` and from every `PATCH`.
990
+ *
991
+ * ⚠️ `onboarded` is the gate and it comes from the profile, not from the
992
+ * cursor: a finished member on a new device must be recognised even when the
993
+ * cursor row is gone, and a cursor that failed to load must never make an
994
+ * unfinished member look finished.
995
+ */
996
+ export declare const onboardingStatusSchema: z.ZodObject<{
997
+ onboarded: z.ZodBoolean;
998
+ step: z.ZodNumber;
999
+ draft: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
1000
+ location: "location";
1001
+ about: "about";
1002
+ displayName: "displayName";
1003
+ headline: "headline";
1004
+ venture: "venture";
1005
+ skills: "skills";
1006
+ goals: "goals";
1007
+ links: "links";
1008
+ interests: "interests";
1009
+ gender: "gender";
1010
+ dateOfBirth: "dateOfBirth";
1011
+ avatarUploadKey: "avatarUploadKey";
1012
+ phone: "phone";
1013
+ businessType: "businessType";
1014
+ guidelinesVersion: "guidelinesVersion";
1015
+ }> & z.core.$partial, z.ZodUnknown>>;
1016
+ }, z.core.$strip>;
1017
+ export type OnboardingStatus = z.infer<typeof onboardingStatusSchema>;
1018
+ //# sourceMappingURL=onboarding.d.ts.map