@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,14 +1,9 @@
1
- import { z } from 'zod'
2
- import {
3
- OPERATIONS_COMMAND_VIEW_SURFACE_ID,
4
- PROJECTS_VIEW_CAPABILITY_ID,
5
- PROJECTS_FEATURE_ID,
6
- PROJECTS_INDEX_SURFACE_ID,
7
- SETTINGS_ROLES_SURFACE_ID
8
- } from '../contracts'
9
- import { DescriptionSchema, IconNameSchema, LabelSchema, ModelIdSchema, PathSchema, ReferenceIdsSchema } from './shared'
1
+ import { z, type ZodType } from 'zod'
2
+ import { DescriptionSchema, IconNameSchema, LabelSchema, ModelIdSchema, PathSchema } from './shared'
10
3
 
11
- export const SurfaceTypeSchema = z.enum(['page', 'dashboard', 'graph', 'detail', 'list', 'settings'])
4
+ export const SurfaceTypeSchema = z
5
+ .enum(['page', 'dashboard', 'graph', 'detail', 'list', 'settings'])
6
+ .meta({ label: 'Surface type', color: 'blue' })
12
7
 
13
8
  export const SurfaceDefinitionSchema = z.object({
14
9
  id: ModelIdSchema,
@@ -19,14 +14,107 @@ export const SurfaceDefinitionSchema = z.object({
19
14
  enabled: z.boolean().default(true),
20
15
  devOnly: z.boolean().optional(),
21
16
  icon: IconNameSchema.optional(),
22
- featureId: ModelIdSchema.optional(),
23
- featureIds: ReferenceIdsSchema,
24
- entityIds: ReferenceIdsSchema,
25
- resourceIds: ReferenceIdsSchema,
26
- capabilityIds: ReferenceIdsSchema,
27
- parentId: ModelIdSchema.optional()
17
+ systemIds: z.array(ModelIdSchema.meta({ ref: 'system' })).default([]),
18
+ entityIds: z.array(ModelIdSchema.meta({ ref: 'entity' })).default([]),
19
+ resourceIds: z.array(ModelIdSchema.meta({ ref: 'resource' })).default([]),
20
+ actionIds: z.array(ModelIdSchema.meta({ ref: 'action' })).default([]),
21
+ parentId: ModelIdSchema.meta({ ref: 'surface' }).optional()
28
22
  })
29
23
 
24
+ export const SidebarSurfaceTargetsSchema = z
25
+ .object({
26
+ systems: z.array(ModelIdSchema.meta({ ref: 'system' })).default([]).optional(),
27
+ entities: z.array(ModelIdSchema.meta({ ref: 'entity' })).default([]).optional(),
28
+ resources: z.array(ModelIdSchema.meta({ ref: 'resource' })).default([]).optional(),
29
+ actions: z.array(ModelIdSchema.meta({ ref: 'action' })).default([]).optional()
30
+ })
31
+ .default({})
32
+
33
+ export interface SidebarSurfaceNode {
34
+ type: 'surface'
35
+ label: string
36
+ path: string
37
+ surfaceType: z.infer<typeof SurfaceTypeSchema>
38
+ description?: string
39
+ icon?: string
40
+ order?: number
41
+ targets?: {
42
+ systems?: string[]
43
+ entities?: string[]
44
+ resources?: string[]
45
+ actions?: string[]
46
+ }
47
+ devOnly?: boolean
48
+ requiresAdmin?: boolean
49
+ }
50
+
51
+ export interface SidebarGroupNode {
52
+ type: 'group'
53
+ label: string
54
+ description?: string
55
+ icon?: string
56
+ order?: number
57
+ children: Record<string, SidebarNode>
58
+ }
59
+
60
+ export type SidebarNode = SidebarSurfaceNode | SidebarGroupNode
61
+
62
+ export const SidebarNodeSchema: ZodType<SidebarNode> = z.lazy(() =>
63
+ z.discriminatedUnion('type', [
64
+ z.object({
65
+ type: z.literal('group'),
66
+ label: LabelSchema,
67
+ description: DescriptionSchema.optional(),
68
+ icon: IconNameSchema.optional(),
69
+ order: z.number().int().optional(),
70
+ children: z.record(z.string(), SidebarNodeSchema).default({})
71
+ }),
72
+ z.object({
73
+ type: z.literal('surface'),
74
+ label: LabelSchema,
75
+ path: PathSchema,
76
+ surfaceType: SurfaceTypeSchema,
77
+ description: DescriptionSchema.optional(),
78
+ icon: IconNameSchema.optional(),
79
+ order: z.number().int().optional(),
80
+ targets: SidebarSurfaceTargetsSchema.optional(),
81
+ devOnly: z.boolean().optional(),
82
+ requiresAdmin: z.boolean().optional()
83
+ })
84
+ ])
85
+ )
86
+
87
+ export const SidebarSectionSchema = z.record(z.string(), SidebarNodeSchema).default({})
88
+
89
+ export const SidebarNavigationSchema = z
90
+ .object({
91
+ primary: SidebarSectionSchema,
92
+ bottom: SidebarSectionSchema
93
+ })
94
+ .default({ primary: {}, bottom: {} })
95
+
96
+ export const OrganizationModelNavigationSchema = z
97
+ .object({
98
+ sidebar: SidebarNavigationSchema
99
+ })
100
+ .default({ sidebar: { primary: {}, bottom: {} } })
101
+
102
+ export const DEFAULT_ORGANIZATION_MODEL_NAVIGATION: z.infer<typeof OrganizationModelNavigationSchema> = {
103
+ sidebar: {
104
+ primary: {},
105
+ bottom: {}
106
+ }
107
+ }
108
+
109
+ export function getSortedSidebarEntries<TNode extends SidebarNode>(
110
+ nodes: Record<string, TNode>
111
+ ): Array<[string, TNode]> {
112
+ return Object.entries(nodes).sort(([leftId, left], [rightId, right]) => {
113
+ const orderDelta = (left.order ?? Number.MAX_SAFE_INTEGER) - (right.order ?? Number.MAX_SAFE_INTEGER)
114
+ return orderDelta === 0 ? leftId.localeCompare(rightId) : orderDelta
115
+ })
116
+ }
117
+
30
118
  /**
31
119
  * Core placement values: 'primary' | 'secondary' | 'bottom'.
32
120
  *
@@ -44,373 +132,8 @@ export const NavigationGroupSchema = z.object({
44
132
  id: ModelIdSchema,
45
133
  label: LabelSchema,
46
134
  placement: z.string().trim().min(1).max(50),
47
- surfaceIds: z.array(ModelIdSchema).default([])
135
+ surfaceIds: z.array(ModelIdSchema.meta({ ref: 'surface' })).default([])
48
136
  })
49
137
 
50
- export const OrganizationModelNavigationSchema = z.object({
51
- defaultSurfaceId: ModelIdSchema.optional(),
52
- surfaces: z.array(SurfaceDefinitionSchema).default([]),
53
- groups: z.array(NavigationGroupSchema).default([])
54
- })
55
-
56
- export const DEFAULT_ORGANIZATION_MODEL_NAVIGATION: z.infer<typeof OrganizationModelNavigationSchema> = {
57
- defaultSurfaceId: 'crm.pipeline',
58
- surfaces: [
59
- {
60
- id: 'crm.pipeline',
61
- label: 'Pipeline',
62
- path: '/crm/pipeline',
63
- surfaceType: 'graph',
64
- enabled: true,
65
- featureId: 'crm',
66
- featureIds: ['crm'],
67
- entityIds: ['crm.deal'],
68
- resourceIds: [],
69
- capabilityIds: ['crm.pipeline.manage']
70
- },
71
- {
72
- id: 'lead-gen.lists',
73
- label: 'Lists',
74
- path: '/lead-gen/lists',
75
- surfaceType: 'list',
76
- enabled: true,
77
- featureId: 'lead-gen',
78
- featureIds: ['lead-gen'],
79
- entityIds: ['leadgen.list'],
80
- resourceIds: [],
81
- capabilityIds: ['leadgen.lists.manage']
82
- },
83
- {
84
- id: PROJECTS_INDEX_SURFACE_ID,
85
- label: 'Projects',
86
- path: '/projects',
87
- surfaceType: 'list',
88
- enabled: true,
89
- featureId: PROJECTS_FEATURE_ID,
90
- featureIds: [PROJECTS_FEATURE_ID],
91
- entityIds: ['delivery.project'],
92
- resourceIds: [],
93
- capabilityIds: [PROJECTS_VIEW_CAPABILITY_ID]
94
- },
95
- {
96
- id: 'knowledge.base',
97
- label: 'Knowledge Base',
98
- path: '/knowledge',
99
- surfaceType: 'page',
100
- enabled: true,
101
- featureId: 'knowledge',
102
- featureIds: ['knowledge'],
103
- entityIds: [],
104
- resourceIds: [],
105
- capabilityIds: []
106
- },
107
- {
108
- id: OPERATIONS_COMMAND_VIEW_SURFACE_ID,
109
- label: 'Command View',
110
- path: '/knowledge/command-view',
111
- surfaceType: 'graph',
112
- enabled: true,
113
- devOnly: true,
114
- featureId: 'knowledge',
115
- featureIds: ['knowledge'],
116
- entityIds: [],
117
- resourceIds: [],
118
- capabilityIds: ['knowledge.command-view']
119
- },
120
- {
121
- id: 'operations.overview',
122
- label: 'Overview',
123
- path: '/operations',
124
- surfaceType: 'dashboard',
125
- enabled: true,
126
- featureId: 'operations',
127
- featureIds: ['operations'],
128
- entityIds: [],
129
- resourceIds: [],
130
- capabilityIds: []
131
- },
132
- {
133
- id: 'operations.resources',
134
- label: 'Resources',
135
- path: '/operations/resources',
136
- surfaceType: 'list',
137
- enabled: true,
138
- featureId: 'operations',
139
- featureIds: ['operations'],
140
- entityIds: [],
141
- resourceIds: [],
142
- capabilityIds: []
143
- },
144
- {
145
- id: 'operations.command-queue',
146
- label: 'Command Queue',
147
- path: '/operations/command-queue',
148
- surfaceType: 'list',
149
- enabled: true,
150
- featureId: 'operations',
151
- featureIds: ['operations'],
152
- entityIds: [],
153
- resourceIds: [],
154
- capabilityIds: []
155
- },
156
- {
157
- id: 'operations.sessions',
158
- label: 'Sessions',
159
- path: '/operations/sessions',
160
- surfaceType: 'page',
161
- enabled: false,
162
- featureId: 'operations',
163
- featureIds: ['operations'],
164
- entityIds: [],
165
- resourceIds: [],
166
- capabilityIds: []
167
- },
168
- {
169
- id: 'operations.task-scheduler',
170
- label: 'Task Scheduler',
171
- path: '/operations/task-scheduler',
172
- surfaceType: 'page',
173
- enabled: true,
174
- featureId: 'operations',
175
- featureIds: ['operations'],
176
- entityIds: [],
177
- resourceIds: [],
178
- capabilityIds: []
179
- },
180
- {
181
- id: 'monitoring.activity-log',
182
- label: 'Activity Log',
183
- path: '/monitoring/activity-log',
184
- surfaceType: 'list',
185
- enabled: true,
186
- featureId: 'monitoring',
187
- featureIds: ['monitoring'],
188
- entityIds: [],
189
- resourceIds: [],
190
- capabilityIds: []
191
- },
192
- {
193
- id: 'monitoring.execution-logs',
194
- label: 'Execution Logs',
195
- path: '/monitoring/execution-logs',
196
- surfaceType: 'list',
197
- enabled: true,
198
- featureId: 'monitoring',
199
- featureIds: ['monitoring'],
200
- entityIds: [],
201
- resourceIds: [],
202
- capabilityIds: []
203
- },
204
- {
205
- id: 'monitoring.execution-health',
206
- label: 'Execution Health',
207
- path: '/monitoring/execution-health',
208
- surfaceType: 'dashboard',
209
- enabled: true,
210
- featureId: 'monitoring',
211
- featureIds: ['monitoring'],
212
- entityIds: [],
213
- resourceIds: [],
214
- capabilityIds: []
215
- },
216
- {
217
- id: 'monitoring.cost-analytics',
218
- label: 'Cost Analytics',
219
- path: '/monitoring/cost-analytics',
220
- surfaceType: 'dashboard',
221
- enabled: false,
222
- featureId: 'monitoring',
223
- featureIds: ['monitoring'],
224
- entityIds: [],
225
- resourceIds: [],
226
- capabilityIds: []
227
- },
228
- {
229
- id: 'monitoring.notifications',
230
- label: 'Notifications',
231
- path: '/monitoring/notifications',
232
- surfaceType: 'page',
233
- enabled: true,
234
- featureId: 'monitoring',
235
- featureIds: ['monitoring'],
236
- entityIds: [],
237
- resourceIds: [],
238
- capabilityIds: []
239
- },
240
- {
241
- id: 'submitted-requests.list',
242
- label: 'Submitted Requests',
243
- path: '/monitoring/requests',
244
- surfaceType: 'list',
245
- enabled: true,
246
- featureId: 'submitted-requests',
247
- featureIds: ['submitted-requests'],
248
- entityIds: ['reported_request'],
249
- resourceIds: [],
250
- capabilityIds: []
251
- },
252
- {
253
- id: 'submitted-requests.detail',
254
- label: 'Request Detail',
255
- path: '/monitoring/requests/:requestId',
256
- surfaceType: 'detail',
257
- enabled: true,
258
- featureId: 'submitted-requests',
259
- featureIds: ['submitted-requests'],
260
- entityIds: ['reported_request'],
261
- resourceIds: [],
262
- capabilityIds: []
263
- },
264
- {
265
- id: 'settings.account',
266
- label: 'Account',
267
- path: '/settings/account',
268
- surfaceType: 'settings',
269
- enabled: true,
270
- featureId: 'settings',
271
- featureIds: ['settings'],
272
- entityIds: [],
273
- resourceIds: [],
274
- capabilityIds: []
275
- },
276
- {
277
- id: 'settings.appearance',
278
- label: 'Appearance',
279
- path: '/settings/appearance',
280
- surfaceType: 'settings',
281
- enabled: true,
282
- featureId: 'settings',
283
- featureIds: ['settings'],
284
- entityIds: [],
285
- resourceIds: [],
286
- capabilityIds: []
287
- },
288
- {
289
- id: SETTINGS_ROLES_SURFACE_ID,
290
- label: 'My Roles',
291
- path: '/settings/roles',
292
- surfaceType: 'settings',
293
- enabled: true,
294
- featureId: 'settings',
295
- featureIds: ['settings'],
296
- entityIds: [],
297
- resourceIds: [],
298
- capabilityIds: []
299
- },
300
- {
301
- id: 'settings.organization',
302
- label: 'Organization',
303
- path: '/settings/organization',
304
- surfaceType: 'settings',
305
- enabled: true,
306
- featureId: 'settings',
307
- featureIds: ['settings'],
308
- entityIds: [],
309
- resourceIds: [],
310
- capabilityIds: []
311
- },
312
- {
313
- id: 'settings.credentials',
314
- label: 'Credentials',
315
- path: '/settings/credentials',
316
- surfaceType: 'settings',
317
- enabled: true,
318
- featureId: 'settings',
319
- featureIds: ['settings'],
320
- entityIds: [],
321
- resourceIds: [],
322
- capabilityIds: []
323
- },
324
- {
325
- id: 'settings.api-keys',
326
- label: 'API Keys',
327
- path: '/settings/api-keys',
328
- surfaceType: 'settings',
329
- enabled: true,
330
- featureId: 'settings',
331
- featureIds: ['settings'],
332
- entityIds: [],
333
- resourceIds: [],
334
- capabilityIds: []
335
- },
336
- {
337
- id: 'settings.webhooks',
338
- label: 'Webhooks',
339
- path: '/settings/webhooks',
340
- surfaceType: 'settings',
341
- enabled: true,
342
- featureId: 'settings',
343
- featureIds: ['settings'],
344
- entityIds: [],
345
- resourceIds: [],
346
- capabilityIds: []
347
- },
348
- {
349
- id: 'settings.deployments',
350
- label: 'Deployments',
351
- path: '/settings/deployments',
352
- surfaceType: 'settings',
353
- enabled: true,
354
- featureId: 'settings',
355
- featureIds: ['settings'],
356
- entityIds: [],
357
- resourceIds: [],
358
- capabilityIds: []
359
- }
360
- ],
361
- groups: [
362
- {
363
- id: 'primary-workspace',
364
- label: 'Workspace',
365
- placement: 'primary',
366
- surfaceIds: ['crm.pipeline', 'lead-gen.lists', PROJECTS_INDEX_SURFACE_ID]
367
- },
368
- {
369
- id: 'primary-operations',
370
- label: 'Operations',
371
- placement: 'primary',
372
- surfaceIds: [
373
- 'operations.overview',
374
- 'operations.resources',
375
- 'operations.command-queue',
376
- 'operations.sessions',
377
- 'operations.task-scheduler'
378
- ]
379
- },
380
- {
381
- id: 'primary-monitoring',
382
- label: 'Monitoring',
383
- placement: 'primary',
384
- surfaceIds: [
385
- 'monitoring.activity-log',
386
- 'monitoring.execution-logs',
387
- 'monitoring.execution-health',
388
- 'monitoring.cost-analytics',
389
- 'monitoring.notifications',
390
- 'submitted-requests.list',
391
- 'submitted-requests.detail'
392
- ]
393
- },
394
- {
395
- id: 'primary-knowledge',
396
- label: 'Knowledge',
397
- placement: 'primary',
398
- surfaceIds: ['knowledge.base', OPERATIONS_COMMAND_VIEW_SURFACE_ID]
399
- },
400
- {
401
- id: 'primary-settings',
402
- label: 'Settings',
403
- placement: 'bottom',
404
- surfaceIds: [
405
- 'settings.account',
406
- 'settings.appearance',
407
- SETTINGS_ROLES_SURFACE_ID,
408
- 'settings.organization',
409
- 'settings.credentials',
410
- 'settings.api-keys',
411
- 'settings.webhooks',
412
- 'settings.deployments'
413
- ]
414
- }
415
- ]
416
- }
138
+ // SurfaceDefinitionSchema and NavigationGroupSchema remain for derived DTOs and
139
+ // transitional call sites. They are not authored top-level OrganizationModel fields.
@@ -1,66 +1,71 @@
1
- import { z } from 'zod'
2
-
3
- // ---------------------------------------------------------------------------
4
- // Pricing model — the four canonical pricing structures used in B2B SaaS and
5
- // professional services. "custom" covers bespoke / negotiated pricing.
6
- // ---------------------------------------------------------------------------
7
-
8
- export const PricingModelSchema = z.enum(['one-time', 'subscription', 'usage-based', 'custom'])
9
-
10
- // ---------------------------------------------------------------------------
11
- // Product schema — one entry per distinct offering (product or service).
12
- // Modeled after Business Model Canvas "Value Propositions" and company profile
13
- // product/service catalog language. Fields use plain English throughout.
14
- // ---------------------------------------------------------------------------
15
-
16
- export const ProductSchema = z.object({
17
- /** Stable unique identifier for the product (e.g. "product-starter-plan"). */
18
- id: z.string().trim().min(1).max(100),
19
- /** Human-readable name shown to agents and in UI (e.g. "Starter Plan"). */
20
- name: z.string().trim().max(200).default(''),
21
- /** One or two sentences describing what this product/service delivers. */
22
- description: z.string().trim().max(2000).default(''),
23
- /**
24
- * How this product is priced:
25
- * - "one-time" single purchase (setup fee, project fee)
26
- * - "subscription" — recurring (monthly/annual SaaS, retainer)
27
- * - "usage-based" — metered by consumption (API calls, seats)
28
- * - "custom" negotiated or bespoke pricing
29
- */
30
- pricingModel: PricingModelSchema.default('custom'),
31
- /** Base price amount (≥ 0). Currency unit defined by `currency`. */
32
- price: z.number().min(0).default(0),
33
- /**
34
- * ISO 4217 currency code (e.g. "USD", "EUR", "GBP").
35
- * Free-form string to accommodate any currency; defaults to "USD".
36
- */
37
- currency: z.string().trim().max(10).default('USD'),
38
- /**
39
- * IDs of customer segments this product targets.
40
- * Each id must reference a declared `customers.segments[].id`.
41
- * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
42
- */
43
- targetSegmentIds: z.array(z.string().trim().min(1)).default([]),
44
- /**
45
- * Optional: ID of the platform feature responsible for delivering this product.
46
- * When present, must reference a declared `features[].id`.
47
- * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
48
- */
49
- deliveryFeatureId: z.string().trim().min(1).optional()
50
- })
51
-
52
- // ---------------------------------------------------------------------------
53
- // Offerings domain schema — a collection of products and services.
54
- // ---------------------------------------------------------------------------
55
-
56
- export const OfferingsDomainSchema = z.object({
57
- products: z.array(ProductSchema).default([])
58
- })
59
-
60
- // ---------------------------------------------------------------------------
61
- // Seed — empty by default; adapters populate with real product definitions.
62
- // ---------------------------------------------------------------------------
63
-
64
- export const DEFAULT_ORGANIZATION_MODEL_OFFERINGS: z.infer<typeof OfferingsDomainSchema> = {
65
- products: []
66
- }
1
+ import { z } from 'zod'
2
+
3
+ // ---------------------------------------------------------------------------
4
+ // Pricing model — the four canonical pricing structures used in B2B SaaS and
5
+ // professional services. "custom" covers bespoke / negotiated pricing.
6
+ // ---------------------------------------------------------------------------
7
+
8
+ export const PricingModelSchema = z
9
+ .enum(['one-time', 'subscription', 'usage-based', 'custom'])
10
+ .meta({ label: 'Pricing model', color: 'green' })
11
+
12
+ // ---------------------------------------------------------------------------
13
+ // Product schema one entry per distinct offering (product or service).
14
+ // Modeled after Business Model Canvas "Value Propositions" and company profile
15
+ // product/service catalog language. Fields use plain English throughout.
16
+ // ---------------------------------------------------------------------------
17
+
18
+ export const ProductSchema = z.object({
19
+ /** Stable unique identifier for the product (e.g. "product-starter-plan"). */
20
+ id: z.string().trim().min(1).max(100),
21
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
22
+ order: z.number(),
23
+ /** Human-readable name shown to agents and in UI (e.g. "Starter Plan"). */
24
+ name: z.string().trim().max(200).default(''),
25
+ /** One or two sentences describing what this product/service delivers. */
26
+ description: z.string().trim().max(2000).default(''),
27
+ /**
28
+ * How this product is priced:
29
+ * - "one-time" — single purchase (setup fee, project fee)
30
+ * - "subscription" — recurring (monthly/annual SaaS, retainer)
31
+ * - "usage-based" metered by consumption (API calls, seats)
32
+ * - "custom" — negotiated or bespoke pricing
33
+ */
34
+ pricingModel: PricingModelSchema.default('custom'),
35
+ /** Base price amount (≥ 0). Currency unit defined by `currency`. */
36
+ price: z.number().min(0).default(0),
37
+ /**
38
+ * ISO 4217 currency code (e.g. "USD", "EUR", "GBP").
39
+ * Free-form string to accommodate any currency; defaults to "USD".
40
+ */
41
+ currency: z.string().trim().max(10).default('USD'),
42
+ /**
43
+ * IDs of customer segments this product targets.
44
+ * Each id must reference a declared `customers.segments[].id`.
45
+ * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
46
+ */
47
+ targetSegmentIds: z.array(z.string().trim().min(1)).default([]),
48
+ /**
49
+ * Optional: ID of the platform system responsible for delivering this product.
50
+ * When present, must reference a declared `systems.systems[].id`.
51
+ * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
52
+ */
53
+ deliveryFeatureId: z.string().trim().min(1).optional()
54
+ })
55
+
56
+ // ---------------------------------------------------------------------------
57
+ // Offerings domain schema — id-keyed map of products and services.
58
+ // ---------------------------------------------------------------------------
59
+
60
+ export const OfferingsDomainSchema = z
61
+ .record(z.string(), ProductSchema)
62
+ .refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
63
+ message: 'Each product entry id must match its map key'
64
+ })
65
+ .default({})
66
+
67
+ // ---------------------------------------------------------------------------
68
+ // Seed — empty by default; adapters populate with real product definitions.
69
+ // ---------------------------------------------------------------------------
70
+
71
+ export const DEFAULT_ORGANIZATION_MODEL_OFFERINGS: z.infer<typeof OfferingsDomainSchema> = {}