@elevasis/core 0.18.0 → 0.20.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 (54) hide show
  1. package/dist/index.d.ts +82 -1
  2. package/dist/index.js +353 -171
  3. package/dist/knowledge/index.d.ts +44 -1
  4. package/dist/organization-model/index.d.ts +82 -1
  5. package/dist/organization-model/index.js +353 -171
  6. package/dist/test-utils/index.d.ts +41 -12
  7. package/dist/test-utils/index.js +352 -171
  8. package/package.json +4 -3
  9. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +89 -69
  10. package/src/auth/multi-tenancy/organizations/__tests__/api-schemas.test.ts +194 -0
  11. package/src/auth/multi-tenancy/organizations/api-schemas.ts +136 -128
  12. package/src/business/acquisition/api-schemas.test.ts +199 -15
  13. package/src/business/acquisition/api-schemas.ts +116 -51
  14. package/src/business/acquisition/build-templates.test.ts +212 -0
  15. package/src/business/acquisition/derive-actions.test.ts +1 -1
  16. package/src/business/acquisition/types.ts +21 -38
  17. package/src/business/deals/api-schemas.ts +2 -2
  18. package/src/execution/engine/index.ts +436 -434
  19. package/src/execution/engine/tools/integration/server/adapters/google-calendar/google-calendar-adapter.ts +428 -0
  20. package/src/execution/engine/tools/integration/server/adapters/google-calendar/index.ts +2 -0
  21. package/src/execution/engine/tools/lead-service-types.ts +51 -9
  22. package/src/execution/engine/tools/platform/acquisition/company-tools.ts +7 -6
  23. package/src/execution/engine/tools/platform/acquisition/contact-tools.ts +6 -5
  24. package/src/execution/engine/tools/platform/acquisition/types.ts +20 -9
  25. package/src/execution/engine/tools/registry.ts +700 -698
  26. package/src/execution/engine/tools/tool-maps.ts +10 -0
  27. package/src/execution/external/__tests__/api-schemas.test.ts +127 -0
  28. package/src/integrations/oauth/__tests__/provider-registry.test.ts +7 -6
  29. package/src/integrations/oauth/provider-registry.ts +74 -61
  30. package/src/integrations/oauth/server/credentials.ts +43 -39
  31. package/src/knowledge/__tests__/queries.test.ts +89 -0
  32. package/src/organization-model/__tests__/graph.test.ts +108 -2
  33. package/src/organization-model/__tests__/icons.test.ts +61 -0
  34. package/src/organization-model/__tests__/knowledge.test.ts +118 -1
  35. package/src/organization-model/__tests__/prospecting-ssot.test.ts +91 -0
  36. package/src/organization-model/__tests__/schema.test.ts +122 -0
  37. package/src/organization-model/__tests__/surface-projection.test.ts +174 -0
  38. package/src/organization-model/defaults.ts +8 -0
  39. package/src/organization-model/domains/knowledge.ts +9 -0
  40. package/src/organization-model/domains/prospecting.ts +347 -226
  41. package/src/organization-model/domains/sales.ts +40 -30
  42. package/src/organization-model/graph/build.ts +74 -0
  43. package/src/organization-model/graph/schema.ts +1 -0
  44. package/src/organization-model/graph/types.ts +1 -0
  45. package/src/organization-model/icons.ts +3 -0
  46. package/src/organization-model/schema.ts +63 -0
  47. package/src/organization-model/surface-projection.ts +218 -0
  48. package/src/organization-model/types.ts +9 -1
  49. package/src/platform/constants/versions.ts +1 -1
  50. package/src/platform/utils/__tests__/validation.test.ts +1084 -1083
  51. package/src/platform/utils/validation.ts +425 -425
  52. package/src/reference/_generated/contracts.md +89 -69
  53. package/src/server.ts +6 -0
  54. package/src/supabase/database.types.ts +6 -12
@@ -1,11 +1,12 @@
1
- import { z } from 'zod'
2
- import { DescriptionSchema, DisplayMetadataSchema, ModelIdSchema } from './shared'
3
-
4
- export const ProspectingLifecycleStageSchema = DisplayMetadataSchema.extend({
5
- id: ModelIdSchema,
6
- order: z.number().int().min(0)
7
- })
8
-
1
+ import { z } from 'zod'
2
+ import { LEAD_GEN_STAGE_CATALOG, type LeadGenStageCatalogEntry } from './sales'
3
+ import { DescriptionSchema, DisplayMetadataSchema, ModelIdSchema } from './shared'
4
+
5
+ export const ProspectingLifecycleStageSchema = DisplayMetadataSchema.extend({
6
+ id: ModelIdSchema,
7
+ order: z.number().int().min(0)
8
+ })
9
+
9
10
  export const ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
10
11
  id: ModelIdSchema,
11
12
  primaryEntity: z.enum(['company', 'contact']),
@@ -16,221 +17,341 @@ export const ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
16
17
  capabilityKey: ModelIdSchema,
17
18
  defaultBatchSize: z.number().int().positive(),
18
19
  maxBatchSize: z.number().int().positive()
19
- }).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
20
- message: 'defaultBatchSize must be less than or equal to maxBatchSize',
21
- path: ['defaultBatchSize']
22
- })
23
-
24
- export const ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
25
- id: ModelIdSchema,
26
- steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
27
- })
28
-
29
- export const OrganizationModelProspectingSchema = z.object({
30
- listEntityId: ModelIdSchema,
31
- companyEntityId: ModelIdSchema,
32
- contactEntityId: ModelIdSchema,
33
- description: DescriptionSchema.optional(),
34
- companyStages: z.array(ProspectingLifecycleStageSchema).min(1),
35
- contactStages: z.array(ProspectingLifecycleStageSchema).min(1),
36
- defaultBuildTemplateId: ModelIdSchema,
37
- buildTemplates: z.array(ProspectingBuildTemplateSchema).min(1)
38
- })
39
-
40
- export const DEFAULT_ORGANIZATION_MODEL_PROSPECTING: z.infer<typeof OrganizationModelProspectingSchema> = {
41
- listEntityId: 'leadgen.list',
42
- companyEntityId: 'leadgen.company',
43
- contactEntityId: 'leadgen.contact',
44
- companyStages: [
45
- { id: 'populated', label: 'Populated', order: 1 },
46
- { id: 'extracted', label: 'Extracted', order: 2 },
47
- { id: 'qualified', label: 'Qualified', order: 3 }
48
- ],
49
- contactStages: [
50
- { id: 'discovered', label: 'Discovered', order: 1 },
51
- { id: 'verified', label: 'Verified', order: 2 },
52
- { id: 'personalized', label: 'Personalized', order: 3 },
53
- { id: 'uploaded', label: 'Uploaded', order: 4 }
54
- ],
55
- defaultBuildTemplateId: 'local-services',
56
- buildTemplates: [
57
- {
58
- id: 'local-services',
59
- label: 'Local Services Prospecting',
60
- description:
61
- 'Curated local-services list build using company sourcing, website analysis, qualification, contact discovery, verification, personalization, and review.',
62
- steps: [
63
- {
64
- id: 'source-companies',
65
- label: 'Source companies',
66
- primaryEntity: 'company',
67
- outputs: ['company'],
68
- stageKey: 'populated',
69
- dependencyMode: 'per-record-eligibility',
70
- capabilityKey: 'lead-gen.company.source',
71
- defaultBatchSize: 100,
72
- maxBatchSize: 250
73
- },
74
- {
75
- id: 'analyze-websites',
76
- label: 'Analyze websites',
77
- primaryEntity: 'company',
78
- outputs: ['company'],
79
- stageKey: 'extracted',
80
- dependsOn: ['source-companies'],
81
- dependencyMode: 'per-record-eligibility',
82
- capabilityKey: 'lead-gen.company.website-extract',
83
- defaultBatchSize: 50,
84
- maxBatchSize: 100
85
- },
86
- {
87
- id: 'qualify-companies',
88
- label: 'Qualify companies',
89
- primaryEntity: 'company',
90
- outputs: ['company'],
91
- stageKey: 'qualified',
92
- dependsOn: ['analyze-websites'],
93
- dependencyMode: 'per-record-eligibility',
94
- capabilityKey: 'lead-gen.company.qualify',
95
- defaultBatchSize: 100,
96
- maxBatchSize: 250
97
- },
98
- {
99
- id: 'find-contacts',
100
- label: 'Find contacts',
101
- primaryEntity: 'contact',
102
- outputs: ['contact'],
103
- stageKey: 'discovered',
104
- dependsOn: ['qualify-companies'],
105
- dependencyMode: 'per-record-eligibility',
106
- capabilityKey: 'lead-gen.contact.discover',
107
- defaultBatchSize: 50,
108
- maxBatchSize: 100
109
- },
110
- {
111
- id: 'verify-emails',
112
- label: 'Verify emails',
113
- primaryEntity: 'contact',
114
- outputs: ['contact'],
115
- stageKey: 'verified',
116
- dependsOn: ['find-contacts'],
117
- dependencyMode: 'per-record-eligibility',
118
- capabilityKey: 'lead-gen.contact.verify-email',
119
- defaultBatchSize: 100,
120
- maxBatchSize: 500
121
- },
122
- {
123
- id: 'personalize',
124
- label: 'Personalize',
125
- primaryEntity: 'contact',
126
- outputs: ['contact'],
127
- stageKey: 'personalized',
128
- dependsOn: ['verify-emails'],
129
- dependencyMode: 'per-record-eligibility',
130
- capabilityKey: 'lead-gen.contact.personalize',
131
- defaultBatchSize: 25,
132
- maxBatchSize: 100
133
- },
134
- {
135
- id: 'review',
136
- label: 'Review',
137
- primaryEntity: 'contact',
138
- outputs: ['export'],
139
- stageKey: 'uploaded',
140
- dependsOn: ['personalize'],
141
- dependencyMode: 'per-record-eligibility',
142
- capabilityKey: 'lead-gen.review.outreach-ready',
143
- defaultBatchSize: 25,
144
- maxBatchSize: 100
145
- }
146
- ]
147
- },
148
- {
149
- id: 'dtc-subscription-apollo-clickup',
150
- label: 'DTC Subscription Apollo Export',
151
- description:
152
- 'Prospecting pipeline for DTC subscription or subscription-ready brands where Apollo is the source and contact-enrichment layer, Elevasis handles company research and fit scoring, and approved leads export as an approved lead list.',
153
- steps: [
154
- {
155
- id: 'import-apollo-search',
156
- label: 'Import Apollo search',
157
- description: 'Pull companies and seed contact data from a predefined Apollo search or list.',
158
- primaryEntity: 'company',
159
- outputs: ['company', 'contact'],
160
- stageKey: 'populated',
161
- dependencyMode: 'per-record-eligibility',
162
- capabilityKey: 'lead-gen.company.apollo-import',
163
- defaultBatchSize: 250,
164
- maxBatchSize: 1000
165
- },
166
- {
167
- id: 'analyze-websites',
168
- label: 'Analyze websites',
169
- description: 'Extract subscription, product, retention, and tech-stack signals from each brand website.',
170
- primaryEntity: 'company',
171
- outputs: ['company'],
172
- stageKey: 'extracted',
173
- dependsOn: ['import-apollo-search'],
174
- dependencyMode: 'per-record-eligibility',
175
- capabilityKey: 'lead-gen.company.website-extract',
176
- defaultBatchSize: 50,
177
- maxBatchSize: 100
178
- },
179
- {
180
- id: 'score-dtc-fit',
181
- label: 'Score DTC fit',
182
- description:
183
- 'Classify subscription potential, consumable-product fit, retention maturity, and disqualifiers.',
184
- primaryEntity: 'company',
185
- outputs: ['company'],
186
- stageKey: 'qualified',
187
- dependsOn: ['analyze-websites'],
188
- dependencyMode: 'per-record-eligibility',
189
- capabilityKey: 'lead-gen.company.dtc-subscription-qualify',
190
- defaultBatchSize: 100,
191
- maxBatchSize: 250
192
- },
193
- {
194
- id: 'enrich-decision-makers',
195
- label: 'Enrich decision-makers',
196
- description:
197
- 'Use Apollo to find qualified contacts such as founders, retention leads, lifecycle leads, and marketing owners.',
198
- primaryEntity: 'contact',
199
- outputs: ['contact'],
200
- stageKey: 'discovered',
201
- dependsOn: ['score-dtc-fit'],
202
- dependencyMode: 'per-record-eligibility',
203
- capabilityKey: 'lead-gen.contact.apollo-decision-maker-enrich',
204
- defaultBatchSize: 100,
205
- maxBatchSize: 250
206
- },
207
- {
208
- id: 'verify-emails',
209
- label: 'Verify emails',
210
- description: 'Verify deliverability before the QC and handoff step.',
211
- primaryEntity: 'contact',
212
- outputs: ['contact'],
213
- stageKey: 'verified',
214
- dependsOn: ['enrich-decision-makers'],
215
- dependencyMode: 'per-record-eligibility',
216
- capabilityKey: 'lead-gen.contact.verify-email',
217
- defaultBatchSize: 250,
218
- maxBatchSize: 500
219
- },
220
- {
221
- id: 'review-and-export',
222
- label: 'Review and export',
223
- description: 'Operator QC approves or rejects leads, then approved records are exported as a lead list.',
224
- primaryEntity: 'company',
225
- outputs: ['export'],
226
- stageKey: 'uploaded',
227
- dependsOn: ['verify-emails'],
228
- dependencyMode: 'per-record-eligibility',
229
- capabilityKey: 'lead-gen.export.list',
230
- defaultBatchSize: 100,
231
- maxBatchSize: 250
232
- }
233
- ]
234
- }
235
- ]
236
- }
20
+ }).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
21
+ message: 'defaultBatchSize must be less than or equal to maxBatchSize',
22
+ path: ['defaultBatchSize']
23
+ })
24
+
25
+ export const ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
26
+ id: ModelIdSchema,
27
+ steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
28
+ })
29
+
30
+ export type ListBuilderStep = z.infer<typeof ProspectingBuildTemplateStepSchema>
31
+ export type TemplateName = 'localServices' | 'dtcApolloClickup'
32
+ export type StepName = string
33
+
34
+ export const CapabilitySchema = z.object({
35
+ id: ModelIdSchema,
36
+ label: z.string(),
37
+ description: z.string(),
38
+ resourceId: ModelIdSchema
39
+ })
40
+
41
+ export type Capability = z.infer<typeof CapabilitySchema>
42
+ export type CapabilityRegistry = Capability[]
43
+
44
+ export const CAPABILITY_REGISTRY: CapabilityRegistry = [
45
+ {
46
+ id: 'lead-gen.company.source',
47
+ label: 'Source companies',
48
+ description: 'Import source companies from a list provider.',
49
+ resourceId: 'lgn-import-workflow'
50
+ },
51
+ {
52
+ id: 'lead-gen.company.apollo-import',
53
+ label: 'Import from Apollo',
54
+ description: 'Pull companies and seed contact data from an Apollo search or list.',
55
+ resourceId: 'lgn-01c-apollo-import-workflow'
56
+ },
57
+ {
58
+ id: 'lead-gen.contact.discover',
59
+ label: 'Discover contact emails',
60
+ description: 'Find email addresses for contacts at qualified companies.',
61
+ resourceId: 'lgn-04-email-discovery-workflow'
62
+ },
63
+ {
64
+ id: 'lead-gen.contact.verify-email',
65
+ label: 'Verify emails',
66
+ description: 'Check email deliverability before outreach.',
67
+ resourceId: 'lgn-05-email-verification-workflow'
68
+ },
69
+ {
70
+ id: 'lead-gen.company.website-extract',
71
+ label: 'Extract website signals',
72
+ description: 'Scrape and analyze company websites for qualification signals.',
73
+ resourceId: 'lgn-02-website-extract-workflow'
74
+ },
75
+ {
76
+ id: 'lead-gen.company.qualify',
77
+ label: 'Qualify companies',
78
+ description: 'Score and filter companies against the ICP rubric.',
79
+ resourceId: 'lgn-03-company-qualification-workflow'
80
+ },
81
+ {
82
+ id: 'lead-gen.company.dtc-subscription-qualify',
83
+ label: 'Qualify DTC subscription fit',
84
+ description: 'Classify subscription potential and consumable-product fit for DTC brands.',
85
+ resourceId: 'lgn-03b-dtc-subscription-score-workflow'
86
+ },
87
+ {
88
+ id: 'lead-gen.contact.apollo-decision-maker-enrich',
89
+ label: 'Enrich decision-makers',
90
+ description: 'Find and enrich qualified contacts at qualified companies via Apollo.',
91
+ resourceId: 'lgn-04b-apollo-decision-maker-enrich-workflow'
92
+ },
93
+ {
94
+ id: 'lead-gen.contact.personalize',
95
+ label: 'Personalize outreach',
96
+ description: 'Generate personalized opening lines for each contact.',
97
+ resourceId: 'ist-personalization-workflow'
98
+ },
99
+ {
100
+ id: 'lead-gen.review.outreach-ready',
101
+ label: 'Upload to outreach',
102
+ description: 'Upload approved contacts to the outreach sequence after QC review.',
103
+ resourceId: 'ist-upload-contacts-workflow'
104
+ },
105
+ {
106
+ id: 'lead-gen.export.list',
107
+ label: 'Export lead list',
108
+ description: 'Export approved leads as a downloadable lead list.',
109
+ resourceId: 'lgn-06-export-list-workflow'
110
+ },
111
+ {
112
+ id: 'lead-gen.company.cleanup',
113
+ label: 'Clean up companies',
114
+ description: 'Remove disqualified or duplicate companies from the list.',
115
+ resourceId: 'lgn-company-cleanup-workflow'
116
+ }
117
+ ]
118
+
119
+ export function findCapabilityById(id: string): Capability | undefined {
120
+ return CAPABILITY_REGISTRY.find((c) => c.id === id)
121
+ }
122
+
123
+ export const PROSPECTING_STEPS = {
124
+ localServices: {
125
+ sourceCompanies: {
126
+ id: 'source-companies',
127
+ label: 'Companies found',
128
+ primaryEntity: 'company',
129
+ outputs: ['company'],
130
+ stageKey: 'populated',
131
+ dependencyMode: 'per-record-eligibility',
132
+ capabilityKey: 'lead-gen.company.source',
133
+ defaultBatchSize: 100,
134
+ maxBatchSize: 250
135
+ },
136
+ analyzeWebsites: {
137
+ id: 'analyze-websites',
138
+ label: 'Websites analyzed',
139
+ primaryEntity: 'company',
140
+ outputs: ['company'],
141
+ stageKey: 'extracted',
142
+ dependsOn: ['source-companies'],
143
+ dependencyMode: 'per-record-eligibility',
144
+ capabilityKey: 'lead-gen.company.website-extract',
145
+ defaultBatchSize: 50,
146
+ maxBatchSize: 100
147
+ },
148
+ qualifyCompanies: {
149
+ id: 'qualify-companies',
150
+ label: 'Companies qualified',
151
+ primaryEntity: 'company',
152
+ outputs: ['company'],
153
+ stageKey: 'qualified',
154
+ dependsOn: ['analyze-websites'],
155
+ dependencyMode: 'per-record-eligibility',
156
+ capabilityKey: 'lead-gen.company.qualify',
157
+ defaultBatchSize: 100,
158
+ maxBatchSize: 250
159
+ },
160
+ findContacts: {
161
+ id: 'find-contacts',
162
+ label: 'Decision-makers found',
163
+ primaryEntity: 'contact',
164
+ outputs: ['contact'],
165
+ stageKey: 'discovered',
166
+ dependsOn: ['qualify-companies'],
167
+ dependencyMode: 'per-record-eligibility',
168
+ capabilityKey: 'lead-gen.contact.discover',
169
+ defaultBatchSize: 50,
170
+ maxBatchSize: 100
171
+ },
172
+ verifyEmails: {
173
+ id: 'verify-emails',
174
+ label: 'Emails verified',
175
+ primaryEntity: 'contact',
176
+ outputs: ['contact'],
177
+ stageKey: 'verified',
178
+ dependsOn: ['find-contacts'],
179
+ dependencyMode: 'per-record-eligibility',
180
+ capabilityKey: 'lead-gen.contact.verify-email',
181
+ defaultBatchSize: 100,
182
+ maxBatchSize: 500
183
+ },
184
+ personalize: {
185
+ id: 'personalize',
186
+ label: 'Personalize',
187
+ primaryEntity: 'contact',
188
+ outputs: ['contact'],
189
+ stageKey: 'personalized',
190
+ dependsOn: ['verify-emails'],
191
+ dependencyMode: 'per-record-eligibility',
192
+ capabilityKey: 'lead-gen.contact.personalize',
193
+ defaultBatchSize: 25,
194
+ maxBatchSize: 100
195
+ },
196
+ review: {
197
+ id: 'review',
198
+ label: 'Reviewed and exported',
199
+ primaryEntity: 'contact',
200
+ outputs: ['export'],
201
+ stageKey: 'uploaded',
202
+ dependsOn: ['personalize'],
203
+ dependencyMode: 'per-record-eligibility',
204
+ capabilityKey: 'lead-gen.review.outreach-ready',
205
+ defaultBatchSize: 25,
206
+ maxBatchSize: 100
207
+ }
208
+ },
209
+ dtcApolloClickup: {
210
+ importApolloSearch: {
211
+ id: 'import-apollo-search',
212
+ label: 'Companies found',
213
+ description: 'Pull companies and seed contact data from a predefined Apollo search or list.',
214
+ primaryEntity: 'company',
215
+ outputs: ['company', 'contact'],
216
+ stageKey: 'populated',
217
+ dependencyMode: 'per-record-eligibility',
218
+ capabilityKey: 'lead-gen.company.apollo-import',
219
+ defaultBatchSize: 250,
220
+ maxBatchSize: 1000
221
+ },
222
+ analyzeWebsites: {
223
+ id: 'analyze-websites',
224
+ label: 'Websites analyzed',
225
+ description: 'Extract subscription, product, retention, and tech-stack signals from each brand website.',
226
+ primaryEntity: 'company',
227
+ outputs: ['company'],
228
+ stageKey: 'extracted',
229
+ dependsOn: ['import-apollo-search'],
230
+ dependencyMode: 'per-record-eligibility',
231
+ capabilityKey: 'lead-gen.company.website-extract',
232
+ defaultBatchSize: 50,
233
+ maxBatchSize: 100
234
+ },
235
+ scoreDtcFit: {
236
+ id: 'score-dtc-fit',
237
+ label: 'Companies qualified',
238
+ description: 'Classify subscription potential, consumable-product fit, retention maturity, and disqualifiers.',
239
+ primaryEntity: 'company',
240
+ outputs: ['company'],
241
+ stageKey: 'qualified',
242
+ dependsOn: ['analyze-websites'],
243
+ dependencyMode: 'per-record-eligibility',
244
+ capabilityKey: 'lead-gen.company.dtc-subscription-qualify',
245
+ defaultBatchSize: 100,
246
+ maxBatchSize: 250
247
+ },
248
+ enrichDecisionMakers: {
249
+ id: 'enrich-decision-makers',
250
+ label: 'Decision-makers found',
251
+ description:
252
+ 'Use Apollo to find qualified contacts at qualified companies - founders, retention leads, lifecycle leads, and marketing owners.',
253
+ primaryEntity: 'company',
254
+ outputs: ['contact'],
255
+ stageKey: 'decision-makers-enriched',
256
+ dependsOn: ['score-dtc-fit'],
257
+ dependencyMode: 'per-record-eligibility',
258
+ capabilityKey: 'lead-gen.contact.apollo-decision-maker-enrich',
259
+ defaultBatchSize: 100,
260
+ maxBatchSize: 250
261
+ },
262
+ verifyEmails: {
263
+ id: 'verify-emails',
264
+ label: 'Emails verified',
265
+ description: 'Verify deliverability before the QC and handoff step.',
266
+ primaryEntity: 'contact',
267
+ outputs: ['contact'],
268
+ stageKey: 'verified',
269
+ dependsOn: ['enrich-decision-makers'],
270
+ dependencyMode: 'per-record-eligibility',
271
+ capabilityKey: 'lead-gen.contact.verify-email',
272
+ defaultBatchSize: 250,
273
+ maxBatchSize: 500
274
+ },
275
+ reviewAndExport: {
276
+ id: 'review-and-export',
277
+ label: 'Reviewed and exported',
278
+ description: 'Operator QC approves or rejects leads, then approved records are exported as a lead list.',
279
+ primaryEntity: 'company',
280
+ outputs: ['export'],
281
+ stageKey: 'uploaded',
282
+ dependsOn: ['verify-emails'],
283
+ dependencyMode: 'per-record-eligibility',
284
+ capabilityKey: 'lead-gen.export.list',
285
+ defaultBatchSize: 100,
286
+ maxBatchSize: 250
287
+ }
288
+ }
289
+ } as const satisfies Record<TemplateName, Record<StepName, ListBuilderStep>>
290
+
291
+ export const OrganizationModelProspectingSchema = z.object({
292
+ listEntityId: ModelIdSchema,
293
+ companyEntityId: ModelIdSchema,
294
+ contactEntityId: ModelIdSchema,
295
+ description: DescriptionSchema.optional(),
296
+ companyStages: z.array(ProspectingLifecycleStageSchema).min(1),
297
+ contactStages: z.array(ProspectingLifecycleStageSchema).min(1),
298
+ defaultBuildTemplateId: ModelIdSchema,
299
+ buildTemplates: z.array(ProspectingBuildTemplateSchema).min(1)
300
+ })
301
+
302
+ function toProspectingLifecycleStage(stage: LeadGenStageCatalogEntry): z.infer<typeof ProspectingLifecycleStageSchema> {
303
+ return {
304
+ id: stage.key,
305
+ label: stage.label,
306
+ order: stage.order
307
+ }
308
+ }
309
+
310
+ function leadGenStagesForEntity(
311
+ entity: LeadGenStageCatalogEntry['entity']
312
+ ): z.infer<typeof ProspectingLifecycleStageSchema>[] {
313
+ return Object.values(LEAD_GEN_STAGE_CATALOG)
314
+ .filter((stage) => stage.entity === entity)
315
+ .sort((a, b) => a.order - b.order)
316
+ .map(toProspectingLifecycleStage)
317
+ }
318
+
319
+ export const DEFAULT_ORGANIZATION_MODEL_PROSPECTING: z.infer<typeof OrganizationModelProspectingSchema> = {
320
+ listEntityId: 'leadgen.list',
321
+ companyEntityId: 'leadgen.company',
322
+ contactEntityId: 'leadgen.contact',
323
+ companyStages: leadGenStagesForEntity('company'),
324
+ contactStages: leadGenStagesForEntity('contact'),
325
+ defaultBuildTemplateId: 'local-services',
326
+ buildTemplates: [
327
+ {
328
+ id: 'local-services',
329
+ label: 'Local Services Prospecting',
330
+ description:
331
+ 'Curated local-services list build using company sourcing, website analysis, qualification, contact discovery, verification, personalization, and review.',
332
+ steps: [
333
+ PROSPECTING_STEPS.localServices.sourceCompanies,
334
+ PROSPECTING_STEPS.localServices.analyzeWebsites,
335
+ PROSPECTING_STEPS.localServices.qualifyCompanies,
336
+ PROSPECTING_STEPS.localServices.findContacts,
337
+ PROSPECTING_STEPS.localServices.verifyEmails,
338
+ PROSPECTING_STEPS.localServices.personalize,
339
+ PROSPECTING_STEPS.localServices.review
340
+ ]
341
+ },
342
+ {
343
+ id: 'dtc-subscription-apollo-clickup',
344
+ label: 'DTC Subscription Apollo Export',
345
+ description:
346
+ 'Prospecting pipeline for DTC subscription or subscription-ready brands where Apollo is the source and contact-enrichment layer, Elevasis handles company research and fit scoring, and approved leads export as an approved lead list.',
347
+ steps: [
348
+ PROSPECTING_STEPS.dtcApolloClickup.importApolloSearch,
349
+ PROSPECTING_STEPS.dtcApolloClickup.analyzeWebsites,
350
+ PROSPECTING_STEPS.dtcApolloClickup.scoreDtcFit,
351
+ PROSPECTING_STEPS.dtcApolloClickup.enrichDecisionMakers,
352
+ PROSPECTING_STEPS.dtcApolloClickup.verifyEmails,
353
+ PROSPECTING_STEPS.dtcApolloClickup.reviewAndExport
354
+ ]
355
+ }
356
+ ]
357
+ }