@elevasis/core 0.22.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 (112) hide show
  1. package/dist/index.d.ts +2330 -2391
  2. package/dist/index.js +2322 -1147
  3. package/dist/knowledge/index.d.ts +702 -1136
  4. package/dist/knowledge/index.js +9 -9
  5. package/dist/organization-model/index.d.ts +2330 -2391
  6. package/dist/organization-model/index.js +2322 -1147
  7. package/dist/test-utils/index.d.ts +703 -1106
  8. package/dist/test-utils/index.js +1735 -1089
  9. package/package.json +1 -1
  10. package/src/__tests__/template-core-compatibility.test.ts +11 -79
  11. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +360 -98
  12. package/src/business/acquisition/api-schemas.test.ts +2 -2
  13. package/src/business/acquisition/api-schemas.ts +7 -9
  14. package/src/business/acquisition/build-templates.test.ts +4 -4
  15. package/src/business/acquisition/build-templates.ts +72 -30
  16. package/src/business/acquisition/crm-state-actions.test.ts +13 -11
  17. package/src/business/acquisition/types.ts +7 -3
  18. package/src/execution/engine/agent/core/types.ts +1 -1
  19. package/src/execution/engine/workflow/types.ts +2 -2
  20. package/src/knowledge/README.md +8 -7
  21. package/src/knowledge/__tests__/queries.test.ts +74 -73
  22. package/src/knowledge/format.ts +10 -9
  23. package/src/knowledge/index.ts +1 -1
  24. package/src/knowledge/published.ts +1 -1
  25. package/src/knowledge/queries.ts +26 -25
  26. package/src/organization-model/README.md +66 -26
  27. package/src/organization-model/__tests__/content-kinds-registry.test.ts +210 -0
  28. package/src/organization-model/__tests__/defaults.test.ts +72 -98
  29. package/src/organization-model/__tests__/domains/actions.test.ts +56 -0
  30. package/src/organization-model/__tests__/domains/customers.test.ts +299 -295
  31. package/src/organization-model/__tests__/domains/entities.test.ts +56 -0
  32. package/src/organization-model/__tests__/domains/goals.test.ts +493 -479
  33. package/src/organization-model/__tests__/domains/identity.test.ts +280 -279
  34. package/src/organization-model/__tests__/domains/navigation.test.ts +268 -212
  35. package/src/organization-model/__tests__/domains/offerings.test.ts +414 -419
  36. package/src/organization-model/__tests__/domains/policies.test.ts +323 -0
  37. package/src/organization-model/__tests__/domains/resource-mappings.test.ts +271 -271
  38. package/src/organization-model/__tests__/domains/resources.test.ts +159 -37
  39. package/src/organization-model/__tests__/domains/roles.test.ts +147 -86
  40. package/src/organization-model/__tests__/domains/statuses.test.ts +246 -243
  41. package/src/organization-model/__tests__/domains/systems.test.ts +67 -51
  42. package/src/organization-model/__tests__/flatten-additive-merge.test.ts +361 -0
  43. package/src/organization-model/__tests__/foundation.test.ts +74 -102
  44. package/src/organization-model/__tests__/get-resources-for-system.test.ts +144 -0
  45. package/src/organization-model/__tests__/graph.test.ts +899 -71
  46. package/src/organization-model/__tests__/knowledge.test.ts +173 -52
  47. package/src/organization-model/__tests__/lookup-helpers.test.ts +438 -0
  48. package/src/organization-model/__tests__/migration-helpers.test.ts +591 -0
  49. package/src/organization-model/__tests__/prospecting-ssot.test.ts +36 -27
  50. package/src/organization-model/__tests__/recursive-system-schema.test.ts +520 -0
  51. package/src/organization-model/__tests__/resolve.test.ts +174 -23
  52. package/src/organization-model/__tests__/schema.test.ts +291 -114
  53. package/src/organization-model/__tests__/surface-projection.test.ts +207 -97
  54. package/src/organization-model/catalogs/lead-gen.ts +144 -0
  55. package/src/organization-model/content-kinds/config.ts +36 -0
  56. package/src/organization-model/content-kinds/index.ts +74 -0
  57. package/src/organization-model/content-kinds/pipeline.ts +68 -0
  58. package/src/organization-model/content-kinds/registry.ts +44 -0
  59. package/src/organization-model/content-kinds/status.ts +71 -0
  60. package/src/organization-model/content-kinds/template.ts +83 -0
  61. package/src/organization-model/content-kinds/types.ts +117 -0
  62. package/src/organization-model/contracts.ts +13 -3
  63. package/src/organization-model/defaults.ts +488 -96
  64. package/src/organization-model/domains/actions.ts +239 -0
  65. package/src/organization-model/domains/customers.ts +78 -75
  66. package/src/organization-model/domains/entities.ts +144 -0
  67. package/src/organization-model/domains/goals.ts +83 -80
  68. package/src/organization-model/domains/knowledge.ts +74 -16
  69. package/src/organization-model/domains/navigation.ts +107 -384
  70. package/src/organization-model/domains/offerings.ts +71 -66
  71. package/src/organization-model/domains/policies.ts +102 -0
  72. package/src/organization-model/domains/projects.ts +14 -48
  73. package/src/organization-model/domains/prospecting.ts +62 -181
  74. package/src/organization-model/domains/resources.ts +81 -24
  75. package/src/organization-model/domains/roles.ts +13 -10
  76. package/src/organization-model/domains/sales.ts +10 -219
  77. package/src/organization-model/domains/shared.ts +57 -57
  78. package/src/organization-model/domains/statuses.ts +339 -130
  79. package/src/organization-model/domains/systems.ts +186 -29
  80. package/src/organization-model/foundation.ts +54 -67
  81. package/src/organization-model/graph/build.ts +682 -54
  82. package/src/organization-model/graph/link.ts +1 -1
  83. package/src/organization-model/graph/schema.ts +24 -9
  84. package/src/organization-model/graph/types.ts +20 -7
  85. package/src/organization-model/helpers.ts +231 -26
  86. package/src/organization-model/index.ts +116 -5
  87. package/src/organization-model/migration-helpers.ts +249 -0
  88. package/src/organization-model/organization-graph.mdx +16 -15
  89. package/src/organization-model/organization-model.mdx +89 -41
  90. package/src/organization-model/published.ts +120 -18
  91. package/src/organization-model/resolve.ts +117 -54
  92. package/src/organization-model/schema.ts +561 -140
  93. package/src/organization-model/surface-projection.ts +116 -122
  94. package/src/organization-model/types.ts +102 -21
  95. package/src/platform/constants/versions.ts +1 -1
  96. package/src/platform/registry/__tests__/command-view.test.ts +6 -8
  97. package/src/platform/registry/__tests__/resource-link.test.ts +13 -8
  98. package/src/platform/registry/__tests__/resource-registry.integration.test.ts +16 -31
  99. package/src/platform/registry/__tests__/resource-registry.nested-systems.test.ts +245 -0
  100. package/src/platform/registry/__tests__/resource-registry.test.ts +9 -7
  101. package/src/platform/registry/__tests__/validation.test.ts +15 -11
  102. package/src/platform/registry/resource-registry.ts +20 -8
  103. package/src/platform/registry/serialization.ts +7 -7
  104. package/src/platform/registry/types.ts +3 -3
  105. package/src/platform/registry/validation.ts +17 -15
  106. package/src/reference/_generated/contracts.md +362 -99
  107. package/src/reference/glossary.md +18 -18
  108. package/src/supabase/database.types.ts +60 -0
  109. package/src/test-utils/test-utils.test.ts +1 -6
  110. package/src/organization-model/__tests__/domains/operations.test.ts +0 -203
  111. package/src/organization-model/domains/features.ts +0 -31
  112. package/src/organization-model/domains/operations.ts +0 -85
@@ -1,46 +1,203 @@
1
- import { z } from 'zod'
2
- import { DescriptionSchema, LabelSchema, ModelIdSchema, ReferenceIdsSchema } from './shared'
1
+ import { z, type ZodType } from 'zod'
2
+ import { ActionRefSchema } from './actions'
3
+ import {
4
+ ColorTokenSchema,
5
+ DescriptionSchema,
6
+ IconNameSchema,
7
+ LabelSchema,
8
+ ModelIdSchema,
9
+ PathSchema,
10
+ ReferenceIdsSchema
11
+ } from './shared'
12
+ import { ContentNodeSchema } from '../content-kinds/types'
3
13
 
4
14
  // ---------------------------------------------------------------------------
5
15
  // Systems domain
6
16
  // ---------------------------------------------------------------------------
7
17
  //
8
- // A System is a tenant-defined bounded context that groups operational
9
- // resources and carries governance metadata. The shared schema validates the
10
- // shape and references; each tenant supplies its own catalog.
18
+ // A System is a tenant-defined bounded context. It can carry UI presence,
19
+ // hierarchy, and governance metadata; non-UI systems simply omit `ui`.
11
20
 
12
- export const SystemKindSchema = z.enum(['product', 'operational', 'platform', 'diagnostic'])
13
- export const SystemStatusSchema = z.enum(['active', 'deprecated', 'archived'])
21
+ export const SystemKindSchema = z
22
+ .enum(['product', 'operational', 'platform', 'diagnostic'])
23
+ .meta({ label: 'System kind', color: 'blue' })
24
+ export const SystemLifecycleSchema = z
25
+ .enum(['draft', 'beta', 'active', 'deprecated', 'archived'])
26
+ .meta({ label: 'Lifecycle', color: 'teal' })
27
+ /** @deprecated Use SystemLifecycleSchema. Accepted for one publish cycle. */
28
+ export const SystemStatusSchema = z.enum(['active', 'deprecated', 'archived']).meta({ label: 'Status', color: 'teal' })
14
29
  export const SystemIdSchema = ModelIdSchema
30
+ /**
31
+ * Validates a dot-separated system path (e.g. "sales.lead-gen", "sales.crm").
32
+ * Each segment is lowercase, starts with a letter or digit, and may contain hyphens.
33
+ * This is the canonical form used in `resource.systemPath`.
34
+ */
35
+ export const SystemPathSchema = z
36
+ .string()
37
+ .trim()
38
+ .min(1)
39
+ .regex(
40
+ /^[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)*$/,
41
+ 'must be a dotted lowercase path (e.g. "sales.lead-gen" or "sales.crm")'
42
+ )
43
+ export const UiPositionSchema = z.enum(['sidebar-primary', 'sidebar-bottom']).meta({ label: 'UI position' })
44
+ export const NodeIdPathSchema = SystemIdSchema
45
+ export const NodeIdStringSchema = z
46
+ .string()
47
+ .trim()
48
+ .min(1)
49
+ .max(200)
50
+ // D4: kind prefix allows hyphens (e.g. 'content-node'); id allows colons for
51
+ // qualified content-node references ('content-node:sales.crm:default-pipeline').
52
+ .regex(
53
+ /^[a-z][a-z-]*:([a-z0-9-]+)(\.[a-z0-9-]+)*(:[a-z0-9.-]+)*$/,
54
+ 'Node references must use kind:dotted-path (e.g. system:sales.crm or content-node:sales.crm:pipeline-id)'
55
+ )
15
56
 
16
- export const SystemEntrySchema = z.object({
17
- /** Stable tenant-defined system id (e.g. "sys.lead-gen"). */
18
- id: SystemIdSchema,
19
- /** Human-readable system title shown in governance and operations UI. */
20
- title: LabelSchema,
21
- /** One-paragraph purpose statement for the bounded context. */
22
- description: DescriptionSchema,
23
- /** Closed system shape enum; catalog values remain tenant-defined. */
24
- kind: SystemKindSchema,
25
- /** Optional role responsible for this system. */
26
- responsibleRoleId: ModelIdSchema.optional(),
27
- /** Optional knowledge nodes that govern this system. */
28
- governedByKnowledge: ReferenceIdsSchema,
29
- /** Optional goals this system contributes to. */
30
- drivesGoals: ReferenceIdsSchema,
31
- status: SystemStatusSchema
57
+ export const SystemUiSchema = z.object({
58
+ path: PathSchema,
59
+ surfaces: ReferenceIdsSchema,
60
+ icon: IconNameSchema.optional(),
61
+ order: z.number().int().optional()
32
62
  })
33
63
 
34
- export const SystemsDomainSchema = z.object({
35
- systems: z.array(SystemEntrySchema).default([])
36
- })
64
+ // ---------------------------------------------------------------------------
65
+ // Recursive SystemEntry schema.
66
+ //
67
+ // TypeScript cannot infer the type of a schema that references itself through
68
+ // z.lazy(). The standard Zod fix is to:
69
+ // 1. Declare the output type as an explicit interface BEFORE the schema.
70
+ // 2. Annotate the schema variable with `ZodType<SystemEntry>` so TS uses
71
+ // the declared interface instead of trying to infer through the cycle.
72
+ // ---------------------------------------------------------------------------
73
+
74
+ import type { ContentNode } from '../content-kinds/types'
37
75
 
38
- export const DEFAULT_ORGANIZATION_MODEL_SYSTEMS: z.infer<typeof SystemsDomainSchema> = {
39
- systems: []
76
+ /** Explicit interface needed to annotate the recursive SystemEntrySchema. */
77
+ export interface SystemEntry {
78
+ id: string
79
+ label?: string
80
+ title?: string
81
+ description?: string
82
+ kind?: 'product' | 'operational' | 'platform' | 'diagnostic'
83
+ parentSystemId?: string
84
+ ui?: { path: string; surfaces: string[]; icon?: string; order?: number }
85
+ lifecycle?: 'draft' | 'beta' | 'active' | 'deprecated' | 'archived'
86
+ responsibleRoleId?: string
87
+ governedByKnowledge?: string[]
88
+ actions?: { actionId: string; intent: 'exposes' | 'consumes'; invocation?: unknown }[]
89
+ policies?: string[]
90
+ drivesGoals?: string[]
91
+ /** @deprecated Use lifecycle. Accepted for one publish cycle. */
92
+ status?: 'active' | 'deprecated' | 'archived'
93
+ path?: string
94
+ icon?: string
95
+ color?: string
96
+ uiPosition?: 'sidebar-primary' | 'sidebar-bottom'
97
+ enabled?: boolean
98
+ devOnly?: boolean
99
+ requiresAdmin?: boolean
100
+ order: number
101
+ content?: Record<string, ContentNode>
102
+ subsystems?: Record<string, SystemEntry>
40
103
  }
41
104
 
105
+ export const SystemEntrySchema: ZodType<SystemEntry> = z
106
+ .object({
107
+ /** Stable tenant-defined system id (e.g. "sys.lead-gen" or "sales.crm"). */
108
+ id: SystemIdSchema,
109
+ /** Human-readable system label shown in UI, governance, and operations surfaces. */
110
+ label: LabelSchema.optional(),
111
+ /** @deprecated Use label. Accepted for pre-consolidation System declarations. */
112
+ title: LabelSchema.optional(),
113
+ /** One-paragraph purpose statement for the bounded context. */
114
+ description: DescriptionSchema.optional(),
115
+ /** Closed system shape enum; catalog values remain tenant-defined. */
116
+ kind: SystemKindSchema.optional(),
117
+ /** Optional self-reference for System hierarchy. */
118
+ parentSystemId: SystemIdSchema.optional(),
119
+ /** Optional UI presence. Systems without UI omit this. */
120
+ ui: SystemUiSchema.optional(),
121
+ /** Canonical lifecycle state. Replaces Feature.enabled/devOnly and System.status. */
122
+ lifecycle: SystemLifecycleSchema.optional(),
123
+ /** Optional role responsible for this system. */
124
+ responsibleRoleId: ModelIdSchema.meta({ ref: 'role' }).optional(),
125
+ /** Optional knowledge nodes that govern this system. */
126
+ governedByKnowledge: z
127
+ .array(ModelIdSchema.meta({ ref: 'knowledge' }))
128
+ .default([])
129
+ .optional(),
130
+ /** Optional actions this system exposes or consumes. */
131
+ actions: z.array(ActionRefSchema).optional(),
132
+ /** Optional operational policies that apply to this system. */
133
+ policies: z
134
+ .array(ModelIdSchema.meta({ ref: 'policy' }))
135
+ .default([])
136
+ .optional(),
137
+ /** Optional goals this system contributes to. */
138
+ drivesGoals: z
139
+ .array(ModelIdSchema.meta({ ref: 'goal' }))
140
+ .default([])
141
+ .optional(),
142
+ /** @deprecated Use lifecycle. Accepted for one publish cycle. */
143
+ status: SystemStatusSchema.optional(),
144
+ /** @deprecated Use ui.path. Kept for one-cycle Feature compatibility. */
145
+ path: PathSchema.optional(),
146
+ /** @deprecated Use ui.icon. Kept for one-cycle Feature compatibility. */
147
+ icon: IconNameSchema.optional(),
148
+ /** @deprecated Feature color token, retained for one-cycle compatibility. */
149
+ color: ColorTokenSchema.optional(),
150
+ /** @deprecated UI placement hint, retained for one-cycle compatibility. */
151
+ uiPosition: UiPositionSchema.optional(),
152
+ /** @deprecated Use lifecycle. */
153
+ enabled: z.boolean().optional(),
154
+ /** @deprecated Use lifecycle: "beta". */
155
+ devOnly: z.boolean().optional(),
156
+ requiresAdmin: z.boolean().optional(),
157
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
158
+ order: z.number(),
159
+ /**
160
+ * System-scoped operational data, co-located with the owning system.
161
+ * Per L1, L3, L13: keyed by local NodeId (the key is the local id; qualified
162
+ * id is `<system-path>:<local-id>`, computed by graph projection).
163
+ * Per L14: every ContentNode carries both `kind` and `type`.
164
+ * Per D2: unregistered (kind, type) pairs parse successfully.
165
+ */
166
+ content: z.record(z.string().trim().min(1).max(200), ContentNodeSchema).optional(),
167
+ /**
168
+ * Recursive child systems, authored via nesting (per L11).
169
+ * The key is the local system id; the full path is computed by joining
170
+ * ancestor keys with `.` (e.g. parent key `'sales'` + child key `'crm'` → `'sales.crm'`).
171
+ * Per Phase 4: `id` and `parentSystemId` fields will be removed in favour of
172
+ * position-derived paths. Both still exist on this schema for backward compat.
173
+ */
174
+ subsystems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional()
175
+ })
176
+ .refine((system: SystemEntry) => system.label !== undefined || system.title !== undefined, {
177
+ path: ['label'],
178
+ message: 'System must provide label or title'
179
+ })
180
+ .transform((system: SystemEntry) => {
181
+ if (system.status === undefined) return system
182
+
183
+ console.warn('[organization-model] System.status is deprecated; use System.lifecycle instead.')
184
+ return system.lifecycle === undefined ? { ...system, lifecycle: system.status } : system
185
+ })
186
+
187
+ export const SystemsDomainSchema = z
188
+ .record(z.string(), SystemEntrySchema)
189
+ .refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
190
+ message: 'Each system entry id must match its map key'
191
+ })
192
+ .default({})
193
+
194
+ export const DEFAULT_ORGANIZATION_MODEL_SYSTEMS: z.infer<typeof SystemsDomainSchema> = {}
195
+
42
196
  export type SystemId = z.infer<typeof SystemIdSchema>
43
197
  export type SystemKind = z.infer<typeof SystemKindSchema>
198
+ export type SystemLifecycle = z.infer<typeof SystemLifecycleSchema>
199
+ /** @deprecated Use SystemLifecycle. Accepted for one publish cycle. */
44
200
  export type SystemStatus = z.infer<typeof SystemStatusSchema>
45
- export type SystemEntry = z.infer<typeof SystemEntrySchema>
201
+ // SystemEntry is declared as an explicit interface above the schema (required for
202
+ // recursive z.lazy() type inference). Re-export omitted — the interface IS the type.
46
203
  export type SystemsDomain = z.infer<typeof SystemsDomainSchema>
@@ -1,88 +1,75 @@
1
1
  import { resolveOrganizationModel } from './resolve'
2
2
  import type { OrganizationModelBuiltinIconToken } from './icons'
3
- import type { DeepPartial, OrganizationModel, OrganizationModelFeature } from './types'
3
+ import { projectOrganizationSurfaces, type OrganizationSurfaceProjection } from './surface-projection'
4
+ import type { DeepPartial, OrganizationModel } from './types'
4
5
 
5
6
  export type FoundationSurfaceType = 'page' | 'dashboard' | 'graph' | 'detail' | 'list' | 'settings'
6
7
 
7
8
  export type FoundationSurfaceIcon = Extract<
8
9
  OrganizationModelBuiltinIconToken,
9
- 'feature.dashboard' | 'feature.crm' | 'feature.lead-gen' | 'feature.projects' | 'feature.operations' | 'feature.settings'
10
+ | 'feature.dashboard'
11
+ | 'feature.crm'
12
+ | 'feature.lead-gen'
13
+ | 'feature.projects'
14
+ | 'feature.operations'
15
+ | 'feature.settings'
10
16
  >
11
17
 
12
- export interface FoundationNavigationSurface extends Omit<OrganizationModelFeature, 'icon' | 'uiPosition'> {
13
- icon?: FoundationSurfaceIcon
14
- surfaceType?: FoundationSurfaceType
18
+ export type FoundationNavigationSurface = Omit<OrganizationSurfaceProjection, 'icon' | 'surfaceType'> & {
19
+ icon?: FoundationSurfaceIcon | OrganizationModelBuiltinIconToken | string
20
+ surfaceType: FoundationSurfaceType
15
21
  }
16
22
 
17
23
  export interface FoundationOrganizationModel extends Omit<OrganizationModel, 'navigation'> {
18
24
  navigation: {
19
25
  defaultSurfaceId: string
20
26
  homeLabel: string
21
- quickAccessSurfaceIds: readonly string[]
22
- surfaces: FoundationNavigationSurface[]
23
- }
24
- }
25
-
26
- export interface FoundationBranding {
27
- organizationName: string
28
- productName: string
29
- shortName: string
30
- }
31
-
32
- export function createFoundationOrganizationModel(override: DeepPartial<OrganizationModel>): {
33
- canonical: OrganizationModel
34
- model: FoundationOrganizationModel
35
- homeLabel: string
36
- quickAccessSurfaceIds: readonly string[]
37
- getOrganizationSurface: (surfaceId: string) => FoundationNavigationSurface | undefined
38
- } {
39
- const canonical = resolveOrganizationModel(override)
27
+ quickAccessSurfaceIds: readonly string[]
28
+ surfaces: FoundationNavigationSurface[]
29
+ }
30
+ }
40
31
 
41
- function requireCoreFeature(featureId: string): OrganizationModelFeature {
42
- const feature = canonical.features.find((candidate) => candidate.id === featureId)
32
+ export interface FoundationBranding {
33
+ organizationName: string
34
+ productName: string
35
+ shortName: string
36
+ }
43
37
 
44
- if (!feature) {
45
- throw new Error(`Missing organization surface/feature: ${featureId}`)
46
- }
38
+ export function createFoundationOrganizationModel(override: DeepPartial<OrganizationModel>): {
39
+ canonical: OrganizationModel
40
+ model: FoundationOrganizationModel
41
+ homeLabel: string
42
+ quickAccessSurfaceIds: readonly string[]
43
+ getOrganizationSurface: (surfaceId: string) => FoundationNavigationSurface | undefined
44
+ } {
45
+ const canonical = resolveOrganizationModel(override)
46
+ const navigationSurfaces: FoundationNavigationSurface[] = projectOrganizationSurfaces(canonical)
47
+ const defaultSurface = navigationSurfaces.find((surface) => surface.path === '/') ?? navigationSurfaces[0]
48
+ const homeLabel = defaultSurface?.label ?? 'Dashboard'
49
+ const quickAccessSurfaceIds = navigationSurfaces
50
+ .filter((surface) => surface.id !== defaultSurface?.id && surface.surfaceType !== 'settings')
51
+ .slice(0, 4)
52
+ .map((surface) => surface.id)
47
53
 
48
- return feature
54
+ const model: FoundationOrganizationModel = {
55
+ ...canonical,
56
+ navigation: {
57
+ defaultSurfaceId: defaultSurface?.id ?? '',
58
+ homeLabel,
59
+ quickAccessSurfaceIds: [...quickAccessSurfaceIds],
60
+ surfaces: navigationSurfaces
61
+ }
49
62
  }
50
63
 
51
- const operationsFeature = requireCoreFeature('operations')
52
- const projectsFeature = requireCoreFeature('projects')
53
- const leadGenFeature = requireCoreFeature('sales.lead-gen')
54
- const crmFeature = requireCoreFeature('sales.crm')
64
+ function getOrganizationSurface(surfaceId: string): FoundationNavigationSurface | undefined {
65
+ return model.navigation.surfaces.find((candidate) => candidate.id === surfaceId)
66
+ }
55
67
 
56
- const navigationSurfaces: FoundationNavigationSurface[] = [
57
- { ...operationsFeature, id: 'operations', path: '/operations', icon: 'feature.operations', surfaceType: 'dashboard' },
58
- { ...projectsFeature, icon: 'feature.projects', surfaceType: 'list' },
59
- { ...leadGenFeature, id: 'lead-gen', icon: 'feature.lead-gen', surfaceType: 'list' },
60
- { ...crmFeature, id: 'crm', icon: 'feature.crm', surfaceType: 'graph' },
61
- { ...requireCoreFeature('settings.account'), id: 'settings', icon: 'feature.settings', surfaceType: 'settings' }
62
- ]
63
-
64
- const homeLabel = 'Dashboard'
65
- const quickAccessSurfaceIds = ['operations', 'projects', 'lead-gen', 'crm'] as const
66
-
67
- const model: FoundationOrganizationModel = {
68
- ...canonical,
69
- navigation: {
70
- defaultSurfaceId: 'operations',
71
- homeLabel,
72
- quickAccessSurfaceIds: [...quickAccessSurfaceIds],
73
- surfaces: navigationSurfaces
74
- }
75
- }
76
-
77
- function getOrganizationSurface(surfaceId: string): FoundationNavigationSurface | undefined {
78
- return model.navigation.surfaces.find((candidate) => candidate.id === surfaceId)
79
- }
80
-
81
- return {
82
- canonical,
83
- model,
84
- homeLabel,
85
- quickAccessSurfaceIds,
86
- getOrganizationSurface
87
- }
88
- }
68
+ return {
69
+ canonical,
70
+ model,
71
+ homeLabel,
72
+ quickAccessSurfaceIds,
73
+ getOrganizationSurface
74
+ }
75
+ }