@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,148 +1,283 @@
1
- import type { OrganizationModel } from './types'
2
- import {
3
- SALES_FEATURE_ID,
4
- SALES_PIPELINE_SURFACE_ID,
5
- PROJECTS_VIEW_CAPABILITY_ID,
6
- PROSPECTING_FEATURE_ID,
7
- PROSPECTING_LISTS_SURFACE_ID,
8
- MONITORING_FEATURE_ID,
9
- OPERATIONS_FEATURE_ID,
10
- OPERATIONS_ORGANIZATION_GRAPH_SURFACE_ID,
11
- PROJECTS_FEATURE_ID,
12
- PROJECTS_INDEX_SURFACE_ID,
13
- SETTINGS_FEATURE_ID,
14
- SEO_FEATURE_ID
15
- } from './contracts'
16
- import { DEFAULT_ORGANIZATION_MODEL_BRANDING } from './domains/branding'
17
- import { DEFAULT_ORGANIZATION_MODEL_IDENTITY } from './domains/identity'
18
- import { DEFAULT_ORGANIZATION_MODEL_CUSTOMERS } from './domains/customers'
1
+ import type { OrganizationModel } from './types'
2
+ import { DEFAULT_ORGANIZATION_MODEL_BRANDING } from './domains/branding'
3
+ import { DEFAULT_ORGANIZATION_MODEL_IDENTITY } from './domains/identity'
4
+ import { DEFAULT_ORGANIZATION_MODEL_CUSTOMERS } from './domains/customers'
19
5
  import { DEFAULT_ORGANIZATION_MODEL_OFFERINGS } from './domains/offerings'
20
- import { DEFAULT_ORGANIZATION_MODEL_SALES } from './domains/sales'
21
- import { DEFAULT_ORGANIZATION_MODEL_PROJECTS } from './domains/projects'
22
- import { DEFAULT_ORGANIZATION_MODEL_PROSPECTING } from './domains/prospecting'
23
- import { DEFAULT_ORGANIZATION_MODEL_NAVIGATION } from './domains/navigation'
24
- import { DEFAULT_ORGANIZATION_MODEL_OPERATIONS } from './domains/operations'
25
- import { DEFAULT_ORGANIZATION_MODEL_ROLES } from './domains/roles'
26
- import { DEFAULT_ORGANIZATION_MODEL_GOALS } from './domains/goals'
6
+ import { DEFAULT_ORGANIZATION_MODEL_SALES } from './domains/sales'
7
+ import { DEFAULT_ORGANIZATION_MODEL_PROJECTS } from './domains/projects'
8
+ import { DEFAULT_ORGANIZATION_MODEL_PROSPECTING } from './domains/prospecting'
9
+ import { DEFAULT_ORGANIZATION_MODEL_OPERATIONS } from './domains/operations'
10
+ import { DEFAULT_ORGANIZATION_MODEL_ROLES } from './domains/roles'
11
+ import { DEFAULT_ORGANIZATION_MODEL_GOALS } from './domains/goals'
27
12
  import { DEFAULT_ORGANIZATION_MODEL_STATUSES } from './domains/statuses'
28
13
 
29
14
  export const DEFAULT_ORGANIZATION_MODEL: OrganizationModel = {
30
- version: 1,
31
- features: [
32
- {
33
- id: SALES_FEATURE_ID,
34
- label: 'CRM',
35
- description: 'Relationship pipeline and deal management',
36
- enabled: true,
37
- color: 'blue',
38
- entityIds: ['crm.deal'],
39
- surfaceIds: [SALES_PIPELINE_SURFACE_ID],
40
- resourceIds: [],
41
- capabilityIds: ['crm.pipeline.manage']
42
- },
43
- {
44
- id: PROSPECTING_FEATURE_ID,
45
- label: 'Lead Gen',
46
- description: 'Prospecting, qualification, and outreach preparation',
47
- enabled: true,
48
- color: 'cyan',
49
- entityIds: ['leadgen.list', 'leadgen.company', 'leadgen.contact'],
50
- surfaceIds: [PROSPECTING_LISTS_SURFACE_ID],
51
- resourceIds: [],
52
- capabilityIds: ['leadgen.lists.manage']
53
- },
54
- {
55
- id: PROJECTS_FEATURE_ID,
56
- label: 'Projects',
57
- description: 'Projects, milestones, and client work execution',
58
- enabled: true,
59
- color: 'orange',
60
- entityIds: ['delivery.project', 'delivery.milestone', 'delivery.task'],
61
- surfaceIds: [PROJECTS_INDEX_SURFACE_ID],
62
- resourceIds: [],
63
- capabilityIds: [PROJECTS_VIEW_CAPABILITY_ID]
64
- },
65
- {
66
- id: OPERATIONS_FEATURE_ID,
67
- label: 'Operations',
68
- description: 'Operational resources, topology, and orchestration visibility',
69
- enabled: true,
70
- color: 'violet',
71
- entityIds: [],
72
- surfaceIds: [
73
- OPERATIONS_ORGANIZATION_GRAPH_SURFACE_ID,
74
- 'operations.command-view',
75
- 'operations.overview',
76
- 'operations.resources',
77
- 'operations.command-queue',
78
- 'operations.sessions',
79
- 'operations.task-scheduler'
80
- ],
81
- resourceIds: [],
82
- capabilityIds: ['operations.organization-graph', 'operations.command-view']
83
- },
84
- {
85
- id: MONITORING_FEATURE_ID,
86
- label: 'Monitoring',
87
- enabled: true,
88
- entityIds: [],
89
- surfaceIds: [
90
- 'monitoring.activity-log',
91
- 'monitoring.execution-logs',
92
- 'monitoring.execution-health',
93
- 'monitoring.cost-analytics',
94
- 'monitoring.notifications'
95
- ],
96
- resourceIds: [],
97
- capabilityIds: []
98
- },
99
- {
100
- id: SETTINGS_FEATURE_ID,
101
- label: 'Settings',
102
- enabled: true,
103
- entityIds: [],
104
- surfaceIds: [
105
- 'settings.account',
106
- 'settings.appearance',
107
- 'settings.organization',
108
- 'settings.credentials',
109
- 'settings.api-keys',
110
- 'settings.webhooks',
111
- 'settings.deployments'
112
- ],
113
- resourceIds: [],
114
- capabilityIds: []
115
- },
116
- {
117
- id: 'submitted-requests',
118
- label: 'Submitted Requests',
119
- enabled: true,
120
- entityIds: ['reported_request'],
121
- surfaceIds: ['submitted-requests.list', 'submitted-requests.detail'],
122
- resourceIds: [],
123
- capabilityIds: []
124
- },
125
- {
126
- id: SEO_FEATURE_ID,
127
- label: 'SEO',
128
- enabled: false,
129
- entityIds: [],
130
- surfaceIds: [],
131
- resourceIds: [],
132
- capabilityIds: []
133
- }
134
- ],
135
- branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
136
- navigation: DEFAULT_ORGANIZATION_MODEL_NAVIGATION,
137
- sales: DEFAULT_ORGANIZATION_MODEL_SALES,
138
- prospecting: DEFAULT_ORGANIZATION_MODEL_PROSPECTING,
139
- projects: DEFAULT_ORGANIZATION_MODEL_PROJECTS,
15
+ version: 1,
16
+ features: [
17
+ {
18
+ id: 'dashboard',
19
+ label: 'Dashboard',
20
+ enabled: true,
21
+ path: '/',
22
+ icon: 'dashboard',
23
+ uiPosition: 'sidebar-primary'
24
+ },
25
+ {
26
+ id: 'sales',
27
+ label: 'Sales',
28
+ description: 'Revenue workflows and customer acquisition',
29
+ enabled: true,
30
+ color: 'blue',
31
+ icon: 'crm',
32
+ uiPosition: 'sidebar-primary'
33
+ },
34
+ {
35
+ id: 'sales.crm',
36
+ label: 'CRM',
37
+ description: 'Relationship pipeline and deal management',
38
+ enabled: true,
39
+ color: 'blue',
40
+ icon: 'crm',
41
+ path: '/crm'
42
+ },
43
+ {
44
+ id: 'sales.lead-gen',
45
+ label: 'Lead Gen',
46
+ description: 'Prospecting, qualification, and outreach preparation',
47
+ enabled: true,
48
+ color: 'cyan',
49
+ icon: 'lead-gen',
50
+ path: '/lead-gen'
51
+ },
52
+ {
53
+ id: 'projects',
54
+ label: 'Projects',
55
+ description: 'Projects, milestones, and client work execution',
56
+ enabled: true,
57
+ color: 'orange',
58
+ icon: 'projects',
59
+ path: '/projects',
60
+ uiPosition: 'sidebar-primary'
61
+ },
62
+ {
63
+ id: 'operations',
64
+ label: 'Operations',
65
+ description: 'Operational resources, topology, and orchestration visibility',
66
+ enabled: true,
67
+ color: 'violet',
68
+ icon: 'operations',
69
+ uiPosition: 'sidebar-primary'
70
+ },
71
+ {
72
+ id: 'operations.graph',
73
+ label: 'Organization Graph',
74
+ enabled: true,
75
+ path: '/operations/organization-graph'
76
+ },
77
+ {
78
+ id: 'operations.command-view',
79
+ label: 'Command View',
80
+ enabled: false,
81
+ path: '/operations/command-view'
82
+ },
83
+ {
84
+ id: 'operations.overview',
85
+ label: 'Overview',
86
+ enabled: true,
87
+ path: '/operations'
88
+ },
89
+ {
90
+ id: 'operations.resources',
91
+ label: 'Resources',
92
+ enabled: true,
93
+ path: '/operations/resources'
94
+ },
95
+ {
96
+ id: 'operations.command-queue',
97
+ label: 'Command Queue',
98
+ enabled: true,
99
+ path: '/operations/command-queue'
100
+ },
101
+ {
102
+ id: 'operations.sessions',
103
+ label: 'Sessions',
104
+ enabled: false,
105
+ path: '/operations/sessions'
106
+ },
107
+ {
108
+ id: 'operations.task-scheduler',
109
+ label: 'Task Scheduler',
110
+ enabled: true,
111
+ path: '/operations/task-scheduler'
112
+ },
113
+ {
114
+ id: 'monitoring',
115
+ label: 'Monitoring',
116
+ enabled: true,
117
+ uiPosition: 'sidebar-primary'
118
+ },
119
+ {
120
+ id: 'monitoring.activity-log',
121
+ label: 'Activity Log',
122
+ enabled: true,
123
+ path: '/monitoring/activity-log'
124
+ },
125
+ {
126
+ id: 'monitoring.execution-logs',
127
+ label: 'Execution Logs',
128
+ enabled: true,
129
+ path: '/monitoring/execution-logs'
130
+ },
131
+ {
132
+ id: 'monitoring.execution-health',
133
+ label: 'Execution Health',
134
+ enabled: true,
135
+ path: '/monitoring/execution-health'
136
+ },
137
+ {
138
+ id: 'monitoring.cost-analytics',
139
+ label: 'Cost Analytics',
140
+ enabled: false,
141
+ path: '/monitoring/cost-analytics'
142
+ },
143
+ {
144
+ id: 'monitoring.notifications',
145
+ label: 'Notifications',
146
+ enabled: true,
147
+ path: '/monitoring/notifications'
148
+ },
149
+ {
150
+ id: 'monitoring.submitted-requests',
151
+ label: 'Submitted Requests',
152
+ enabled: true,
153
+ path: '/monitoring/requests'
154
+ },
155
+ {
156
+ id: 'settings',
157
+ label: 'Settings',
158
+ enabled: true,
159
+ icon: 'settings',
160
+ uiPosition: 'sidebar-bottom'
161
+ },
162
+ {
163
+ id: 'settings.account',
164
+ label: 'Account',
165
+ enabled: true,
166
+ path: '/settings/account'
167
+ },
168
+ {
169
+ id: 'settings.appearance',
170
+ label: 'Appearance',
171
+ enabled: true,
172
+ path: '/settings/appearance'
173
+ },
174
+ {
175
+ id: 'settings.organization',
176
+ label: 'Organization',
177
+ enabled: true,
178
+ path: '/settings/organization'
179
+ },
180
+ {
181
+ id: 'settings.credentials',
182
+ label: 'Credentials',
183
+ enabled: true,
184
+ path: '/settings/credentials'
185
+ },
186
+ {
187
+ id: 'settings.api-keys',
188
+ label: 'API Keys',
189
+ enabled: true,
190
+ path: '/settings/api-keys'
191
+ },
192
+ {
193
+ id: 'settings.webhooks',
194
+ label: 'Webhooks',
195
+ enabled: true,
196
+ path: '/settings/webhooks'
197
+ },
198
+ {
199
+ id: 'settings.deployments',
200
+ label: 'Deployments',
201
+ enabled: true,
202
+ path: '/settings/deployments'
203
+ },
204
+ {
205
+ id: 'admin',
206
+ label: 'Admin',
207
+ enabled: true,
208
+ path: '/admin',
209
+ icon: 'settings',
210
+ uiPosition: 'sidebar-bottom',
211
+ requiresAdmin: true
212
+ },
213
+ {
214
+ id: 'admin.system-health',
215
+ label: 'System Health',
216
+ enabled: true,
217
+ path: '/admin/system-health'
218
+ },
219
+ {
220
+ id: 'admin.organizations',
221
+ label: 'Organizations',
222
+ enabled: true,
223
+ path: '/admin/organizations'
224
+ },
225
+ {
226
+ id: 'admin.users',
227
+ label: 'Users',
228
+ enabled: true,
229
+ path: '/admin/users'
230
+ },
231
+ {
232
+ id: 'admin.design-showcase',
233
+ label: 'Design Showcase',
234
+ enabled: true,
235
+ path: '/admin/design-showcase'
236
+ },
237
+ {
238
+ id: 'admin.debug',
239
+ label: 'Debug',
240
+ enabled: true,
241
+ path: '/admin/debug'
242
+ },
243
+ {
244
+ id: 'archive',
245
+ label: 'Archive',
246
+ enabled: true,
247
+ path: '/archive',
248
+ icon: 'archive',
249
+ uiPosition: 'sidebar-bottom',
250
+ devOnly: true
251
+ },
252
+ {
253
+ id: 'archive.agent-chat',
254
+ label: 'Agent Chat',
255
+ enabled: true,
256
+ path: '/archive/agent-chat'
257
+ },
258
+ {
259
+ id: 'archive.execution-runner',
260
+ label: 'Execution Runner',
261
+ enabled: true,
262
+ path: '/archive/execution-runner'
263
+ },
264
+ {
265
+ id: 'seo',
266
+ label: 'SEO',
267
+ enabled: false,
268
+ path: '/seo'
269
+ }
270
+ ],
271
+ branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
272
+ navigation: { surfaces: [], groups: [] },
273
+ sales: DEFAULT_ORGANIZATION_MODEL_SALES,
274
+ prospecting: DEFAULT_ORGANIZATION_MODEL_PROSPECTING,
275
+ projects: DEFAULT_ORGANIZATION_MODEL_PROJECTS,
140
276
  identity: DEFAULT_ORGANIZATION_MODEL_IDENTITY,
141
277
  customers: DEFAULT_ORGANIZATION_MODEL_CUSTOMERS,
142
278
  offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
143
- roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
144
- goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
145
- statuses: DEFAULT_ORGANIZATION_MODEL_STATUSES,
146
- operations: DEFAULT_ORGANIZATION_MODEL_OPERATIONS,
147
- resourceMappings: []
148
- }
279
+ roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
280
+ goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
281
+ statuses: DEFAULT_ORGANIZATION_MODEL_STATUSES,
282
+ operations: DEFAULT_ORGANIZATION_MODEL_OPERATIONS
283
+ }
@@ -1,22 +1,31 @@
1
- import { z } from 'zod'
2
- import {
3
- ColorTokenSchema,
4
- DescriptionSchema,
5
- IconNameSchema,
6
- LabelSchema,
7
- ModelIdSchema,
8
- ReferenceIdsSchema
9
- } from './shared'
10
-
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
22
- })
1
+ import { z } from 'zod'
2
+ import { ColorTokenSchema, DescriptionSchema, IconNameSchema, LabelSchema, PathSchema } from './shared'
3
+
4
+ export const NodeIdPathSchema = z
5
+ .string()
6
+ .trim()
7
+ .min(1)
8
+ .max(100)
9
+ .regex(/^([a-z0-9-]+)(\.[a-z0-9-]+)*$/, 'Node IDs must be lowercase dotted paths')
10
+
11
+ export const NodeIdStringSchema = z
12
+ .string()
13
+ .trim()
14
+ .min(1)
15
+ .max(200)
16
+ .regex(/^[a-z]+:([a-z0-9-]+)(\.[a-z0-9-]+)*$/, 'Node references must use kind:dotted-path')
17
+
18
+ export const UiPositionSchema = z.enum(['sidebar-primary', 'sidebar-bottom'])
19
+
20
+ export const FeatureSchema = z.object({
21
+ id: NodeIdPathSchema,
22
+ label: LabelSchema,
23
+ description: DescriptionSchema.optional(),
24
+ enabled: z.boolean().default(true),
25
+ path: PathSchema.optional(),
26
+ icon: IconNameSchema.optional(),
27
+ color: ColorTokenSchema.optional(),
28
+ uiPosition: UiPositionSchema.optional(),
29
+ requiresAdmin: z.boolean().optional(),
30
+ devOnly: z.boolean().optional()
31
+ })
@@ -1,19 +1,19 @@
1
- import { PROJECTS_FEATURE_ID, PROJECTS_INDEX_SURFACE_ID } from './contracts'
2
- import { resolveOrganizationModel } from './resolve'
3
- import type { DeepPartial, 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
1
+ import { resolveOrganizationModel } from './resolve'
2
+ import type { DeepPartial, OrganizationModel, OrganizationModelFeature } from './types'
3
+
4
+ export type FoundationSurfaceType = 'page' | 'dashboard' | 'graph' | 'detail' | 'list' | 'settings'
5
+
6
+ export type FoundationSurfaceIcon = 'dashboard' | 'crm' | 'lead-gen' | 'projects' | 'operations' | 'settings'
7
+
8
+ export interface FoundationNavigationSurface extends Omit<OrganizationModelFeature, 'icon' | 'uiPosition'> {
9
+ icon?: FoundationSurfaceIcon
10
+ surfaceType?: FoundationSurfaceType
11
+ }
12
+
13
+ export interface FoundationOrganizationModel extends Omit<OrganizationModel, 'navigation'> {
14
+ navigation: {
15
+ defaultSurfaceId: string
16
+ homeLabel: string
17
17
  quickAccessSurfaceIds: readonly string[]
18
18
  surfaces: FoundationNavigationSurface[]
19
19
  }
@@ -32,46 +32,34 @@ export function createFoundationOrganizationModel(override: DeepPartial<Organiza
32
32
  quickAccessSurfaceIds: readonly string[]
33
33
  getOrganizationSurface: (surfaceId: string) => FoundationNavigationSurface | undefined
34
34
  } {
35
- const canonical = resolveOrganizationModel(override)
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
- enabled: true,
64
- icon: 'settings',
65
- featureId: 'settings',
66
- featureIds: ['settings'],
67
- entityIds: [],
68
- resourceIds: [],
69
- capabilityIds: []
70
- }
71
- ]
35
+ const canonical = resolveOrganizationModel(override)
36
+
37
+ function requireCoreFeature(featureId: string): OrganizationModelFeature {
38
+ const feature = canonical.features.find((candidate) => candidate.id === featureId)
39
+
40
+ if (!feature) {
41
+ throw new Error(`Missing organization surface/feature: ${featureId}`)
42
+ }
43
+
44
+ return feature
45
+ }
46
+
47
+ const operationsGraphFeature = requireCoreFeature('operations.graph')
48
+ const projectsFeature = requireCoreFeature('projects')
49
+ const leadGenFeature = requireCoreFeature('sales.lead-gen')
50
+ const crmFeature = requireCoreFeature('sales.crm')
51
+
52
+ const navigationSurfaces: FoundationNavigationSurface[] = [
53
+ { ...operationsGraphFeature, id: 'operations', path: '/operations', icon: 'operations', surfaceType: 'graph' },
54
+ { ...operationsGraphFeature, path: '/operations', icon: 'operations', surfaceType: 'graph' },
55
+ { ...projectsFeature, icon: 'projects', surfaceType: 'list' },
56
+ { ...leadGenFeature, id: 'lead-gen', icon: 'lead-gen', surfaceType: 'list' },
57
+ { ...crmFeature, id: 'crm', icon: 'crm', surfaceType: 'graph' },
58
+ { ...requireCoreFeature('settings.account'), id: 'settings', icon: 'settings', surfaceType: 'settings' }
59
+ ]
72
60
 
73
61
  const homeLabel = 'Dashboard'
74
- const quickAccessSurfaceIds = ['operations', PROJECTS_FEATURE_ID, 'lead-gen', 'crm'] as const
62
+ const quickAccessSurfaceIds = ['operations', 'projects', 'lead-gen', 'crm'] as const
75
63
 
76
64
  const model: FoundationOrganizationModel = {
77
65
  ...canonical,