@elevasis/core 0.21.0 → 0.23.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 +2518 -2169
- package/dist/index.js +2495 -1095
- package/dist/knowledge/index.d.ts +706 -1044
- package/dist/knowledge/index.js +9 -9
- package/dist/organization-model/index.d.ts +2518 -2169
- package/dist/organization-model/index.js +2495 -1095
- package/dist/test-utils/index.d.ts +826 -1014
- package/dist/test-utils/index.js +1894 -1032
- package/package.json +3 -3
- package/src/__tests__/template-core-compatibility.test.ts +11 -79
- package/src/_gen/__tests__/__snapshots__/contracts.md.snap +852 -397
- package/src/auth/multi-tenancy/permissions.ts +20 -8
- package/src/business/README.md +2 -2
- package/src/business/acquisition/api-schemas.test.ts +175 -2
- package/src/business/acquisition/api-schemas.ts +132 -16
- package/src/business/acquisition/build-templates.test.ts +4 -4
- package/src/business/acquisition/build-templates.ts +72 -30
- package/src/business/acquisition/crm-state-actions.test.ts +13 -11
- package/src/business/acquisition/index.ts +12 -0
- package/src/business/acquisition/types.ts +7 -3
- package/src/business/clients/api-schemas.test.ts +115 -0
- package/src/business/clients/api-schemas.ts +158 -0
- package/src/business/clients/index.ts +1 -0
- package/src/business/deals/api-schemas.ts +8 -0
- package/src/business/index.ts +5 -2
- package/src/business/projects/types.ts +19 -0
- package/src/execution/engine/__tests__/fixtures/test-agents.ts +10 -8
- package/src/execution/engine/agent/core/__tests__/agent.test.ts +16 -12
- package/src/execution/engine/agent/core/__tests__/error-passthrough.test.ts +4 -3
- package/src/execution/engine/agent/core/types.ts +25 -15
- package/src/execution/engine/agent/index.ts +6 -4
- package/src/execution/engine/agent/reasoning/__tests__/request-builder.test.ts +24 -18
- package/src/execution/engine/index.ts +3 -0
- package/src/execution/engine/workflow/types.ts +9 -2
- package/src/knowledge/README.md +8 -7
- package/src/knowledge/__tests__/queries.test.ts +74 -73
- package/src/knowledge/format.ts +10 -9
- package/src/knowledge/index.ts +1 -1
- package/src/knowledge/published.ts +1 -1
- package/src/knowledge/queries.ts +26 -25
- package/src/organization-model/README.md +73 -26
- package/src/organization-model/__tests__/content-kinds-registry.test.ts +210 -0
- package/src/organization-model/__tests__/defaults.test.ts +76 -96
- package/src/organization-model/__tests__/domains/actions.test.ts +56 -0
- package/src/organization-model/__tests__/domains/customers.test.ts +299 -295
- package/src/organization-model/__tests__/domains/entities.test.ts +56 -0
- package/src/organization-model/__tests__/domains/goals.test.ts +493 -479
- package/src/organization-model/__tests__/domains/identity.test.ts +280 -279
- package/src/organization-model/__tests__/domains/navigation.test.ts +268 -212
- package/src/organization-model/__tests__/domains/offerings.test.ts +414 -419
- package/src/organization-model/__tests__/domains/policies.test.ts +323 -0
- package/src/organization-model/__tests__/domains/resource-mappings.test.ts +271 -271
- package/src/organization-model/__tests__/domains/resources.test.ts +310 -0
- package/src/organization-model/__tests__/domains/roles.test.ts +463 -347
- package/src/organization-model/__tests__/domains/statuses.test.ts +246 -243
- package/src/organization-model/__tests__/domains/systems.test.ts +209 -0
- package/src/organization-model/__tests__/flatten-additive-merge.test.ts +361 -0
- package/src/organization-model/__tests__/foundation.test.ts +74 -102
- package/src/organization-model/__tests__/get-resources-for-system.test.ts +144 -0
- package/src/organization-model/__tests__/graph.test.ts +899 -71
- package/src/organization-model/__tests__/knowledge.test.ts +209 -49
- package/src/organization-model/__tests__/lookup-helpers.test.ts +438 -0
- package/src/organization-model/__tests__/migration-helpers.test.ts +591 -0
- package/src/organization-model/__tests__/prospecting-ssot.test.ts +36 -27
- package/src/organization-model/__tests__/recursive-system-schema.test.ts +520 -0
- package/src/organization-model/__tests__/resolve.test.ts +174 -23
- package/src/organization-model/__tests__/schema.test.ts +291 -114
- package/src/organization-model/__tests__/surface-projection.test.ts +207 -97
- package/src/organization-model/catalogs/lead-gen.ts +144 -0
- package/src/organization-model/content-kinds/config.ts +36 -0
- package/src/organization-model/content-kinds/index.ts +74 -0
- package/src/organization-model/content-kinds/pipeline.ts +68 -0
- package/src/organization-model/content-kinds/registry.ts +44 -0
- package/src/organization-model/content-kinds/status.ts +71 -0
- package/src/organization-model/content-kinds/template.ts +83 -0
- package/src/organization-model/content-kinds/types.ts +117 -0
- package/src/organization-model/contracts.ts +13 -3
- package/src/organization-model/defaults.ts +499 -86
- package/src/organization-model/domains/actions.ts +239 -0
- package/src/organization-model/domains/customers.ts +78 -75
- package/src/organization-model/domains/entities.ts +144 -0
- package/src/organization-model/domains/goals.ts +83 -80
- package/src/organization-model/domains/knowledge.ts +76 -17
- package/src/organization-model/domains/navigation.ts +107 -384
- package/src/organization-model/domains/offerings.ts +71 -66
- package/src/organization-model/domains/policies.ts +102 -0
- package/src/organization-model/domains/projects.ts +14 -48
- package/src/organization-model/domains/prospecting.ts +62 -181
- package/src/organization-model/domains/resources.ts +145 -0
- package/src/organization-model/domains/roles.ts +96 -55
- package/src/organization-model/domains/sales.ts +10 -219
- package/src/organization-model/domains/shared.ts +57 -57
- package/src/organization-model/domains/statuses.ts +339 -130
- package/src/organization-model/domains/systems.ts +203 -0
- package/src/organization-model/foundation.ts +54 -67
- package/src/organization-model/graph/build.ts +682 -54
- package/src/organization-model/graph/link.ts +1 -1
- package/src/organization-model/graph/schema.ts +24 -9
- package/src/organization-model/graph/types.ts +20 -7
- package/src/organization-model/helpers.ts +231 -26
- package/src/organization-model/icons.ts +1 -0
- package/src/organization-model/index.ts +118 -5
- package/src/organization-model/migration-helpers.ts +249 -0
- package/src/organization-model/organization-graph.mdx +16 -15
- package/src/organization-model/organization-model.mdx +111 -44
- package/src/organization-model/published.ts +172 -19
- package/src/organization-model/resolve.ts +117 -54
- package/src/organization-model/schema.ts +654 -112
- package/src/organization-model/surface-projection.ts +116 -122
- package/src/organization-model/types.ts +146 -20
- package/src/platform/api/types.ts +38 -35
- package/src/platform/constants/versions.ts +1 -1
- package/src/platform/registry/__tests__/command-view.test.ts +6 -8
- package/src/platform/registry/__tests__/resource-link.test.ts +13 -8
- package/src/platform/registry/__tests__/resource-registry.integration.test.ts +16 -31
- package/src/platform/registry/__tests__/resource-registry.nested-systems.test.ts +245 -0
- package/src/platform/registry/__tests__/resource-registry.test.ts +2053 -2005
- package/src/platform/registry/__tests__/validation.test.ts +1347 -1086
- package/src/platform/registry/index.ts +14 -0
- package/src/platform/registry/resource-registry.ts +52 -2
- package/src/platform/registry/serialization.ts +241 -202
- package/src/platform/registry/serialized-types.ts +1 -0
- package/src/platform/registry/types.ts +411 -361
- package/src/platform/registry/validation.ts +745 -513
- package/src/projects/api-schemas.ts +290 -267
- package/src/reference/_generated/contracts.md +853 -397
- package/src/reference/glossary.md +23 -18
- package/src/supabase/database.types.ts +181 -0
- package/src/test-utils/test-utils.test.ts +1 -6
- package/src/organization-model/__tests__/domains/operations.test.ts +0 -203
- package/src/organization-model/domains/features.ts +0 -31
- package/src/organization-model/domains/operations.ts +0 -85
|
@@ -6,13 +6,18 @@
|
|
|
6
6
|
* - API middleware (via requireOrganizationPermission(key))
|
|
7
7
|
* - UI hooks (via useOrganizationPermissions().hasPermission(key))
|
|
8
8
|
*
|
|
9
|
-
* The DB table `org_rol_permissions` mirrors this constant.
|
|
10
|
-
*
|
|
11
|
-
*
|
|
9
|
+
* The DB table `org_rol_permissions` mirrors this constant. There is no
|
|
10
|
+
* runtime reconciler; parity is enforced two ways:
|
|
11
|
+
* 1. Each migration that adds/removes/modifies a permission must INSERT
|
|
12
|
+
* (or UPDATE / DELETE) the corresponding `org_rol_permissions` row in
|
|
13
|
+
* the same transaction.
|
|
14
|
+
* 2. `apps/api/src/auth/multi-tenancy/__tests__/permissions-catalog-sync.integration.test.ts`
|
|
15
|
+
* asserts the TS catalog and the DB rows agree; CI fails on drift.
|
|
12
16
|
*
|
|
13
17
|
* Adding a permission:
|
|
14
18
|
* 1. Add an entry below.
|
|
15
|
-
* 2. Add a row to the migration
|
|
19
|
+
* 2. Add a row to the migration (INSERT INTO org_rol_permissions ...) in
|
|
20
|
+
* the same transaction as any policies/grants that reference the key.
|
|
16
21
|
* 3. Reference it in RLS / middleware as needed.
|
|
17
22
|
* 4. Optionally grant it to one or more system roles in org_rol_grants.
|
|
18
23
|
*
|
|
@@ -30,15 +35,17 @@ export const PERMISSIONS = {
|
|
|
30
35
|
OPERATIONS_READ: 'operations.read',
|
|
31
36
|
OPERATIONS_MANAGE: 'operations.manage',
|
|
32
37
|
ACQUISITION_MANAGE: 'acquisition.manage',
|
|
33
|
-
PROJECTS_MANAGE: 'projects.manage'
|
|
38
|
+
PROJECTS_MANAGE: 'projects.manage',
|
|
39
|
+
CLIENTS_MANAGE: 'clients.manage'
|
|
34
40
|
} as const
|
|
35
41
|
|
|
36
42
|
export type PermissionKey = (typeof PERMISSIONS)[keyof typeof PERMISSIONS]
|
|
37
43
|
|
|
38
44
|
/**
|
|
39
|
-
* Static metadata for each permission. Mirrored into org_rol_permissions
|
|
40
|
-
*
|
|
41
|
-
*
|
|
45
|
+
* Static metadata for each permission. Mirrored into org_rol_permissions by
|
|
46
|
+
* a migration `INSERT` in the same transaction as any change to this catalog.
|
|
47
|
+
* is_org_grantable=false means the permission is reserved to system roles
|
|
48
|
+
* only — custom roles cannot include it (privilege-escalation guard).
|
|
42
49
|
*/
|
|
43
50
|
export interface PermissionDescriptor {
|
|
44
51
|
key: PermissionKey
|
|
@@ -97,6 +104,11 @@ export const PERMISSION_CATALOG: readonly PermissionDescriptor[] = [
|
|
|
97
104
|
key: 'projects.manage',
|
|
98
105
|
description: 'Create, update, and delete project records (prj_projects, prj_milestones, prj_tasks, prj_notes)',
|
|
99
106
|
isOrgGrantable: false
|
|
107
|
+
},
|
|
108
|
+
{
|
|
109
|
+
key: 'clients.manage',
|
|
110
|
+
description: 'Create, update, and delete client hub records (clients, clt_* satellites)',
|
|
111
|
+
isOrgGrantable: false
|
|
100
112
|
}
|
|
101
113
|
] as const
|
|
102
114
|
|
package/src/business/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Published base entity contracts for the Elevasis platform. Each entity ships as a TypeScript interface, a matching Zod schema, and an inferred `Input` type, generic over a `<TMeta>` extension slot.
|
|
4
4
|
|
|
5
|
-
External projects extend these in `
|
|
5
|
+
External projects extend these in `core/types/entities.ts` to attach project-specific metadata while keeping the canonical shape stable.
|
|
6
6
|
|
|
7
7
|
## Published Exports
|
|
8
8
|
|
|
@@ -49,4 +49,4 @@ export type Deal = BaseDeal
|
|
|
49
49
|
|
|
50
50
|
The full pattern is documented in the SDK scaffold bundle: `node_modules/@elevasis/sdk/reference/scaffold/recipes/extend-a-base-entity.md`.
|
|
51
51
|
|
|
52
|
-
The canonical template demo lives at `external/_template/
|
|
52
|
+
The canonical template demo lives at `external/_template/core/types/entities.ts`.
|
|
@@ -10,10 +10,12 @@ import {
|
|
|
10
10
|
AddCompaniesToListRequestSchema,
|
|
11
11
|
AddContactsToListRequestSchema,
|
|
12
12
|
AcqArtifactOwnerKindSchema,
|
|
13
|
+
AcqListDetailResponseSchema,
|
|
13
14
|
AcqContactResponseSchema,
|
|
14
15
|
AcqContactStatusSchema,
|
|
15
16
|
AcqEmailValidSchema,
|
|
16
17
|
AcqListResponseSchema,
|
|
18
|
+
AcqListStatusResponseSchema,
|
|
17
19
|
BuildPlanSnapshotSchema,
|
|
18
20
|
CreateArtifactRequestSchema,
|
|
19
21
|
CreateCompanyRequestSchema,
|
|
@@ -32,12 +34,14 @@ import {
|
|
|
32
34
|
DealTaskResponseSchema,
|
|
33
35
|
ExecuteActionRequestSchema,
|
|
34
36
|
IcpRubricSchema,
|
|
37
|
+
GetListQuerySchema,
|
|
35
38
|
ListArtifactsQuerySchema,
|
|
36
39
|
ListCompaniesQuerySchema,
|
|
37
40
|
ListContactsQuerySchema,
|
|
38
41
|
ListDealsQuerySchema,
|
|
39
42
|
ListDealTasksDueQuerySchema,
|
|
40
43
|
ListMembersQuerySchema,
|
|
44
|
+
ListReadQuerySchema,
|
|
41
45
|
ListRecordsQuerySchema,
|
|
42
46
|
ListStatusSchema,
|
|
43
47
|
PipelineStageSchema,
|
|
@@ -857,6 +861,24 @@ describe('DealDetailResponseSchema (forward-compat)', () => {
|
|
|
857
861
|
expect(DealDetailResponseSchema.safeParse(withContact).success).toBe(true)
|
|
858
862
|
})
|
|
859
863
|
|
|
864
|
+
it('accepts thin client lineage refs on deal detail responses', () => {
|
|
865
|
+
expect(
|
|
866
|
+
DealDetailResponseSchema.safeParse({
|
|
867
|
+
...baseDeal,
|
|
868
|
+
client_id: VALID_UUID,
|
|
869
|
+
lineage: {
|
|
870
|
+
list: null,
|
|
871
|
+
projects: [],
|
|
872
|
+
client: {
|
|
873
|
+
id: VALID_UUID,
|
|
874
|
+
name: 'Acme Client',
|
|
875
|
+
status: 'active'
|
|
876
|
+
}
|
|
877
|
+
}
|
|
878
|
+
}).success
|
|
879
|
+
).toBe(true)
|
|
880
|
+
})
|
|
881
|
+
|
|
860
882
|
it('accepts extra unknown fields at top level (not strict)', () => {
|
|
861
883
|
expect(DealDetailResponseSchema.safeParse({ ...baseDeal, futureField: 'value' }).success).toBe(true)
|
|
862
884
|
})
|
|
@@ -1008,10 +1030,10 @@ describe('BuildPlanSnapshotSchema', () => {
|
|
|
1008
1030
|
expect(result.success).toBe(false)
|
|
1009
1031
|
})
|
|
1010
1032
|
|
|
1011
|
-
it('rejects a step
|
|
1033
|
+
it('rejects a step actionKey outside ACTION_REGISTRY', () => {
|
|
1012
1034
|
const result = BuildPlanSnapshotSchema.safeParse({
|
|
1013
1035
|
...validSnapshot,
|
|
1014
|
-
steps: [{ ...validSnapshot!.steps[0],
|
|
1036
|
+
steps: [{ ...validSnapshot!.steps[0], actionKey: 'lead-gen.missing.action' }]
|
|
1015
1037
|
})
|
|
1016
1038
|
|
|
1017
1039
|
expect(result.success).toBe(false)
|
|
@@ -1602,6 +1624,67 @@ describe('ListMembersQuerySchema', () => {
|
|
|
1602
1624
|
})
|
|
1603
1625
|
})
|
|
1604
1626
|
|
|
1627
|
+
// ---------------------------------------------------------------------------
|
|
1628
|
+
// ListReadQuerySchema
|
|
1629
|
+
// ---------------------------------------------------------------------------
|
|
1630
|
+
|
|
1631
|
+
describe('ListReadQuerySchema', () => {
|
|
1632
|
+
it('accepts SDK list filters and coerces pagination', () => {
|
|
1633
|
+
const result = ListReadQuerySchema.safeParse({
|
|
1634
|
+
status: 'launched',
|
|
1635
|
+
batch: 'batch-2026-05',
|
|
1636
|
+
vertical: 'veterinary',
|
|
1637
|
+
limit: '25',
|
|
1638
|
+
offset: '50'
|
|
1639
|
+
})
|
|
1640
|
+
|
|
1641
|
+
expect(result.success).toBe(true)
|
|
1642
|
+
if (result.success) {
|
|
1643
|
+
expect(result.data).toMatchObject({ limit: 25, offset: 50 })
|
|
1644
|
+
}
|
|
1645
|
+
})
|
|
1646
|
+
|
|
1647
|
+
it('keeps pagination optional for backward-compatible list reads', () => {
|
|
1648
|
+
expect(ListReadQuerySchema.safeParse({}).success).toBe(true)
|
|
1649
|
+
})
|
|
1650
|
+
|
|
1651
|
+
it('rejects unknown fields (strict mode)', () => {
|
|
1652
|
+
expect(ListReadQuerySchema.safeParse({ includeDeals: true }).success).toBe(false)
|
|
1653
|
+
})
|
|
1654
|
+
})
|
|
1655
|
+
|
|
1656
|
+
// ---------------------------------------------------------------------------
|
|
1657
|
+
// GetListQuerySchema
|
|
1658
|
+
// ---------------------------------------------------------------------------
|
|
1659
|
+
|
|
1660
|
+
describe('GetListQuerySchema', () => {
|
|
1661
|
+
it('defaults to thin deal refs and omits progress unless requested', () => {
|
|
1662
|
+
const result = GetListQuerySchema.safeParse({})
|
|
1663
|
+
|
|
1664
|
+
expect(result.success).toBe(true)
|
|
1665
|
+
if (result.success) {
|
|
1666
|
+
expect(result.data).toEqual({ includeDeals: true, includeProgress: false, dealLimit: 25 })
|
|
1667
|
+
}
|
|
1668
|
+
})
|
|
1669
|
+
|
|
1670
|
+
it('coerces boolean include flags from query strings', () => {
|
|
1671
|
+
const result = GetListQuerySchema.safeParse({
|
|
1672
|
+
includeDeals: 'false',
|
|
1673
|
+
includeProgress: 'true',
|
|
1674
|
+
dealLimit: '10'
|
|
1675
|
+
})
|
|
1676
|
+
|
|
1677
|
+
expect(result.success).toBe(true)
|
|
1678
|
+
if (result.success) {
|
|
1679
|
+
expect(result.data).toEqual({ includeDeals: false, includeProgress: true, dealLimit: 10 })
|
|
1680
|
+
}
|
|
1681
|
+
})
|
|
1682
|
+
|
|
1683
|
+
it('rejects unknown fields (strict mode)', () => {
|
|
1684
|
+
expect(GetListQuerySchema.safeParse({ depth: 2 }).success).toBe(false)
|
|
1685
|
+
})
|
|
1686
|
+
})
|
|
1687
|
+
|
|
1605
1688
|
// ---------------------------------------------------------------------------
|
|
1606
1689
|
// ListRecordsQuerySchema
|
|
1607
1690
|
// ---------------------------------------------------------------------------
|
|
@@ -1657,6 +1740,96 @@ describe('AcqListResponseSchema (forward-compat)', () => {
|
|
|
1657
1740
|
})
|
|
1658
1741
|
})
|
|
1659
1742
|
|
|
1743
|
+
// ---------------------------------------------------------------------------
|
|
1744
|
+
// AcqListDetailResponseSchema
|
|
1745
|
+
// ---------------------------------------------------------------------------
|
|
1746
|
+
|
|
1747
|
+
describe('AcqListDetailResponseSchema', () => {
|
|
1748
|
+
const baseList = {
|
|
1749
|
+
id: VALID_UUID,
|
|
1750
|
+
organizationId: VALID_UUID,
|
|
1751
|
+
name: 'Test List',
|
|
1752
|
+
description: null,
|
|
1753
|
+
batchIds: [],
|
|
1754
|
+
instantlyCampaignId: null,
|
|
1755
|
+
status: 'draft' as const,
|
|
1756
|
+
metadata: {},
|
|
1757
|
+
launchedAt: null,
|
|
1758
|
+
completedAt: null,
|
|
1759
|
+
createdAt: ISO_TS,
|
|
1760
|
+
scrapingConfig: {},
|
|
1761
|
+
icp: {},
|
|
1762
|
+
pipelineConfig: {}
|
|
1763
|
+
}
|
|
1764
|
+
|
|
1765
|
+
it('accepts thin lineage deal refs on list detail responses', () => {
|
|
1766
|
+
expect(
|
|
1767
|
+
AcqListDetailResponseSchema.safeParse({
|
|
1768
|
+
...baseList,
|
|
1769
|
+
lineage: {
|
|
1770
|
+
deals: {
|
|
1771
|
+
total: 1,
|
|
1772
|
+
refs: [
|
|
1773
|
+
{
|
|
1774
|
+
id: VALID_UUID,
|
|
1775
|
+
contactEmail: 'lead@example.com',
|
|
1776
|
+
stageKey: 'proposal',
|
|
1777
|
+
stateKey: null,
|
|
1778
|
+
sourceType: 'outreach',
|
|
1779
|
+
lastActivityAt: ISO_TS
|
|
1780
|
+
}
|
|
1781
|
+
],
|
|
1782
|
+
truncated: false
|
|
1783
|
+
}
|
|
1784
|
+
}
|
|
1785
|
+
}).success
|
|
1786
|
+
).toBe(true)
|
|
1787
|
+
})
|
|
1788
|
+
|
|
1789
|
+
it('accepts optional progress on list detail responses', () => {
|
|
1790
|
+
expect(
|
|
1791
|
+
AcqListDetailResponseSchema.safeParse({
|
|
1792
|
+
...baseList,
|
|
1793
|
+
progress: {
|
|
1794
|
+
totalMembers: 0,
|
|
1795
|
+
totalCompanies: 0,
|
|
1796
|
+
byCompanyStage: {},
|
|
1797
|
+
byContactStage: {}
|
|
1798
|
+
}
|
|
1799
|
+
}).success
|
|
1800
|
+
).toBe(true)
|
|
1801
|
+
})
|
|
1802
|
+
})
|
|
1803
|
+
|
|
1804
|
+
// ---------------------------------------------------------------------------
|
|
1805
|
+
// AcqListStatusResponseSchema
|
|
1806
|
+
// ---------------------------------------------------------------------------
|
|
1807
|
+
|
|
1808
|
+
describe('AcqListStatusResponseSchema', () => {
|
|
1809
|
+
it('accepts a portfolio summary across acquisition lists', () => {
|
|
1810
|
+
expect(
|
|
1811
|
+
AcqListStatusResponseSchema.safeParse({
|
|
1812
|
+
totalLists: 1,
|
|
1813
|
+
totalCompanies: 10,
|
|
1814
|
+
totalContacts: 5,
|
|
1815
|
+
totalDeals: 2,
|
|
1816
|
+
byStatus: { launched: 1 },
|
|
1817
|
+
lists: [
|
|
1818
|
+
{
|
|
1819
|
+
listId: VALID_UUID,
|
|
1820
|
+
name: 'Pipeline',
|
|
1821
|
+
status: 'launched',
|
|
1822
|
+
totalCompanies: 10,
|
|
1823
|
+
totalContacts: 5,
|
|
1824
|
+
totalDeals: 2,
|
|
1825
|
+
createdAt: ISO_TS
|
|
1826
|
+
}
|
|
1827
|
+
]
|
|
1828
|
+
}).success
|
|
1829
|
+
).toBe(true)
|
|
1830
|
+
})
|
|
1831
|
+
})
|
|
1832
|
+
|
|
1660
1833
|
// ---------------------------------------------------------------------------
|
|
1661
1834
|
// AcqContactResponseSchema (forward-compat)
|
|
1662
1835
|
// ---------------------------------------------------------------------------
|
|
@@ -2,7 +2,7 @@ import { z } from 'zod'
|
|
|
2
2
|
import { UuidSchema, NonEmptyStringSchema } from '../../platform/utils/validation'
|
|
3
3
|
import { CRM_PIPELINE_DEFINITION, LEAD_GEN_STAGE_CATALOG } from '../../organization-model/domains/sales'
|
|
4
4
|
import {
|
|
5
|
-
|
|
5
|
+
ACTION_REGISTRY,
|
|
6
6
|
CredentialRequirementSchema,
|
|
7
7
|
RecordColumnConfigSchema
|
|
8
8
|
} from '../../organization-model/domains/prospecting'
|
|
@@ -18,11 +18,9 @@ export const LeadGenStageKeySchema = z
|
|
|
18
18
|
message: 'processing state key must match LEAD_GEN_STAGE_CATALOG'
|
|
19
19
|
})
|
|
20
20
|
|
|
21
|
-
export const
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
message: 'capabilityKey must match CAPABILITY_REGISTRY'
|
|
25
|
-
})
|
|
21
|
+
export const LeadGenActionKeySchema = z.string().refine((value) => ACTION_REGISTRY.some((c) => c.id === value), {
|
|
22
|
+
message: 'actionKey must match ACTION_REGISTRY'
|
|
23
|
+
})
|
|
26
24
|
|
|
27
25
|
const crmStageKeys = CRM_PIPELINE_DEFINITION.stages.map((stage) => stage.stageKey) as [string, ...string[]]
|
|
28
26
|
const crmStateKeys = CRM_PIPELINE_DEFINITION.stages.flatMap((stage) => stage.states.map((state) => state.stateKey)) as [
|
|
@@ -84,6 +82,9 @@ export const DealTaskIdParamsSchema = z.object({
|
|
|
84
82
|
export const ListDealsQuerySchema = z
|
|
85
83
|
.object({
|
|
86
84
|
stage: DealStageSchema.optional(),
|
|
85
|
+
list: UuidSchema.optional(),
|
|
86
|
+
batch: z.string().trim().min(1).max(255).optional(),
|
|
87
|
+
staleSince: z.string().datetime().optional(),
|
|
87
88
|
search: z.string().optional(),
|
|
88
89
|
limit: z.coerce.number().int().positive().default(50),
|
|
89
90
|
offset: z.coerce.number().int().min(0).default(0)
|
|
@@ -215,6 +216,7 @@ export const DealListItemSchema = z.object({
|
|
|
215
216
|
// acq_deals columns
|
|
216
217
|
id: z.string(),
|
|
217
218
|
organization_id: z.string(),
|
|
219
|
+
client_id: z.string().nullable().optional(),
|
|
218
220
|
contact_id: z.string().nullable(),
|
|
219
221
|
contact_email: z.string(),
|
|
220
222
|
pipeline_key: z.string(),
|
|
@@ -304,12 +306,39 @@ export const DealConversationSchema = z.object({
|
|
|
304
306
|
messages: z.array(ConversationMessageSchema)
|
|
305
307
|
})
|
|
306
308
|
|
|
309
|
+
export const DealLineageListRefSchema = z.object({
|
|
310
|
+
id: z.string(),
|
|
311
|
+
name: z.string(),
|
|
312
|
+
status: z.string()
|
|
313
|
+
})
|
|
314
|
+
|
|
315
|
+
export const DealLineageProjectRefSchema = z.object({
|
|
316
|
+
id: z.string(),
|
|
317
|
+
name: z.string(),
|
|
318
|
+
kind: z.string(),
|
|
319
|
+
status: z.string(),
|
|
320
|
+
updatedAt: z.string()
|
|
321
|
+
})
|
|
322
|
+
|
|
323
|
+
export const DealLineageClientRefSchema = z.object({
|
|
324
|
+
id: z.string(),
|
|
325
|
+
name: z.string(),
|
|
326
|
+
status: z.string()
|
|
327
|
+
})
|
|
328
|
+
|
|
329
|
+
export const DealLineageSchema = z.object({
|
|
330
|
+
list: DealLineageListRefSchema.nullable(),
|
|
331
|
+
projects: z.array(DealLineageProjectRefSchema),
|
|
332
|
+
client: DealLineageClientRefSchema.nullable()
|
|
333
|
+
})
|
|
334
|
+
|
|
307
335
|
/**
|
|
308
336
|
* Deal detail shape — currently the same as a list item (full joined record).
|
|
309
337
|
* Additive fields keep existing DealListItem callers compatible.
|
|
310
338
|
*/
|
|
311
339
|
export const DealDetailResponseSchema = DealListItemSchema.extend({
|
|
312
|
-
conversation: DealConversationSchema
|
|
340
|
+
conversation: DealConversationSchema,
|
|
341
|
+
lineage: DealLineageSchema.optional()
|
|
313
342
|
})
|
|
314
343
|
|
|
315
344
|
/**
|
|
@@ -382,6 +411,10 @@ export const DealSchemas = {
|
|
|
382
411
|
DealSummaryResponse: DealSummaryResponseSchema,
|
|
383
412
|
DealLookupResponse: DealLookupResponseSchema,
|
|
384
413
|
ConversationMessage: ConversationMessageSchema,
|
|
414
|
+
DealLineageListRef: DealLineageListRefSchema,
|
|
415
|
+
DealLineageProjectRef: DealLineageProjectRefSchema,
|
|
416
|
+
DealLineageClientRef: DealLineageClientRefSchema,
|
|
417
|
+
DealLineage: DealLineageSchema,
|
|
385
418
|
DealDetailResponse: DealDetailResponseSchema,
|
|
386
419
|
DealNoteResponse: DealNoteResponseSchema,
|
|
387
420
|
DealNoteListResponse: DealNoteListResponseSchema,
|
|
@@ -415,6 +448,10 @@ export type DealSummaryResponse = z.infer<typeof DealSummaryResponseSchema>
|
|
|
415
448
|
export type DealLookupItem = z.infer<typeof DealLookupItemSchema>
|
|
416
449
|
export type DealLookupResponse = z.infer<typeof DealLookupResponseSchema>
|
|
417
450
|
export type ConversationMessage = z.infer<typeof ConversationMessageSchema>
|
|
451
|
+
export type DealLineageListRef = z.infer<typeof DealLineageListRefSchema>
|
|
452
|
+
export type DealLineageProjectRef = z.infer<typeof DealLineageProjectRefSchema>
|
|
453
|
+
export type DealLineageClientRef = z.infer<typeof DealLineageClientRefSchema>
|
|
454
|
+
export type DealLineage = z.infer<typeof DealLineageSchema>
|
|
418
455
|
export type DealDetailResponse = z.infer<typeof DealDetailResponseSchema>
|
|
419
456
|
export type DealNoteResponse = z.infer<typeof DealNoteResponseSchema>
|
|
420
457
|
export type DealNoteListResponse = z.infer<typeof DealNoteListResponseSchema>
|
|
@@ -505,7 +542,7 @@ export const BuildPlanSnapshotStepSchema = z
|
|
|
505
542
|
recordSourceStageKey: LeadGenStageKeySchema.optional(),
|
|
506
543
|
dependsOn: z.array(z.string().trim().min(1).max(100)).optional(),
|
|
507
544
|
dependencyMode: z.literal('per-record-eligibility'),
|
|
508
|
-
|
|
545
|
+
actionKey: LeadGenActionKeySchema,
|
|
509
546
|
defaultBatchSize: z.number().int().positive(),
|
|
510
547
|
maxBatchSize: z.number().int().positive(),
|
|
511
548
|
recordColumns: z
|
|
@@ -732,6 +769,30 @@ export const ListTelemetryResponseSchema = ListTelemetrySchema
|
|
|
732
769
|
|
|
733
770
|
export const ListTelemetryListResponseSchema = z.array(ListTelemetrySchema)
|
|
734
771
|
|
|
772
|
+
const QueryBooleanSchema = z.preprocess((value) => {
|
|
773
|
+
if (value === 'true' || value === '1' || value === true) return true
|
|
774
|
+
if (value === 'false' || value === '0' || value === false) return false
|
|
775
|
+
return value
|
|
776
|
+
}, z.boolean())
|
|
777
|
+
|
|
778
|
+
export const ListReadQuerySchema = z
|
|
779
|
+
.object({
|
|
780
|
+
status: ListStatusSchema.optional(),
|
|
781
|
+
batch: z.string().trim().min(1).max(255).optional(),
|
|
782
|
+
vertical: z.string().trim().min(1).max(255).optional(),
|
|
783
|
+
limit: z.coerce.number().int().min(1).max(500).optional(),
|
|
784
|
+
offset: z.coerce.number().int().min(0).optional()
|
|
785
|
+
})
|
|
786
|
+
.strict()
|
|
787
|
+
|
|
788
|
+
export const GetListQuerySchema = z
|
|
789
|
+
.object({
|
|
790
|
+
includeDeals: QueryBooleanSchema.default(true),
|
|
791
|
+
includeProgress: QueryBooleanSchema.default(false),
|
|
792
|
+
dealLimit: z.coerce.number().int().min(0).max(100).default(25)
|
|
793
|
+
})
|
|
794
|
+
.strict()
|
|
795
|
+
|
|
735
796
|
/**
|
|
736
797
|
* Per-stage progress aggregate for a single pipeline stage.
|
|
737
798
|
* `attempted` counts terminal statuses, including success, no-result, skipped,
|
|
@@ -761,6 +822,47 @@ export const ListProgressResponseSchema = z.object({
|
|
|
761
822
|
byContactStage: z.record(z.string(), ListStageProgressSchema)
|
|
762
823
|
})
|
|
763
824
|
|
|
825
|
+
export const AcqListDealRefSchema = z.object({
|
|
826
|
+
id: z.string(),
|
|
827
|
+
contactEmail: z.string(),
|
|
828
|
+
stageKey: z.string().nullable(),
|
|
829
|
+
stateKey: z.string().nullable(),
|
|
830
|
+
sourceType: z.string().nullable(),
|
|
831
|
+
lastActivityAt: z.string()
|
|
832
|
+
})
|
|
833
|
+
|
|
834
|
+
export const AcqListLineageSchema = z.object({
|
|
835
|
+
deals: z.object({
|
|
836
|
+
total: z.number().int().min(0),
|
|
837
|
+
refs: z.array(AcqListDealRefSchema),
|
|
838
|
+
truncated: z.boolean()
|
|
839
|
+
})
|
|
840
|
+
})
|
|
841
|
+
|
|
842
|
+
export const AcqListDetailResponseSchema = AcqListResponseSchema.extend({
|
|
843
|
+
lineage: AcqListLineageSchema.optional(),
|
|
844
|
+
progress: ListProgressResponseSchema.optional()
|
|
845
|
+
})
|
|
846
|
+
|
|
847
|
+
export const AcqListStatusListItemSchema = z.object({
|
|
848
|
+
listId: z.string(),
|
|
849
|
+
name: z.string(),
|
|
850
|
+
status: ListStatusSchema,
|
|
851
|
+
totalCompanies: z.number().int().min(0),
|
|
852
|
+
totalContacts: z.number().int().min(0),
|
|
853
|
+
totalDeals: z.number().int().min(0),
|
|
854
|
+
createdAt: z.string()
|
|
855
|
+
})
|
|
856
|
+
|
|
857
|
+
export const AcqListStatusResponseSchema = z.object({
|
|
858
|
+
totalLists: z.number().int().min(0),
|
|
859
|
+
totalCompanies: z.number().int().min(0),
|
|
860
|
+
totalContacts: z.number().int().min(0),
|
|
861
|
+
totalDeals: z.number().int().min(0),
|
|
862
|
+
byStatus: z.record(z.string(), z.number().int().min(0)),
|
|
863
|
+
lists: z.array(AcqListStatusListItemSchema)
|
|
864
|
+
})
|
|
865
|
+
|
|
764
866
|
/**
|
|
765
867
|
* Row from acq_list_executions joined with the execution summary,
|
|
766
868
|
* shaped for the /lists/:id/executions response.
|
|
@@ -781,12 +883,6 @@ export const ListExecutionsResponseSchema = z.array(ListExecutionSummarySchema)
|
|
|
781
883
|
// Company / Contact API Schemas
|
|
782
884
|
// ---------------------------------------------------------------------------
|
|
783
885
|
|
|
784
|
-
const QueryBooleanSchema = z.preprocess((value) => {
|
|
785
|
-
if (value === 'true' || value === '1' || value === true) return true
|
|
786
|
-
if (value === 'false' || value === '0' || value === false) return false
|
|
787
|
-
return value
|
|
788
|
-
}, z.boolean())
|
|
789
|
-
|
|
790
886
|
export const AcqCompanyStatusSchema = z.enum(['active', 'invalid'])
|
|
791
887
|
export const AcqContactStatusSchema = z.enum(['active', 'invalid'])
|
|
792
888
|
export const AcqEmailValidSchema = z.enum(['VALID', 'INVALID', 'RISKY', 'UNKNOWN'])
|
|
@@ -831,6 +927,7 @@ export const ListContactsQuerySchema = z
|
|
|
831
927
|
export const CreateCompanyRequestSchema = z
|
|
832
928
|
.object({
|
|
833
929
|
name: z.string().trim().min(1).max(255),
|
|
930
|
+
clientId: UuidSchema.nullable().optional(),
|
|
834
931
|
domain: z.string().trim().min(1).max(255).optional(),
|
|
835
932
|
linkedinUrl: z.string().trim().url().optional(),
|
|
836
933
|
website: z.string().trim().url().optional(),
|
|
@@ -849,6 +946,7 @@ export const CreateCompanyRequestSchema = z
|
|
|
849
946
|
export const UpdateCompanyRequestSchema = z
|
|
850
947
|
.object({
|
|
851
948
|
name: z.string().trim().min(1).max(255).optional(),
|
|
949
|
+
clientId: UuidSchema.nullable().optional(),
|
|
852
950
|
domain: z.string().trim().min(1).max(255).optional(),
|
|
853
951
|
linkedinUrl: z.string().trim().url().optional(),
|
|
854
952
|
website: z.string().trim().url().optional(),
|
|
@@ -870,6 +968,7 @@ export const UpdateCompanyRequestSchema = z
|
|
|
870
968
|
.refine(
|
|
871
969
|
(data) =>
|
|
872
970
|
data.name !== undefined ||
|
|
971
|
+
data.clientId !== undefined ||
|
|
873
972
|
data.domain !== undefined ||
|
|
874
973
|
data.linkedinUrl !== undefined ||
|
|
875
974
|
data.website !== undefined ||
|
|
@@ -894,6 +993,7 @@ export const UpdateCompanyRequestSchema = z
|
|
|
894
993
|
export const CreateContactRequestSchema = z
|
|
895
994
|
.object({
|
|
896
995
|
email: z.string().trim().email(),
|
|
996
|
+
clientId: UuidSchema.nullable().optional(),
|
|
897
997
|
companyId: UuidSchema.optional(),
|
|
898
998
|
firstName: z.string().trim().min(1).max(255).optional(),
|
|
899
999
|
lastName: z.string().trim().min(1).max(255).optional(),
|
|
@@ -909,6 +1009,7 @@ export const CreateContactRequestSchema = z
|
|
|
909
1009
|
export const UpdateContactRequestSchema = z
|
|
910
1010
|
.object({
|
|
911
1011
|
companyId: UuidSchema.optional(),
|
|
1012
|
+
clientId: UuidSchema.nullable().optional(),
|
|
912
1013
|
emailValid: AcqEmailValidSchema.optional(),
|
|
913
1014
|
firstName: z.string().trim().min(1).max(255).optional(),
|
|
914
1015
|
lastName: z.string().trim().min(1).max(255).optional(),
|
|
@@ -926,6 +1027,7 @@ export const UpdateContactRequestSchema = z
|
|
|
926
1027
|
.refine(
|
|
927
1028
|
(data) =>
|
|
928
1029
|
data.companyId !== undefined ||
|
|
1030
|
+
data.clientId !== undefined ||
|
|
929
1031
|
data.emailValid !== undefined ||
|
|
930
1032
|
data.firstName !== undefined ||
|
|
931
1033
|
data.lastName !== undefined ||
|
|
@@ -946,6 +1048,7 @@ export const UpdateContactRequestSchema = z
|
|
|
946
1048
|
export const AcqCompanyResponseSchema = z.object({
|
|
947
1049
|
id: z.string(),
|
|
948
1050
|
organizationId: z.string(),
|
|
1051
|
+
clientId: z.string().nullable().optional(),
|
|
949
1052
|
name: z.string(),
|
|
950
1053
|
domain: z.string().nullable(),
|
|
951
1054
|
linkedinUrl: z.string().nullable(),
|
|
@@ -996,6 +1099,7 @@ export const AcqContactCompanySummarySchema = z.object({
|
|
|
996
1099
|
export const AcqContactResponseSchema = z.object({
|
|
997
1100
|
id: z.string(),
|
|
998
1101
|
organizationId: z.string(),
|
|
1102
|
+
clientId: z.string().nullable().optional(),
|
|
999
1103
|
companyId: z.string().nullable(),
|
|
1000
1104
|
email: z.string(),
|
|
1001
1105
|
emailValid: AcqEmailValidSchema.nullable(),
|
|
@@ -1290,13 +1394,15 @@ export const AcqListSchemas = {
|
|
|
1290
1394
|
BuildPlanSnapshotStep: BuildPlanSnapshotStepSchema,
|
|
1291
1395
|
AcqListMetadata: AcqListMetadataSchema,
|
|
1292
1396
|
LeadGenStageKey: LeadGenStageKeySchema,
|
|
1293
|
-
|
|
1397
|
+
LeadGenActionKey: LeadGenActionKeySchema,
|
|
1294
1398
|
ProcessingStageStatus: ProcessingStageStatusSchema,
|
|
1295
1399
|
ProcessingState: ProcessingStateSchema,
|
|
1296
1400
|
ListStageCounts: ListStageCountsSchema,
|
|
1297
1401
|
ListTelemetry: ListTelemetrySchema,
|
|
1298
1402
|
|
|
1299
1403
|
// Requests
|
|
1404
|
+
ListReadQuery: ListReadQuerySchema,
|
|
1405
|
+
GetListQuery: GetListQuerySchema,
|
|
1300
1406
|
CreateListRequest: CreateListRequestSchema,
|
|
1301
1407
|
UpdateListRequest: UpdateListRequestSchema,
|
|
1302
1408
|
UpdateListStatusRequest: UpdateListStatusRequestSchema,
|
|
@@ -1308,7 +1414,11 @@ export const AcqListSchemas = {
|
|
|
1308
1414
|
|
|
1309
1415
|
// Responses
|
|
1310
1416
|
AcqListResponse: AcqListResponseSchema,
|
|
1417
|
+
AcqListDetailResponse: AcqListDetailResponseSchema,
|
|
1311
1418
|
AcqListListResponse: AcqListListResponseSchema,
|
|
1419
|
+
AcqListDealRef: AcqListDealRefSchema,
|
|
1420
|
+
AcqListLineage: AcqListLineageSchema,
|
|
1421
|
+
AcqListStatusResponse: AcqListStatusResponseSchema,
|
|
1312
1422
|
ListTelemetryResponse: ListTelemetryResponseSchema,
|
|
1313
1423
|
ListTelemetryListResponse: ListTelemetryListResponseSchema,
|
|
1314
1424
|
ListExecutionsResponse: ListExecutionsResponseSchema,
|
|
@@ -1382,11 +1492,13 @@ export type PipelineConfig = z.infer<typeof PipelineConfigSchema>
|
|
|
1382
1492
|
export type BuildPlanSnapshotStep = z.infer<typeof BuildPlanSnapshotStepSchema>
|
|
1383
1493
|
export type BuildPlanSnapshot = z.infer<typeof BuildPlanSnapshotSchema>
|
|
1384
1494
|
export type AcqListMetadata = z.infer<typeof AcqListMetadataSchema>
|
|
1385
|
-
export type
|
|
1495
|
+
export type LeadGenActionKey = z.infer<typeof LeadGenActionKeySchema>
|
|
1386
1496
|
export type ProcessingStageStatus = z.infer<typeof ProcessingStageStatusSchema>
|
|
1387
1497
|
export type ListStageCountsInput = z.infer<typeof ListStageCountsSchema>['stageCounts']
|
|
1388
1498
|
export type ListTelemetryInput = z.infer<typeof ListTelemetrySchema>
|
|
1389
1499
|
export type ListIdParams = z.infer<typeof ListIdParamsSchema>
|
|
1500
|
+
export type ListReadQuery = z.infer<typeof ListReadQuerySchema>
|
|
1501
|
+
export type GetListQuery = z.infer<typeof GetListQuerySchema>
|
|
1390
1502
|
export type CreateListRequest = z.infer<typeof CreateListRequestSchema>
|
|
1391
1503
|
export type UpdateListRequest = z.infer<typeof UpdateListRequestSchema>
|
|
1392
1504
|
export type UpdateListStatusRequest = z.infer<typeof UpdateListStatusRequestSchema>
|
|
@@ -1396,7 +1508,11 @@ export type RemoveCompaniesFromListRequest = z.infer<typeof RemoveCompaniesFromL
|
|
|
1396
1508
|
export type AddContactsToListRequest = z.infer<typeof AddContactsToListRequestSchema>
|
|
1397
1509
|
export type RecordListExecutionRequest = z.infer<typeof RecordListExecutionRequestSchema>
|
|
1398
1510
|
export type AcqListResponse = z.infer<typeof AcqListResponseSchema>
|
|
1511
|
+
export type AcqListDetailResponse = z.infer<typeof AcqListDetailResponseSchema>
|
|
1399
1512
|
export type AcqListListResponse = z.infer<typeof AcqListListResponseSchema>
|
|
1513
|
+
export type AcqListDealRef = z.infer<typeof AcqListDealRefSchema>
|
|
1514
|
+
export type AcqListLineage = z.infer<typeof AcqListLineageSchema>
|
|
1515
|
+
export type AcqListStatusResponse = z.infer<typeof AcqListStatusResponseSchema>
|
|
1400
1516
|
export type ListTelemetryResponse = z.infer<typeof ListTelemetryResponseSchema>
|
|
1401
1517
|
export type ListTelemetryListResponse = z.infer<typeof ListTelemetryListResponseSchema>
|
|
1402
1518
|
export type ListExecutionSummaryInput = z.infer<typeof ListExecutionSummarySchema>
|
|
@@ -88,7 +88,7 @@ describe('createBuildPlanSnapshotFromTemplateId — "local-services"', () => {
|
|
|
88
88
|
expect(snapshot?.steps).toHaveLength(7)
|
|
89
89
|
})
|
|
90
90
|
|
|
91
|
-
it('every step has required fields: id, label, primaryEntity, outputs, stageKey, dependencyMode,
|
|
91
|
+
it('every step has required fields: id, label, primaryEntity, outputs, stageKey, dependencyMode, actionKey', () => {
|
|
92
92
|
for (const step of snapshot?.steps ?? []) {
|
|
93
93
|
expect(step.id).toBeTruthy()
|
|
94
94
|
expect(step.label).toBeTruthy()
|
|
@@ -96,7 +96,7 @@ describe('createBuildPlanSnapshotFromTemplateId — "local-services"', () => {
|
|
|
96
96
|
expect(step.outputs.length).toBeGreaterThanOrEqual(1)
|
|
97
97
|
expect(step.stageKey).toBeTruthy()
|
|
98
98
|
expect(step.dependencyMode).toBe('per-record-eligibility')
|
|
99
|
-
expect(step.
|
|
99
|
+
expect(step.actionKey).toBeTruthy()
|
|
100
100
|
}
|
|
101
101
|
})
|
|
102
102
|
|
|
@@ -149,7 +149,7 @@ describe('createBuildPlanSnapshotFromTemplateId — "dtc-subscription-apollo-cli
|
|
|
149
149
|
expect(snapshot?.steps).toHaveLength(6)
|
|
150
150
|
})
|
|
151
151
|
|
|
152
|
-
it('every step has required fields: id, label, primaryEntity, outputs, stageKey, dependencyMode,
|
|
152
|
+
it('every step has required fields: id, label, primaryEntity, outputs, stageKey, dependencyMode, actionKey', () => {
|
|
153
153
|
for (const step of snapshot?.steps ?? []) {
|
|
154
154
|
expect(step.id).toBeTruthy()
|
|
155
155
|
expect(step.label).toBeTruthy()
|
|
@@ -157,7 +157,7 @@ describe('createBuildPlanSnapshotFromTemplateId — "dtc-subscription-apollo-cli
|
|
|
157
157
|
expect(step.outputs.length).toBeGreaterThanOrEqual(1)
|
|
158
158
|
expect(step.stageKey).toBeTruthy()
|
|
159
159
|
expect(step.dependencyMode).toBe('per-record-eligibility')
|
|
160
|
-
expect(step.
|
|
160
|
+
expect(step.actionKey).toBeTruthy()
|
|
161
161
|
}
|
|
162
162
|
})
|
|
163
163
|
|