@elevasis/core 0.15.1 → 0.16.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 (68) hide show
  1. package/dist/index.d.ts +1662 -23
  2. package/dist/index.js +171 -24
  3. package/dist/organization-model/index.d.ts +1662 -23
  4. package/dist/organization-model/index.js +171 -24
  5. package/dist/test-utils/index.d.ts +711 -10
  6. package/dist/test-utils/index.js +159 -16
  7. package/package.json +7 -3
  8. package/src/__tests__/publish.test.ts +14 -13
  9. package/src/__tests__/template-core-compatibility.test.ts +4 -4
  10. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +305 -201
  11. package/src/auth/multi-tenancy/index.ts +3 -0
  12. package/src/auth/multi-tenancy/theme-presets.ts +45 -0
  13. package/src/auth/multi-tenancy/types.ts +57 -83
  14. package/src/auth/multi-tenancy/users/api-schemas.ts +165 -194
  15. package/src/business/acquisition/activity-events.ts +1 -1
  16. package/src/business/acquisition/api-schemas.ts +1196 -1177
  17. package/src/business/acquisition/crm-state-actions.test.ts +139 -139
  18. package/src/business/acquisition/types.ts +381 -390
  19. package/src/business/crm/api-schemas.ts +40 -0
  20. package/src/business/crm/index.ts +1 -0
  21. package/src/business/deals/api-schemas.ts +79 -0
  22. package/src/business/deals/index.ts +1 -0
  23. package/src/business/projects/types.ts +124 -88
  24. package/src/execution/core/runner-types.ts +61 -80
  25. package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-tools.ts +105 -104
  26. package/src/execution/engine/tools/integration/server/adapters/instantly/instantly-tools.ts +1474 -1473
  27. package/src/execution/engine/tools/integration/server/adapters/millionverifier/millionverifier-tools.ts +103 -102
  28. package/src/execution/engine/tools/integration/server/adapters/signature-api/signature-api-tools.ts +182 -179
  29. package/src/execution/engine/tools/integration/server/adapters/stripe/stripe-tools.ts +310 -309
  30. package/src/execution/engine/tools/integration/tool.ts +255 -253
  31. package/src/execution/engine/tools/lead-service-types.ts +895 -894
  32. package/src/execution/engine/tools/messages.ts +43 -0
  33. package/src/execution/engine/tools/platform/acquisition/types.ts +2 -1
  34. package/src/execution/engine/tools/platform/email/types.ts +97 -96
  35. package/src/execution/engine/tools/types.ts +234 -233
  36. package/src/execution/engine/workflow/types.ts +195 -193
  37. package/src/execution/external/api-schemas.ts +40 -0
  38. package/src/execution/external/index.ts +1 -0
  39. package/src/knowledge/README.md +32 -0
  40. package/src/knowledge/__tests__/queries.test.ts +504 -0
  41. package/src/knowledge/format.ts +99 -0
  42. package/src/knowledge/index.ts +5 -0
  43. package/src/knowledge/queries.ts +256 -0
  44. package/src/organization-model/__tests__/defaults.test.ts +172 -172
  45. package/src/organization-model/__tests__/foundation.test.ts +7 -7
  46. package/src/organization-model/__tests__/icons.test.ts +27 -0
  47. package/src/organization-model/__tests__/knowledge.test.ts +214 -0
  48. package/src/organization-model/contracts.ts +17 -15
  49. package/src/organization-model/defaults.ts +74 -19
  50. package/src/organization-model/domains/knowledge.ts +53 -0
  51. package/src/organization-model/domains/navigation.ts +416 -399
  52. package/src/organization-model/domains/shared.ts +6 -5
  53. package/src/organization-model/foundation.ts +10 -6
  54. package/src/organization-model/graph/build.ts +209 -182
  55. package/src/organization-model/graph/schema.ts +37 -34
  56. package/src/organization-model/graph/types.ts +47 -31
  57. package/src/organization-model/icons.ts +81 -0
  58. package/src/organization-model/index.ts +8 -3
  59. package/src/organization-model/organization-model.mdx +1 -1
  60. package/src/organization-model/published.ts +103 -86
  61. package/src/organization-model/schema.ts +90 -85
  62. package/src/organization-model/types.ts +40 -33
  63. package/src/platform/index.ts +23 -27
  64. package/src/platform/registry/index.ts +0 -4
  65. package/src/platform/registry/resource-registry.ts +0 -77
  66. package/src/platform/registry/serialized-types.ts +148 -219
  67. package/src/platform/registry/stats-types.ts +60 -60
  68. package/src/reference/_generated/contracts.md +1265 -1154
@@ -1,191 +1,182 @@
1
- import type { Database } from '../../supabase/database.types'
2
-
3
- // =============================================================================
4
- // Supabase-Generated Types (Re-exported from database.types)
5
- // =============================================================================
6
-
7
- /** Raw database row type for acq_lists table */
8
- export type AcqListRow = Database['public']['Tables']['acq_lists']['Row']
9
- /** Insert type for acq_lists table */
10
- export type AcqListInsert = Database['public']['Tables']['acq_lists']['Insert']
11
-
12
- /** Raw database row type for acq_companies table */
13
- export type AcqCompanyRow = Database['public']['Tables']['acq_companies']['Row']
14
- /** Insert type for acq_companies table */
15
- export type AcqCompanyInsert = Database['public']['Tables']['acq_companies']['Insert']
16
-
17
- /** Raw database row type for acq_contacts table */
18
- export type AcqContactRow = Database['public']['Tables']['acq_contacts']['Row']
19
- /** Insert type for acq_contacts table */
20
- export type AcqContactInsert = Database['public']['Tables']['acq_contacts']['Insert']
21
-
22
- /** Raw database row type for acq_deals table */
23
- export type AcqDealRow = Database['public']['Tables']['acq_deals']['Row']
24
- /** Insert type for acq_deals table */
25
- export type AcqDealInsert = Database['public']['Tables']['acq_deals']['Insert']
26
-
27
- /** Raw database row type for acq_deal_tasks table */
28
- export type AcqDealTaskRow = Database['public']['Tables']['acq_deal_tasks']['Row']
29
- /** Insert type for acq_deal_tasks table */
30
- export type AcqDealTaskInsert = Database['public']['Tables']['acq_deal_tasks']['Insert']
31
-
32
- // =============================================================================
33
- // Supporting Types
34
- // =============================================================================
35
-
36
- /**
37
- * Represents a web post from company website scraping.
38
- * Used for recent blog posts, news, or announcements.
39
- */
40
- export interface WebPost {
41
- /** ISO date string of when the post was published */
42
- date: string
43
- /** Title of the web post */
44
- title: string
45
- /** Brief summary of the post content */
46
- summary: string
47
- /** AI-generated insight about the post's relevance */
48
- aiInsight?: string
49
- }
50
-
51
- /**
52
- * Tracks pipeline status for a company across all processing stages.
53
- */
54
- export interface CompanyPipelineStatus {
55
- acquired: boolean
56
- enrichment: {
57
- [source: string]: {
58
- status: 'pending' | 'complete' | 'failed' | 'skipped'
59
- completedAt?: string
60
- error?: string
61
- }
62
- }
63
- }
64
-
65
- /**
66
- * Tracks pipeline status for a contact across all processing stages.
67
- */
68
- export interface ContactPipelineStatus {
69
- enrichment: {
70
- [source: string]: {
71
- status: 'pending' | 'complete' | 'failed' | 'skipped'
72
- completedAt?: string
73
- error?: string
74
- }
75
- }
76
- personalization: {
77
- status: 'pending' | 'complete' | 'failed' | 'skipped'
78
- completedAt?: string
79
- }
80
- outreach: {
81
- status: 'pending' | 'sent' | 'replied' | 'bounced' | 'opted-out'
82
- sentAt?: string
83
- channel?: string
84
- campaignId?: string
85
- }
86
- }
87
-
88
- /**
89
- * Enrichment data collected for a company from various sources.
90
- */
91
- export interface CompanyEnrichmentData {
92
- googleMaps?: {
93
- placeId?: string
94
- totalScore?: number
95
- reviewsCount?: number
96
- address?: string
97
- phone?: string
98
- categoryName?: string
99
- googleMapsUrl?: string
100
- scrapedAt?: string
101
- }
102
- websiteCrawl?: {
103
- companyDescription?: string
104
- services?: string[]
105
- specialties?: string[]
106
- staff?: Array<{ name: string; title?: string; email?: string }>
107
- automationGaps?: string[]
108
- targetAudience?: string
109
- category?: string
110
- segment?: string
111
- recentWin?: string
112
- emailCount?: number
113
- pageCount?: number
114
- totalChars?: number
115
- crawledAt?: string
116
- extractedAt?: string
117
- }
118
- website?: {
119
- missionVision?: string
120
- uniqueAttributes?: string
121
- coreOfferings?: string
122
- targetAudience?: string
123
- companyValues?: string
124
- businessDescription?: string
125
- recentPosts?: Array<{ date?: string; title?: string; summary?: string; aiInsight?: string }>
126
- }
127
- tomba?: {
128
- waterfallEmail?: {
129
- email: string
130
- name?: string
131
- title?: string
132
- department?: string
133
- } | null
134
- genericEmail?: string | null
135
- totalFound?: number
136
- searchedAt?: string
137
- }
138
- }
139
-
140
- /**
141
- * Enrichment data collected for a contact from various sources.
142
- */
143
- export interface ContactEnrichmentData {
144
- linkedin?: {
145
- summary?: string
146
- pastExperience?: string
147
- education?: string
148
- activity?: Array<{ date?: string; content?: string }>
149
- }
150
- }
151
-
152
- // =============================================================================
153
- // Domain Types (camelCase transformations of database rows)
154
- // =============================================================================
155
-
156
- export type ListStatus = 'draft' | 'enriching' | 'launched' | 'closing' | 'archived'
157
-
158
- export interface ScrapingConfig {
159
- source?: string
160
- query?: string
161
- filters?: Record<string, unknown>
162
- [key: string]: unknown
163
- }
164
-
165
- export interface IcpRubric {
166
- targetDescription?: string
167
- minReviewCount?: number
168
- minRating?: number
169
- excludeFranchises?: boolean
170
- customRules?: string
171
- qualificationRubricKey?: string | null
172
- [key: string]: unknown
173
- }
174
-
175
- export interface PipelineStage {
176
- key: string
177
- label?: string
178
- description?: string
179
- resourceId?: string
180
- inputTemplate?: Record<string, unknown>
181
- enabled?: boolean
182
- order?: number
183
- }
184
-
185
- export interface PipelineConfig {
186
- stages: PipelineStage[]
187
- }
188
-
1
+ import type { Database } from '../../supabase/database.types'
2
+ import type { PipelineStage } from './api-schemas'
3
+
4
+ // =============================================================================
5
+ // Supabase-Generated Types (Re-exported from database.types)
6
+ // =============================================================================
7
+
8
+ /** Raw database row type for acq_lists table */
9
+ export type AcqListRow = Database['public']['Tables']['acq_lists']['Row']
10
+ /** Insert type for acq_lists table */
11
+ export type AcqListInsert = Database['public']['Tables']['acq_lists']['Insert']
12
+
13
+ /** Raw database row type for acq_companies table */
14
+ export type AcqCompanyRow = Database['public']['Tables']['acq_companies']['Row']
15
+ /** Insert type for acq_companies table */
16
+ export type AcqCompanyInsert = Database['public']['Tables']['acq_companies']['Insert']
17
+
18
+ /** Raw database row type for acq_contacts table */
19
+ export type AcqContactRow = Database['public']['Tables']['acq_contacts']['Row']
20
+ /** Insert type for acq_contacts table */
21
+ export type AcqContactInsert = Database['public']['Tables']['acq_contacts']['Insert']
22
+
23
+ /** Raw database row type for acq_deals table */
24
+ export type AcqDealRow = Database['public']['Tables']['acq_deals']['Row']
25
+ /** Insert type for acq_deals table */
26
+ export type AcqDealInsert = Database['public']['Tables']['acq_deals']['Insert']
27
+
28
+ /** Raw database row type for acq_deal_tasks table */
29
+ export type AcqDealTaskRow = Database['public']['Tables']['acq_deal_tasks']['Row']
30
+ /** Insert type for acq_deal_tasks table */
31
+ export type AcqDealTaskInsert = Database['public']['Tables']['acq_deal_tasks']['Insert']
32
+
33
+ // =============================================================================
34
+ // Supporting Types
35
+ // =============================================================================
36
+
37
+ /**
38
+ * Represents a web post from company website scraping.
39
+ * Used for recent blog posts, news, or announcements.
40
+ */
41
+ export interface WebPost {
42
+ /** ISO date string of when the post was published */
43
+ date: string
44
+ /** Title of the web post */
45
+ title: string
46
+ /** Brief summary of the post content */
47
+ summary: string
48
+ /** AI-generated insight about the post's relevance */
49
+ aiInsight?: string
50
+ }
51
+
52
+ /**
53
+ * Tracks pipeline status for a company across all processing stages.
54
+ */
55
+ export interface CompanyPipelineStatus {
56
+ acquired: boolean
57
+ enrichment: {
58
+ [source: string]: {
59
+ status: 'pending' | 'complete' | 'failed' | 'skipped'
60
+ completedAt?: string
61
+ error?: string
62
+ }
63
+ }
64
+ }
65
+
66
+ /**
67
+ * Tracks pipeline status for a contact across all processing stages.
68
+ */
69
+ export interface ContactPipelineStatus {
70
+ enrichment: {
71
+ [source: string]: {
72
+ status: 'pending' | 'complete' | 'failed' | 'skipped'
73
+ completedAt?: string
74
+ error?: string
75
+ }
76
+ }
77
+ personalization: {
78
+ status: 'pending' | 'complete' | 'failed' | 'skipped'
79
+ completedAt?: string
80
+ }
81
+ outreach: {
82
+ status: 'pending' | 'sent' | 'replied' | 'bounced' | 'opted-out'
83
+ sentAt?: string
84
+ channel?: string
85
+ campaignId?: string
86
+ }
87
+ }
88
+
89
+ /**
90
+ * Enrichment data collected for a company from various sources.
91
+ */
92
+ export interface CompanyEnrichmentData {
93
+ googleMaps?: {
94
+ placeId?: string
95
+ totalScore?: number
96
+ reviewsCount?: number
97
+ address?: string
98
+ phone?: string
99
+ categoryName?: string
100
+ googleMapsUrl?: string
101
+ scrapedAt?: string
102
+ }
103
+ websiteCrawl?: {
104
+ companyDescription?: string
105
+ services?: string[]
106
+ specialties?: string[]
107
+ staff?: Array<{ name: string; title?: string; email?: string }>
108
+ automationGaps?: string[]
109
+ targetAudience?: string
110
+ category?: string
111
+ segment?: string
112
+ recentWin?: string
113
+ emailCount?: number
114
+ pageCount?: number
115
+ totalChars?: number
116
+ crawledAt?: string
117
+ extractedAt?: string
118
+ }
119
+ website?: {
120
+ missionVision?: string
121
+ uniqueAttributes?: string
122
+ coreOfferings?: string
123
+ targetAudience?: string
124
+ companyValues?: string
125
+ businessDescription?: string
126
+ recentPosts?: Array<{ date?: string; title?: string; summary?: string; aiInsight?: string }>
127
+ }
128
+ tomba?: {
129
+ waterfallEmail?: {
130
+ email: string
131
+ name?: string
132
+ title?: string
133
+ department?: string
134
+ } | null
135
+ genericEmail?: string | null
136
+ totalFound?: number
137
+ searchedAt?: string
138
+ }
139
+ }
140
+
141
+ /**
142
+ * Enrichment data collected for a contact from various sources.
143
+ */
144
+ export interface ContactEnrichmentData {
145
+ linkedin?: {
146
+ summary?: string
147
+ pastExperience?: string
148
+ education?: string
149
+ activity?: Array<{ date?: string; content?: string }>
150
+ }
151
+ }
152
+
153
+ // =============================================================================
154
+ // Domain Types (camelCase transformations of database rows)
155
+ // =============================================================================
156
+
157
+ export type ListStatus = 'draft' | 'enriching' | 'launched' | 'closing' | 'archived'
158
+
159
+ export interface ScrapingConfig {
160
+ source?: string
161
+ query?: string
162
+ filters?: Record<string, unknown>
163
+ [key: string]: unknown
164
+ }
165
+
166
+ export interface IcpRubric {
167
+ targetDescription?: string
168
+ minReviewCount?: number
169
+ minRating?: number
170
+ excludeFranchises?: boolean
171
+ customRules?: string
172
+ qualificationRubricKey?: string | null
173
+ [key: string]: unknown
174
+ }
175
+
176
+ export interface PipelineConfig {
177
+ stages: PipelineStage[]
178
+ }
179
+
189
180
  export type BuildPlanSnapshotPrimaryEntity = 'company' | 'contact'
190
181
  export type BuildPlanSnapshotOutput = 'company' | 'contact' | 'export'
191
182
  export type BuildPlanSnapshotDependencyMode = 'per-record-eligibility'
@@ -203,211 +194,211 @@ export interface BuildPlanSnapshotStep {
203
194
  defaultBatchSize: number
204
195
  maxBatchSize: number
205
196
  }
206
-
207
- export interface BuildPlanSnapshot {
208
- templateId: string
209
- templateLabel: string
210
- steps: BuildPlanSnapshotStep[]
211
- }
212
-
213
- export interface AcqListMetadata extends Record<string, unknown> {
214
- buildPlanSnapshot?: BuildPlanSnapshot
215
- }
216
-
217
- export interface AcqList {
218
- id: string
219
- organizationId: string
220
- name: string
221
- description: string | null
222
- batchIds: string[]
223
- instantlyCampaignId: string | null
224
- status: ListStatus
225
- scrapingConfig: ScrapingConfig
226
- icp: IcpRubric
227
- pipelineConfig: PipelineConfig
228
- metadata: AcqListMetadata
229
- launchedAt: Date | null
230
- completedAt: Date | null
231
- createdAt: Date
232
- }
233
-
234
- /**
235
- * Company record in the acquisition database.
236
- * Contains enriched company data from various sources.
237
- * Transformed from AcqCompanyRow with camelCase properties.
238
- */
239
- export interface AcqCompany {
240
- id: string
241
- organizationId: string
242
- name: string
243
- domain: string | null
244
- linkedinUrl: string | null
245
- website: string | null
246
- numEmployees: number | null
247
- foundedYear: number | null
248
- locationCity: string | null
249
- locationState: string | null
250
- category: string | null
251
- categoryPain: string | null
252
- segment: string | null
253
- pipelineStatus: CompanyPipelineStatus | null
254
- enrichmentData: CompanyEnrichmentData | null
255
- source: string | null
256
- batchId: string | null
257
- status: 'active' | 'invalid'
258
- verticalResearch: string | null
259
- /** Track A: flat qualification score (null until a scoring rubric is defined). Added by W1 migration. */
260
- qualificationScore: number | null
261
- /** Track A: flat qualification signals jsonb preserving the result payload shape. Added by W1 migration. */
262
- qualificationSignals: Record<string, unknown> | null
263
- /** Track A: key identifying the rubric used for qualification. Added by W1 migration. */
264
- qualificationRubricKey: string | null
265
- createdAt: Date
266
- updatedAt: Date
267
- }
268
-
269
- /**
270
- * Contact record in the acquisition database.
271
- * Contains enriched contact data and personalization content.
272
- * Transformed from AcqContactRow with camelCase properties.
273
- */
274
- export interface AcqContact {
275
- id: string
276
- organizationId: string
277
- companyId: string | null
278
- email: string
279
- emailValid: 'VALID' | 'INVALID' | 'RISKY' | 'UNKNOWN' | null
280
- firstName: string | null
281
- lastName: string | null
282
- linkedinUrl: string | null
283
- title: string | null
284
- headline: string | null
285
- filterReason: string | null
286
- openingLine: string | null
287
- source: string | null
288
- sourceId: string | null
289
- pipelineStatus: ContactPipelineStatus | null
290
- enrichmentData: ContactEnrichmentData | null
291
- /** Attio Person record ID - set when contact responds and is added to CRM */
292
- attioPersonId: string | null
293
- batchId: string | null
294
- status: 'active' | 'invalid'
295
- createdAt: Date
296
- updatedAt: Date
297
- }
298
-
299
- // ─── Deal UI Types ───────────────────────────────────────────────────────────
300
-
301
- export type DealStage = 'interested' | 'proposal' | 'closing' | 'closed_won' | 'closed_lost' | 'nurturing'
302
-
303
- export type DealPriorityBucketKey = 'needs_response' | 'follow_up_due' | 'waiting' | 'stale' | 'closed_low'
304
-
305
- export interface DealPriority {
306
- bucketKey: DealPriorityBucketKey
307
- rank: number
308
- label: string
309
- color: string
310
- reason: string
311
- latestActivityAt: string | null
312
- nextActionAt: string | null
313
- }
314
-
315
- export interface KanbanStageConfig {
316
- color: string // Mantine color token (e.g. 'blue', 'teal')
317
- label?: string // Optional display label override
318
- }
319
-
320
- export type KanbanBoardConfig = Partial<Record<DealStage, KanbanStageConfig>>
321
-
322
- export interface DealContact {
323
- id: string
324
- first_name: string | null
325
- last_name: string | null
326
- email: string
327
- title: string | null
328
- headline: string | null
329
- linkedin_url: string | null
330
- pipeline_status: Record<string, unknown> | null
331
- enrichment_data: Record<string, unknown> | null
332
- company: {
333
- id: string
334
- name: string
335
- domain: string | null
336
- website: string | null
337
- linkedin_url: string | null
338
- segment: string | null
339
- category: string | null
340
- num_employees: number | null
341
- } | null
342
- }
343
-
344
- export interface DealFilters {
345
- stage?: DealStage
346
- search?: string
347
- limit?: number
348
- offset?: number
349
- }
350
-
351
- /** Deal list item with joined contact and company data */
197
+
198
+ export interface BuildPlanSnapshot {
199
+ templateId: string
200
+ templateLabel: string
201
+ steps: BuildPlanSnapshotStep[]
202
+ }
203
+
204
+ export interface AcqListMetadata extends Record<string, unknown> {
205
+ buildPlanSnapshot?: BuildPlanSnapshot
206
+ }
207
+
208
+ export interface AcqList {
209
+ id: string
210
+ organizationId: string
211
+ name: string
212
+ description: string | null
213
+ batchIds: string[]
214
+ instantlyCampaignId: string | null
215
+ status: ListStatus
216
+ scrapingConfig: ScrapingConfig
217
+ icp: IcpRubric
218
+ pipelineConfig: PipelineConfig
219
+ metadata: AcqListMetadata
220
+ launchedAt: Date | null
221
+ completedAt: Date | null
222
+ createdAt: Date
223
+ }
224
+
225
+ /**
226
+ * Company record in the acquisition database.
227
+ * Contains enriched company data from various sources.
228
+ * Transformed from AcqCompanyRow with camelCase properties.
229
+ */
230
+ export interface AcqCompany {
231
+ id: string
232
+ organizationId: string
233
+ name: string
234
+ domain: string | null
235
+ linkedinUrl: string | null
236
+ website: string | null
237
+ numEmployees: number | null
238
+ foundedYear: number | null
239
+ locationCity: string | null
240
+ locationState: string | null
241
+ category: string | null
242
+ categoryPain: string | null
243
+ segment: string | null
244
+ pipelineStatus: CompanyPipelineStatus | null
245
+ enrichmentData: CompanyEnrichmentData | null
246
+ source: string | null
247
+ batchId: string | null
248
+ status: 'active' | 'invalid'
249
+ verticalResearch: string | null
250
+ /** Track A: flat qualification score (null until a scoring rubric is defined). Added by W1 migration. */
251
+ qualificationScore: number | null
252
+ /** Track A: flat qualification signals jsonb preserving the result payload shape. Added by W1 migration. */
253
+ qualificationSignals: Record<string, unknown> | null
254
+ /** Track A: key identifying the rubric used for qualification. Added by W1 migration. */
255
+ qualificationRubricKey: string | null
256
+ createdAt: Date
257
+ updatedAt: Date
258
+ }
259
+
260
+ /**
261
+ * Contact record in the acquisition database.
262
+ * Contains enriched contact data and personalization content.
263
+ * Transformed from AcqContactRow with camelCase properties.
264
+ */
265
+ export interface AcqContact {
266
+ id: string
267
+ organizationId: string
268
+ companyId: string | null
269
+ email: string
270
+ emailValid: 'VALID' | 'INVALID' | 'RISKY' | 'UNKNOWN' | null
271
+ firstName: string | null
272
+ lastName: string | null
273
+ linkedinUrl: string | null
274
+ title: string | null
275
+ headline: string | null
276
+ filterReason: string | null
277
+ openingLine: string | null
278
+ source: string | null
279
+ sourceId: string | null
280
+ pipelineStatus: ContactPipelineStatus | null
281
+ enrichmentData: ContactEnrichmentData | null
282
+ /** Attio Person record ID - set when contact responds and is added to CRM */
283
+ attioPersonId: string | null
284
+ batchId: string | null
285
+ status: 'active' | 'invalid'
286
+ createdAt: Date
287
+ updatedAt: Date
288
+ }
289
+
290
+ // ─── Deal UI Types ───────────────────────────────────────────────────────────
291
+
292
+ export type DealStage = 'interested' | 'proposal' | 'closing' | 'closed_won' | 'closed_lost' | 'nurturing'
293
+
294
+ export type DealPriorityBucketKey = 'needs_response' | 'follow_up_due' | 'waiting' | 'stale' | 'closed_low'
295
+
296
+ export interface DealPriority {
297
+ bucketKey: DealPriorityBucketKey
298
+ rank: number
299
+ label: string
300
+ color: string
301
+ reason: string
302
+ latestActivityAt: string | null
303
+ nextActionAt: string | null
304
+ }
305
+
306
+ export interface KanbanStageConfig {
307
+ color: string // Mantine color token (e.g. 'blue', 'teal')
308
+ label?: string // Optional display label override
309
+ }
310
+
311
+ export type KanbanBoardConfig = Partial<Record<DealStage, KanbanStageConfig>>
312
+
313
+ export interface DealContact {
314
+ id: string
315
+ first_name: string | null
316
+ last_name: string | null
317
+ email: string
318
+ title: string | null
319
+ headline: string | null
320
+ linkedin_url: string | null
321
+ pipeline_status: Record<string, unknown> | null
322
+ enrichment_data: Record<string, unknown> | null
323
+ company: {
324
+ id: string
325
+ name: string
326
+ domain: string | null
327
+ website: string | null
328
+ linkedin_url: string | null
329
+ segment: string | null
330
+ category: string | null
331
+ num_employees: number | null
332
+ } | null
333
+ }
334
+
335
+ export interface DealFilters {
336
+ stage?: DealStage
337
+ search?: string
338
+ limit?: number
339
+ offset?: number
340
+ }
341
+
342
+ /** Deal list item with joined contact and company data */
352
343
  export interface DealListItem extends AcqDealRow {
353
344
  priority: DealPriority
354
345
  ownership: 'us' | 'them' | null
355
346
  nextAction: string | null
356
347
  contact: DealContact | null
357
348
  }
358
-
359
- export type DealDetail = DealListItem
360
-
361
- /** Task kind options for a deal task (human follow-up action type) */
362
- export type AcqDealTaskKind = 'call' | 'email' | 'meeting' | 'other'
363
-
364
- /**
365
- * A CRM to-do item attached to a deal representing a human follow-up action.
366
- * Transformed from AcqDealTaskRow with camelCase properties.
367
- */
368
- export interface AcqDealTask {
369
- id: string
370
- organizationId: string
371
- dealId: string
372
- title: string
373
- description: string | null
374
- kind: AcqDealTaskKind
375
- dueAt: string | null
376
- assigneeUserId: string | null
377
- completedAt: string | null
378
- completedByUserId: string | null
379
- createdAt: string
380
- updatedAt: string
381
- createdByUserId: string | null
382
- }
383
-
384
- // ─── Progress / Telemetry Types ──────────────────────────────────────────────
385
-
386
- /**
387
- * Live-scan aggregate telemetry for a single list, computed on demand from
388
- * the list junction tables and current contact deliverability state.
389
- * `stageCounts` are attempted counts from list-row processing_state.
390
- */
391
- export interface ListTelemetry {
392
- listId: string
393
- totalCompanies: number
394
- totalContacts: number
395
- stageCounts: {
396
- populated: number
397
- extracted: number
398
- qualified: number
399
- discovered: number
400
- verified: number
401
- personalized: number
402
- uploaded: number
403
- }
404
- deliverability: {
405
- valid: number
406
- risky: number
407
- invalid: number
408
- unknown: number
409
- bounced: number
410
- }
411
- /** Reserved -- active workflow IDs associated with this list. */
412
- activeWorkflows?: string[]
413
- }
349
+
350
+ export type DealDetail = DealListItem
351
+
352
+ /** Task kind options for a deal task (human follow-up action type) */
353
+ export type AcqDealTaskKind = 'call' | 'email' | 'meeting' | 'other'
354
+
355
+ /**
356
+ * A CRM to-do item attached to a deal representing a human follow-up action.
357
+ * Transformed from AcqDealTaskRow with camelCase properties.
358
+ */
359
+ export interface AcqDealTask {
360
+ id: string
361
+ organizationId: string
362
+ dealId: string
363
+ title: string
364
+ description: string | null
365
+ kind: AcqDealTaskKind
366
+ dueAt: string | null
367
+ assigneeUserId: string | null
368
+ completedAt: string | null
369
+ completedByUserId: string | null
370
+ createdAt: string
371
+ updatedAt: string
372
+ createdByUserId: string | null
373
+ }
374
+
375
+ // ─── Progress / Telemetry Types ──────────────────────────────────────────────
376
+
377
+ /**
378
+ * Live-scan aggregate telemetry for a single list, computed on demand from
379
+ * the list junction tables and current contact deliverability state.
380
+ * `stageCounts` are attempted counts from list-row processing_state.
381
+ */
382
+ export interface ListTelemetry {
383
+ listId: string
384
+ totalCompanies: number
385
+ totalContacts: number
386
+ stageCounts: {
387
+ populated: number
388
+ extracted: number
389
+ qualified: number
390
+ discovered: number
391
+ verified: number
392
+ personalized: number
393
+ uploaded: number
394
+ }
395
+ deliverability: {
396
+ valid: number
397
+ risky: number
398
+ invalid: number
399
+ unknown: number
400
+ bounced: number
401
+ }
402
+ /** Reserved -- active workflow IDs associated with this list. */
403
+ activeWorkflows?: string[]
404
+ }