@elevasis/core 0.22.0 → 0.24.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 (244) hide show
  1. package/dist/index.d.ts +3214 -2501
  2. package/dist/index.js +3112 -1222
  3. package/dist/knowledge/index.d.ts +1108 -1264
  4. package/dist/knowledge/index.js +112 -9
  5. package/dist/organization-model/index.d.ts +3214 -2501
  6. package/dist/organization-model/index.js +3112 -1222
  7. package/dist/test-utils/index.d.ts +985 -1103
  8. package/dist/test-utils/index.js +2464 -1165
  9. package/package.json +5 -5
  10. package/src/README.md +14 -14
  11. package/src/__tests__/publish.test.ts +24 -24
  12. package/src/__tests__/template-core-compatibility.test.ts +9 -80
  13. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +2389 -2121
  14. package/src/_gen/__tests__/scaffold-contracts.test.ts +30 -30
  15. package/src/auth/multi-tenancy/credentials/__tests__/encryption.test.ts +217 -217
  16. package/src/auth/multi-tenancy/credentials/server/encryption.ts +69 -69
  17. package/src/auth/multi-tenancy/credentials/server/kek-loader.ts +37 -37
  18. package/src/auth/multi-tenancy/index.ts +26 -26
  19. package/src/auth/multi-tenancy/invitations/api-schemas.ts +104 -104
  20. package/src/auth/multi-tenancy/memberships/api-schemas.ts +143 -143
  21. package/src/auth/multi-tenancy/memberships/index.ts +26 -26
  22. package/src/auth/multi-tenancy/memberships/membership.ts +130 -130
  23. package/src/auth/multi-tenancy/organizations/__tests__/api-schemas.test.ts +194 -194
  24. package/src/auth/multi-tenancy/organizations/api-schemas.ts +136 -136
  25. package/src/auth/multi-tenancy/permissions.test.ts +42 -42
  26. package/src/auth/multi-tenancy/permissions.ts +123 -123
  27. package/src/auth/multi-tenancy/role-management/api-schemas.ts +78 -78
  28. package/src/auth/multi-tenancy/role-management/index.ts +16 -16
  29. package/src/auth/multi-tenancy/theme-presets.ts +45 -45
  30. package/src/auth/multi-tenancy/types.ts +57 -57
  31. package/src/auth/multi-tenancy/users/api-schemas.ts +165 -165
  32. package/src/business/README.md +2 -2
  33. package/src/business/acquisition/activity-events.test.ts +250 -250
  34. package/src/business/acquisition/activity-events.ts +93 -93
  35. package/src/business/acquisition/api-schemas.test.ts +1883 -1843
  36. package/src/business/acquisition/api-schemas.ts +1493 -1500
  37. package/src/business/acquisition/build-templates.test.ts +240 -240
  38. package/src/business/acquisition/build-templates.ts +83 -41
  39. package/src/business/acquisition/crm-next-action.test.ts +262 -262
  40. package/src/business/acquisition/crm-next-action.ts +220 -220
  41. package/src/business/acquisition/crm-priority.test.ts +216 -216
  42. package/src/business/acquisition/crm-priority.ts +349 -349
  43. package/src/business/acquisition/crm-state-actions.test.ts +153 -151
  44. package/src/business/acquisition/deal-ownership.test.ts +351 -351
  45. package/src/business/acquisition/deal-ownership.ts +120 -120
  46. package/src/business/acquisition/derive-actions.test.ts +129 -104
  47. package/src/business/acquisition/derive-actions.ts +74 -84
  48. package/src/business/acquisition/index.ts +171 -170
  49. package/src/business/acquisition/ontology-validation.ts +309 -0
  50. package/src/business/acquisition/stateful.ts +30 -30
  51. package/src/business/acquisition/types.ts +396 -392
  52. package/src/business/clients/api-schemas.test.ts +115 -115
  53. package/src/business/clients/api-schemas.ts +158 -158
  54. package/src/business/clients/index.ts +1 -1
  55. package/src/business/crm/api-schemas.ts +40 -40
  56. package/src/business/crm/index.ts +1 -1
  57. package/src/business/deals/api-schemas.ts +87 -87
  58. package/src/business/deals/index.ts +1 -1
  59. package/src/business/index.ts +5 -5
  60. package/src/business/projects/types.ts +144 -144
  61. package/src/commands/queue/types/task.ts +15 -15
  62. package/src/execution/core/runner-types.ts +61 -61
  63. package/src/execution/core/sse-executions.ts +7 -7
  64. package/src/execution/engine/__tests__/fixtures/test-agents.ts +10 -10
  65. package/src/execution/engine/agent/core/__tests__/agent.test.ts +16 -16
  66. package/src/execution/engine/agent/core/__tests__/error-passthrough.test.ts +4 -4
  67. package/src/execution/engine/agent/core/types.ts +25 -25
  68. package/src/execution/engine/agent/index.ts +6 -6
  69. package/src/execution/engine/agent/reasoning/__tests__/request-builder.test.ts +24 -24
  70. package/src/execution/engine/index.ts +443 -443
  71. package/src/execution/engine/tools/integration/server/adapters/apify/__tests__/apify-run-actor.integration.test.ts +298 -298
  72. package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.test.ts +55 -55
  73. package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.ts +107 -107
  74. package/src/execution/engine/tools/integration/server/adapters/apollo/apollo-adapter.test.ts +48 -48
  75. package/src/execution/engine/tools/integration/server/adapters/apollo/apollo-adapter.ts +99 -99
  76. package/src/execution/engine/tools/integration/server/adapters/apollo/index.ts +1 -1
  77. package/src/execution/engine/tools/integration/server/adapters/attio/__tests__/attio-crud.integration.test.ts +363 -363
  78. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/get-record/index.test.ts +162 -162
  79. package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-records/index.test.ts +316 -316
  80. package/src/execution/engine/tools/integration/server/adapters/clickup/clickup-adapter.test.ts +18 -18
  81. package/src/execution/engine/tools/integration/server/adapters/clickup/clickup-adapter.ts +194 -194
  82. package/src/execution/engine/tools/integration/server/adapters/clickup/index.ts +7 -7
  83. package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-adapter.ts +204 -204
  84. package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-tools.ts +105 -105
  85. package/src/execution/engine/tools/integration/server/adapters/google-calendar/google-calendar-adapter.ts +428 -428
  86. package/src/execution/engine/tools/integration/server/adapters/google-calendar/index.ts +2 -2
  87. package/src/execution/engine/tools/integration/server/adapters/google-sheets/__tests__/google-sheets.integration.test.ts +261 -261
  88. package/src/execution/engine/tools/integration/server/adapters/instantly/instantly-tools.ts +1474 -1474
  89. package/src/execution/engine/tools/integration/server/adapters/millionverifier/millionverifier-tools.ts +103 -103
  90. package/src/execution/engine/tools/integration/server/adapters/resend/fetch/send-email/index.test.ts +88 -88
  91. package/src/execution/engine/tools/integration/server/adapters/resend/fetch/send-email/index.ts +141 -141
  92. package/src/execution/engine/tools/integration/server/adapters/resend/fetch/utils/types.ts +76 -76
  93. package/src/execution/engine/tools/integration/server/adapters/signature-api/signature-api-tools.ts +182 -182
  94. package/src/execution/engine/tools/integration/server/adapters/stripe/stripe-tools.ts +310 -310
  95. package/src/execution/engine/tools/integration/service.test.ts +239 -239
  96. package/src/execution/engine/tools/integration/service.ts +172 -172
  97. package/src/execution/engine/tools/integration/tool.ts +255 -255
  98. package/src/execution/engine/tools/lead-service-types.ts +1005 -1005
  99. package/src/execution/engine/tools/messages.ts +43 -43
  100. package/src/execution/engine/tools/platform/acquisition/company-tools.ts +7 -7
  101. package/src/execution/engine/tools/platform/acquisition/contact-tools.ts +6 -6
  102. package/src/execution/engine/tools/platform/acquisition/list-tools.ts +6 -6
  103. package/src/execution/engine/tools/platform/acquisition/types.ts +280 -280
  104. package/src/execution/engine/tools/platform/email/types.ts +97 -97
  105. package/src/execution/engine/tools/registry.ts +704 -704
  106. package/src/execution/engine/tools/tool-maps.ts +831 -831
  107. package/src/execution/engine/tools/types.ts +234 -234
  108. package/src/execution/engine/workflow/types.ts +202 -202
  109. package/src/execution/external/__tests__/api-schemas.test.ts +127 -127
  110. package/src/execution/external/api-schemas.ts +40 -40
  111. package/src/execution/external/index.ts +1 -1
  112. package/src/index.ts +18 -18
  113. package/src/integrations/credentials/__tests__/api-schemas.test.ts +420 -420
  114. package/src/integrations/credentials/api-schemas.ts +146 -146
  115. package/src/integrations/credentials/schemas.ts +200 -200
  116. package/src/integrations/oauth/__tests__/provider-registry.test.ts +7 -7
  117. package/src/integrations/oauth/provider-registry.ts +74 -74
  118. package/src/integrations/oauth/server/credentials.ts +43 -43
  119. package/src/integrations/webhook-endpoints/__tests__/api-schemas.test.ts +327 -327
  120. package/src/integrations/webhook-endpoints/api-schemas.ts +103 -103
  121. package/src/integrations/webhook-endpoints/types.ts +58 -58
  122. package/src/knowledge/README.md +33 -32
  123. package/src/knowledge/__tests__/queries.test.ts +633 -541
  124. package/src/knowledge/format.ts +100 -99
  125. package/src/knowledge/index.ts +5 -5
  126. package/src/knowledge/published.ts +5 -5
  127. package/src/knowledge/queries.ts +274 -222
  128. package/src/operations/activities/api-schemas.ts +80 -80
  129. package/src/operations/activities/types.ts +64 -64
  130. package/src/organization-model/README.md +149 -109
  131. package/src/organization-model/__tests__/content-kinds-registry.test.ts +210 -0
  132. package/src/organization-model/__tests__/defaults.test.ts +168 -194
  133. package/src/organization-model/__tests__/domains/actions.test.ts +78 -0
  134. package/src/organization-model/__tests__/domains/customers.test.ts +48 -44
  135. package/src/organization-model/__tests__/domains/entities.test.ts +56 -0
  136. package/src/organization-model/__tests__/domains/goals.test.ts +110 -96
  137. package/src/organization-model/__tests__/domains/identity.test.ts +4 -3
  138. package/src/organization-model/__tests__/domains/navigation.test.ts +222 -166
  139. package/src/organization-model/__tests__/domains/offerings.test.ts +83 -88
  140. package/src/organization-model/__tests__/domains/policies.test.ts +323 -0
  141. package/src/organization-model/__tests__/domains/resource-mappings.test.ts +30 -30
  142. package/src/organization-model/__tests__/domains/resources.test.ts +396 -175
  143. package/src/organization-model/__tests__/domains/roles.test.ts +463 -402
  144. package/src/organization-model/__tests__/domains/statuses.test.ts +13 -10
  145. package/src/organization-model/__tests__/domains/systems.test.ts +209 -193
  146. package/src/organization-model/__tests__/flatten-additive-merge.test.ts +362 -0
  147. package/src/organization-model/__tests__/foundation.test.ts +47 -75
  148. package/src/organization-model/__tests__/get-resources-for-system.test.ts +144 -0
  149. package/src/organization-model/__tests__/graph.test.ts +1336 -149
  150. package/src/organization-model/__tests__/icons.test.ts +10 -1
  151. package/src/organization-model/__tests__/knowledge.test.ts +418 -61
  152. package/src/organization-model/__tests__/lookup-helpers.test.ts +438 -0
  153. package/src/organization-model/__tests__/migration-helpers.test.ts +591 -0
  154. package/src/organization-model/__tests__/prospecting-ssot.test.ts +103 -94
  155. package/src/organization-model/__tests__/recursive-system-schema.test.ts +549 -0
  156. package/src/organization-model/__tests__/resolve.test.ts +303 -42
  157. package/src/organization-model/__tests__/schema.test.ts +863 -153
  158. package/src/organization-model/__tests__/surface-projection.test.ts +284 -174
  159. package/src/organization-model/catalogs/lead-gen.ts +144 -0
  160. package/src/organization-model/content-kinds/config.ts +36 -0
  161. package/src/organization-model/content-kinds/index.ts +78 -0
  162. package/src/organization-model/content-kinds/pipeline.ts +68 -0
  163. package/src/organization-model/content-kinds/registry.ts +44 -0
  164. package/src/organization-model/content-kinds/status.ts +71 -0
  165. package/src/organization-model/content-kinds/template.ts +83 -0
  166. package/src/organization-model/content-kinds/types.ts +117 -0
  167. package/src/organization-model/contracts.ts +27 -17
  168. package/src/organization-model/defaults.ts +489 -107
  169. package/src/organization-model/domains/actions.ts +333 -0
  170. package/src/organization-model/domains/customers.ts +10 -7
  171. package/src/organization-model/domains/entities.ts +144 -0
  172. package/src/organization-model/domains/goals.ts +9 -6
  173. package/src/organization-model/domains/knowledge.ts +128 -54
  174. package/src/organization-model/domains/navigation.ts +139 -416
  175. package/src/organization-model/domains/offerings.ts +15 -10
  176. package/src/organization-model/domains/policies.ts +102 -0
  177. package/src/organization-model/domains/projects.ts +6 -40
  178. package/src/organization-model/domains/prospecting.ts +395 -514
  179. package/src/organization-model/domains/resources.ts +173 -81
  180. package/src/organization-model/domains/roles.ts +96 -93
  181. package/src/organization-model/domains/sales.test.ts +218 -218
  182. package/src/organization-model/domains/sales.ts +380 -589
  183. package/src/organization-model/domains/shared.ts +8 -8
  184. package/src/organization-model/domains/statuses.ts +298 -89
  185. package/src/organization-model/domains/systems.ts +240 -38
  186. package/src/organization-model/foundation.ts +35 -48
  187. package/src/organization-model/graph/build.ts +1035 -279
  188. package/src/organization-model/graph/index.ts +4 -4
  189. package/src/organization-model/graph/link.ts +10 -10
  190. package/src/organization-model/graph/schema.ts +77 -56
  191. package/src/organization-model/graph/types.ts +75 -56
  192. package/src/organization-model/helpers.ts +312 -59
  193. package/src/organization-model/icons.ts +78 -66
  194. package/src/organization-model/index.ts +129 -16
  195. package/src/organization-model/migration-helpers.ts +252 -0
  196. package/src/organization-model/ontology.ts +661 -0
  197. package/src/organization-model/organization-graph.mdx +110 -89
  198. package/src/organization-model/organization-model.mdx +226 -171
  199. package/src/organization-model/published.ts +295 -139
  200. package/src/organization-model/resolve.ts +139 -21
  201. package/src/organization-model/schema.ts +841 -301
  202. package/src/organization-model/surface-projection.ts +212 -218
  203. package/src/organization-model/types.ts +181 -90
  204. package/src/platform/api/types.ts +38 -38
  205. package/src/platform/constants/versions.ts +3 -3
  206. package/src/platform/index.ts +23 -23
  207. package/src/platform/registry/__tests__/command-view.test.ts +5 -7
  208. package/src/platform/registry/__tests__/resource-link.test.ts +35 -30
  209. package/src/platform/registry/__tests__/resource-registry.integration.test.ts +17 -32
  210. package/src/platform/registry/__tests__/resource-registry.nested-systems.test.ts +245 -0
  211. package/src/platform/registry/__tests__/resource-registry.test.ts +2053 -2051
  212. package/src/platform/registry/__tests__/validation.test.ts +1347 -1343
  213. package/src/platform/registry/command-view.ts +10 -10
  214. package/src/platform/registry/index.ts +103 -103
  215. package/src/platform/registry/resource-link.ts +32 -32
  216. package/src/platform/registry/resource-registry.ts +890 -878
  217. package/src/platform/registry/serialization.ts +295 -295
  218. package/src/platform/registry/serialized-types.ts +166 -166
  219. package/src/platform/registry/stats-types.ts +68 -68
  220. package/src/platform/registry/types.ts +425 -425
  221. package/src/platform/registry/validation.ts +745 -743
  222. package/src/platform/utils/__tests__/validation.test.ts +1084 -1084
  223. package/src/platform/utils/validation.ts +425 -425
  224. package/src/projects/api-schemas.test.ts +39 -39
  225. package/src/projects/api-schemas.ts +291 -291
  226. package/src/reference/_generated/contracts.md +2389 -2121
  227. package/src/reference/glossary.md +76 -76
  228. package/src/scaffold-registry/__tests__/index.test.ts +206 -206
  229. package/src/scaffold-registry/__tests__/schema.test.ts +166 -166
  230. package/src/scaffold-registry/index.ts +392 -392
  231. package/src/scaffold-registry/schema.ts +243 -243
  232. package/src/server.ts +289 -289
  233. package/src/supabase/database.types.ts +3153 -3093
  234. package/src/test-utils/README.md +37 -37
  235. package/src/test-utils/entities.ts +108 -108
  236. package/src/test-utils/fixtures/memberships.ts +82 -82
  237. package/src/test-utils/index.ts +12 -12
  238. package/src/test-utils/organization-model.ts +65 -65
  239. package/src/test-utils/published.ts +6 -6
  240. package/src/test-utils/rls/RLSTestContext.ts +588 -588
  241. package/src/test-utils/test-utils.test.ts +44 -49
  242. package/src/organization-model/__tests__/domains/operations.test.ts +0 -203
  243. package/src/organization-model/domains/features.ts +0 -31
  244. package/src/organization-model/domains/operations.ts +0 -85
@@ -1,514 +1,395 @@
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().min(0)
8
- })
9
-
10
- export const RecordColumnConfigSchema = z.object({
11
- key: ModelIdSchema,
12
- label: z.string().trim().min(1).max(120),
13
- path: z.string().trim().min(1).max(500),
14
- width: z.union([z.number().positive(), z.string().trim().min(1).max(100)]).optional(),
15
- renderType: z.enum(['text', 'badge', 'datetime', 'count', 'json']).optional(),
16
- badgeColor: z.string().trim().min(1).max(40).optional()
17
- })
18
-
19
- export const RecordColumnsConfigSchema = z
20
- .object({
21
- company: z.array(RecordColumnConfigSchema).optional(),
22
- contact: z.array(RecordColumnConfigSchema).optional()
23
- })
24
- .refine((columns) => Boolean(columns.company?.length || columns.contact?.length), {
25
- message: 'recordColumns must include at least one entity column set'
26
- })
27
-
28
- export const CredentialRequirementSchema = z.object({
29
- key: ModelIdSchema,
30
- provider: ModelIdSchema,
31
- credentialType: z.enum(['api-key', 'api-key-secret', 'oauth', 'webhook-secret']),
32
- label: z.string().trim().min(1).max(120),
33
- required: z.boolean(),
34
- selectionMode: z.enum(['single', 'multiple']).optional(),
35
- inputPath: z.string().trim().min(1).max(500),
36
- verifyOnRun: z.boolean().optional()
37
- })
38
-
39
- export const ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
40
- id: ModelIdSchema,
41
- primaryEntity: z.enum(['company', 'contact']),
42
- outputs: z.array(z.enum(['company', 'contact', 'export'])).min(1),
43
- stageKey: ModelIdSchema,
44
- recordEntity: z.enum(['company', 'contact']).optional(),
45
- recordsStageKey: ModelIdSchema.optional(),
46
- recordSourceStageKey: ModelIdSchema.optional(),
47
- dependsOn: z.array(ModelIdSchema).optional(),
48
- dependencyMode: z.literal('per-record-eligibility'),
49
- capabilityKey: ModelIdSchema,
50
- defaultBatchSize: z.number().int().positive(),
51
- maxBatchSize: z.number().int().positive(),
52
- recordColumns: RecordColumnsConfigSchema.optional(),
53
- credentialRequirements: z.array(CredentialRequirementSchema).optional()
54
- }).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
55
- message: 'defaultBatchSize must be less than or equal to maxBatchSize',
56
- path: ['defaultBatchSize']
57
- })
58
-
59
- export const ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
60
- id: ModelIdSchema,
61
- steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
62
- })
63
-
64
- export type ListBuilderStep = z.infer<typeof ProspectingBuildTemplateStepSchema>
65
- export type RecordColumnConfig = z.infer<typeof RecordColumnConfigSchema>
66
- export type CredentialRequirement = z.infer<typeof CredentialRequirementSchema>
67
- export type TemplateName = 'localServices' | 'dtcApolloClickup'
68
- export type StepName = string
69
-
70
- const DTC_RECORD_COLUMNS = {
71
- populated: {
72
- company: [
73
- { key: 'name', label: 'Company', path: 'company.name' },
74
- { key: 'domain', label: 'Domain', path: 'company.domain' },
75
- { key: 'employee-count', label: 'Employees', path: 'company.numEmployees', renderType: 'count' },
76
- { key: 'apollo-industry', label: 'Apollo industry', path: 'company.category' },
77
- { key: 'location', label: 'Location', path: 'company.locationState' }
78
- ]
79
- },
80
- crawled: {
81
- company: [
82
- { key: 'name', label: 'Company', path: 'company.name' },
83
- { key: 'domain', label: 'Domain', path: 'company.domain' },
84
- { key: 'page-count', label: 'Pages', path: 'company.enrichmentData.websiteCrawl.pageCount', renderType: 'count' },
85
- { key: 'crawl-status', label: 'Crawl status', path: 'processingState.crawled.status', renderType: 'badge' }
86
- ]
87
- },
88
- extracted: {
89
- company: [
90
- { key: 'name', label: 'Company', path: 'company.name' },
91
- { key: 'domain', label: 'Domain', path: 'company.domain' },
92
- { key: 'description', label: 'Description', path: 'company.enrichmentData.websiteCrawl.companyDescription' },
93
- { key: 'services', label: 'Services', path: 'company.enrichmentData.websiteCrawl.services', renderType: 'json' },
94
- { key: 'automation-gaps', label: 'Automation gaps', path: 'company.enrichmentData.websiteCrawl.automationGaps', renderType: 'json' },
95
- { key: 'contact-count', label: 'Contacts', path: 'company.enrichmentData.websiteCrawl.emailCount', renderType: 'count' }
96
- ]
97
- },
98
- qualified: {
99
- company: [
100
- { key: 'name', label: 'Company', path: 'company.name' },
101
- { key: 'domain', label: 'Domain', path: 'company.domain' },
102
- { key: 'score', label: 'Score', path: 'company.qualificationScore', renderType: 'badge', badgeColor: 'green' },
103
- { key: 'signals', label: 'Signals', path: 'company.qualificationSignals', renderType: 'json' },
104
- { key: 'disqualified-reason', label: 'Disqualified reason', path: 'processingState.qualified.data.disqualifiedReason' }
105
- ]
106
- },
107
- decisionMakers: {
108
- contact: [
109
- { key: 'name', label: 'Name', path: 'contact.name' },
110
- { key: 'title', label: 'Title', path: 'contact.title' },
111
- { key: 'email', label: 'Email', path: 'contact.email' },
112
- { key: 'linkedin', label: 'LinkedIn', path: 'contact.linkedinUrl' },
113
- { key: 'priority-score', label: 'Priority', path: 'contact.enrichmentData.apollo.priorityScore', renderType: 'badge' }
114
- ]
115
- },
116
- uploaded: {
117
- company: [
118
- { key: 'name', label: 'Company', path: 'company.name' },
119
- { key: 'domain', label: 'Domain', path: 'company.domain' },
120
- { key: 'contacts', label: 'Contacts', path: 'company.enrichmentData.approvedLeadListExport.contacts', renderType: 'json' },
121
- { key: 'score', label: 'Score', path: 'company.qualificationScore', renderType: 'badge', badgeColor: 'green' },
122
- { key: 'approval', label: 'Approval', path: 'company.enrichmentData.approvedLeadListExport.approvalStatus', renderType: 'badge' }
123
- ]
124
- }
125
- } as const satisfies Record<string, z.infer<typeof RecordColumnsConfigSchema>>
126
-
127
- export const CapabilitySchema = z.object({
128
- id: ModelIdSchema,
129
- label: z.string(),
130
- description: z.string(),
131
- resourceId: ModelIdSchema
132
- })
133
-
134
- export type Capability = z.infer<typeof CapabilitySchema>
135
- export type CapabilityRegistry = Capability[]
136
-
137
- export const CAPABILITY_REGISTRY: CapabilityRegistry = [
138
- {
139
- id: 'lead-gen.company.source',
140
- label: 'Source companies',
141
- description: 'Import source companies from a list provider.',
142
- resourceId: 'lgn-import-workflow'
143
- },
144
- {
145
- id: 'lead-gen.company.apollo-import',
146
- label: 'Import from Apollo',
147
- description: 'Pull companies and seed contact data from an Apollo search or list.',
148
- resourceId: 'lgn-01c-apollo-import-workflow'
149
- },
150
- {
151
- id: 'lead-gen.contact.discover',
152
- label: 'Discover contact emails',
153
- description: 'Find email addresses for contacts at qualified companies.',
154
- resourceId: 'lgn-04-email-discovery-workflow'
155
- },
156
- {
157
- id: 'lead-gen.contact.verify-email',
158
- label: 'Verify emails',
159
- description: 'Check email deliverability before outreach.',
160
- resourceId: 'lgn-05-email-verification-workflow'
161
- },
162
- {
163
- id: 'lead-gen.company.apify-crawl',
164
- label: 'Crawl websites',
165
- description:
166
- 'Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis.',
167
- resourceId: 'lgn-02a-apify-website-crawl-workflow'
168
- },
169
- {
170
- id: 'lead-gen.company.website-extract',
171
- label: 'Extract website signals',
172
- description: 'Scrape and analyze company websites for qualification signals.',
173
- resourceId: 'lgn-02-website-extract-workflow'
174
- },
175
- {
176
- id: 'lead-gen.company.qualify',
177
- label: 'Qualify companies',
178
- description: 'Score and filter companies against the ICP rubric.',
179
- resourceId: 'lgn-03-company-qualification-workflow'
180
- },
181
- {
182
- id: 'lead-gen.company.dtc-subscription-qualify',
183
- label: 'Qualify DTC subscription fit',
184
- description: 'Classify subscription potential and consumable-product fit for DTC brands.',
185
- resourceId: 'lgn-03b-dtc-subscription-score-workflow'
186
- },
187
- {
188
- id: 'lead-gen.contact.apollo-decision-maker-enrich',
189
- label: 'Enrich decision-makers',
190
- description: 'Find and enrich qualified contacts at qualified companies via Apollo.',
191
- resourceId: 'lgn-04b-apollo-decision-maker-enrich-workflow'
192
- },
193
- {
194
- id: 'lead-gen.contact.personalize',
195
- label: 'Personalize outreach',
196
- description: 'Generate personalized opening lines for each contact.',
197
- resourceId: 'ist-personalization-workflow'
198
- },
199
- {
200
- id: 'lead-gen.review.outreach-ready',
201
- label: 'Upload to outreach',
202
- description: 'Upload approved contacts to the outreach sequence after QC review.',
203
- resourceId: 'ist-upload-contacts-workflow'
204
- },
205
- {
206
- id: 'lead-gen.export.list',
207
- label: 'Export lead list',
208
- description: 'Export approved leads as a downloadable lead list.',
209
- resourceId: 'lgn-06-export-list-workflow'
210
- },
211
- {
212
- id: 'lead-gen.company.cleanup',
213
- label: 'Clean up companies',
214
- description: 'Remove disqualified or duplicate companies from the list.',
215
- resourceId: 'lgn-company-cleanup-workflow'
216
- }
217
- ]
218
-
219
- export function findCapabilityById(id: string): Capability | undefined {
220
- return CAPABILITY_REGISTRY.find((c) => c.id === id)
221
- }
222
-
223
- export const PROSPECTING_STEPS = {
224
- localServices: {
225
- sourceCompanies: {
226
- id: 'source-companies',
227
- label: 'Companies found',
228
- primaryEntity: 'company',
229
- outputs: ['company'],
230
- stageKey: 'populated',
231
- dependencyMode: 'per-record-eligibility',
232
- capabilityKey: 'lead-gen.company.source',
233
- defaultBatchSize: 100,
234
- maxBatchSize: 250
235
- },
236
- analyzeWebsites: {
237
- id: 'analyze-websites',
238
- label: 'Websites analyzed',
239
- primaryEntity: 'company',
240
- outputs: ['company'],
241
- stageKey: 'extracted',
242
- dependsOn: ['source-companies'],
243
- dependencyMode: 'per-record-eligibility',
244
- capabilityKey: 'lead-gen.company.website-extract',
245
- defaultBatchSize: 50,
246
- maxBatchSize: 100
247
- },
248
- qualifyCompanies: {
249
- id: 'qualify-companies',
250
- label: 'Companies qualified',
251
- primaryEntity: 'company',
252
- outputs: ['company'],
253
- stageKey: 'qualified',
254
- dependsOn: ['analyze-websites'],
255
- dependencyMode: 'per-record-eligibility',
256
- capabilityKey: 'lead-gen.company.qualify',
257
- defaultBatchSize: 100,
258
- maxBatchSize: 250
259
- },
260
- findContacts: {
261
- id: 'find-contacts',
262
- label: 'Decision-makers found',
263
- primaryEntity: 'contact',
264
- outputs: ['contact'],
265
- stageKey: 'discovered',
266
- dependsOn: ['qualify-companies'],
267
- dependencyMode: 'per-record-eligibility',
268
- capabilityKey: 'lead-gen.contact.discover',
269
- defaultBatchSize: 50,
270
- maxBatchSize: 100
271
- },
272
- verifyEmails: {
273
- id: 'verify-emails',
274
- label: 'Emails verified',
275
- primaryEntity: 'contact',
276
- outputs: ['contact'],
277
- stageKey: 'verified',
278
- dependsOn: ['find-contacts'],
279
- dependencyMode: 'per-record-eligibility',
280
- capabilityKey: 'lead-gen.contact.verify-email',
281
- defaultBatchSize: 100,
282
- maxBatchSize: 500
283
- },
284
- personalize: {
285
- id: 'personalize',
286
- label: 'Personalize',
287
- primaryEntity: 'contact',
288
- outputs: ['contact'],
289
- stageKey: 'personalized',
290
- dependsOn: ['verify-emails'],
291
- dependencyMode: 'per-record-eligibility',
292
- capabilityKey: 'lead-gen.contact.personalize',
293
- defaultBatchSize: 25,
294
- maxBatchSize: 100
295
- },
296
- review: {
297
- id: 'review',
298
- label: 'Reviewed and exported',
299
- primaryEntity: 'contact',
300
- outputs: ['export'],
301
- stageKey: 'uploaded',
302
- dependsOn: ['personalize'],
303
- dependencyMode: 'per-record-eligibility',
304
- capabilityKey: 'lead-gen.review.outreach-ready',
305
- defaultBatchSize: 25,
306
- maxBatchSize: 100
307
- }
308
- },
309
- dtcApolloClickup: {
310
- importApolloSearch: {
311
- id: 'import-apollo-search',
312
- label: 'Companies found',
313
- description: 'Pull companies and seed contact data from a predefined Apollo search or list.',
314
- primaryEntity: 'company',
315
- outputs: ['company', 'contact'],
316
- stageKey: 'populated',
317
- dependencyMode: 'per-record-eligibility',
318
- capabilityKey: 'lead-gen.company.apollo-import',
319
- defaultBatchSize: 250,
320
- maxBatchSize: 1000,
321
- recordColumns: DTC_RECORD_COLUMNS.populated,
322
- credentialRequirements: [
323
- {
324
- key: 'apollo',
325
- provider: 'apollo',
326
- credentialType: 'api-key-secret',
327
- label: 'Apollo API key',
328
- required: true,
329
- selectionMode: 'single',
330
- inputPath: 'credential'
331
- }
332
- ]
333
- },
334
- apifyCrawl: {
335
- id: 'apify-crawl',
336
- label: 'Websites crawled',
337
- description:
338
- 'Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis. Overwrites the synthetic seed Apollo Import wrote with real page content.',
339
- primaryEntity: 'company',
340
- outputs: ['company'],
341
- stageKey: 'crawled',
342
- dependsOn: ['import-apollo-search'],
343
- dependencyMode: 'per-record-eligibility',
344
- capabilityKey: 'lead-gen.company.apify-crawl',
345
- defaultBatchSize: 50,
346
- maxBatchSize: 100,
347
- recordColumns: DTC_RECORD_COLUMNS.crawled,
348
- credentialRequirements: [
349
- {
350
- key: 'apify',
351
- provider: 'apify',
352
- credentialType: 'api-key-secret',
353
- label: 'Apify API token',
354
- required: true,
355
- selectionMode: 'single',
356
- inputPath: 'credential',
357
- verifyOnRun: true
358
- }
359
- ]
360
- },
361
- analyzeWebsites: {
362
- id: 'analyze-websites',
363
- label: 'Websites analyzed',
364
- description: 'Extract subscription, product, retention, and tech-stack signals from each brand website.',
365
- primaryEntity: 'company',
366
- outputs: ['company'],
367
- stageKey: 'extracted',
368
- dependsOn: ['apify-crawl'],
369
- dependencyMode: 'per-record-eligibility',
370
- capabilityKey: 'lead-gen.company.website-extract',
371
- defaultBatchSize: 50,
372
- maxBatchSize: 100,
373
- recordColumns: DTC_RECORD_COLUMNS.extracted
374
- },
375
- scoreDtcFit: {
376
- id: 'score-dtc-fit',
377
- label: 'Companies qualified',
378
- description: 'Classify subscription potential, consumable-product fit, retention maturity, and disqualifiers.',
379
- primaryEntity: 'company',
380
- outputs: ['company'],
381
- stageKey: 'qualified',
382
- dependsOn: ['analyze-websites'],
383
- dependencyMode: 'per-record-eligibility',
384
- capabilityKey: 'lead-gen.company.dtc-subscription-qualify',
385
- defaultBatchSize: 100,
386
- maxBatchSize: 250,
387
- recordColumns: DTC_RECORD_COLUMNS.qualified
388
- },
389
- enrichDecisionMakers: {
390
- id: 'enrich-decision-makers',
391
- label: 'Decision-makers found',
392
- description:
393
- 'Use Apollo to find qualified contacts at qualified companies - founders, retention leads, lifecycle leads, and marketing owners.',
394
- primaryEntity: 'company',
395
- outputs: ['contact'],
396
- stageKey: 'decision-makers-enriched',
397
- recordEntity: 'contact',
398
- dependsOn: ['score-dtc-fit'],
399
- dependencyMode: 'per-record-eligibility',
400
- capabilityKey: 'lead-gen.contact.apollo-decision-maker-enrich',
401
- defaultBatchSize: 100,
402
- maxBatchSize: 250,
403
- recordColumns: DTC_RECORD_COLUMNS.decisionMakers,
404
- credentialRequirements: [
405
- {
406
- key: 'apollo',
407
- provider: 'apollo',
408
- credentialType: 'api-key-secret',
409
- label: 'Apollo API key',
410
- required: true,
411
- selectionMode: 'single',
412
- inputPath: 'credential'
413
- }
414
- ]
415
- },
416
- reviewAndExport: {
417
- id: 'review-and-export',
418
- label: 'Reviewed and exported',
419
- description:
420
- 'Operator QC approves or rejects qualified companies, then approved records are exported as a lead list with unverified emails.',
421
- primaryEntity: 'company',
422
- outputs: ['export'],
423
- stageKey: 'uploaded',
424
- recordsStageKey: 'uploaded',
425
- recordSourceStageKey: 'qualified',
426
- dependsOn: ['enrich-decision-makers'],
427
- dependencyMode: 'per-record-eligibility',
428
- capabilityKey: 'lead-gen.export.list',
429
- defaultBatchSize: 100,
430
- maxBatchSize: 250,
431
- recordColumns: DTC_RECORD_COLUMNS.uploaded,
432
- credentialRequirements: [
433
- {
434
- key: 'clickup',
435
- provider: 'clickup',
436
- credentialType: 'api-key-secret',
437
- label: 'ClickUp API token',
438
- required: true,
439
- selectionMode: 'single',
440
- inputPath: 'clickupCredential',
441
- verifyOnRun: true
442
- }
443
- ]
444
- }
445
- }
446
- } as const satisfies Record<TemplateName, Record<StepName, ListBuilderStep>>
447
-
448
- export const OrganizationModelProspectingSchema = z.object({
449
- listEntityId: ModelIdSchema,
450
- companyEntityId: ModelIdSchema,
451
- contactEntityId: ModelIdSchema,
452
- description: DescriptionSchema.optional(),
453
- companyStages: z.array(ProspectingLifecycleStageSchema).min(1),
454
- contactStages: z.array(ProspectingLifecycleStageSchema).min(1),
455
- defaultBuildTemplateId: ModelIdSchema,
456
- buildTemplates: z.array(ProspectingBuildTemplateSchema).min(1)
457
- })
458
-
459
- function toProspectingLifecycleStage(stage: LeadGenStageCatalogEntry): z.infer<typeof ProspectingLifecycleStageSchema> {
460
- return {
461
- id: stage.key,
462
- label: stage.label,
463
- order: stage.order
464
- }
465
- }
466
-
467
- function leadGenStagesForEntity(
468
- entity: LeadGenStageCatalogEntry['entity']
469
- ): z.infer<typeof ProspectingLifecycleStageSchema>[] {
470
- return Object.values(LEAD_GEN_STAGE_CATALOG)
471
- .filter((stage) => stage.entity === entity || stage.additionalEntities?.includes(entity))
472
- .sort((a, b) => a.order - b.order)
473
- .map(toProspectingLifecycleStage)
474
- }
475
-
476
- export const DEFAULT_ORGANIZATION_MODEL_PROSPECTING: z.infer<typeof OrganizationModelProspectingSchema> = {
477
- listEntityId: 'leadgen.list',
478
- companyEntityId: 'leadgen.company',
479
- contactEntityId: 'leadgen.contact',
480
- companyStages: leadGenStagesForEntity('company'),
481
- contactStages: leadGenStagesForEntity('contact'),
482
- defaultBuildTemplateId: 'local-services',
483
- buildTemplates: [
484
- {
485
- id: 'local-services',
486
- label: 'Local Services Prospecting',
487
- description:
488
- 'Curated local-services list build using company sourcing, website analysis, qualification, contact discovery, verification, personalization, and review.',
489
- steps: [
490
- PROSPECTING_STEPS.localServices.sourceCompanies,
491
- PROSPECTING_STEPS.localServices.analyzeWebsites,
492
- PROSPECTING_STEPS.localServices.qualifyCompanies,
493
- PROSPECTING_STEPS.localServices.findContacts,
494
- PROSPECTING_STEPS.localServices.verifyEmails,
495
- PROSPECTING_STEPS.localServices.personalize,
496
- PROSPECTING_STEPS.localServices.review
497
- ]
498
- },
499
- {
500
- id: 'dtc-subscription-apollo-clickup',
501
- label: 'DTC Subscription Apollo Export',
502
- description:
503
- '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.',
504
- steps: [
505
- PROSPECTING_STEPS.dtcApolloClickup.importApolloSearch,
506
- PROSPECTING_STEPS.dtcApolloClickup.apifyCrawl,
507
- PROSPECTING_STEPS.dtcApolloClickup.analyzeWebsites,
508
- PROSPECTING_STEPS.dtcApolloClickup.scoreDtcFit,
509
- PROSPECTING_STEPS.dtcApolloClickup.enrichDecisionMakers,
510
- PROSPECTING_STEPS.dtcApolloClickup.reviewAndExport
511
- ]
512
- }
513
- ]
514
- }
1
+ import { z } from 'zod'
2
+ import { findOrganizationActionById, LEAD_GEN_ACTION_ENTRIES, type Action as TopLevelAction } from './actions'
3
+ import { DisplayMetadataSchema, ModelIdSchema } from './shared'
4
+
5
+ export const ProspectingLifecycleStageSchema = DisplayMetadataSchema.extend({
6
+ id: ModelIdSchema,
7
+ order: z.number().min(0)
8
+ })
9
+
10
+ export const RecordColumnConfigSchema = z.object({
11
+ key: ModelIdSchema,
12
+ label: z.string().trim().min(1).max(120),
13
+ path: z.string().trim().min(1).max(500),
14
+ width: z.union([z.number().positive(), z.string().trim().min(1).max(100)]).optional(),
15
+ renderType: z.enum(['text', 'badge', 'datetime', 'count', 'json']).optional(),
16
+ badgeColor: z.string().trim().min(1).max(40).optional()
17
+ })
18
+
19
+ export const RecordColumnsConfigSchema = z
20
+ .object({
21
+ company: z.array(RecordColumnConfigSchema).optional(),
22
+ contact: z.array(RecordColumnConfigSchema).optional()
23
+ })
24
+ .refine((columns) => Boolean(columns.company?.length || columns.contact?.length), {
25
+ message: 'recordColumns must include at least one entity column set'
26
+ })
27
+
28
+ export const CredentialRequirementSchema = z.object({
29
+ key: ModelIdSchema,
30
+ provider: ModelIdSchema,
31
+ credentialType: z.enum(['api-key', 'api-key-secret', 'oauth', 'webhook-secret']),
32
+ label: z.string().trim().min(1).max(120),
33
+ required: z.boolean(),
34
+ selectionMode: z.enum(['single', 'multiple']).optional(),
35
+ inputPath: z.string().trim().min(1).max(500),
36
+ verifyOnRun: z.boolean().optional()
37
+ })
38
+
39
+ export const ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
40
+ id: ModelIdSchema,
41
+ primaryEntity: z.enum(['company', 'contact']),
42
+ outputs: z.array(z.enum(['company', 'contact', 'export'])).min(1),
43
+ stageKey: ModelIdSchema,
44
+ recordEntity: z.enum(['company', 'contact']).optional(),
45
+ recordsStageKey: ModelIdSchema.optional(),
46
+ recordSourceStageKey: ModelIdSchema.optional(),
47
+ dependsOn: z.array(ModelIdSchema).optional(),
48
+ dependencyMode: z.literal('per-record-eligibility'),
49
+ actionKey: ModelIdSchema,
50
+ defaultBatchSize: z.number().int().positive(),
51
+ maxBatchSize: z.number().int().positive(),
52
+ recordColumns: RecordColumnsConfigSchema.optional(),
53
+ credentialRequirements: z.array(CredentialRequirementSchema).optional()
54
+ }).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
55
+ message: 'defaultBatchSize must be less than or equal to maxBatchSize',
56
+ path: ['defaultBatchSize']
57
+ })
58
+
59
+ export const ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
60
+ id: ModelIdSchema,
61
+ steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
62
+ })
63
+
64
+ export type ListBuilderStep = z.infer<typeof ProspectingBuildTemplateStepSchema>
65
+ export type RecordColumnConfig = z.infer<typeof RecordColumnConfigSchema>
66
+ export type CredentialRequirement = z.infer<typeof CredentialRequirementSchema>
67
+ export type TemplateName = 'localServices' | 'dtcApolloClickup'
68
+ export type StepName = string
69
+
70
+ const DTC_RECORD_COLUMNS = {
71
+ populated: {
72
+ company: [
73
+ { key: 'name', label: 'Company', path: 'company.name' },
74
+ { key: 'domain', label: 'Domain', path: 'company.domain' },
75
+ { key: 'employee-count', label: 'Employees', path: 'company.numEmployees', renderType: 'count' },
76
+ { key: 'apollo-industry', label: 'Apollo industry', path: 'company.category' },
77
+ { key: 'location', label: 'Location', path: 'company.locationState' }
78
+ ]
79
+ },
80
+ crawled: {
81
+ company: [
82
+ { key: 'name', label: 'Company', path: 'company.name' },
83
+ { key: 'domain', label: 'Domain', path: 'company.domain' },
84
+ { key: 'page-count', label: 'Pages', path: 'company.enrichmentData.websiteCrawl.pageCount', renderType: 'count' },
85
+ { key: 'crawl-status', label: 'Crawl status', path: 'processingState.crawled.status', renderType: 'badge' }
86
+ ]
87
+ },
88
+ extracted: {
89
+ company: [
90
+ { key: 'name', label: 'Company', path: 'company.name' },
91
+ { key: 'domain', label: 'Domain', path: 'company.domain' },
92
+ { key: 'description', label: 'Description', path: 'company.enrichmentData.websiteCrawl.companyDescription' },
93
+ { key: 'services', label: 'Services', path: 'company.enrichmentData.websiteCrawl.services', renderType: 'json' },
94
+ {
95
+ key: 'automation-gaps',
96
+ label: 'Automation gaps',
97
+ path: 'company.enrichmentData.websiteCrawl.automationGaps',
98
+ renderType: 'json'
99
+ },
100
+ {
101
+ key: 'contact-count',
102
+ label: 'Contacts',
103
+ path: 'company.enrichmentData.websiteCrawl.emailCount',
104
+ renderType: 'count'
105
+ }
106
+ ]
107
+ },
108
+ qualified: {
109
+ company: [
110
+ { key: 'name', label: 'Company', path: 'company.name' },
111
+ { key: 'domain', label: 'Domain', path: 'company.domain' },
112
+ { key: 'score', label: 'Score', path: 'company.qualificationScore', renderType: 'badge', badgeColor: 'green' },
113
+ { key: 'signals', label: 'Signals', path: 'company.qualificationSignals', renderType: 'json' },
114
+ {
115
+ key: 'disqualified-reason',
116
+ label: 'Disqualified reason',
117
+ path: 'processingState.qualified.data.disqualifiedReason'
118
+ }
119
+ ]
120
+ },
121
+ decisionMakers: {
122
+ contact: [
123
+ { key: 'name', label: 'Name', path: 'contact.name' },
124
+ { key: 'title', label: 'Title', path: 'contact.title' },
125
+ { key: 'email', label: 'Email', path: 'contact.email' },
126
+ { key: 'linkedin', label: 'LinkedIn', path: 'contact.linkedinUrl' },
127
+ {
128
+ key: 'priority-score',
129
+ label: 'Priority',
130
+ path: 'contact.enrichmentData.apollo.priorityScore',
131
+ renderType: 'badge'
132
+ }
133
+ ]
134
+ },
135
+ uploaded: {
136
+ company: [
137
+ { key: 'name', label: 'Company', path: 'company.name' },
138
+ { key: 'domain', label: 'Domain', path: 'company.domain' },
139
+ {
140
+ key: 'contacts',
141
+ label: 'Contacts',
142
+ path: 'company.enrichmentData.approvedLeadListExport.contacts',
143
+ renderType: 'json'
144
+ },
145
+ { key: 'score', label: 'Score', path: 'company.qualificationScore', renderType: 'badge', badgeColor: 'green' },
146
+ {
147
+ key: 'approval',
148
+ label: 'Approval',
149
+ path: 'company.enrichmentData.approvedLeadListExport.approvalStatus',
150
+ renderType: 'badge'
151
+ }
152
+ ]
153
+ }
154
+ } as const satisfies Record<string, z.infer<typeof RecordColumnsConfigSchema>>
155
+
156
+ export type ActionRegistry = TopLevelAction[]
157
+
158
+ export const ACTION_REGISTRY: ActionRegistry = Object.values(LEAD_GEN_ACTION_ENTRIES)
159
+
160
+ export function findActionById(id: string): TopLevelAction | undefined {
161
+ return findOrganizationActionById(id)
162
+ }
163
+
164
+ export const PROSPECTING_STEPS = {
165
+ localServices: {
166
+ sourceCompanies: {
167
+ id: 'source-companies',
168
+ label: 'Companies found',
169
+ primaryEntity: 'company',
170
+ outputs: ['company'],
171
+ stageKey: 'populated',
172
+ dependencyMode: 'per-record-eligibility',
173
+ actionKey: 'lead-gen.company.source',
174
+ defaultBatchSize: 100,
175
+ maxBatchSize: 250
176
+ },
177
+ analyzeWebsites: {
178
+ id: 'analyze-websites',
179
+ label: 'Websites analyzed',
180
+ primaryEntity: 'company',
181
+ outputs: ['company'],
182
+ stageKey: 'extracted',
183
+ dependsOn: ['source-companies'],
184
+ dependencyMode: 'per-record-eligibility',
185
+ actionKey: 'lead-gen.company.website-extract',
186
+ defaultBatchSize: 50,
187
+ maxBatchSize: 100
188
+ },
189
+ qualifyCompanies: {
190
+ id: 'qualify-companies',
191
+ label: 'Companies qualified',
192
+ primaryEntity: 'company',
193
+ outputs: ['company'],
194
+ stageKey: 'qualified',
195
+ dependsOn: ['analyze-websites'],
196
+ dependencyMode: 'per-record-eligibility',
197
+ actionKey: 'lead-gen.company.qualify',
198
+ defaultBatchSize: 100,
199
+ maxBatchSize: 250
200
+ },
201
+ findContacts: {
202
+ id: 'find-contacts',
203
+ label: 'Decision-makers found',
204
+ primaryEntity: 'contact',
205
+ outputs: ['contact'],
206
+ stageKey: 'discovered',
207
+ dependsOn: ['qualify-companies'],
208
+ dependencyMode: 'per-record-eligibility',
209
+ actionKey: 'lead-gen.contact.discover',
210
+ defaultBatchSize: 50,
211
+ maxBatchSize: 100
212
+ },
213
+ verifyEmails: {
214
+ id: 'verify-emails',
215
+ label: 'Emails verified',
216
+ primaryEntity: 'contact',
217
+ outputs: ['contact'],
218
+ stageKey: 'verified',
219
+ dependsOn: ['find-contacts'],
220
+ dependencyMode: 'per-record-eligibility',
221
+ actionKey: 'lead-gen.contact.verify-email',
222
+ defaultBatchSize: 100,
223
+ maxBatchSize: 500
224
+ },
225
+ personalize: {
226
+ id: 'personalize',
227
+ label: 'Personalize',
228
+ primaryEntity: 'contact',
229
+ outputs: ['contact'],
230
+ stageKey: 'personalized',
231
+ dependsOn: ['verify-emails'],
232
+ dependencyMode: 'per-record-eligibility',
233
+ actionKey: 'lead-gen.contact.personalize',
234
+ defaultBatchSize: 25,
235
+ maxBatchSize: 100
236
+ },
237
+ review: {
238
+ id: 'review',
239
+ label: 'Reviewed and exported',
240
+ primaryEntity: 'contact',
241
+ outputs: ['export'],
242
+ stageKey: 'uploaded',
243
+ dependsOn: ['personalize'],
244
+ dependencyMode: 'per-record-eligibility',
245
+ actionKey: 'lead-gen.review.outreach-ready',
246
+ defaultBatchSize: 25,
247
+ maxBatchSize: 100
248
+ }
249
+ },
250
+ dtcApolloClickup: {
251
+ importApolloSearch: {
252
+ id: 'import-apollo-search',
253
+ label: 'Companies found',
254
+ description: 'Pull companies and seed contact data from a predefined Apollo search or list.',
255
+ primaryEntity: 'company',
256
+ outputs: ['company', 'contact'],
257
+ stageKey: 'populated',
258
+ dependencyMode: 'per-record-eligibility',
259
+ actionKey: 'lead-gen.company.apollo-import',
260
+ defaultBatchSize: 250,
261
+ maxBatchSize: 1000,
262
+ recordColumns: DTC_RECORD_COLUMNS.populated,
263
+ credentialRequirements: [
264
+ {
265
+ key: 'apollo',
266
+ provider: 'apollo',
267
+ credentialType: 'api-key-secret',
268
+ label: 'Apollo API key',
269
+ required: true,
270
+ selectionMode: 'single',
271
+ inputPath: 'credential'
272
+ }
273
+ ]
274
+ },
275
+ apifyCrawl: {
276
+ id: 'apify-crawl',
277
+ label: 'Websites crawled',
278
+ description:
279
+ 'Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis. Overwrites the synthetic seed Apollo Import wrote with real page content.',
280
+ primaryEntity: 'company',
281
+ outputs: ['company'],
282
+ stageKey: 'crawled',
283
+ dependsOn: ['import-apollo-search'],
284
+ dependencyMode: 'per-record-eligibility',
285
+ actionKey: 'lead-gen.company.apify-crawl',
286
+ defaultBatchSize: 50,
287
+ maxBatchSize: 100,
288
+ recordColumns: DTC_RECORD_COLUMNS.crawled,
289
+ credentialRequirements: [
290
+ {
291
+ key: 'apify',
292
+ provider: 'apify',
293
+ credentialType: 'api-key-secret',
294
+ label: 'Apify API token',
295
+ required: true,
296
+ selectionMode: 'single',
297
+ inputPath: 'credential',
298
+ verifyOnRun: true
299
+ }
300
+ ]
301
+ },
302
+ analyzeWebsites: {
303
+ id: 'analyze-websites',
304
+ label: 'Websites analyzed',
305
+ description: 'Extract subscription, product, retention, and tech-stack signals from each brand website.',
306
+ primaryEntity: 'company',
307
+ outputs: ['company'],
308
+ stageKey: 'extracted',
309
+ dependsOn: ['apify-crawl'],
310
+ dependencyMode: 'per-record-eligibility',
311
+ actionKey: 'lead-gen.company.website-extract',
312
+ defaultBatchSize: 50,
313
+ maxBatchSize: 100,
314
+ recordColumns: DTC_RECORD_COLUMNS.extracted
315
+ },
316
+ scoreDtcFit: {
317
+ id: 'score-dtc-fit',
318
+ label: 'Companies qualified',
319
+ description: 'Classify subscription potential, consumable-product fit, retention maturity, and disqualifiers.',
320
+ primaryEntity: 'company',
321
+ outputs: ['company'],
322
+ stageKey: 'qualified',
323
+ dependsOn: ['analyze-websites'],
324
+ dependencyMode: 'per-record-eligibility',
325
+ actionKey: 'lead-gen.company.dtc-subscription-qualify',
326
+ defaultBatchSize: 100,
327
+ maxBatchSize: 250,
328
+ recordColumns: DTC_RECORD_COLUMNS.qualified
329
+ },
330
+ enrichDecisionMakers: {
331
+ id: 'enrich-decision-makers',
332
+ label: 'Decision-makers found',
333
+ description:
334
+ 'Use Apollo to find qualified contacts at qualified companies - founders, retention leads, lifecycle leads, and marketing owners.',
335
+ primaryEntity: 'company',
336
+ outputs: ['contact'],
337
+ stageKey: 'decision-makers-enriched',
338
+ recordEntity: 'contact',
339
+ dependsOn: ['score-dtc-fit'],
340
+ dependencyMode: 'per-record-eligibility',
341
+ actionKey: 'lead-gen.contact.apollo-decision-maker-enrich',
342
+ defaultBatchSize: 100,
343
+ maxBatchSize: 250,
344
+ recordColumns: DTC_RECORD_COLUMNS.decisionMakers,
345
+ credentialRequirements: [
346
+ {
347
+ key: 'apollo',
348
+ provider: 'apollo',
349
+ credentialType: 'api-key-secret',
350
+ label: 'Apollo API key',
351
+ required: true,
352
+ selectionMode: 'single',
353
+ inputPath: 'credential'
354
+ }
355
+ ]
356
+ },
357
+ reviewAndExport: {
358
+ id: 'review-and-export',
359
+ label: 'Reviewed and exported',
360
+ description:
361
+ 'Operator QC approves or rejects qualified companies, then approved records are exported as a lead list with unverified emails.',
362
+ primaryEntity: 'company',
363
+ outputs: ['export'],
364
+ stageKey: 'uploaded',
365
+ recordsStageKey: 'uploaded',
366
+ recordSourceStageKey: 'qualified',
367
+ dependsOn: ['enrich-decision-makers'],
368
+ dependencyMode: 'per-record-eligibility',
369
+ actionKey: 'lead-gen.export.list',
370
+ defaultBatchSize: 100,
371
+ maxBatchSize: 250,
372
+ recordColumns: DTC_RECORD_COLUMNS.uploaded,
373
+ credentialRequirements: [
374
+ {
375
+ key: 'clickup',
376
+ provider: 'clickup',
377
+ credentialType: 'api-key-secret',
378
+ label: 'ClickUp API token',
379
+ required: true,
380
+ selectionMode: 'single',
381
+ inputPath: 'clickupCredential',
382
+ verifyOnRun: true
383
+ }
384
+ ]
385
+ }
386
+ }
387
+ } as const satisfies Record<TemplateName, Record<StepName, ListBuilderStep>>
388
+
389
+ // Phase 4 cut: OrganizationModelProspectingSchema and DEFAULT_ORGANIZATION_MODEL_PROSPECTING removed.
390
+ // Build-template/stage data moved into system.content as (schema:template), (schema:template-step),
391
+ // and (schema:stage) content nodes. Use getAllBuildTemplates() / getAllProspectingStages()
392
+ // from migration-helpers to read prospecting data portably.
393
+ //
394
+ // ProspectingBuildTemplateSchema, ProspectingBuildTemplateStepSchema, ProspectingLifecycleStageSchema,
395
+ // PROSPECTING_STEPS, and ACTION_REGISTRY are retained for use by business logic and UI.