@elevasis/core 0.10.0 → 0.11.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 (43) hide show
  1. package/dist/index.d.ts +67 -159
  2. package/dist/index.js +321 -613
  3. package/dist/organization-model/index.d.ts +67 -159
  4. package/dist/organization-model/index.js +321 -613
  5. package/dist/test-utils/index.d.ts +17 -45
  6. package/dist/test-utils/index.js +254 -600
  7. package/package.json +1 -1
  8. package/src/__tests__/template-core-compatibility.test.ts +73 -91
  9. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +62 -148
  10. package/src/organization-model/README.md +101 -97
  11. package/src/organization-model/__tests__/domains/resource-mappings.test.ts +24 -93
  12. package/src/organization-model/__tests__/graph.test.ts +82 -894
  13. package/src/organization-model/__tests__/resolve.test.ts +59 -690
  14. package/src/organization-model/__tests__/schema.test.ts +83 -407
  15. package/src/organization-model/defaults.ts +276 -141
  16. package/src/organization-model/domains/features.ts +31 -22
  17. package/src/organization-model/foundation.ts +42 -54
  18. package/src/organization-model/graph/build.ts +42 -217
  19. package/src/organization-model/graph/index.ts +4 -4
  20. package/src/organization-model/graph/link.ts +10 -0
  21. package/src/organization-model/graph/schema.ts +21 -16
  22. package/src/organization-model/graph/types.ts +10 -10
  23. package/src/organization-model/helpers.ts +74 -0
  24. package/src/organization-model/index.ts +7 -7
  25. package/src/organization-model/organization-graph.mdx +89 -272
  26. package/src/organization-model/organization-model.mdx +149 -320
  27. package/src/organization-model/published.ts +15 -15
  28. package/src/organization-model/resolve.ts +8 -33
  29. package/src/organization-model/schema.ts +63 -205
  30. package/src/organization-model/types.ts +12 -11
  31. package/src/platform/registry/__tests__/command-view.test.ts +6 -5
  32. package/src/platform/registry/__tests__/resource-link.test.ts +30 -0
  33. package/src/platform/registry/__tests__/resource-registry.integration.test.ts +15 -15
  34. package/src/platform/registry/command-view.ts +10 -12
  35. package/src/platform/registry/index.ts +13 -8
  36. package/src/platform/registry/resource-link.ts +32 -0
  37. package/src/platform/registry/resource-registry.ts +12 -10
  38. package/src/platform/registry/serialization.ts +56 -73
  39. package/src/platform/registry/serialized-types.ts +17 -12
  40. package/src/platform/registry/types.ts +14 -43
  41. package/src/reference/_generated/contracts.md +62 -148
  42. package/src/reference/glossary.md +71 -105
  43. package/src/platform/registry/domains.ts +0 -165
@@ -1,97 +1,101 @@
1
- # Organization Model
2
-
3
- The organization model is the published semantic contract that maps a tenant's product shape to domain surfaces, features, and navigation.
4
-
5
- Use this module when you need to resolve or validate an organization's contract before wiring UI shells, routing, or domain-specific capability checks.
6
-
7
- ## Published Exports
8
-
9
- The public entry point exposes:
10
-
11
- - `OrganizationModelSchema`
12
- - `DEFAULT_ORGANIZATION_MODEL`
13
- - `defineOrganizationModel`
14
- - `resolveOrganizationModel`
15
- - `PROJECTS_FEATURE_ID`
16
- - `PROJECTS_INDEX_SURFACE_ID`
17
- - `PROJECTS_VIEW_CAPABILITY_ID`
18
- - `OrganizationModel` and the supporting domain types
19
-
20
- Import it from the published subpath:
21
-
22
- ```ts
23
- import {
24
- DEFAULT_ORGANIZATION_MODEL,
25
- PROJECTS_VIEW_CAPABILITY_ID,
26
- defineOrganizationModel,
27
- PROJECTS_FEATURE_ID,
28
- PROJECTS_INDEX_SURFACE_ID,
29
- resolveOrganizationModel,
30
- type OrganizationModel
31
- } from '@elevasis/core/organization-model'
32
- ```
33
-
34
- ## Contract Shape
35
-
36
- The model is versioned and currently validates against `version: 1`.
37
-
38
- Top-level fields:
39
-
40
- - `version` - schema version for the resolved contract.
41
- - `branding` - organization branding defaults and overrides.
42
- - `features` - unified feature entries that combine enablement, labels, and semantic references.
43
- - `navigation` - navigation model for the product shell.
44
- - `sales` - sales pipeline and relationship management.
45
- - `prospecting` - lists, companies, and contacts.
46
- - `projects` - projects, milestones, and tasks.
47
- - `identity`, `customers`, `offerings`, `roles`, `goals` - reality domains (2026-04 expansion).
48
- - `statuses` - unified status registry across delivery / hitl / execution / request / schedule.
49
- - `operations` - catalog of stateful runtime entities (HITL queue, sessions, executions, notifications, schedules).
50
- - `resourceMappings` - cross-surface resource mappings (includes techStack subsection).
51
-
52
- ## Default Feature Set
53
-
54
- The default model includes eight feature IDs:
55
-
56
- - `sales` - deal pipeline and relationship management.
57
- - `prospecting` - lists, companies, and contacts.
58
- - `projects` - projects, milestones, and tasks.
59
- - `operations` - organization graph and command-view surfaces.
60
- - `monitoring` - monitoring surfaces.
61
- - `settings` - organization settings.
62
- - `seo` - SEO surfaces (disabled by default).
63
- - `configure` - `/configure` skill entry point (external projects).
64
-
65
- ## Project Bridge Constants
66
-
67
- The organization-model surface exports a narrow set of canonical IDs for the shared Projects bridge:
68
-
69
- - `PROJECTS_FEATURE_ID` -> `projects`
70
- - `PROJECTS_INDEX_SURFACE_ID` -> `projects.index`
71
- - `PROJECTS_VIEW_CAPABILITY_ID` -> `delivery.projects.view`
72
-
73
- Use these when wiring shared UI manifests, template adapters, or other consumers that need to agree on the same Projects contract without repeating raw literals.
74
-
75
- ## Resolution Semantics
76
-
77
- - `defineOrganizationModel()` is a typed helper. It does not validate or merge anything by itself.
78
- - `resolveOrganizationModel()` deep-merges a partial override into the default model, then validates the result with `OrganizationModelSchema`.
79
- - Plain objects merge recursively.
80
- - Arrays replace the default value instead of merging element-by-element.
81
- - If `navigation.surfaces` is replaced without also supplying `navigation.groups`, inherited default groups are dropped when they no longer point at declared surfaces.
82
- - Missing fields fall back to `DEFAULT_ORGANIZATION_MODEL`.
83
-
84
- ## Referential Integrity
85
-
86
- - `navigation.defaultSurfaceId` must point at a declared navigation surface.
87
- - Every navigation group `surfaceId` must resolve to a declared surface.
88
- - Feature, surface, and resource-mapping IDs must resolve to declared counterparts; dangling references fail validation.
89
- - Feature-to-surface and feature/surface-to-resource links are validated in both directions so one-sided declarations fail during resolution.
90
- - Feature-bearing surfaces validate `featureId` against the canonical feature set.
91
-
92
- ## Practical Guidance
93
-
94
- - Use `resolveOrganizationModel()` when you need a runtime-safe model for rendering or policy checks.
95
- - Use `defineOrganizationModel()` when authoring a static partial model in source.
96
- - Treat feature IDs such as `sales`, `prospecting`, and `projects` as the canonical shell-level contract in new organization-model authoring.
97
- - Keep feature IDs, surface IDs, and capability IDs stable because downstream UI and policy code depend on them.
1
+ # Organization Model
2
+
3
+ The organization model is the published semantic contract that maps a tenant's product shape to flat feature hierarchy, shell navigation, business semantics, and graph bindings.
4
+
5
+ Use this module when resolving or validating an organization's contract before wiring UI shells, routing, feature gates, or domain-specific capability checks.
6
+
7
+ ## Published Exports
8
+
9
+ The public entry point exposes:
10
+
11
+ - `OrganizationModelSchema`
12
+ - `FeatureSchema`
13
+ - `DEFAULT_ORGANIZATION_MODEL`
14
+ - `defineOrganizationModel`
15
+ - `resolveOrganizationModel`
16
+ - `createFoundationOrganizationModel`
17
+ - node ID and feature helper types
18
+ - `OrganizationModel` and supporting domain types
19
+
20
+ Import it from the published subpath:
21
+
22
+ ```ts
23
+ import {
24
+ DEFAULT_ORGANIZATION_MODEL,
25
+ createFoundationOrganizationModel,
26
+ defineOrganizationModel,
27
+ resolveOrganizationModel,
28
+ type OrganizationModel
29
+ } from '@elevasis/core/organization-model'
30
+ ```
31
+
32
+ ## Contract Shape
33
+
34
+ The model is versioned and currently validates against `version: 1`.
35
+
36
+ Top-level fields:
37
+
38
+ - `version`
39
+ - `branding`
40
+ - `features`
41
+ - `navigation`
42
+ - `sales`
43
+ - `prospecting`
44
+ - `projects`
45
+ - `identity`
46
+ - `customers`
47
+ - `offerings`
48
+ - `roles`
49
+ - `goals`
50
+ - `statuses`
51
+ - `operations`
52
+
53
+ Resources bind to the graph from deployment metadata through `links` and `category`.
54
+
55
+ ## Feature Set
56
+
57
+ Feature hierarchy is authored as a flat array. Dotted IDs define parent/child relationships:
58
+
59
+ ```ts
60
+ features: [
61
+ { id: 'dashboard', label: 'Dashboard', enabled: true, path: '/', uiPosition: 'sidebar-primary' },
62
+ { id: 'sales', label: 'Sales', enabled: true, uiPosition: 'sidebar-primary' },
63
+ { id: 'sales.crm', label: 'CRM', enabled: true, path: '/crm' },
64
+ { id: 'operations.resources', label: 'Resources', enabled: true, path: '/operations/resources' }
65
+ ]
66
+ ```
67
+
68
+ Containers omit `path`; leaves provide `path`. `uiPosition`, `requiresAdmin`, and `devOnly` inherit from ancestors.
69
+
70
+ ## Graph IDs
71
+
72
+ Cross-collection links use kind-prefixed IDs:
73
+
74
+ - `feature:sales.crm`
75
+ - `integration:instantly`
76
+ - `resource:lead-import`
77
+ - `capability:operations.queue.review`
78
+
79
+ ## Resolution Semantics
80
+
81
+ - `defineOrganizationModel()` is a typed helper.
82
+ - `resolveOrganizationModel()` deep-merges a partial override into the default model, then validates it.
83
+ - `createFoundationOrganizationModel()` resolves the canonical model and returns UI-facing helper outputs.
84
+ - Plain objects merge recursively.
85
+ - Arrays replace the default value.
86
+ - Missing fields fall back to `DEFAULT_ORGANIZATION_MODEL`.
87
+
88
+ ## Referential Integrity
89
+
90
+ - Feature IDs must be unique.
91
+ - Child feature IDs require ancestor feature nodes.
92
+ - Container features omit `path`.
93
+ - Leaf features provide `path`.
94
+ - Resource links are validated against graph node IDs during registry registration.
95
+
96
+ ## Practical Guidance
97
+
98
+ - Use `resolveOrganizationModel()` when you need a runtime-safe model.
99
+ - Use `defineOrganizationModel()` when authoring static overrides.
100
+ - Keep feature IDs stable because shell routing, gating, breadcrumbs, and docs depend on them.
101
+ - Put semantic resource relationships on resource metadata, not on feature nodes.
@@ -267,96 +267,27 @@ describe('ResourceMappingSchema — mixed techStack presence across entries', ()
267
267
  // Group 6: Integration via resolveOrganizationModel
268
268
  // ---------------------------------------------------------------------------
269
269
 
270
- describe('resolveOrganizationModel resourceMappings with techStack', () => {
271
- it('resolves a model with no resourceMappings (default empty array)', () => {
272
- const model = resolveOrganizationModel({})
273
- expect(model.resourceMappings).toEqual([])
274
- })
275
-
276
- it('resolves a model with a resourceMapping that has no techStack', () => {
277
- const model = resolveOrganizationModel({
278
- resourceMappings: [
279
- {
280
- id: 'rm-legacy',
281
- label: 'Legacy mapping',
282
- resourceId: 'legacy-workflow',
283
- resourceType: 'workflow',
284
- featureIds: [],
285
- entityIds: [],
286
- surfaceIds: [],
287
- capabilityIds: []
288
- }
289
- ]
290
- })
291
- expect(model.resourceMappings).toHaveLength(1)
292
- expect(model.resourceMappings[0].techStack).toBeUndefined()
293
- })
294
-
295
- it('resolves a model with a resourceMapping that has techStack', () => {
296
- const model = resolveOrganizationModel({
297
- resourceMappings: [
298
- {
299
- id: 'rm-crm-sync',
300
- label: 'CRM Sync',
301
- resourceId: 'crm-sync-workflow',
302
- resourceType: 'workflow',
303
- featureIds: [],
304
- entityIds: [],
305
- surfaceIds: [],
306
- capabilityIds: [],
307
- techStack: {
308
- platform: 'Salesforce',
309
- purpose: 'Enterprise CRM integration',
310
- credentialStatus: 'configured',
311
- isSystemOfRecord: true
312
- }
313
- }
314
- ]
315
- })
316
- expect(model.resourceMappings).toHaveLength(1)
317
- const mapping = model.resourceMappings[0]
318
- expect(mapping.techStack).toBeDefined()
319
- expect(mapping.techStack?.platform).toBe('Salesforce')
320
- expect(mapping.techStack?.isSystemOfRecord).toBe(true)
321
- })
322
-
323
- it('resolves multiple mappings with mixed techStack presence', () => {
324
- const model = resolveOrganizationModel({
325
- resourceMappings: [
326
- {
327
- id: 'rm-a',
328
- label: 'Mapping A',
329
- resourceId: 'workflow-a',
330
- resourceType: 'workflow',
331
- featureIds: [],
332
- entityIds: [],
333
- surfaceIds: [],
334
- capabilityIds: [],
335
- techStack: {
336
- platform: 'HubSpot',
337
- purpose: 'Contacts',
338
- credentialStatus: 'pending'
339
- }
340
- },
341
- {
342
- id: 'rm-b',
343
- label: 'Mapping B',
344
- resourceId: 'workflow-b',
345
- resourceType: 'agent',
346
- featureIds: [],
347
- entityIds: [],
348
- surfaceIds: [],
349
- capabilityIds: []
350
- }
351
- ]
352
- })
353
- expect(model.resourceMappings).toHaveLength(2)
354
- expect(model.resourceMappings[0].techStack?.platform).toBe('HubSpot')
355
- expect(model.resourceMappings[0].techStack?.isSystemOfRecord).toBe(false)
356
- expect(model.resourceMappings[1].techStack).toBeUndefined()
357
- })
358
-
359
- it('resolved model still validates without errors when resourceMappings omitted', () => {
360
- expect(() => resolveOrganizationModel({})).not.toThrow()
361
- })
362
- })
270
+ describe('resolveOrganizationModel resource mapping removal', () => {
271
+ it('resolved model validates without resourceMappings', () => {
272
+ expect(() => resolveOrganizationModel({})).not.toThrow()
273
+ })
274
+
275
+ it('drops resourceMappings overrides because graph links now live on resources', () => {
276
+ const model = resolveOrganizationModel({
277
+ resourceMappings: [
278
+ {
279
+ id: 'rm-legacy',
280
+ label: 'Legacy mapping',
281
+ resourceId: 'legacy-workflow',
282
+ resourceType: 'workflow',
283
+ featureIds: [],
284
+ entityIds: [],
285
+ surfaceIds: [],
286
+ capabilityIds: []
287
+ }
288
+ ]
289
+ } as Parameters<typeof resolveOrganizationModel>[0])
290
+
291
+ expect('resourceMappings' in model).toBe(false)
292
+ })
293
+ })