@elevasis/core 0.2.0 → 0.3.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 (44) hide show
  1. package/dist/index.d.ts +60 -103
  2. package/dist/index.js +162 -109
  3. package/dist/organization-model/index.d.ts +60 -103
  4. package/dist/organization-model/index.js +162 -109
  5. package/package.json +1 -1
  6. package/src/README.md +24 -17
  7. package/src/__tests__/template-foundations-compatibility.test.ts +28 -36
  8. package/src/auth/multi-tenancy/types.ts +4 -11
  9. package/src/auth/multi-tenancy/users/api-schemas.ts +1 -1
  10. package/src/business/base-entities.test.ts +481 -0
  11. package/src/business/base-entities.ts +241 -0
  12. package/src/business/delivery/types.ts +1 -1
  13. package/src/business/index.ts +3 -0
  14. package/src/execution/index.ts +3 -6
  15. package/src/index.ts +1 -1
  16. package/src/organization-model/README.md +25 -26
  17. package/src/organization-model/__tests__/graph.test.ts +103 -71
  18. package/src/organization-model/__tests__/resolve.test.ts +20 -29
  19. package/src/organization-model/contracts.ts +3 -0
  20. package/src/organization-model/defaults.ts +40 -6
  21. package/src/organization-model/domains/features.ts +19 -54
  22. package/src/organization-model/domains/navigation.ts +25 -16
  23. package/src/organization-model/domains/shared.ts +1 -10
  24. package/src/organization-model/foundation.ts +96 -0
  25. package/src/organization-model/graph/build.ts +34 -67
  26. package/src/organization-model/graph/schema.ts +2 -4
  27. package/src/organization-model/graph/types.ts +3 -15
  28. package/src/organization-model/index.ts +2 -0
  29. package/src/organization-model/organization-model.mdx +34 -36
  30. package/src/organization-model/published.ts +12 -3
  31. package/src/organization-model/schema.ts +38 -34
  32. package/src/organization-model/types.ts +5 -10
  33. package/src/platform/constants/versions.ts +1 -1
  34. package/src/platform/sse/events.ts +1 -34
  35. package/src/projects/api-schemas.ts +2 -1
  36. package/src/reference/_generated/contracts.md +10 -31
  37. package/src/reference/glossary.md +14 -18
  38. package/src/supabase/database.types.ts +0 -107
  39. package/src/test-utils/rls/RLSTestContext.ts +1 -31
  40. package/src/execution/calibration/__tests__/schemas.test.ts +0 -320
  41. package/src/execution/calibration/index.ts +0 -3
  42. package/src/execution/calibration/schemas.ts +0 -121
  43. package/src/execution/calibration/sse-events.ts +0 -125
  44. package/src/execution/calibration/types.ts +0 -190
@@ -1,18 +1,23 @@
1
1
  import type { OrganizationModel } from './types'
2
+ import {
3
+ DELIVERY_PROJECTS_VIEW_CAPABILITY_ID,
4
+ PROJECTS_FEATURE_ID,
5
+ PROJECTS_INDEX_SURFACE_ID
6
+ } from './contracts'
2
7
  import { DEFAULT_ORGANIZATION_MODEL_BRANDING } from './domains/branding'
3
8
  import { DEFAULT_ORGANIZATION_MODEL_CRM } from './domains/crm'
4
9
  import { DEFAULT_ORGANIZATION_MODEL_DELIVERY } from './domains/delivery'
5
- import { DEFAULT_ORGANIZATION_MODEL_FEATURES } from './domains/features'
6
10
  import { DEFAULT_ORGANIZATION_MODEL_LEAD_GEN } from './domains/lead-gen'
7
11
  import { DEFAULT_ORGANIZATION_MODEL_NAVIGATION } from './domains/navigation'
8
12
 
9
13
  export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
10
14
  version: 1,
11
- domains: [
15
+ features: [
12
16
  {
13
17
  id: 'crm',
14
18
  label: 'CRM',
15
19
  description: 'Relationship pipeline and deal management',
20
+ enabled: true,
16
21
  color: 'blue',
17
22
  entityIds: ['crm.deal'],
18
23
  surfaceIds: ['crm.pipeline'],
@@ -23,6 +28,7 @@ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
23
28
  id: 'lead-gen',
24
29
  label: 'Lead Gen',
25
30
  description: 'Prospecting, qualification, and outreach preparation',
31
+ enabled: true,
26
32
  color: 'cyan',
27
33
  entityIds: ['leadgen.list', 'leadgen.company', 'leadgen.contact'],
28
34
  surfaceIds: ['lead-gen.lists'],
@@ -30,28 +36,56 @@ export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
30
36
  capabilityIds: ['leadgen.lists.manage']
31
37
  },
32
38
  {
33
- id: 'delivery',
39
+ id: PROJECTS_FEATURE_ID,
34
40
  label: 'Projects',
35
41
  description: 'Projects, milestones, and client work execution',
42
+ enabled: true,
36
43
  color: 'orange',
37
44
  entityIds: ['delivery.project', 'delivery.milestone', 'delivery.task'],
38
- surfaceIds: ['projects.index'],
45
+ surfaceIds: [PROJECTS_INDEX_SURFACE_ID],
39
46
  resourceIds: [],
40
- capabilityIds: ['delivery.projects.view']
47
+ capabilityIds: [DELIVERY_PROJECTS_VIEW_CAPABILITY_ID]
41
48
  },
42
49
  {
43
50
  id: 'operations',
44
51
  label: 'Operations',
45
52
  description: 'Operational resources, topology, and orchestration visibility',
53
+ enabled: true,
46
54
  color: 'violet',
47
55
  entityIds: [],
48
56
  surfaceIds: ['operations.organization-graph', 'operations.command-view'],
49
57
  resourceIds: [],
50
58
  capabilityIds: ['operations.organization-graph', 'operations.command-view']
59
+ },
60
+ {
61
+ id: 'monitoring',
62
+ label: 'Monitoring',
63
+ enabled: true,
64
+ entityIds: [],
65
+ surfaceIds: [],
66
+ resourceIds: [],
67
+ capabilityIds: []
68
+ },
69
+ {
70
+ id: 'settings',
71
+ label: 'Settings',
72
+ enabled: true,
73
+ entityIds: [],
74
+ surfaceIds: [],
75
+ resourceIds: [],
76
+ capabilityIds: []
77
+ },
78
+ {
79
+ id: 'seo',
80
+ label: 'SEO',
81
+ enabled: false,
82
+ entityIds: [],
83
+ surfaceIds: [],
84
+ resourceIds: [],
85
+ capabilityIds: []
51
86
  }
52
87
  ],
53
88
  branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
54
- features: DEFAULT_ORGANIZATION_MODEL_FEATURES,
55
89
  navigation: DEFAULT_ORGANIZATION_MODEL_NAVIGATION,
56
90
  crm: DEFAULT_ORGANIZATION_MODEL_CRM,
57
91
  leadGen: DEFAULT_ORGANIZATION_MODEL_LEAD_GEN,
@@ -1,57 +1,22 @@
1
1
  import { z } from 'zod'
2
+ import {
3
+ ColorTokenSchema,
4
+ DescriptionSchema,
5
+ IconNameSchema,
6
+ LabelSchema,
7
+ ModelIdSchema,
8
+ ReferenceIdsSchema
9
+ } from './shared'
2
10
 
3
- export const FeatureKeySchema = z.enum([
4
- 'acquisition',
5
- 'delivery',
6
- 'operations',
7
- 'monitoring',
8
- 'settings',
9
- 'seo',
10
- 'calibration'
11
- ])
12
-
13
- export const OrganizationModelFeaturesSchema = z.object({
14
- enabled: z
15
- .object({
16
- acquisition: z.boolean().default(true),
17
- delivery: z.boolean().default(true),
18
- operations: z.boolean().default(true),
19
- monitoring: z.boolean().default(true),
20
- settings: z.boolean().default(true),
21
- seo: z.boolean().default(false),
22
- calibration: z.boolean().default(false)
23
- })
24
- .default({
25
- acquisition: true,
26
- delivery: true,
27
- operations: true,
28
- monitoring: true,
29
- settings: true,
30
- seo: false,
31
- calibration: false
32
- }),
33
- labels: z
34
- .object({
35
- acquisition: z.string().trim().min(1).max(80).optional(),
36
- delivery: z.string().trim().min(1).max(80).optional(),
37
- operations: z.string().trim().min(1).max(80).optional(),
38
- monitoring: z.string().trim().min(1).max(80).optional(),
39
- settings: z.string().trim().min(1).max(80).optional(),
40
- seo: z.string().trim().min(1).max(80).optional(),
41
- calibration: z.string().trim().min(1).max(80).optional()
42
- })
43
- .default({})
11
+ export const FeatureSchema = z.object({
12
+ id: ModelIdSchema,
13
+ label: LabelSchema,
14
+ description: DescriptionSchema.optional(),
15
+ enabled: z.boolean().default(true),
16
+ color: ColorTokenSchema.optional(),
17
+ icon: IconNameSchema.optional(),
18
+ entityIds: ReferenceIdsSchema,
19
+ surfaceIds: ReferenceIdsSchema,
20
+ resourceIds: ReferenceIdsSchema,
21
+ capabilityIds: ReferenceIdsSchema
44
22
  })
45
-
46
- export const DEFAULT_ORGANIZATION_MODEL_FEATURES: z.infer<typeof OrganizationModelFeaturesSchema> = {
47
- enabled: {
48
- acquisition: true,
49
- delivery: true,
50
- operations: true,
51
- monitoring: true,
52
- settings: true,
53
- seo: false,
54
- calibration: false
55
- },
56
- labels: {}
57
- }
@@ -1,5 +1,9 @@
1
1
  import { z } from 'zod'
2
- import { FeatureKeySchema } from './features'
2
+ import {
3
+ DELIVERY_PROJECTS_VIEW_CAPABILITY_ID,
4
+ PROJECTS_FEATURE_ID,
5
+ PROJECTS_INDEX_SURFACE_ID
6
+ } from '../contracts'
3
7
  import { DescriptionSchema, IconNameSchema, LabelSchema, ModelIdSchema, PathSchema, ReferenceIdsSchema } from './shared'
4
8
 
5
9
  export const SurfaceTypeSchema = z.enum(['page', 'dashboard', 'graph', 'detail', 'list', 'settings'])
@@ -11,8 +15,8 @@ export const SurfaceDefinitionSchema = z.object({
11
15
  surfaceType: SurfaceTypeSchema,
12
16
  description: DescriptionSchema.optional(),
13
17
  icon: IconNameSchema.optional(),
14
- featureKey: FeatureKeySchema.optional(),
15
- domainIds: ReferenceIdsSchema,
18
+ featureId: ModelIdSchema.optional(),
19
+ featureIds: ReferenceIdsSchema,
16
20
  entityIds: ReferenceIdsSchema,
17
21
  resourceIds: ReferenceIdsSchema,
18
22
  capabilityIds: ReferenceIdsSchema,
@@ -40,8 +44,8 @@ export const DEFAULT_ORGANIZATION_MODEL_NAVIGATION: z.infer<typeof OrganizationM
40
44
  label: 'Pipeline',
41
45
  path: '/crm/pipeline',
42
46
  surfaceType: 'graph',
43
- featureKey: 'acquisition',
44
- domainIds: ['crm'],
47
+ featureId: 'crm',
48
+ featureIds: ['crm'],
45
49
  entityIds: ['crm.deal'],
46
50
  resourceIds: [],
47
51
  capabilityIds: ['crm.pipeline.manage']
@@ -51,30 +55,30 @@ export const DEFAULT_ORGANIZATION_MODEL_NAVIGATION: z.infer<typeof OrganizationM
51
55
  label: 'Lists',
52
56
  path: '/lead-gen/lists',
53
57
  surfaceType: 'list',
54
- featureKey: 'acquisition',
55
- domainIds: ['lead-gen'],
58
+ featureId: 'lead-gen',
59
+ featureIds: ['lead-gen'],
56
60
  entityIds: ['leadgen.list'],
57
61
  resourceIds: [],
58
62
  capabilityIds: ['leadgen.lists.manage']
59
63
  },
60
64
  {
61
- id: 'projects.index',
65
+ id: PROJECTS_INDEX_SURFACE_ID,
62
66
  label: 'Projects',
63
67
  path: '/projects',
64
68
  surfaceType: 'list',
65
- featureKey: 'delivery',
66
- domainIds: ['delivery'],
69
+ featureId: PROJECTS_FEATURE_ID,
70
+ featureIds: [PROJECTS_FEATURE_ID],
67
71
  entityIds: ['delivery.project'],
68
72
  resourceIds: [],
69
- capabilityIds: ['delivery.projects.view']
73
+ capabilityIds: [DELIVERY_PROJECTS_VIEW_CAPABILITY_ID]
70
74
  },
71
75
  {
72
76
  id: 'operations.organization-graph',
73
77
  label: 'Organization Graph',
74
78
  path: '/operations/organization-graph',
75
79
  surfaceType: 'graph',
76
- featureKey: 'operations',
77
- domainIds: ['operations'],
80
+ featureId: 'operations',
81
+ featureIds: ['operations'],
78
82
  entityIds: [],
79
83
  resourceIds: [],
80
84
  capabilityIds: ['operations.organization-graph']
@@ -84,15 +88,20 @@ export const DEFAULT_ORGANIZATION_MODEL_NAVIGATION: z.infer<typeof OrganizationM
84
88
  label: 'Command View',
85
89
  path: '/operations/command-view',
86
90
  surfaceType: 'graph',
87
- featureKey: 'operations',
88
- domainIds: ['operations'],
91
+ featureId: 'operations',
92
+ featureIds: ['operations'],
89
93
  entityIds: [],
90
94
  resourceIds: [],
91
95
  capabilityIds: ['operations.command-view']
92
96
  }
93
97
  ],
94
98
  groups: [
95
- { id: 'primary-workspace', label: 'Workspace', placement: 'primary', surfaceIds: ['crm.pipeline', 'lead-gen.lists', 'projects.index'] },
99
+ {
100
+ id: 'primary-workspace',
101
+ label: 'Workspace',
102
+ placement: 'primary',
103
+ surfaceIds: ['crm.pipeline', 'lead-gen.lists', PROJECTS_INDEX_SURFACE_ID]
104
+ },
96
105
  {
97
106
  id: 'primary-operations',
98
107
  label: 'Operations',
@@ -22,21 +22,12 @@ export const DisplayMetadataSchema = z.object({
22
22
  icon: IconNameSchema.optional()
23
23
  })
24
24
 
25
- export const SemanticDomainSchema = DisplayMetadataSchema.extend({
26
- id: ModelIdSchema,
27
- entityIds: ReferenceIdsSchema,
28
- surfaceIds: ReferenceIdsSchema,
29
- resourceIds: ReferenceIdsSchema,
30
- capabilityIds: ReferenceIdsSchema
31
- })
32
-
33
25
  export const ResourceMappingSchema = DisplayMetadataSchema.extend({
34
26
  id: ModelIdSchema,
35
27
  resourceId: z.string().trim().min(1).max(255),
36
28
  resourceType: z.enum(['workflow', 'agent', 'trigger', 'integration', 'external', 'human_checkpoint']),
37
- domainIds: ReferenceIdsSchema,
29
+ featureIds: ReferenceIdsSchema,
38
30
  entityIds: ReferenceIdsSchema,
39
31
  surfaceIds: ReferenceIdsSchema,
40
32
  capabilityIds: ReferenceIdsSchema
41
33
  })
42
-
@@ -0,0 +1,96 @@
1
+ import { PROJECTS_FEATURE_ID, PROJECTS_INDEX_SURFACE_ID } from './contracts'
2
+ import { resolveOrganizationModel } from './resolve'
3
+ import type { OrganizationModel, OrganizationModelSurface } from './types'
4
+
5
+ export type FoundationSurfaceType = OrganizationModelSurface['surfaceType']
6
+
7
+ export type FoundationSurfaceIcon = 'dashboard' | 'crm' | 'lead-gen' | 'projects' | 'operations' | 'settings'
8
+
9
+ export interface FoundationNavigationSurface extends Omit<OrganizationModelSurface, 'icon'> {
10
+ icon?: FoundationSurfaceIcon
11
+ }
12
+
13
+ export interface FoundationOrganizationModel extends Omit<OrganizationModel, 'navigation'> {
14
+ navigation: {
15
+ defaultSurfaceId: string
16
+ homeLabel: string
17
+ quickAccessSurfaceIds: readonly string[]
18
+ surfaces: FoundationNavigationSurface[]
19
+ }
20
+ }
21
+
22
+ export interface FoundationBranding {
23
+ organizationName: string
24
+ productName: string
25
+ shortName: string
26
+ }
27
+
28
+ export function createFoundationOrganizationModel(branding: FoundationBranding): {
29
+ canonical: OrganizationModel
30
+ model: FoundationOrganizationModel
31
+ homeLabel: string
32
+ quickAccessSurfaceIds: readonly string[]
33
+ getOrganizationSurface: (surfaceId: string) => FoundationNavigationSurface | undefined
34
+ } {
35
+ const canonical = resolveOrganizationModel({ branding })
36
+
37
+ function requireCoreSurface(surfaceId: string): OrganizationModelSurface {
38
+ const surface = canonical.navigation.surfaces.find((candidate) => candidate.id === surfaceId)
39
+
40
+ if (!surface) {
41
+ throw new Error(`Missing organization surface: ${surfaceId}`)
42
+ }
43
+
44
+ return surface
45
+ }
46
+
47
+ const operationsGraphSurface = requireCoreSurface('operations.organization-graph')
48
+ const projectsSurface = requireCoreSurface(PROJECTS_INDEX_SURFACE_ID)
49
+ const leadGenSurface = requireCoreSurface('lead-gen.lists')
50
+ const crmSurface = requireCoreSurface('crm.pipeline')
51
+
52
+ const navigationSurfaces: FoundationNavigationSurface[] = [
53
+ { ...operationsGraphSurface, id: 'operations', path: '/operations', icon: 'operations' },
54
+ { ...operationsGraphSurface, path: '/operations', icon: 'operations' },
55
+ { ...projectsSurface, id: PROJECTS_FEATURE_ID, icon: 'projects' },
56
+ { ...leadGenSurface, id: 'lead-gen', icon: 'lead-gen' },
57
+ { ...crmSurface, id: 'crm', icon: 'crm' },
58
+ {
59
+ id: 'settings',
60
+ label: 'Settings',
61
+ path: '/settings/account',
62
+ surfaceType: 'settings',
63
+ icon: 'settings',
64
+ featureId: 'settings',
65
+ featureIds: ['settings'],
66
+ entityIds: [],
67
+ resourceIds: [],
68
+ capabilityIds: []
69
+ }
70
+ ]
71
+
72
+ const homeLabel = 'Dashboard'
73
+ const quickAccessSurfaceIds = ['operations', PROJECTS_FEATURE_ID, 'lead-gen', 'crm'] as const
74
+
75
+ const model: FoundationOrganizationModel = {
76
+ ...canonical,
77
+ navigation: {
78
+ defaultSurfaceId: 'operations',
79
+ homeLabel,
80
+ quickAccessSurfaceIds: [...quickAccessSurfaceIds],
81
+ surfaces: navigationSurfaces
82
+ }
83
+ }
84
+
85
+ function getOrganizationSurface(surfaceId: string): FoundationNavigationSurface | undefined {
86
+ return model.navigation.surfaces.find((candidate) => candidate.id === surfaceId)
87
+ }
88
+
89
+ return {
90
+ canonical,
91
+ model,
92
+ homeLabel,
93
+ quickAccessSurfaceIds,
94
+ getOrganizationSurface
95
+ }
96
+ }
@@ -73,16 +73,6 @@ function ensureResourceNode(
73
73
  })
74
74
  }
75
75
 
76
- function titleCase(value: string): string {
77
- return value
78
- .replace(/[-_.]+/g, ' ')
79
- .replace(/\s+/g, ' ')
80
- .trim()
81
- .split(' ')
82
- .map((part) => part.charAt(0).toUpperCase() + part.slice(1))
83
- .join(' ')
84
- }
85
-
86
76
  type CommandViewResource =
87
77
  | CommandViewData['workflows'][number]
88
78
  | CommandViewData['agents'][number]
@@ -126,38 +116,10 @@ export function buildOrganizationGraph(input: BuildOrganizationGraphInput): Orga
126
116
  }
127
117
  pushUniqueNode(nodes, nodeIds, organizationNode)
128
118
 
129
- const featureEntries = Object.entries(organizationModel.features.enabled)
130
- .map(([featureKey, enabled]) => {
131
- const key = featureKey as keyof typeof organizationModel.features.enabled
132
- return {
133
- key: featureKey,
134
- enabled,
135
- label: organizationModel.features.labels[key] ?? titleCase(featureKey)
136
- }
137
- })
138
- .sort((a, b) => a.key.localeCompare(b.key))
139
-
140
- for (const feature of featureEntries) {
141
- const id = nodeId('feature', feature.key)
142
- pushUniqueNode(nodes, nodeIds, {
143
- id,
144
- kind: 'feature',
145
- label: feature.label,
146
- sourceId: feature.key,
147
- enabled: feature.enabled,
148
- featureKey: feature.key as OrganizationGraphNode['featureKey']
149
- })
150
- pushUniqueEdge(edges, edgeIds, {
151
- id: edgeId('contains', organizationNode.id, id),
152
- kind: 'contains',
153
- sourceId: organizationNode.id,
154
- targetId: id
155
- })
156
- }
157
-
158
- const domainMap = new Map<string, (typeof organizationModel.domains)[number]>()
159
- for (const domain of organizationModel.domains) {
160
- domainMap.set(domain.id, domain)
119
+ // Build feature map for lookups
120
+ const featureMap = new Map<string, (typeof organizationModel.features)[number]>()
121
+ for (const feature of organizationModel.features) {
122
+ featureMap.set(feature.id, feature)
161
123
  }
162
124
 
163
125
  const surfaceMap = new Map<string, (typeof organizationModel.navigation.surfaces)[number]>()
@@ -167,7 +129,9 @@ export function buildOrganizationGraph(input: BuildOrganizationGraphInput): Orga
167
129
 
168
130
  const entityIds = new Set<string>()
169
131
  const capabilityIds = new Set<string>()
170
- const resourceMappings = [...organizationModel.resourceMappings].sort((a, b) => a.resourceId.localeCompare(b.resourceId))
132
+ const resourceMappings = [...organizationModel.resourceMappings].sort((a, b) =>
133
+ a.resourceId.localeCompare(b.resourceId)
134
+ )
171
135
  for (const resourceMapping of resourceMappings) {
172
136
  for (const entityId of resourceMapping.entityIds) {
173
137
  entityIds.add(entityId)
@@ -177,14 +141,17 @@ export function buildOrganizationGraph(input: BuildOrganizationGraphInput): Orga
177
141
  }
178
142
  }
179
143
 
180
- for (const domain of [...organizationModel.domains].sort((a, b) => a.id.localeCompare(b.id))) {
181
- const id = nodeId('domain', domain.id)
144
+ // Unified feature loop: creates feature nodes with semantic data (replaces old feature + domain loops)
145
+ for (const feature of [...organizationModel.features].sort((a, b) => a.id.localeCompare(b.id))) {
146
+ const id = nodeId('feature', feature.id)
182
147
  pushUniqueNode(nodes, nodeIds, {
183
148
  id,
184
- kind: 'domain',
185
- label: domain.label,
186
- sourceId: domain.id,
187
- description: domain.description
149
+ kind: 'feature',
150
+ label: feature.label,
151
+ sourceId: feature.id,
152
+ description: feature.description,
153
+ enabled: feature.enabled,
154
+ featureId: feature.id
188
155
  })
189
156
  pushUniqueEdge(edges, edgeIds, {
190
157
  id: edgeId('contains', organizationNode.id, id),
@@ -193,13 +160,13 @@ export function buildOrganizationGraph(input: BuildOrganizationGraphInput): Orga
193
160
  targetId: id
194
161
  })
195
162
 
196
- for (const entityId of domain.entityIds) {
163
+ for (const entityId of feature.entityIds) {
197
164
  entityIds.add(entityId)
198
165
  }
199
- for (const capabilityId of domain.capabilityIds) {
166
+ for (const capabilityId of feature.capabilityIds) {
200
167
  capabilityIds.add(capabilityId)
201
168
  }
202
- for (const surfaceId of domain.surfaceIds) {
169
+ for (const surfaceId of feature.surfaceIds) {
203
170
  const surface = surfaceMap.get(surfaceId)
204
171
  if (surface) {
205
172
  pushUniqueEdge(edges, edgeIds, {
@@ -229,22 +196,22 @@ export function buildOrganizationGraph(input: BuildOrganizationGraphInput): Orga
229
196
  targetId: id
230
197
  })
231
198
 
232
- if (surface.featureKey) {
199
+ if (surface.featureId) {
233
200
  pushUniqueEdge(edges, edgeIds, {
234
- id: edgeId('exposes', nodeId('feature', surface.featureKey), id),
201
+ id: edgeId('exposes', nodeId('feature', surface.featureId), id),
235
202
  kind: 'exposes',
236
- sourceId: nodeId('feature', surface.featureKey),
203
+ sourceId: nodeId('feature', surface.featureId),
237
204
  targetId: id
238
205
  })
239
206
  }
240
207
 
241
- for (const domainId of surface.domainIds) {
242
- if (domainMap.has(domainId)) {
208
+ for (const featureId of surface.featureIds) {
209
+ if (featureMap.has(featureId)) {
243
210
  pushUniqueEdge(edges, edgeIds, {
244
- id: edgeId('references', id, nodeId('domain', domainId)),
211
+ id: edgeId('references', id, nodeId('feature', featureId)),
245
212
  kind: 'references',
246
213
  sourceId: id,
247
- targetId: nodeId('domain', domainId)
214
+ targetId: nodeId('feature', featureId)
248
215
  })
249
216
  }
250
217
  }
@@ -317,13 +284,13 @@ export function buildOrganizationGraph(input: BuildOrganizationGraphInput): Orga
317
284
  targetId: id
318
285
  })
319
286
 
320
- for (const domainId of resourceMapping.domainIds) {
321
- if (domainMap.has(domainId)) {
287
+ for (const featureId of resourceMapping.featureIds) {
288
+ if (featureMap.has(featureId)) {
322
289
  pushUniqueEdge(edges, edgeIds, {
323
- id: edgeId('maps_to', id, nodeId('domain', domainId)),
290
+ id: edgeId('maps_to', id, nodeId('feature', featureId)),
324
291
  kind: 'maps_to',
325
292
  sourceId: id,
326
- targetId: nodeId('domain', domainId)
293
+ targetId: nodeId('feature', featureId)
327
294
  })
328
295
  }
329
296
  }
@@ -374,13 +341,13 @@ export function buildOrganizationGraph(input: BuildOrganizationGraphInput): Orga
374
341
  resourceType: normalizeCommandViewResourceType(resource.type)
375
342
  })
376
343
 
377
- for (const domainId of resource.domains ?? []) {
378
- if (domainMap.has(domainId)) {
344
+ for (const featureId of resource.domains ?? []) {
345
+ if (featureMap.has(featureId)) {
379
346
  pushUniqueEdge(edges, edgeIds, {
380
- id: edgeId('references', resourceNode.id, nodeId('domain', domainId), 'domain'),
347
+ id: edgeId('references', resourceNode.id, nodeId('feature', featureId), 'feature'),
381
348
  kind: 'references',
382
349
  sourceId: resourceNode.id,
383
- targetId: nodeId('domain', domainId)
350
+ targetId: nodeId('feature', featureId)
384
351
  })
385
352
  }
386
353
  }
@@ -1,13 +1,11 @@
1
1
  import { z } from 'zod'
2
- import { DescriptionSchema, LabelSchema } from '../domains/shared'
3
- import { FeatureKeySchema } from '../domains/features'
2
+ import { DescriptionSchema, LabelSchema, ModelIdSchema } from '../domains/shared'
4
3
  import { SurfaceTypeSchema } from '../domains/navigation'
5
4
  import { OrganizationModelSchema } from '../schema'
6
5
 
7
6
  export const OrganizationGraphNodeKindSchema = z.enum([
8
7
  'organization',
9
8
  'feature',
10
- 'domain',
11
9
  'surface',
12
10
  'entity',
13
11
  'capability',
@@ -23,7 +21,7 @@ export const OrganizationGraphNodeSchema = z.object({
23
21
  sourceId: z.string().trim().min(1).max(255).optional(),
24
22
  description: DescriptionSchema.optional(),
25
23
  enabled: z.boolean().optional(),
26
- featureKey: FeatureKeySchema.optional(),
24
+ featureId: ModelIdSchema.optional(),
27
25
  surfaceType: SurfaceTypeSchema.optional(),
28
26
  resourceType: z.enum(['workflow', 'agent', 'trigger', 'integration', 'external', 'human_checkpoint']).optional()
29
27
  })
@@ -1,20 +1,8 @@
1
1
  import type { CommandViewData } from '../../platform/registry/command-view'
2
- import type {
3
- OrganizationModel,
4
- OrganizationModelFeatureKey,
5
- OrganizationModelResourceMapping,
6
- OrganizationModelSurface
7
- } from '../types'
2
+ import type { OrganizationModel, OrganizationModelResourceMapping, OrganizationModelSurface } from '../types'
8
3
  import type { RelationshipType } from '../../platform/registry/command-view'
9
4
 
10
- export type OrganizationGraphNodeKind =
11
- | 'organization'
12
- | 'feature'
13
- | 'domain'
14
- | 'surface'
15
- | 'entity'
16
- | 'capability'
17
- | 'resource'
5
+ export type OrganizationGraphNodeKind = 'organization' | 'feature' | 'surface' | 'entity' | 'capability' | 'resource'
18
6
 
19
7
  export type OrganizationGraphEdgeKind = 'contains' | 'references' | 'exposes' | 'maps_to'
20
8
 
@@ -25,7 +13,7 @@ export interface OrganizationGraphNode {
25
13
  sourceId?: string
26
14
  description?: string
27
15
  enabled?: boolean
28
- featureKey?: OrganizationModelFeatureKey
16
+ featureId?: string
29
17
  surfaceType?: OrganizationModelSurface['surfaceType']
30
18
  resourceType?: OrganizationModelResourceMapping['resourceType']
31
19
  }
@@ -1,7 +1,9 @@
1
1
  export * from './schema'
2
2
  export * from './types'
3
+ export * from './contracts'
3
4
  export * from './defaults'
4
5
  export * from './resolve'
6
+ export * from './foundation'
5
7
  export * from './graph'
6
8
  export * from './domains/branding'
7
9
  export * from './domains/crm'