@elevasis/core 0.18.0 → 0.19.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.
- package/dist/index.d.ts +82 -1
- package/dist/index.js +291 -171
- package/dist/knowledge/index.d.ts +43 -0
- package/dist/organization-model/index.d.ts +82 -1
- package/dist/organization-model/index.js +291 -171
- package/dist/test-utils/index.d.ts +41 -12
- package/dist/test-utils/index.js +291 -171
- package/package.json +2 -1
- package/src/_gen/__tests__/__snapshots__/contracts.md.snap +78 -65
- package/src/auth/multi-tenancy/organizations/__tests__/api-schemas.test.ts +194 -0
- package/src/auth/multi-tenancy/organizations/api-schemas.ts +136 -128
- package/src/business/acquisition/api-schemas.test.ts +100 -2
- package/src/business/acquisition/api-schemas.ts +81 -43
- package/src/business/acquisition/build-templates.test.ts +212 -0
- package/src/business/acquisition/types.ts +21 -38
- package/src/execution/engine/index.ts +436 -434
- package/src/execution/engine/tools/integration/server/adapters/google-calendar/google-calendar-adapter.ts +428 -0
- package/src/execution/engine/tools/integration/server/adapters/google-calendar/index.ts +2 -0
- package/src/execution/engine/tools/lead-service-types.ts +51 -9
- package/src/execution/engine/tools/platform/acquisition/company-tools.ts +7 -6
- package/src/execution/engine/tools/platform/acquisition/contact-tools.ts +6 -5
- package/src/execution/engine/tools/platform/acquisition/types.ts +20 -9
- package/src/execution/engine/tools/registry.ts +700 -698
- package/src/execution/engine/tools/tool-maps.ts +10 -0
- package/src/execution/external/__tests__/api-schemas.test.ts +127 -0
- package/src/integrations/oauth/__tests__/provider-registry.test.ts +7 -6
- package/src/integrations/oauth/provider-registry.ts +74 -61
- package/src/integrations/oauth/server/credentials.ts +43 -39
- package/src/knowledge/__tests__/queries.test.ts +89 -0
- package/src/organization-model/__tests__/icons.test.ts +61 -0
- package/src/organization-model/__tests__/knowledge.test.ts +118 -1
- package/src/organization-model/__tests__/prospecting-ssot.test.ts +94 -0
- package/src/organization-model/defaults.ts +8 -0
- package/src/organization-model/domains/knowledge.ts +9 -0
- package/src/organization-model/domains/prospecting.ts +272 -226
- package/src/organization-model/domains/sales.ts +32 -25
- package/src/organization-model/icons.ts +3 -0
- package/src/organization-model/types.ts +9 -1
- package/src/platform/constants/versions.ts +1 -1
- package/src/platform/utils/__tests__/validation.test.ts +1084 -1083
- package/src/platform/utils/validation.ts +425 -425
- package/src/reference/_generated/contracts.md +78 -65
- package/src/server.ts +6 -0
- package/src/supabase/database.types.ts +6 -12
|
@@ -1,128 +1,136 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Organizations Domain - Zod Validation Schemas
|
|
3
|
-
*
|
|
4
|
-
* Validation schemas for organization management endpoints.
|
|
5
|
-
* Includes request bodies, query params, and path params.
|
|
6
|
-
*
|
|
7
|
-
* Security:
|
|
8
|
-
* - All schemas use .strict() to prevent mass assignment attacks
|
|
9
|
-
* - UUID/WorkOS ID validation prevents invalid references
|
|
10
|
-
* - String length limits prevent DoS
|
|
11
|
-
* - Domain and metadata size limits
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
import { z } from 'zod'
|
|
15
|
-
import { UuidSchema } from '../../../platform/utils/validation'
|
|
16
|
-
|
|
17
|
-
// ============================================================================
|
|
18
|
-
// Shared Schemas
|
|
19
|
-
// ============================================================================
|
|
20
|
-
|
|
21
|
-
/**
|
|
22
|
-
* Organization name validation
|
|
23
|
-
* - Alphanumeric, spaces, hyphens, underscores only
|
|
24
|
-
* - 2-100 characters
|
|
25
|
-
*
|
|
26
|
-
* Security: Prevents injection, DoS via long names
|
|
27
|
-
*/
|
|
28
|
-
export const OrganizationNameSchema = z
|
|
29
|
-
.
|
|
30
|
-
.
|
|
31
|
-
.
|
|
32
|
-
.
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
.
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
*
|
|
96
|
-
*
|
|
97
|
-
*
|
|
98
|
-
*
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Organizations Domain - Zod Validation Schemas
|
|
3
|
+
*
|
|
4
|
+
* Validation schemas for organization management endpoints.
|
|
5
|
+
* Includes request bodies, query params, and path params.
|
|
6
|
+
*
|
|
7
|
+
* Security:
|
|
8
|
+
* - All schemas use .strict() to prevent mass assignment attacks
|
|
9
|
+
* - UUID/WorkOS ID validation prevents invalid references
|
|
10
|
+
* - String length limits prevent DoS
|
|
11
|
+
* - Domain and metadata size limits
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import { z } from 'zod'
|
|
15
|
+
import { UuidSchema } from '../../../platform/utils/validation'
|
|
16
|
+
|
|
17
|
+
// ============================================================================
|
|
18
|
+
// Shared Schemas
|
|
19
|
+
// ============================================================================
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Organization name validation
|
|
23
|
+
* - Alphanumeric, spaces, hyphens, underscores only
|
|
24
|
+
* - 2-100 characters
|
|
25
|
+
*
|
|
26
|
+
* Security: Prevents injection, DoS via long names
|
|
27
|
+
*/
|
|
28
|
+
export const OrganizationNameSchema = z
|
|
29
|
+
.string()
|
|
30
|
+
.min(2, 'Organization name must be at least 2 characters')
|
|
31
|
+
.max(100, 'Organization name must be at most 100 characters')
|
|
32
|
+
.trim()
|
|
33
|
+
.regex(
|
|
34
|
+
/^[a-zA-Z0-9\s\-_]+$/,
|
|
35
|
+
'Organization name must contain only letters, numbers, spaces, hyphens, and underscores'
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Organization ID validation
|
|
40
|
+
* Supports both UUID and WorkOS org_ prefixed IDs
|
|
41
|
+
*/
|
|
42
|
+
export const OrganizationIdSchema = z.union([
|
|
43
|
+
UuidSchema,
|
|
44
|
+
z.string().regex(/^org_[a-zA-Z0-9]+$/, 'Invalid WorkOS organization ID')
|
|
45
|
+
])
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Organization domain data schema
|
|
49
|
+
*/
|
|
50
|
+
export const OrganizationDomainSchema = z.object({
|
|
51
|
+
domain: z.string().min(3).max(255),
|
|
52
|
+
state: z.enum(['verified', 'pending', 'failed']).optional()
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
// ============================================================================
|
|
56
|
+
// Path Parameters
|
|
57
|
+
// ============================================================================
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Validate organization ID in URL path
|
|
61
|
+
* Used by: GET/PUT/DELETE /organizations/:id
|
|
62
|
+
*/
|
|
63
|
+
export const OrganizationIdParamSchema = z
|
|
64
|
+
.object({
|
|
65
|
+
id: OrganizationIdSchema
|
|
66
|
+
})
|
|
67
|
+
.strict()
|
|
68
|
+
|
|
69
|
+
// ============================================================================
|
|
70
|
+
// Request Bodies
|
|
71
|
+
// ============================================================================
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Create new organization
|
|
75
|
+
* POST /organizations
|
|
76
|
+
*
|
|
77
|
+
* Security:
|
|
78
|
+
* - Name format validated (alphanumeric + spaces + hyphens + underscores)
|
|
79
|
+
* - Domain array size limited (max 10)
|
|
80
|
+
* - Metadata size limited (10KB)
|
|
81
|
+
* - Strict mode prevents unknown field injection
|
|
82
|
+
*/
|
|
83
|
+
export const CreateOrganizationSchema = z
|
|
84
|
+
.object({
|
|
85
|
+
name: OrganizationNameSchema,
|
|
86
|
+
domainData: z.array(OrganizationDomainSchema).max(10).optional(),
|
|
87
|
+
metadata: z
|
|
88
|
+
.record(z.string(), z.unknown())
|
|
89
|
+
.refine((val) => JSON.stringify(val).length <= 10240, 'Metadata must be under 10KB')
|
|
90
|
+
.optional()
|
|
91
|
+
})
|
|
92
|
+
.strict()
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Update organization
|
|
96
|
+
* PUT /organizations/:id
|
|
97
|
+
*
|
|
98
|
+
* Security:
|
|
99
|
+
* - All fields optional (partial update)
|
|
100
|
+
* - Same validation as create
|
|
101
|
+
* - At least one field required (matches documented Update schema convention,
|
|
102
|
+
* see .claude/rules/core-package.md → "api-schemas.ts Pattern")
|
|
103
|
+
*/
|
|
104
|
+
export const UpdateOrganizationSchema = CreateOrganizationSchema.partial()
|
|
105
|
+
.strict()
|
|
106
|
+
.refine((data) => Object.keys(data).length > 0, {
|
|
107
|
+
message: 'At least one field (name, domainData, or metadata) must be provided'
|
|
108
|
+
})
|
|
109
|
+
|
|
110
|
+
// ============================================================================
|
|
111
|
+
// Query Parameters
|
|
112
|
+
// ============================================================================
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* List organizations with filters
|
|
116
|
+
* GET /organizations
|
|
117
|
+
*
|
|
118
|
+
* Security:
|
|
119
|
+
* - Limit bounded (prevents DoS)
|
|
120
|
+
* - WorkOS pagination cursors
|
|
121
|
+
*/
|
|
122
|
+
export const ListOrganizationsQuerySchema = z.object({
|
|
123
|
+
limit: z.coerce.number().int().min(1).max(100).default(20),
|
|
124
|
+
before: z.string().optional(), // WorkOS pagination cursor
|
|
125
|
+
after: z.string().optional() // WorkOS pagination cursor
|
|
126
|
+
})
|
|
127
|
+
|
|
128
|
+
// ============================================================================
|
|
129
|
+
// TypeScript Type Exports
|
|
130
|
+
// ============================================================================
|
|
131
|
+
|
|
132
|
+
// Export inferred types for use in route handlers
|
|
133
|
+
export type CreateOrganizationInput = z.infer<typeof CreateOrganizationSchema>
|
|
134
|
+
export type UpdateOrganizationInput = z.infer<typeof UpdateOrganizationSchema>
|
|
135
|
+
export type ListOrganizationsQuery = z.infer<typeof ListOrganizationsQuerySchema>
|
|
136
|
+
export type OrganizationIdParam = z.infer<typeof OrganizationIdParamSchema>
|
|
@@ -13,6 +13,7 @@ import {
|
|
|
13
13
|
AcqContactStatusSchema,
|
|
14
14
|
AcqEmailValidSchema,
|
|
15
15
|
AcqListResponseSchema,
|
|
16
|
+
BuildPlanSnapshotSchema,
|
|
16
17
|
CreateArtifactRequestSchema,
|
|
17
18
|
CreateCompanyRequestSchema,
|
|
18
19
|
CreateContactRequestSchema,
|
|
@@ -43,6 +44,7 @@ import {
|
|
|
43
44
|
UpdateListRequestSchema,
|
|
44
45
|
UpdateListStatusRequestSchema
|
|
45
46
|
} from './api-schemas'
|
|
47
|
+
import { createBuildPlanSnapshotFromTemplateId } from './build-templates'
|
|
46
48
|
|
|
47
49
|
// ---------------------------------------------------------------------------
|
|
48
50
|
// Helpers
|
|
@@ -416,6 +418,22 @@ describe('UpdateContactRequestSchema', () => {
|
|
|
416
418
|
)
|
|
417
419
|
})
|
|
418
420
|
|
|
421
|
+
it('accepts processingState keyed by the stage catalog', () => {
|
|
422
|
+
const result = UpdateContactRequestSchema.safeParse({
|
|
423
|
+
processingState: {
|
|
424
|
+
[LEAD_GEN_STAGE_CATALOG.verified.key]: {
|
|
425
|
+
status: 'no_result'
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
})
|
|
429
|
+
|
|
430
|
+
expect(result.success).toBe(true)
|
|
431
|
+
})
|
|
432
|
+
|
|
433
|
+
it('accepts deprecated pipelineStatus as a compatibility no-op', () => {
|
|
434
|
+
expect(UpdateContactRequestSchema.safeParse({ pipelineStatus: 'emailed' }).success).toBe(true)
|
|
435
|
+
})
|
|
436
|
+
|
|
419
437
|
it('rejects unknown top-level fields (strict mode)', () => {
|
|
420
438
|
expect(UpdateContactRequestSchema.safeParse({ firstName: 'Alice', unknown: 'x' }).success).toBe(false)
|
|
421
439
|
})
|
|
@@ -743,7 +761,7 @@ describe('DealDetailResponseSchema (forward-compat)', () => {
|
|
|
743
761
|
title: null,
|
|
744
762
|
headline: null,
|
|
745
763
|
linkedin_url: null,
|
|
746
|
-
|
|
764
|
+
processing_state: null,
|
|
747
765
|
enrichment_data: null,
|
|
748
766
|
company: null
|
|
749
767
|
}
|
|
@@ -881,6 +899,58 @@ describe('PipelineStageSchema', () => {
|
|
|
881
899
|
})
|
|
882
900
|
})
|
|
883
901
|
|
|
902
|
+
// ---------------------------------------------------------------------------
|
|
903
|
+
// BuildPlanSnapshotSchema
|
|
904
|
+
// ---------------------------------------------------------------------------
|
|
905
|
+
|
|
906
|
+
describe('BuildPlanSnapshotSchema', () => {
|
|
907
|
+
const validSnapshot = createBuildPlanSnapshotFromTemplateId('dtc-subscription-apollo-clickup')
|
|
908
|
+
|
|
909
|
+
it('accepts a snapshot generated from a prospecting build template', () => {
|
|
910
|
+
expect(validSnapshot).not.toBeNull()
|
|
911
|
+
expect(BuildPlanSnapshotSchema.safeParse(validSnapshot).success).toBe(true)
|
|
912
|
+
})
|
|
913
|
+
|
|
914
|
+
it('rejects a step stageKey outside LEAD_GEN_STAGE_CATALOG', () => {
|
|
915
|
+
const result = BuildPlanSnapshotSchema.safeParse({
|
|
916
|
+
...validSnapshot,
|
|
917
|
+
steps: [{ ...validSnapshot!.steps[0], stageKey: 'made-up-stage' }]
|
|
918
|
+
})
|
|
919
|
+
|
|
920
|
+
expect(result.success).toBe(false)
|
|
921
|
+
})
|
|
922
|
+
|
|
923
|
+
it('rejects a step capabilityKey outside CAPABILITY_REGISTRY', () => {
|
|
924
|
+
const result = BuildPlanSnapshotSchema.safeParse({
|
|
925
|
+
...validSnapshot,
|
|
926
|
+
steps: [{ ...validSnapshot!.steps[0], capabilityKey: 'lead-gen.missing.capability' }]
|
|
927
|
+
})
|
|
928
|
+
|
|
929
|
+
expect(result.success).toBe(false)
|
|
930
|
+
})
|
|
931
|
+
|
|
932
|
+
it('rejects duplicate step ids', () => {
|
|
933
|
+
const first = validSnapshot!.steps[0]!
|
|
934
|
+
const second = validSnapshot!.steps[1]!
|
|
935
|
+
const rest = validSnapshot!.steps.slice(2)
|
|
936
|
+
const result = BuildPlanSnapshotSchema.safeParse({
|
|
937
|
+
...validSnapshot,
|
|
938
|
+
steps: [first, { ...second, id: first.id }, ...rest]
|
|
939
|
+
})
|
|
940
|
+
|
|
941
|
+
expect(result.success).toBe(false)
|
|
942
|
+
})
|
|
943
|
+
|
|
944
|
+
it('rejects dependsOn references to unknown step ids', () => {
|
|
945
|
+
const result = BuildPlanSnapshotSchema.safeParse({
|
|
946
|
+
...validSnapshot,
|
|
947
|
+
steps: [{ ...validSnapshot!.steps[0], dependsOn: ['missing-step'] }]
|
|
948
|
+
})
|
|
949
|
+
|
|
950
|
+
expect(result.success).toBe(false)
|
|
951
|
+
})
|
|
952
|
+
})
|
|
953
|
+
|
|
884
954
|
// ---------------------------------------------------------------------------
|
|
885
955
|
// ScrapingConfigSchema
|
|
886
956
|
// ---------------------------------------------------------------------------
|
|
@@ -1255,6 +1325,33 @@ describe('UpdateCompanyRequestSchema', () => {
|
|
|
1255
1325
|
expect(UpdateCompanyRequestSchema.safeParse({ status: 'invalid' }).success).toBe(true)
|
|
1256
1326
|
})
|
|
1257
1327
|
|
|
1328
|
+
it('accepts processingState keyed by the stage catalog', () => {
|
|
1329
|
+
const result = UpdateCompanyRequestSchema.safeParse({
|
|
1330
|
+
processingState: {
|
|
1331
|
+
[LEAD_GEN_STAGE_CATALOG.qualified.key]: {
|
|
1332
|
+
status: 'success',
|
|
1333
|
+
data: { score: 92 }
|
|
1334
|
+
}
|
|
1335
|
+
}
|
|
1336
|
+
})
|
|
1337
|
+
|
|
1338
|
+
expect(result.success).toBe(true)
|
|
1339
|
+
})
|
|
1340
|
+
|
|
1341
|
+
it('accepts deprecated pipelineStatus as a compatibility no-op', () => {
|
|
1342
|
+
expect(UpdateCompanyRequestSchema.safeParse({ pipelineStatus: 'emailed' }).success).toBe(true)
|
|
1343
|
+
})
|
|
1344
|
+
|
|
1345
|
+
it('rejects processingState keys outside the stage catalog', () => {
|
|
1346
|
+
expect(
|
|
1347
|
+
UpdateCompanyRequestSchema.safeParse({
|
|
1348
|
+
processingState: {
|
|
1349
|
+
madeUpStage: { status: 'success' }
|
|
1350
|
+
}
|
|
1351
|
+
}).success
|
|
1352
|
+
).toBe(false)
|
|
1353
|
+
})
|
|
1354
|
+
|
|
1258
1355
|
it('accepts numEmployees of 0', () => {
|
|
1259
1356
|
expect(UpdateCompanyRequestSchema.safeParse({ numEmployees: 0 }).success).toBe(true)
|
|
1260
1357
|
})
|
|
@@ -1468,7 +1565,7 @@ describe('AcqContactResponseSchema (forward-compat)', () => {
|
|
|
1468
1565
|
openingLine: null,
|
|
1469
1566
|
source: null,
|
|
1470
1567
|
sourceId: null,
|
|
1471
|
-
|
|
1568
|
+
processingState: null,
|
|
1472
1569
|
enrichmentData: null,
|
|
1473
1570
|
attioPersonId: null,
|
|
1474
1571
|
batchId: null,
|
|
@@ -1488,4 +1585,5 @@ describe('AcqContactResponseSchema (forward-compat)', () => {
|
|
|
1488
1585
|
it('rejects an invalid emailValid value', () => {
|
|
1489
1586
|
expect(AcqContactResponseSchema.safeParse({ ...baseContact, emailValid: 'BAD' }).success).toBe(false)
|
|
1490
1587
|
})
|
|
1588
|
+
|
|
1491
1589
|
})
|
|
@@ -1,10 +1,36 @@
|
|
|
1
1
|
import { z } from 'zod'
|
|
2
2
|
import { UuidSchema, NonEmptyStringSchema } from '../../platform/utils/validation'
|
|
3
3
|
import { LEAD_GEN_STAGE_CATALOG } from '../../organization-model/domains/sales'
|
|
4
|
+
import { CAPABILITY_REGISTRY } from '../../organization-model/domains/prospecting'
|
|
4
5
|
import { isProspectingBuildTemplateId } from './build-templates'
|
|
5
6
|
export { CrmPriorityBucketKeySchema, CrmPriorityBucketOverrideSchema, CrmPriorityOverrideSchema } from './crm-priority'
|
|
6
7
|
export type { CrmPriorityBucketOverride, CrmPriorityOverride, ResolvedCrmPriorityRuleConfig } from './crm-priority'
|
|
7
8
|
|
|
9
|
+
export const ProcessingStageStatusSchema = z.enum(['success', 'no_result', 'skipped', 'error'])
|
|
10
|
+
|
|
11
|
+
export const LeadGenStageKeySchema = z
|
|
12
|
+
.string()
|
|
13
|
+
.refine((value) => Object.prototype.hasOwnProperty.call(LEAD_GEN_STAGE_CATALOG, value), {
|
|
14
|
+
message: 'processing state key must match LEAD_GEN_STAGE_CATALOG'
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
export const LeadGenCapabilityKeySchema = z
|
|
18
|
+
.string()
|
|
19
|
+
.refine((value) => Object.prototype.hasOwnProperty.call(CAPABILITY_REGISTRY, value), {
|
|
20
|
+
message: 'capabilityKey must match CAPABILITY_REGISTRY'
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
export const ProcessingStateEntrySchema = z
|
|
24
|
+
.object({
|
|
25
|
+
status: ProcessingStageStatusSchema,
|
|
26
|
+
data: z.unknown().optional()
|
|
27
|
+
})
|
|
28
|
+
.passthrough()
|
|
29
|
+
|
|
30
|
+
export const ProcessingStateSchema = z.record(LeadGenStageKeySchema, ProcessingStateEntrySchema)
|
|
31
|
+
export const CompanyProcessingStateSchema = ProcessingStateSchema
|
|
32
|
+
export const ContactProcessingStateSchema = ProcessingStateSchema
|
|
33
|
+
|
|
8
34
|
/**
|
|
9
35
|
* Deal Management API Schemas
|
|
10
36
|
*
|
|
@@ -132,7 +158,7 @@ export const DealContactSummarySchema = z.object({
|
|
|
132
158
|
title: z.string().nullable(),
|
|
133
159
|
headline: z.string().nullable(),
|
|
134
160
|
linkedin_url: z.string().nullable(),
|
|
135
|
-
|
|
161
|
+
processing_state: ProcessingStateSchema.nullable(),
|
|
136
162
|
enrichment_data: z.record(z.string(), z.unknown()).nullable(),
|
|
137
163
|
company: z
|
|
138
164
|
.object({
|
|
@@ -442,10 +468,10 @@ export const BuildPlanSnapshotStepSchema = z
|
|
|
442
468
|
description: z.string().trim().min(1).max(2000).optional(),
|
|
443
469
|
primaryEntity: z.enum(['company', 'contact']),
|
|
444
470
|
outputs: z.array(z.enum(['company', 'contact', 'export'])).min(1),
|
|
445
|
-
stageKey:
|
|
471
|
+
stageKey: LeadGenStageKeySchema,
|
|
446
472
|
dependsOn: z.array(z.string().trim().min(1).max(100)).optional(),
|
|
447
473
|
dependencyMode: z.literal('per-record-eligibility'),
|
|
448
|
-
capabilityKey:
|
|
474
|
+
capabilityKey: LeadGenCapabilityKeySchema,
|
|
449
475
|
defaultBatchSize: z.number().int().positive(),
|
|
450
476
|
maxBatchSize: z.number().int().positive()
|
|
451
477
|
})
|
|
@@ -454,11 +480,38 @@ export const BuildPlanSnapshotStepSchema = z
|
|
|
454
480
|
path: ['defaultBatchSize']
|
|
455
481
|
})
|
|
456
482
|
|
|
457
|
-
export const BuildPlanSnapshotSchema = z
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
483
|
+
export const BuildPlanSnapshotSchema = z
|
|
484
|
+
.object({
|
|
485
|
+
templateId: z.string().trim().min(1).max(100),
|
|
486
|
+
templateLabel: z.string().trim().min(1).max(120),
|
|
487
|
+
steps: z.array(BuildPlanSnapshotStepSchema).min(1)
|
|
488
|
+
})
|
|
489
|
+
.superRefine((snapshot, ctx) => {
|
|
490
|
+
const stepIds = new Set<string>()
|
|
491
|
+
|
|
492
|
+
snapshot.steps.forEach((step, index) => {
|
|
493
|
+
if (stepIds.has(step.id)) {
|
|
494
|
+
ctx.addIssue({
|
|
495
|
+
code: z.ZodIssueCode.custom,
|
|
496
|
+
message: `duplicate build-plan step id "${step.id}"`,
|
|
497
|
+
path: ['steps', index, 'id']
|
|
498
|
+
})
|
|
499
|
+
}
|
|
500
|
+
stepIds.add(step.id)
|
|
501
|
+
})
|
|
502
|
+
|
|
503
|
+
snapshot.steps.forEach((step, index) => {
|
|
504
|
+
for (const dependencyId of step.dependsOn ?? []) {
|
|
505
|
+
if (!stepIds.has(dependencyId)) {
|
|
506
|
+
ctx.addIssue({
|
|
507
|
+
code: z.ZodIssueCode.custom,
|
|
508
|
+
message: `dependsOn references unknown build-plan step "${dependencyId}"`,
|
|
509
|
+
path: ['steps', index, 'dependsOn']
|
|
510
|
+
})
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
})
|
|
514
|
+
})
|
|
462
515
|
|
|
463
516
|
export const AcqListMetadataSchema = z
|
|
464
517
|
.object({
|
|
@@ -638,13 +691,6 @@ export const ListTelemetryResponseSchema = ListTelemetrySchema
|
|
|
638
691
|
|
|
639
692
|
export const ListTelemetryListResponseSchema = z.array(ListTelemetrySchema)
|
|
640
693
|
|
|
641
|
-
/**
|
|
642
|
-
* Terminal row-level status for one lead-gen processing stage.
|
|
643
|
-
* Missing key still means not attempted; legacy boolean `true` is normalized
|
|
644
|
-
* to `success` by the API reader during rollout.
|
|
645
|
-
*/
|
|
646
|
-
export const ProcessingStageStatusSchema = z.enum(['success', 'no_result', 'skipped', 'error'])
|
|
647
|
-
|
|
648
694
|
/**
|
|
649
695
|
* Per-stage progress aggregate for a single pipeline stage.
|
|
650
696
|
* `attempted` counts terminal statuses, including success, no-result, skipped,
|
|
@@ -704,29 +750,6 @@ export const AcqCompanyStatusSchema = z.enum(['active', 'invalid'])
|
|
|
704
750
|
export const AcqContactStatusSchema = z.enum(['active', 'invalid'])
|
|
705
751
|
export const AcqEmailValidSchema = z.enum(['VALID', 'INVALID', 'RISKY', 'UNKNOWN'])
|
|
706
752
|
|
|
707
|
-
/**
|
|
708
|
-
* Zod schema mirroring the CompanyPipelineStatus interface from types.ts.
|
|
709
|
-
* Used by operations-layer CompanyRecord schemas to validate pipelineStatus
|
|
710
|
-
* against the canonical shape instead of using open passthrough().
|
|
711
|
-
*/
|
|
712
|
-
export const CompanyPipelineStatusSchema = z
|
|
713
|
-
.object({
|
|
714
|
-
acquired: z.boolean().optional(),
|
|
715
|
-
enrichment: z
|
|
716
|
-
.record(
|
|
717
|
-
z.string(),
|
|
718
|
-
z
|
|
719
|
-
.object({
|
|
720
|
-
status: z.enum(['pending', 'complete', 'failed', 'skipped']),
|
|
721
|
-
completedAt: z.string().optional(),
|
|
722
|
-
error: z.string().optional()
|
|
723
|
-
})
|
|
724
|
-
.passthrough()
|
|
725
|
-
)
|
|
726
|
-
.optional()
|
|
727
|
-
})
|
|
728
|
-
.passthrough()
|
|
729
|
-
|
|
730
753
|
export const CompanyIdParamsSchema = z.object({
|
|
731
754
|
companyId: UuidSchema
|
|
732
755
|
})
|
|
@@ -743,6 +766,7 @@ export const ListCompaniesQuerySchema = z
|
|
|
743
766
|
website: z.string().trim().min(1).max(2048).optional(),
|
|
744
767
|
segment: z.string().trim().min(1).max(255).optional(),
|
|
745
768
|
category: z.string().trim().min(1).max(255).optional(),
|
|
769
|
+
pipelineStatus: z.unknown().optional(),
|
|
746
770
|
batchId: z.string().trim().min(1).max(255).optional(),
|
|
747
771
|
status: AcqCompanyStatusSchema.optional(),
|
|
748
772
|
includeAll: QueryBooleanSchema.optional(),
|
|
@@ -776,6 +800,7 @@ export const CreateCompanyRequestSchema = z
|
|
|
776
800
|
category: z.string().trim().min(1).max(255).optional(),
|
|
777
801
|
source: z.string().trim().min(1).max(255).optional(),
|
|
778
802
|
batchId: z.string().trim().min(1).max(255).optional(),
|
|
803
|
+
pipelineStatus: z.unknown().optional(),
|
|
779
804
|
verticalResearch: z.string().trim().min(1).max(5000).optional()
|
|
780
805
|
})
|
|
781
806
|
.strict()
|
|
@@ -792,7 +817,8 @@ export const UpdateCompanyRequestSchema = z
|
|
|
792
817
|
locationState: z.string().trim().min(1).max(255).optional(),
|
|
793
818
|
category: z.string().trim().min(1).max(255).optional(),
|
|
794
819
|
segment: z.string().trim().min(1).max(255).optional(),
|
|
795
|
-
|
|
820
|
+
processingState: CompanyProcessingStateSchema.optional(),
|
|
821
|
+
pipelineStatus: z.unknown().optional(),
|
|
796
822
|
enrichmentData: z.record(z.string(), z.unknown()).optional(),
|
|
797
823
|
source: z.string().trim().min(1).max(255).optional(),
|
|
798
824
|
batchId: z.string().trim().min(1).max(255).optional(),
|
|
@@ -812,6 +838,7 @@ export const UpdateCompanyRequestSchema = z
|
|
|
812
838
|
data.locationState !== undefined ||
|
|
813
839
|
data.category !== undefined ||
|
|
814
840
|
data.segment !== undefined ||
|
|
841
|
+
data.processingState !== undefined ||
|
|
815
842
|
data.pipelineStatus !== undefined ||
|
|
816
843
|
data.enrichmentData !== undefined ||
|
|
817
844
|
data.source !== undefined ||
|
|
@@ -833,7 +860,8 @@ export const CreateContactRequestSchema = z
|
|
|
833
860
|
title: z.string().trim().min(1).max(255).optional(),
|
|
834
861
|
source: z.string().trim().min(1).max(255).optional(),
|
|
835
862
|
sourceId: z.string().trim().min(1).max(255).optional(),
|
|
836
|
-
batchId: z.string().trim().min(1).max(255).optional()
|
|
863
|
+
batchId: z.string().trim().min(1).max(255).optional(),
|
|
864
|
+
pipelineStatus: z.unknown().optional()
|
|
837
865
|
})
|
|
838
866
|
.strict()
|
|
839
867
|
|
|
@@ -848,7 +876,8 @@ export const UpdateContactRequestSchema = z
|
|
|
848
876
|
headline: z.string().trim().min(1).max(5000).optional(),
|
|
849
877
|
filterReason: z.string().trim().min(1).max(5000).optional(),
|
|
850
878
|
openingLine: z.string().trim().min(1).max(5000).optional(),
|
|
851
|
-
|
|
879
|
+
processingState: ContactProcessingStateSchema.optional(),
|
|
880
|
+
pipelineStatus: z.unknown().optional(),
|
|
852
881
|
enrichmentData: z.record(z.string(), z.unknown()).optional(),
|
|
853
882
|
status: AcqContactStatusSchema.optional()
|
|
854
883
|
})
|
|
@@ -864,6 +893,7 @@ export const UpdateContactRequestSchema = z
|
|
|
864
893
|
data.headline !== undefined ||
|
|
865
894
|
data.filterReason !== undefined ||
|
|
866
895
|
data.openingLine !== undefined ||
|
|
896
|
+
data.processingState !== undefined ||
|
|
867
897
|
data.pipelineStatus !== undefined ||
|
|
868
898
|
data.enrichmentData !== undefined ||
|
|
869
899
|
data.status !== undefined,
|
|
@@ -886,7 +916,8 @@ export const AcqCompanyResponseSchema = z.object({
|
|
|
886
916
|
category: z.string().nullable(),
|
|
887
917
|
categoryPain: z.string().nullable(),
|
|
888
918
|
segment: z.string().nullable(),
|
|
889
|
-
|
|
919
|
+
processingState: CompanyProcessingStateSchema.nullable(),
|
|
920
|
+
pipelineStatus: z.unknown().nullable().optional(),
|
|
890
921
|
enrichmentData: z.record(z.string(), z.unknown()).nullable(),
|
|
891
922
|
source: z.string().nullable(),
|
|
892
923
|
batchId: z.string().nullable(),
|
|
@@ -936,7 +967,8 @@ export const AcqContactResponseSchema = z.object({
|
|
|
936
967
|
openingLine: z.string().nullable(),
|
|
937
968
|
source: z.string().nullable(),
|
|
938
969
|
sourceId: z.string().nullable(),
|
|
939
|
-
|
|
970
|
+
processingState: ContactProcessingStateSchema.nullable(),
|
|
971
|
+
pipelineStatus: z.unknown().nullable().optional(),
|
|
940
972
|
enrichmentData: z.record(z.string(), z.unknown()).nullable(),
|
|
941
973
|
attioPersonId: z.string().nullable(),
|
|
942
974
|
batchId: z.string().nullable(),
|
|
@@ -1063,6 +1095,7 @@ export const AcqListCompanyResponseSchema = z.object({
|
|
|
1063
1095
|
// ---------------------------------------------------------------------------
|
|
1064
1096
|
|
|
1065
1097
|
export const AcqCompanySchemas = {
|
|
1098
|
+
CompanyProcessingState: CompanyProcessingStateSchema,
|
|
1066
1099
|
CompanyIdParams: CompanyIdParamsSchema,
|
|
1067
1100
|
ListCompaniesQuery: ListCompaniesQuerySchema,
|
|
1068
1101
|
CreateCompanyRequest: CreateCompanyRequestSchema,
|
|
@@ -1073,6 +1106,7 @@ export const AcqCompanySchemas = {
|
|
|
1073
1106
|
}
|
|
1074
1107
|
|
|
1075
1108
|
export const AcqContactSchemas = {
|
|
1109
|
+
ContactProcessingState: ContactProcessingStateSchema,
|
|
1076
1110
|
ContactIdParams: ContactIdParamsSchema,
|
|
1077
1111
|
ListContactsQuery: ListContactsQuerySchema,
|
|
1078
1112
|
CreateContactRequest: CreateContactRequestSchema,
|
|
@@ -1116,7 +1150,10 @@ export const AcqListSchemas = {
|
|
|
1116
1150
|
BuildPlanSnapshot: BuildPlanSnapshotSchema,
|
|
1117
1151
|
BuildPlanSnapshotStep: BuildPlanSnapshotStepSchema,
|
|
1118
1152
|
AcqListMetadata: AcqListMetadataSchema,
|
|
1153
|
+
LeadGenStageKey: LeadGenStageKeySchema,
|
|
1154
|
+
LeadGenCapabilityKey: LeadGenCapabilityKeySchema,
|
|
1119
1155
|
ProcessingStageStatus: ProcessingStageStatusSchema,
|
|
1156
|
+
ProcessingState: ProcessingStateSchema,
|
|
1120
1157
|
ListStageCounts: ListStageCountsSchema,
|
|
1121
1158
|
ListTelemetry: ListTelemetrySchema,
|
|
1122
1159
|
|
|
@@ -1195,6 +1232,7 @@ export type PipelineConfig = z.infer<typeof PipelineConfigSchema>
|
|
|
1195
1232
|
export type BuildPlanSnapshotStep = z.infer<typeof BuildPlanSnapshotStepSchema>
|
|
1196
1233
|
export type BuildPlanSnapshot = z.infer<typeof BuildPlanSnapshotSchema>
|
|
1197
1234
|
export type AcqListMetadata = z.infer<typeof AcqListMetadataSchema>
|
|
1235
|
+
export type LeadGenCapabilityKey = z.infer<typeof LeadGenCapabilityKeySchema>
|
|
1198
1236
|
export type ProcessingStageStatus = z.infer<typeof ProcessingStageStatusSchema>
|
|
1199
1237
|
export type ListStageCountsInput = z.infer<typeof ListStageCountsSchema>['stageCounts']
|
|
1200
1238
|
export type ListTelemetryInput = z.infer<typeof ListTelemetrySchema>
|