@elevasis/core 0.24.0 → 0.25.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 +3117 -2166
- package/dist/index.js +574 -16
- package/dist/knowledge/index.d.ts +122 -7
- package/dist/organization-model/index.d.ts +3117 -2166
- package/dist/organization-model/index.js +574 -16
- package/dist/test-utils/index.d.ts +135 -45
- package/dist/test-utils/index.js +122 -14
- package/package.json +3 -3
- package/src/_gen/__tests__/__snapshots__/contracts.md.snap +139 -101
- package/src/execution/engine/llm/adapters/__tests__/openrouter.integration.test.ts +10 -10
- package/src/execution/engine/workflow/types.ts +5 -7
- package/src/knowledge/__tests__/queries.test.ts +960 -546
- package/src/knowledge/format.ts +322 -100
- package/src/knowledge/index.ts +18 -5
- package/src/knowledge/queries.ts +1004 -239
- package/src/organization-model/__tests__/deprecate-helpers.test.ts +71 -0
- package/src/organization-model/__tests__/domains/resources.test.ts +19 -8
- package/src/organization-model/__tests__/domains/topology.test.ts +188 -0
- package/src/organization-model/__tests__/graph.test.ts +98 -7
- package/src/organization-model/__tests__/resolve.test.ts +9 -7
- package/src/organization-model/__tests__/scaffolders.test.ts +93 -0
- package/src/organization-model/__tests__/schema.test.ts +14 -4
- package/src/organization-model/defaults.ts +5 -3
- package/src/organization-model/domains/resources.ts +63 -20
- package/src/organization-model/domains/topology.ts +261 -0
- package/src/organization-model/graph/build.ts +63 -15
- package/src/organization-model/graph/schema.ts +4 -3
- package/src/organization-model/graph/types.ts +5 -4
- package/src/organization-model/helpers.ts +76 -9
- package/src/organization-model/icons.ts +1 -0
- package/src/organization-model/index.ts +7 -5
- package/src/organization-model/ontology.ts +2 -5
- package/src/organization-model/organization-model.mdx +16 -11
- package/src/organization-model/published.ts +51 -15
- package/src/organization-model/scaffolders/helpers.ts +84 -0
- package/src/organization-model/scaffolders/index.ts +19 -0
- package/src/organization-model/scaffolders/scaffoldKnowledgeNode.ts +48 -0
- package/src/organization-model/scaffolders/scaffoldOntologyRecord.ts +38 -0
- package/src/organization-model/scaffolders/scaffoldResource.ts +59 -0
- package/src/organization-model/scaffolders/scaffoldSystem.ts +110 -0
- package/src/organization-model/scaffolders/types.ts +81 -0
- package/src/organization-model/schema.ts +51 -11
- package/src/organization-model/types.ts +25 -11
- package/src/platform/constants/versions.ts +1 -1
- package/src/platform/registry/__tests__/validation.test.ts +199 -14
- package/src/platform/registry/resource-registry.ts +11 -11
- package/src/platform/registry/validation.ts +226 -34
- package/src/reference/_generated/contracts.md +139 -101
- package/src/reference/glossary.md +74 -72
- package/src/supabase/database.types.ts +3156 -3153
|
@@ -8,8 +8,9 @@ import { OfferingsDomainSchema, DEFAULT_ORGANIZATION_MODEL_OFFERINGS } from './d
|
|
|
8
8
|
import { RolesDomainSchema, DEFAULT_ORGANIZATION_MODEL_ROLES } from './domains/roles'
|
|
9
9
|
import { GoalsDomainSchema, DEFAULT_ORGANIZATION_MODEL_GOALS } from './domains/goals'
|
|
10
10
|
import { KnowledgeDomainSchema } from './domains/knowledge'
|
|
11
|
-
import { SystemsDomainSchema, DEFAULT_ORGANIZATION_MODEL_SYSTEMS, type SystemEntry } from './domains/systems'
|
|
12
|
-
import { ResourcesDomainSchema, DEFAULT_ORGANIZATION_MODEL_RESOURCES } from './domains/resources'
|
|
11
|
+
import { SystemsDomainSchema, DEFAULT_ORGANIZATION_MODEL_SYSTEMS, type SystemEntry } from './domains/systems'
|
|
12
|
+
import { ResourcesDomainSchema, DEFAULT_ORGANIZATION_MODEL_RESOURCES } from './domains/resources'
|
|
13
|
+
import { OmTopologyDomainSchema, DEFAULT_ORGANIZATION_MODEL_TOPOLOGY, type OmTopologyNodeRef } from './domains/topology'
|
|
13
14
|
import { ActionsDomainSchema, DEFAULT_ORGANIZATION_MODEL_ACTIONS } from './domains/actions'
|
|
14
15
|
import { EntitiesDomainSchema, DEFAULT_ORGANIZATION_MODEL_ENTITIES } from './domains/entities'
|
|
15
16
|
import { PoliciesDomainSchema, DEFAULT_ORGANIZATION_MODEL_POLICIES } from './domains/policies'
|
|
@@ -33,7 +34,8 @@ export const OrganizationModelDomainKeySchema = z.enum([
|
|
|
33
34
|
'systems',
|
|
34
35
|
'ontology',
|
|
35
36
|
'resources',
|
|
36
|
-
'
|
|
37
|
+
'topology',
|
|
38
|
+
'actions',
|
|
37
39
|
'entities',
|
|
38
40
|
'policies',
|
|
39
41
|
'knowledge'
|
|
@@ -57,7 +59,8 @@ export const DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA: Record<
|
|
|
57
59
|
systems: { version: 1, lastModified: '2026-05-10' },
|
|
58
60
|
ontology: { version: 1, lastModified: '2026-05-14' },
|
|
59
61
|
resources: { version: 1, lastModified: '2026-05-10' },
|
|
60
|
-
|
|
62
|
+
topology: { version: 1, lastModified: '2026-05-14' },
|
|
63
|
+
actions: { version: 1, lastModified: '2026-05-10' },
|
|
61
64
|
entities: { version: 1, lastModified: '2026-05-10' },
|
|
62
65
|
policies: { version: 1, lastModified: '2026-05-10' },
|
|
63
66
|
knowledge: { version: 1, lastModified: '2026-05-10' }
|
|
@@ -74,7 +77,8 @@ export const OrganizationModelDomainMetadataByDomainSchema = z
|
|
|
74
77
|
systems: OrganizationModelDomainMetadataSchema,
|
|
75
78
|
ontology: OrganizationModelDomainMetadataSchema,
|
|
76
79
|
resources: OrganizationModelDomainMetadataSchema,
|
|
77
|
-
|
|
80
|
+
topology: OrganizationModelDomainMetadataSchema,
|
|
81
|
+
actions: OrganizationModelDomainMetadataSchema,
|
|
78
82
|
entities: OrganizationModelDomainMetadataSchema,
|
|
79
83
|
policies: OrganizationModelDomainMetadataSchema,
|
|
80
84
|
knowledge: OrganizationModelDomainMetadataSchema
|
|
@@ -104,7 +108,8 @@ const OrganizationModelSchemaBase = z.object({
|
|
|
104
108
|
systems: SystemsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_SYSTEMS),
|
|
105
109
|
ontology: OntologyScopeSchema.default(DEFAULT_ONTOLOGY_SCOPE),
|
|
106
110
|
resources: ResourcesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_RESOURCES),
|
|
107
|
-
|
|
111
|
+
topology: OmTopologyDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_TOPOLOGY),
|
|
112
|
+
actions: ActionsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ACTIONS),
|
|
108
113
|
entities: EntitiesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ENTITIES),
|
|
109
114
|
policies: PoliciesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_POLICIES),
|
|
110
115
|
// D3: flat Record<id, OrgKnowledgeNode> — no wrapper object
|
|
@@ -526,6 +531,32 @@ export const OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((
|
|
|
526
531
|
} satisfies Record<OntologyKind, Record<string, unknown>>
|
|
527
532
|
const ontologyIds = new Set(Object.values(ontologyIndexByKind).flatMap((index) => Object.keys(index)))
|
|
528
533
|
|
|
534
|
+
function topologyTargetExists(ref: OmTopologyNodeRef): boolean {
|
|
535
|
+
if (ref.kind === 'system') return systemsById.has(ref.id)
|
|
536
|
+
if (ref.kind === 'resource') return resourcesById.has(ref.id)
|
|
537
|
+
if (ref.kind === 'ontology') return ontologyIds.has(ref.id)
|
|
538
|
+
if (ref.kind === 'policy') return policiesById.has(ref.id)
|
|
539
|
+
if (ref.kind === 'role') return rolesById.has(ref.id)
|
|
540
|
+
|
|
541
|
+
// Trigger, human checkpoint, and external resource refs are projected
|
|
542
|
+
// topology nodes during the bridge period; their owning runtime indexes are
|
|
543
|
+
// validated by deployment projection in later waves.
|
|
544
|
+
return true
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
Object.entries(model.topology.relationships).forEach(([relationshipId, relationship]) => {
|
|
548
|
+
;(['from', 'to'] as const).forEach((side) => {
|
|
549
|
+
const ref = relationship[side]
|
|
550
|
+
if (topologyTargetExists(ref)) return
|
|
551
|
+
|
|
552
|
+
addIssue(
|
|
553
|
+
ctx,
|
|
554
|
+
['topology', 'relationships', relationshipId, side],
|
|
555
|
+
`Topology relationship "${relationshipId}" ${side} references unknown ${ref.kind} "${ref.id}"`
|
|
556
|
+
)
|
|
557
|
+
})
|
|
558
|
+
})
|
|
559
|
+
|
|
529
560
|
const ontologyReferenceKeyKinds = {
|
|
530
561
|
valueType: 'value-type',
|
|
531
562
|
catalogType: 'catalog',
|
|
@@ -694,15 +725,23 @@ export const OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((
|
|
|
694
725
|
|
|
695
726
|
function validateResourceOntologyBinding(
|
|
696
727
|
resourceId: string,
|
|
697
|
-
bindingKey: '
|
|
728
|
+
bindingKey: 'actions' | 'primaryAction' | 'reads' | 'writes' | 'usesCatalogs' | 'emits',
|
|
698
729
|
expectedKind: OntologyKind,
|
|
699
|
-
ids: string[] | undefined
|
|
730
|
+
ids: string[] | string | undefined
|
|
700
731
|
): void {
|
|
701
|
-
ids
|
|
732
|
+
const ontologyIds = ids === undefined ? [] : Array.isArray(ids) ? ids : [ids]
|
|
733
|
+
|
|
734
|
+
ontologyIds.forEach((ontologyId, ontologyIndex) => {
|
|
702
735
|
if (ontologyIndexByKind[expectedKind][ontologyId] === undefined) {
|
|
703
736
|
addIssue(
|
|
704
737
|
ctx,
|
|
705
|
-
[
|
|
738
|
+
[
|
|
739
|
+
'resources',
|
|
740
|
+
resourceId,
|
|
741
|
+
'ontology',
|
|
742
|
+
bindingKey,
|
|
743
|
+
...(Array.isArray(ids) ? [ontologyIndex] : [])
|
|
744
|
+
],
|
|
706
745
|
`Resource "${resourceId}" ontology binding "${bindingKey}" references unknown ${expectedKind} ontology ID "${ontologyId}"`
|
|
707
746
|
)
|
|
708
747
|
}
|
|
@@ -713,7 +752,8 @@ export const OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((
|
|
|
713
752
|
const binding = resource.ontology
|
|
714
753
|
if (binding === undefined) return
|
|
715
754
|
|
|
716
|
-
validateResourceOntologyBinding(resource.id, '
|
|
755
|
+
validateResourceOntologyBinding(resource.id, 'actions', 'action', binding.actions)
|
|
756
|
+
validateResourceOntologyBinding(resource.id, 'primaryAction', 'action', binding.primaryAction)
|
|
717
757
|
validateResourceOntologyBinding(resource.id, 'reads', 'object', binding.reads)
|
|
718
758
|
validateResourceOntologyBinding(resource.id, 'writes', 'object', binding.writes)
|
|
719
759
|
validateResourceOntologyBinding(resource.id, 'usesCatalogs', 'catalog', binding.usesCatalogs)
|
|
@@ -61,10 +61,18 @@ import {
|
|
|
61
61
|
ResourceOntologyBindingSchema,
|
|
62
62
|
ResourcesDomainSchema,
|
|
63
63
|
ScriptResourceEntrySchema,
|
|
64
|
-
ScriptResourceLanguageSchema,
|
|
65
|
-
ScriptResourceSourceSchema,
|
|
66
|
-
WorkflowResourceEntrySchema
|
|
67
|
-
} from './domains/resources'
|
|
64
|
+
ScriptResourceLanguageSchema,
|
|
65
|
+
ScriptResourceSourceSchema,
|
|
66
|
+
WorkflowResourceEntrySchema
|
|
67
|
+
} from './domains/resources'
|
|
68
|
+
import {
|
|
69
|
+
OmTopologyDomainSchema,
|
|
70
|
+
OmTopologyMetadataSchema,
|
|
71
|
+
OmTopologyNodeKindSchema,
|
|
72
|
+
OmTopologyNodeRefSchema,
|
|
73
|
+
OmTopologyRelationshipKindSchema,
|
|
74
|
+
OmTopologyRelationshipSchema
|
|
75
|
+
} from './domains/topology'
|
|
68
76
|
import {
|
|
69
77
|
ActionsDomainSchema,
|
|
70
78
|
ActionIdSchema,
|
|
@@ -159,13 +167,19 @@ export type OrganizationModelResourceKind = z.infer<typeof ResourceKindSchema>
|
|
|
159
167
|
export type OrganizationModelResourceGovernanceStatus = z.infer<typeof ResourceGovernanceStatusSchema>
|
|
160
168
|
export type OrganizationModelResourceOntologyBinding = z.infer<typeof ResourceOntologyBindingSchema>
|
|
161
169
|
export type OrganizationModelAgentKind = z.infer<typeof AgentKindSchema>
|
|
162
|
-
export type OrganizationModelScriptResourceLanguage = z.infer<typeof ScriptResourceLanguageSchema>
|
|
163
|
-
export type OrganizationModelScriptResourceSource = z.infer<typeof ScriptResourceSourceSchema>
|
|
164
|
-
export type OrganizationModelWorkflowResourceEntry = z.infer<typeof WorkflowResourceEntrySchema>
|
|
165
|
-
export type OrganizationModelAgentResourceEntry = z.infer<typeof AgentResourceEntrySchema>
|
|
166
|
-
export type OrganizationModelIntegrationResourceEntry = z.infer<typeof IntegrationResourceEntrySchema>
|
|
167
|
-
export type OrganizationModelScriptResourceEntry = z.infer<typeof ScriptResourceEntrySchema>
|
|
168
|
-
export type
|
|
170
|
+
export type OrganizationModelScriptResourceLanguage = z.infer<typeof ScriptResourceLanguageSchema>
|
|
171
|
+
export type OrganizationModelScriptResourceSource = z.infer<typeof ScriptResourceSourceSchema>
|
|
172
|
+
export type OrganizationModelWorkflowResourceEntry = z.infer<typeof WorkflowResourceEntrySchema>
|
|
173
|
+
export type OrganizationModelAgentResourceEntry = z.infer<typeof AgentResourceEntrySchema>
|
|
174
|
+
export type OrganizationModelIntegrationResourceEntry = z.infer<typeof IntegrationResourceEntrySchema>
|
|
175
|
+
export type OrganizationModelScriptResourceEntry = z.infer<typeof ScriptResourceEntrySchema>
|
|
176
|
+
export type OrganizationModelTopology = z.infer<typeof OmTopologyDomainSchema>
|
|
177
|
+
export type OrganizationModelTopologyNodeKind = z.infer<typeof OmTopologyNodeKindSchema>
|
|
178
|
+
export type OrganizationModelTopologyNodeRef = z.infer<typeof OmTopologyNodeRefSchema>
|
|
179
|
+
export type OrganizationModelTopologyRelationshipKind = z.infer<typeof OmTopologyRelationshipKindSchema>
|
|
180
|
+
export type OrganizationModelTopologyRelationship = z.infer<typeof OmTopologyRelationshipSchema>
|
|
181
|
+
export type OrganizationModelTopologyMetadata = z.infer<typeof OmTopologyMetadataSchema>
|
|
182
|
+
export type OrganizationModelActions = z.infer<typeof ActionsDomainSchema>
|
|
169
183
|
export type OrganizationModelAction = z.infer<typeof ActionSchema>
|
|
170
184
|
export type OrganizationModelActionId = z.infer<typeof ActionIdSchema>
|
|
171
185
|
export type OrganizationModelActionScope = z.infer<typeof ActionScopeSchema>
|
|
@@ -304,13 +304,24 @@ describe('validateResourceGovernance', () => {
|
|
|
304
304
|
order: 20
|
|
305
305
|
}
|
|
306
306
|
|
|
307
|
-
const workflowResource: ResourceEntry = {
|
|
308
|
-
id: 'lead-import',
|
|
309
|
-
kind: 'workflow',
|
|
310
|
-
systemPath: 'sys.lead-gen',
|
|
311
|
-
status: 'active',
|
|
312
|
-
order: 10
|
|
313
|
-
}
|
|
307
|
+
const workflowResource: ResourceEntry = {
|
|
308
|
+
id: 'lead-import',
|
|
309
|
+
kind: 'workflow',
|
|
310
|
+
systemPath: 'sys.lead-gen',
|
|
311
|
+
status: 'active',
|
|
312
|
+
order: 10
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
const actionBackedWorkflowResource: ResourceEntry = {
|
|
316
|
+
...workflowResource,
|
|
317
|
+
ontology: {
|
|
318
|
+
actions: ['sys.lead-gen:action/import-leads'],
|
|
319
|
+
primaryAction: 'sys.lead-gen:action/import-leads',
|
|
320
|
+
reads: ['sys.lead-gen:object/company'],
|
|
321
|
+
usesCatalogs: ['sys.lead-gen:catalog/source'],
|
|
322
|
+
emits: ['sys.lead-gen:event/imported']
|
|
323
|
+
}
|
|
324
|
+
}
|
|
314
325
|
|
|
315
326
|
const agentResource: ResourceEntry = {
|
|
316
327
|
id: 'lead-import',
|
|
@@ -361,10 +372,42 @@ describe('validateResourceGovernance', () => {
|
|
|
361
372
|
entryPoint: 'start'
|
|
362
373
|
})
|
|
363
374
|
|
|
364
|
-
const
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
375
|
+
const validOntology = {
|
|
376
|
+
objectTypes: {
|
|
377
|
+
'sys.lead-gen:object/company': {
|
|
378
|
+
id: 'sys.lead-gen:object/company',
|
|
379
|
+
label: 'Company'
|
|
380
|
+
}
|
|
381
|
+
},
|
|
382
|
+
actionTypes: {
|
|
383
|
+
'sys.lead-gen:action/import-leads': {
|
|
384
|
+
id: 'sys.lead-gen:action/import-leads',
|
|
385
|
+
label: 'Import leads'
|
|
386
|
+
}
|
|
387
|
+
},
|
|
388
|
+
catalogTypes: {
|
|
389
|
+
'sys.lead-gen:catalog/source': {
|
|
390
|
+
id: 'sys.lead-gen:catalog/source',
|
|
391
|
+
label: 'Source'
|
|
392
|
+
}
|
|
393
|
+
},
|
|
394
|
+
eventTypes: {
|
|
395
|
+
'sys.lead-gen:event/imported': {
|
|
396
|
+
id: 'sys.lead-gen:event/imported',
|
|
397
|
+
label: 'Imported'
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
const createModel = (
|
|
403
|
+
resources: ResourceEntry[] = [workflowResource],
|
|
404
|
+
systems = [systemA],
|
|
405
|
+
extras: Record<string, unknown> = {}
|
|
406
|
+
) => ({
|
|
407
|
+
systems: Object.fromEntries(systems.map((s) => [s.id, s])),
|
|
408
|
+
resources: Object.fromEntries(resources.map((r) => [r.id, r])),
|
|
409
|
+
...extras
|
|
410
|
+
})
|
|
368
411
|
|
|
369
412
|
it('passes when code resources are descriptor-backed and match active OM Resources and Systems', () => {
|
|
370
413
|
const result = validateResourceGovernance(
|
|
@@ -484,7 +527,7 @@ describe('validateResourceGovernance', () => {
|
|
|
484
527
|
).toThrow("Resource 'lead-import' type mismatch: code has 'workflow', OM has 'agent'")
|
|
485
528
|
})
|
|
486
529
|
|
|
487
|
-
it('reports descriptor/OM system mismatches', () => {
|
|
530
|
+
it('reports descriptor/OM system mismatches', () => {
|
|
488
531
|
const codeDescriptor: ResourceEntry = {
|
|
489
532
|
...workflowResource,
|
|
490
533
|
systemPath: 'sys.crm'
|
|
@@ -500,8 +543,150 @@ describe('validateResourceGovernance', () => {
|
|
|
500
543
|
createModel([workflowResource], [systemA, systemB]),
|
|
501
544
|
{ mode: 'strict' }
|
|
502
545
|
)
|
|
503
|
-
).toThrow("Resource 'lead-import' system mismatch: code descriptor has 'sys.crm', OM has 'sys.lead-gen'")
|
|
504
|
-
})
|
|
546
|
+
).toThrow("Resource 'lead-import' system mismatch: code descriptor has 'sys.crm', OM has 'sys.lead-gen'")
|
|
547
|
+
})
|
|
548
|
+
|
|
549
|
+
it('reports descriptor/OM ontology mismatches', () => {
|
|
550
|
+
const codeDescriptor: ResourceEntry = {
|
|
551
|
+
...workflowResource,
|
|
552
|
+
ontology: undefined
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
expect(() =>
|
|
556
|
+
validateResourceGovernance(
|
|
557
|
+
'test-org',
|
|
558
|
+
{
|
|
559
|
+
version: '1.0.0',
|
|
560
|
+
workflows: [createGovernedWorkflow(codeDescriptor)]
|
|
561
|
+
},
|
|
562
|
+
createModel([actionBackedWorkflowResource], [systemA], { ontology: validOntology }),
|
|
563
|
+
{ mode: 'strict' }
|
|
564
|
+
)
|
|
565
|
+
).toThrow("Resource 'lead-import' ontology descriptor mismatch between code and OM")
|
|
566
|
+
})
|
|
567
|
+
|
|
568
|
+
it('reports missing ontology action refs against compiled OM records', () => {
|
|
569
|
+
const resourceWithMissingAction: ResourceEntry = {
|
|
570
|
+
...workflowResource,
|
|
571
|
+
ontology: {
|
|
572
|
+
actions: ['sys.lead-gen:action/missing'],
|
|
573
|
+
primaryAction: 'sys.lead-gen:action/missing'
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
expect(() =>
|
|
578
|
+
validateResourceGovernance(
|
|
579
|
+
'test-org',
|
|
580
|
+
{
|
|
581
|
+
version: '1.0.0',
|
|
582
|
+
workflows: [createGovernedWorkflow(resourceWithMissingAction)]
|
|
583
|
+
},
|
|
584
|
+
createModel([resourceWithMissingAction], [systemA], { ontology: validOntology }),
|
|
585
|
+
{ mode: 'strict' }
|
|
586
|
+
)
|
|
587
|
+
).toThrow(
|
|
588
|
+
"Resource 'lead-import' ontology.actions references missing action ontology record 'sys.lead-gen:action/missing'"
|
|
589
|
+
)
|
|
590
|
+
})
|
|
591
|
+
|
|
592
|
+
it('reports new ontology diagnostics without throwing in warn-only mode', () => {
|
|
593
|
+
const warnings: string[] = []
|
|
594
|
+
const resourceWithMissingAction: ResourceEntry = {
|
|
595
|
+
...workflowResource,
|
|
596
|
+
ontology: {
|
|
597
|
+
actions: ['sys.lead-gen:action/missing'],
|
|
598
|
+
primaryAction: 'sys.lead-gen:action/missing'
|
|
599
|
+
}
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
const result = validateResourceGovernance(
|
|
603
|
+
'test-org',
|
|
604
|
+
{
|
|
605
|
+
version: '1.0.0',
|
|
606
|
+
workflows: [createGovernedWorkflow(resourceWithMissingAction)]
|
|
607
|
+
},
|
|
608
|
+
createModel([resourceWithMissingAction], [systemA], { ontology: validOntology }),
|
|
609
|
+
{
|
|
610
|
+
mode: 'warn-only',
|
|
611
|
+
onWarning: (issue) => warnings.push(issue.message)
|
|
612
|
+
}
|
|
613
|
+
)
|
|
614
|
+
|
|
615
|
+
expect(result.valid).toBe(false)
|
|
616
|
+
expect(result.issues.map((issue) => issue.type)).toContain('ontology-reference-missing')
|
|
617
|
+
expect(warnings).toContain(
|
|
618
|
+
"[test-org] Resource 'lead-import' ontology.actions references missing action ontology record 'sys.lead-gen:action/missing'."
|
|
619
|
+
)
|
|
620
|
+
})
|
|
621
|
+
|
|
622
|
+
it('reports primaryAction values outside ontology.actions', () => {
|
|
623
|
+
const resourceWithMismatchedPrimaryAction: ResourceEntry = {
|
|
624
|
+
...workflowResource,
|
|
625
|
+
ontology: {
|
|
626
|
+
actions: ['sys.lead-gen:action/import-leads'],
|
|
627
|
+
primaryAction: 'sys.lead-gen:action/other'
|
|
628
|
+
}
|
|
629
|
+
}
|
|
630
|
+
|
|
631
|
+
expect(() =>
|
|
632
|
+
validateResourceGovernance(
|
|
633
|
+
'test-org',
|
|
634
|
+
{
|
|
635
|
+
version: '1.0.0',
|
|
636
|
+
workflows: [createGovernedWorkflow(resourceWithMismatchedPrimaryAction)]
|
|
637
|
+
},
|
|
638
|
+
createModel([resourceWithMismatchedPrimaryAction], [systemA], { ontology: validOntology }),
|
|
639
|
+
{ mode: 'strict' }
|
|
640
|
+
)
|
|
641
|
+
).toThrow("Resource 'lead-import' primaryAction 'sys.lead-gen:action/other' must be included in ontology.actions")
|
|
642
|
+
})
|
|
643
|
+
|
|
644
|
+
it('reports action-backed workflow descriptors that omit ontology.actions', () => {
|
|
645
|
+
const resourceWithoutActions: ResourceEntry = {
|
|
646
|
+
...workflowResource,
|
|
647
|
+
ontology: {
|
|
648
|
+
reads: ['sys.lead-gen:object/company']
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
|
|
652
|
+
expect(() =>
|
|
653
|
+
validateResourceGovernance(
|
|
654
|
+
'test-org',
|
|
655
|
+
{
|
|
656
|
+
version: '1.0.0',
|
|
657
|
+
workflows: [createGovernedWorkflow(resourceWithoutActions)]
|
|
658
|
+
},
|
|
659
|
+
createModel([resourceWithoutActions], [systemA], { ontology: validOntology }),
|
|
660
|
+
{ mode: 'strict' }
|
|
661
|
+
)
|
|
662
|
+
).toThrow("Resource 'lead-import' declares ontology bindings but no ontology actions")
|
|
663
|
+
})
|
|
664
|
+
|
|
665
|
+
it('reports dangling required topology refs', () => {
|
|
666
|
+
expect(() =>
|
|
667
|
+
validateResourceGovernance(
|
|
668
|
+
'test-org',
|
|
669
|
+
{
|
|
670
|
+
version: '1.0.0',
|
|
671
|
+
workflows: [createGovernedWorkflow()]
|
|
672
|
+
},
|
|
673
|
+
createModel([workflowResource], [systemA], {
|
|
674
|
+
topology: {
|
|
675
|
+
version: 1,
|
|
676
|
+
relationships: {
|
|
677
|
+
'missing-trigger-starts-import': {
|
|
678
|
+
from: { kind: 'trigger', id: 'missing-trigger' },
|
|
679
|
+
kind: 'triggers',
|
|
680
|
+
to: { kind: 'resource', id: 'lead-import' },
|
|
681
|
+
required: true
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
}),
|
|
686
|
+
{ mode: 'strict' }
|
|
687
|
+
)
|
|
688
|
+
).toThrow("Topology relationship 'missing-trigger-starts-import' from references missing trigger 'missing-trigger'")
|
|
689
|
+
})
|
|
505
690
|
|
|
506
691
|
it('reports active OM resources that reference missing Systems', () => {
|
|
507
692
|
const resourceWithMissingSystem: ResourceEntry = {
|
|
@@ -12,10 +12,8 @@
|
|
|
12
12
|
import type { WorkflowDefinition } from '../../execution/engine/workflow/types'
|
|
13
13
|
import type { AgentDefinition } from '../../execution/engine/agent/core/types'
|
|
14
14
|
import type {
|
|
15
|
-
OrganizationModel
|
|
16
|
-
|
|
17
|
-
OrganizationModelSystems
|
|
18
|
-
} from '../../organization-model/types'
|
|
15
|
+
OrganizationModel
|
|
16
|
+
} from '../../organization-model/types'
|
|
19
17
|
import type { ResourceEntry } from '../../organization-model/domains/resources'
|
|
20
18
|
import type { SystemEntry } from '../../organization-model/domains/systems'
|
|
21
19
|
import { listAllSystems } from '../../organization-model/helpers'
|
|
@@ -106,13 +104,15 @@ export interface SystemConfig {
|
|
|
106
104
|
* Used by ResourceRegistry for discovery and Command View for visualization.
|
|
107
105
|
*/
|
|
108
106
|
export interface DeploymentSpec {
|
|
109
|
-
/** Deployment version (semver) */
|
|
110
|
-
version: string
|
|
111
|
-
/** Optional Organization Model governance catalog used for OM-code validation */
|
|
112
|
-
organizationModel?:
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
107
|
+
/** Deployment version (semver) */
|
|
108
|
+
version: string
|
|
109
|
+
/** Optional Organization Model governance catalog used for OM-code validation */
|
|
110
|
+
organizationModel?: Partial<
|
|
111
|
+
Pick<
|
|
112
|
+
OrganizationModel,
|
|
113
|
+
'systems' | 'resources' | 'ontology' | 'topology' | 'roles' | 'policies' | 'entities' | 'actions'
|
|
114
|
+
>
|
|
115
|
+
>
|
|
116
116
|
/** Workflow definitions */
|
|
117
117
|
workflows?: WorkflowDefinition[]
|
|
118
118
|
/** Agent definitions */
|