@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.
Files changed (132) hide show
  1. package/dist/index.d.ts +2518 -2169
  2. package/dist/index.js +2495 -1095
  3. package/dist/knowledge/index.d.ts +706 -1044
  4. package/dist/knowledge/index.js +9 -9
  5. package/dist/organization-model/index.d.ts +2518 -2169
  6. package/dist/organization-model/index.js +2495 -1095
  7. package/dist/test-utils/index.d.ts +826 -1014
  8. package/dist/test-utils/index.js +1894 -1032
  9. package/package.json +3 -3
  10. package/src/__tests__/template-core-compatibility.test.ts +11 -79
  11. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +852 -397
  12. package/src/auth/multi-tenancy/permissions.ts +20 -8
  13. package/src/business/README.md +2 -2
  14. package/src/business/acquisition/api-schemas.test.ts +175 -2
  15. package/src/business/acquisition/api-schemas.ts +132 -16
  16. package/src/business/acquisition/build-templates.test.ts +4 -4
  17. package/src/business/acquisition/build-templates.ts +72 -30
  18. package/src/business/acquisition/crm-state-actions.test.ts +13 -11
  19. package/src/business/acquisition/index.ts +12 -0
  20. package/src/business/acquisition/types.ts +7 -3
  21. package/src/business/clients/api-schemas.test.ts +115 -0
  22. package/src/business/clients/api-schemas.ts +158 -0
  23. package/src/business/clients/index.ts +1 -0
  24. package/src/business/deals/api-schemas.ts +8 -0
  25. package/src/business/index.ts +5 -2
  26. package/src/business/projects/types.ts +19 -0
  27. package/src/execution/engine/__tests__/fixtures/test-agents.ts +10 -8
  28. package/src/execution/engine/agent/core/__tests__/agent.test.ts +16 -12
  29. package/src/execution/engine/agent/core/__tests__/error-passthrough.test.ts +4 -3
  30. package/src/execution/engine/agent/core/types.ts +25 -15
  31. package/src/execution/engine/agent/index.ts +6 -4
  32. package/src/execution/engine/agent/reasoning/__tests__/request-builder.test.ts +24 -18
  33. package/src/execution/engine/index.ts +3 -0
  34. package/src/execution/engine/workflow/types.ts +9 -2
  35. package/src/knowledge/README.md +8 -7
  36. package/src/knowledge/__tests__/queries.test.ts +74 -73
  37. package/src/knowledge/format.ts +10 -9
  38. package/src/knowledge/index.ts +1 -1
  39. package/src/knowledge/published.ts +1 -1
  40. package/src/knowledge/queries.ts +26 -25
  41. package/src/organization-model/README.md +73 -26
  42. package/src/organization-model/__tests__/content-kinds-registry.test.ts +210 -0
  43. package/src/organization-model/__tests__/defaults.test.ts +76 -96
  44. package/src/organization-model/__tests__/domains/actions.test.ts +56 -0
  45. package/src/organization-model/__tests__/domains/customers.test.ts +299 -295
  46. package/src/organization-model/__tests__/domains/entities.test.ts +56 -0
  47. package/src/organization-model/__tests__/domains/goals.test.ts +493 -479
  48. package/src/organization-model/__tests__/domains/identity.test.ts +280 -279
  49. package/src/organization-model/__tests__/domains/navigation.test.ts +268 -212
  50. package/src/organization-model/__tests__/domains/offerings.test.ts +414 -419
  51. package/src/organization-model/__tests__/domains/policies.test.ts +323 -0
  52. package/src/organization-model/__tests__/domains/resource-mappings.test.ts +271 -271
  53. package/src/organization-model/__tests__/domains/resources.test.ts +310 -0
  54. package/src/organization-model/__tests__/domains/roles.test.ts +463 -347
  55. package/src/organization-model/__tests__/domains/statuses.test.ts +246 -243
  56. package/src/organization-model/__tests__/domains/systems.test.ts +209 -0
  57. package/src/organization-model/__tests__/flatten-additive-merge.test.ts +361 -0
  58. package/src/organization-model/__tests__/foundation.test.ts +74 -102
  59. package/src/organization-model/__tests__/get-resources-for-system.test.ts +144 -0
  60. package/src/organization-model/__tests__/graph.test.ts +899 -71
  61. package/src/organization-model/__tests__/knowledge.test.ts +209 -49
  62. package/src/organization-model/__tests__/lookup-helpers.test.ts +438 -0
  63. package/src/organization-model/__tests__/migration-helpers.test.ts +591 -0
  64. package/src/organization-model/__tests__/prospecting-ssot.test.ts +36 -27
  65. package/src/organization-model/__tests__/recursive-system-schema.test.ts +520 -0
  66. package/src/organization-model/__tests__/resolve.test.ts +174 -23
  67. package/src/organization-model/__tests__/schema.test.ts +291 -114
  68. package/src/organization-model/__tests__/surface-projection.test.ts +207 -97
  69. package/src/organization-model/catalogs/lead-gen.ts +144 -0
  70. package/src/organization-model/content-kinds/config.ts +36 -0
  71. package/src/organization-model/content-kinds/index.ts +74 -0
  72. package/src/organization-model/content-kinds/pipeline.ts +68 -0
  73. package/src/organization-model/content-kinds/registry.ts +44 -0
  74. package/src/organization-model/content-kinds/status.ts +71 -0
  75. package/src/organization-model/content-kinds/template.ts +83 -0
  76. package/src/organization-model/content-kinds/types.ts +117 -0
  77. package/src/organization-model/contracts.ts +13 -3
  78. package/src/organization-model/defaults.ts +499 -86
  79. package/src/organization-model/domains/actions.ts +239 -0
  80. package/src/organization-model/domains/customers.ts +78 -75
  81. package/src/organization-model/domains/entities.ts +144 -0
  82. package/src/organization-model/domains/goals.ts +83 -80
  83. package/src/organization-model/domains/knowledge.ts +76 -17
  84. package/src/organization-model/domains/navigation.ts +107 -384
  85. package/src/organization-model/domains/offerings.ts +71 -66
  86. package/src/organization-model/domains/policies.ts +102 -0
  87. package/src/organization-model/domains/projects.ts +14 -48
  88. package/src/organization-model/domains/prospecting.ts +62 -181
  89. package/src/organization-model/domains/resources.ts +145 -0
  90. package/src/organization-model/domains/roles.ts +96 -55
  91. package/src/organization-model/domains/sales.ts +10 -219
  92. package/src/organization-model/domains/shared.ts +57 -57
  93. package/src/organization-model/domains/statuses.ts +339 -130
  94. package/src/organization-model/domains/systems.ts +203 -0
  95. package/src/organization-model/foundation.ts +54 -67
  96. package/src/organization-model/graph/build.ts +682 -54
  97. package/src/organization-model/graph/link.ts +1 -1
  98. package/src/organization-model/graph/schema.ts +24 -9
  99. package/src/organization-model/graph/types.ts +20 -7
  100. package/src/organization-model/helpers.ts +231 -26
  101. package/src/organization-model/icons.ts +1 -0
  102. package/src/organization-model/index.ts +118 -5
  103. package/src/organization-model/migration-helpers.ts +249 -0
  104. package/src/organization-model/organization-graph.mdx +16 -15
  105. package/src/organization-model/organization-model.mdx +111 -44
  106. package/src/organization-model/published.ts +172 -19
  107. package/src/organization-model/resolve.ts +117 -54
  108. package/src/organization-model/schema.ts +654 -112
  109. package/src/organization-model/surface-projection.ts +116 -122
  110. package/src/organization-model/types.ts +146 -20
  111. package/src/platform/api/types.ts +38 -35
  112. package/src/platform/constants/versions.ts +1 -1
  113. package/src/platform/registry/__tests__/command-view.test.ts +6 -8
  114. package/src/platform/registry/__tests__/resource-link.test.ts +13 -8
  115. package/src/platform/registry/__tests__/resource-registry.integration.test.ts +16 -31
  116. package/src/platform/registry/__tests__/resource-registry.nested-systems.test.ts +245 -0
  117. package/src/platform/registry/__tests__/resource-registry.test.ts +2053 -2005
  118. package/src/platform/registry/__tests__/validation.test.ts +1347 -1086
  119. package/src/platform/registry/index.ts +14 -0
  120. package/src/platform/registry/resource-registry.ts +52 -2
  121. package/src/platform/registry/serialization.ts +241 -202
  122. package/src/platform/registry/serialized-types.ts +1 -0
  123. package/src/platform/registry/types.ts +411 -361
  124. package/src/platform/registry/validation.ts +745 -513
  125. package/src/projects/api-schemas.ts +290 -267
  126. package/src/reference/_generated/contracts.md +853 -397
  127. package/src/reference/glossary.md +23 -18
  128. package/src/supabase/database.types.ts +181 -0
  129. package/src/test-utils/test-utils.test.ts +1 -6
  130. package/src/organization-model/__tests__/domains/operations.test.ts +0 -203
  131. package/src/organization-model/domains/features.ts +0 -31
  132. package/src/organization-model/domains/operations.ts +0 -85
@@ -0,0 +1,310 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { ZodError } from 'zod'
3
+ import { bindResourceDescriptor } from '../../../platform/registry/types'
4
+ import {
5
+ DEFAULT_ORGANIZATION_MODEL_RESOURCES,
6
+ EventIdSchema,
7
+ ResourceEntrySchema,
8
+ ResourceKindSchema,
9
+ ResourcesDomainSchema,
10
+ defineResource,
11
+ defineResources
12
+ } from '../../domains/resources'
13
+ import { resolveOrganizationModel } from '../../resolve'
14
+
15
+ const VALID_SYSTEM = {
16
+ id: 'sys.lead-gen',
17
+ order: 10,
18
+ title: 'Lead Generation Pipeline',
19
+ description: 'Coordinates prospecting, enrichment, qualification, and outreach preparation.',
20
+ kind: 'operational' as const,
21
+ status: 'active' as const
22
+ }
23
+
24
+ const VALID_ROLE = {
25
+ id: 'role.sales-ops',
26
+ order: 10,
27
+ title: 'Sales Ops'
28
+ }
29
+
30
+ const WORKFLOW_RESOURCE = {
31
+ id: 'LGN-01-company-scrape',
32
+ order: 10,
33
+ kind: 'workflow' as const,
34
+ systemPath: 'sys.lead-gen',
35
+ ownerRoleId: 'role.sales-ops',
36
+ status: 'active' as const,
37
+ actionKey: 'lead-gen.company.scrape'
38
+ }
39
+
40
+ const WORKFLOW_EVENT_EMISSION = {
41
+ eventKey: 'processed',
42
+ label: 'Processed',
43
+ payloadSchema: 'leadgen.company.processed',
44
+ lifecycle: 'active' as const
45
+ }
46
+
47
+ const AGENT_RESOURCE = {
48
+ id: 'command-center-assistant',
49
+ order: 20,
50
+ kind: 'agent' as const,
51
+ systemPath: 'sys.lead-gen',
52
+ ownerRoleId: 'role.sales-ops',
53
+ status: 'active' as const,
54
+ agentKind: 'platform' as const,
55
+ actsAsRoleId: 'role.sales-ops',
56
+ sessionCapable: true,
57
+ invocations: [{ kind: 'slash-command' as const, command: '/work handoff' }]
58
+ }
59
+
60
+ const INTEGRATION_RESOURCE = {
61
+ id: 'attio-crm',
62
+ order: 30,
63
+ kind: 'integration' as const,
64
+ systemPath: 'sys.lead-gen',
65
+ ownerRoleId: 'role.sales-ops',
66
+ status: 'active' as const,
67
+ provider: 'attio'
68
+ }
69
+
70
+ const SCRIPT_RESOURCE = {
71
+ id: 'leadgen-backfill-script',
72
+ order: 40,
73
+ kind: 'script' as const,
74
+ systemPath: 'sys.lead-gen',
75
+ ownerRoleId: 'role.sales-ops',
76
+ status: 'active' as const,
77
+ language: 'typescript' as const,
78
+ source: {
79
+ file: 'scripts/leadgen/backfill.ts'
80
+ }
81
+ }
82
+
83
+ function resolveWithResources(resources: Record<string, unknown>) {
84
+ return resolveOrganizationModel({
85
+ roles: { 'role.sales-ops': VALID_ROLE },
86
+ systems: { 'sys.lead-gen': VALID_SYSTEM },
87
+ resources: resources as Record<string, typeof WORKFLOW_RESOURCE>
88
+ })
89
+ }
90
+
91
+ describe('ResourceEntrySchema', () => {
92
+ it('accepts workflow, agent, integration, and script descriptors with required systemPath', () => {
93
+ expect(ResourceEntrySchema.safeParse(WORKFLOW_RESOURCE).success).toBe(true)
94
+ expect(ResourceEntrySchema.safeParse(AGENT_RESOURCE).success).toBe(true)
95
+ expect(ResourceEntrySchema.safeParse(INTEGRATION_RESOURCE).success).toBe(true)
96
+ expect(ResourceEntrySchema.safeParse(SCRIPT_RESOURCE).success).toBe(true)
97
+ })
98
+
99
+ it('rejects resources without a systemPath', () => {
100
+ const { systemPath: _systemPath, ...resourceWithoutSystem } = WORKFLOW_RESOURCE
101
+
102
+ expect(ResourceEntrySchema.safeParse(resourceWithoutSystem).success).toBe(false)
103
+ })
104
+
105
+ it('rejects multi-system membership', () => {
106
+ expect(
107
+ ResourceEntrySchema.safeParse({
108
+ ...WORKFLOW_RESOURCE,
109
+ systemPath: ['sys.lead-gen', 'sys.crm']
110
+ }).success
111
+ ).toBe(false)
112
+ })
113
+
114
+ it('rejects an agent kind outside the code-side mirror enum', () => {
115
+ expect(
116
+ ResourceEntrySchema.safeParse({
117
+ ...AGENT_RESOURCE,
118
+ agentKind: 'runner'
119
+ }).success
120
+ ).toBe(false)
121
+ })
122
+
123
+ it('defaults agent invocations and accepts slash-command orchestration entries', () => {
124
+ const result = ResourceEntrySchema.safeParse({
125
+ ...AGENT_RESOURCE,
126
+ invocations: undefined
127
+ })
128
+
129
+ expect(result.success).toBe(true)
130
+ if (result.success) {
131
+ expect(result.data.kind).toBe('agent')
132
+ if (result.data.kind === 'agent') {
133
+ expect(result.data.invocations).toEqual([])
134
+ }
135
+ }
136
+
137
+ expect(ResourceEntrySchema.safeParse(AGENT_RESOURCE).success).toBe(true)
138
+ })
139
+
140
+ it('rejects malformed agent invocation entries', () => {
141
+ expect(
142
+ ResourceEntrySchema.safeParse({
143
+ ...AGENT_RESOURCE,
144
+ invocations: [{ kind: 'slash-command', command: 'work handoff' }]
145
+ }).success
146
+ ).toBe(false)
147
+ })
148
+
149
+ it('accepts event emissions on workflow and agent resources only', () => {
150
+ const workflowResult = ResourceEntrySchema.safeParse({
151
+ ...WORKFLOW_RESOURCE,
152
+ emits: [WORKFLOW_EVENT_EMISSION]
153
+ })
154
+ const agentResult = ResourceEntrySchema.safeParse({
155
+ ...AGENT_RESOURCE,
156
+ emits: [{ eventKey: 'approved', label: 'Approved' }]
157
+ })
158
+ const integrationResult = ResourceEntrySchema.safeParse({
159
+ ...INTEGRATION_RESOURCE,
160
+ emits: [{ eventKey: 'received', label: 'Received' }]
161
+ })
162
+
163
+ expect(workflowResult.success).toBe(true)
164
+ expect(agentResult.success).toBe(true)
165
+ expect(integrationResult.success).toBe(true)
166
+ if (workflowResult.success && workflowResult.data.kind === 'workflow') {
167
+ expect(workflowResult.data.emits).toEqual([WORKFLOW_EVENT_EMISSION])
168
+ }
169
+ if (agentResult.success && agentResult.data.kind === 'agent') {
170
+ expect(agentResult.data.emits).toEqual([{ eventKey: 'approved', label: 'Approved' }])
171
+ }
172
+ if (integrationResult.success && integrationResult.data.kind === 'integration') {
173
+ expect('emits' in integrationResult.data).toBe(false)
174
+ }
175
+ })
176
+
177
+ it('validates derived event id format', () => {
178
+ expect(EventIdSchema.parse('crm.deal:won')).toBe('crm.deal:won')
179
+ expect(EventIdSchema.parse('LGN-01-company-scrape:processed')).toBe('LGN-01-company-scrape:processed')
180
+ expect(() => EventIdSchema.parse('crm.deal.won')).toThrow()
181
+ })
182
+ })
183
+
184
+ describe('ResourcesDomainSchema', () => {
185
+ it('defaults resources to an empty record when omitted', () => {
186
+ const result = ResourcesDomainSchema.safeParse({})
187
+
188
+ expect(result.success).toBe(true)
189
+ if (result.success) {
190
+ expect(result.data).toEqual(DEFAULT_ORGANIZATION_MODEL_RESOURCES)
191
+ }
192
+ })
193
+
194
+ it.each(['workflow', 'agent', 'integration', 'script'] as const)('accepts kind "%s"', (kind) => {
195
+ expect(ResourceKindSchema.safeParse(kind).success).toBe(true)
196
+ })
197
+ })
198
+
199
+ describe('resolveOrganizationModel - resources domain integration', () => {
200
+ it('accepts valid resources with system and role references', () => {
201
+ const model = resolveWithResources({
202
+ 'LGN-01-company-scrape': WORKFLOW_RESOURCE,
203
+ 'command-center-assistant': AGENT_RESOURCE,
204
+ 'attio-crm': INTEGRATION_RESOURCE,
205
+ 'leadgen-backfill-script': SCRIPT_RESOURCE
206
+ })
207
+
208
+ expect(Object.keys(model.resources)).toHaveLength(4)
209
+ })
210
+
211
+ it('throws when a resource entry id does not match its map key', () => {
212
+ expect(() =>
213
+ resolveWithResources({
214
+ 'LGN-01-company-scrape': WORKFLOW_RESOURCE,
215
+ 'wrong-key': {
216
+ ...WORKFLOW_RESOURCE,
217
+ id: 'LGN-01-company-scrape'
218
+ }
219
+ })
220
+ ).toThrow()
221
+ })
222
+
223
+ it('throws when systemPath references an unknown system', () => {
224
+ expect(() =>
225
+ resolveWithResources({
226
+ 'LGN-01-company-scrape': {
227
+ ...WORKFLOW_RESOURCE,
228
+ systemPath: 'sys.missing'
229
+ }
230
+ })
231
+ ).toThrow(/unknown system path \\"sys\.missing\\"/)
232
+ })
233
+
234
+ it('reports a dangling resource systemPath on the resource systemPath issue path', () => {
235
+ let error: unknown
236
+
237
+ try {
238
+ resolveWithResources({
239
+ 'LGN-01-company-scrape': {
240
+ ...WORKFLOW_RESOURCE,
241
+ systemPath: 'sys.missing'
242
+ }
243
+ })
244
+ } catch (caught) {
245
+ error = caught
246
+ }
247
+
248
+ expect(error).toBeInstanceOf(ZodError)
249
+ if (!(error instanceof ZodError)) {
250
+ throw new Error('Expected resolveOrganizationModel to throw a ZodError')
251
+ }
252
+
253
+ expect(error.issues).toEqual(
254
+ expect.arrayContaining([
255
+ expect.objectContaining({
256
+ path: ['resources', 'LGN-01-company-scrape', 'systemPath']
257
+ })
258
+ ])
259
+ )
260
+ })
261
+
262
+ it('throws when ownerRoleId references an unknown role', () => {
263
+ expect(() =>
264
+ resolveWithResources({
265
+ 'LGN-01-company-scrape': {
266
+ ...WORKFLOW_RESOURCE,
267
+ ownerRoleId: 'role.missing'
268
+ }
269
+ })
270
+ ).toThrow(/unknown ownerRoleId \\"role\.missing\\"/)
271
+ })
272
+
273
+ it('throws when agent actsAsRoleId references an unknown role', () => {
274
+ expect(() =>
275
+ resolveWithResources({
276
+ 'command-center-assistant': {
277
+ ...AGENT_RESOURCE,
278
+ actsAsRoleId: 'role.missing'
279
+ }
280
+ })
281
+ ).toThrow(/unknown actsAsRoleId \\"role\.missing\\"/)
282
+ })
283
+ })
284
+
285
+ describe('descriptor helper contract', () => {
286
+ it('preserves typed descriptor exports through defineResource and defineResources', () => {
287
+ const workflow = defineResource(WORKFLOW_RESOURCE)
288
+ const resources = defineResources({
289
+ companyScrape: WORKFLOW_RESOURCE,
290
+ commandCenterAssistant: AGENT_RESOURCE
291
+ })
292
+
293
+ expect(workflow.id).toBe('LGN-01-company-scrape')
294
+ expect(resources.commandCenterAssistant.agentKind).toBe('platform')
295
+ })
296
+
297
+ it('derives runtime resourceId and type from the descriptor', () => {
298
+ const bound = bindResourceDescriptor({
299
+ resource: WORKFLOW_RESOURCE,
300
+ name: 'Company Scrape',
301
+ description: 'Scrapes company data for lead generation.',
302
+ version: '1.0.0',
303
+ status: 'prod'
304
+ })
305
+
306
+ expect(bound.resourceId).toBe('LGN-01-company-scrape')
307
+ expect(bound.type).toBe('workflow')
308
+ expect(bound.resource).toBe(WORKFLOW_RESOURCE)
309
+ })
310
+ })