@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
@@ -33,7 +33,7 @@ var TechStackEntrySchema = z.object({
33
33
  */
34
34
  isSystemOfRecord: z.boolean().default(false)
35
35
  });
36
- var ResourceMappingSchema = DisplayMetadataSchema.extend({
36
+ DisplayMetadataSchema.extend({
37
37
  id: ModelIdSchema,
38
38
  resourceId: z.string().trim().min(1).max(255),
39
39
  resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]),
@@ -192,17 +192,20 @@ var DEFAULT_ORGANIZATION_MODEL_PROJECTS = {
192
192
  { id: "completed", label: "Completed", order: 9 }
193
193
  ]
194
194
  };
195
+ var NodeIdPathSchema = z.string().trim().min(1).max(100).regex(/^([a-z0-9-]+)(\.[a-z0-9-]+)*$/, "Node IDs must be lowercase dotted paths");
196
+ var NodeIdStringSchema = z.string().trim().min(1).max(200).regex(/^[a-z]+:([a-z0-9-]+)(\.[a-z0-9-]+)*$/, "Node references must use kind:dotted-path");
197
+ var UiPositionSchema = z.enum(["sidebar-primary", "sidebar-bottom"]);
195
198
  var FeatureSchema = z.object({
196
- id: ModelIdSchema,
199
+ id: NodeIdPathSchema,
197
200
  label: LabelSchema,
198
201
  description: DescriptionSchema.optional(),
199
202
  enabled: z.boolean().default(true),
200
- color: ColorTokenSchema.optional(),
203
+ path: PathSchema.optional(),
201
204
  icon: IconNameSchema.optional(),
202
- entityIds: ReferenceIdsSchema,
203
- surfaceIds: ReferenceIdsSchema,
204
- resourceIds: ReferenceIdsSchema,
205
- capabilityIds: ReferenceIdsSchema
205
+ color: ColorTokenSchema.optional(),
206
+ uiPosition: UiPositionSchema.optional(),
207
+ requiresAdmin: z.boolean().optional(),
208
+ devOnly: z.boolean().optional()
206
209
  });
207
210
  var ProspectingLifecycleStageSchema = DisplayMetadataSchema.extend({
208
211
  id: ModelIdSchema,
@@ -275,349 +278,6 @@ var OrganizationModelNavigationSchema = z.object({
275
278
  surfaces: z.array(SurfaceDefinitionSchema).default([]),
276
279
  groups: z.array(NavigationGroupSchema).default([])
277
280
  });
278
- var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
279
- defaultSurfaceId: "crm.pipeline",
280
- surfaces: [
281
- {
282
- id: "crm.pipeline",
283
- label: "Pipeline",
284
- path: "/crm/pipeline",
285
- surfaceType: "graph",
286
- enabled: true,
287
- featureId: "crm",
288
- featureIds: ["crm"],
289
- entityIds: ["crm.deal"],
290
- resourceIds: [],
291
- capabilityIds: ["crm.pipeline.manage"]
292
- },
293
- {
294
- id: "lead-gen.lists",
295
- label: "Lists",
296
- path: "/lead-gen/lists",
297
- surfaceType: "list",
298
- enabled: true,
299
- featureId: "lead-gen",
300
- featureIds: ["lead-gen"],
301
- entityIds: ["leadgen.list"],
302
- resourceIds: [],
303
- capabilityIds: ["leadgen.lists.manage"]
304
- },
305
- {
306
- id: PROJECTS_INDEX_SURFACE_ID,
307
- label: "Projects",
308
- path: "/projects",
309
- surfaceType: "list",
310
- enabled: true,
311
- featureId: PROJECTS_FEATURE_ID,
312
- featureIds: [PROJECTS_FEATURE_ID],
313
- entityIds: ["delivery.project"],
314
- resourceIds: [],
315
- capabilityIds: [PROJECTS_VIEW_CAPABILITY_ID]
316
- },
317
- {
318
- id: "operations.organization-graph",
319
- label: "Organization Graph",
320
- path: "/operations/organization-graph",
321
- surfaceType: "graph",
322
- enabled: true,
323
- featureId: "operations",
324
- featureIds: ["operations"],
325
- entityIds: [],
326
- resourceIds: [],
327
- capabilityIds: ["operations.organization-graph"]
328
- },
329
- {
330
- id: "operations.command-view",
331
- label: "Command View",
332
- path: "/operations/command-view",
333
- surfaceType: "graph",
334
- enabled: false,
335
- featureId: "operations",
336
- featureIds: ["operations"],
337
- entityIds: [],
338
- resourceIds: [],
339
- capabilityIds: ["operations.command-view"]
340
- },
341
- {
342
- id: "operations.overview",
343
- label: "Overview",
344
- path: "/operations",
345
- surfaceType: "dashboard",
346
- enabled: true,
347
- featureId: "operations",
348
- featureIds: ["operations"],
349
- entityIds: [],
350
- resourceIds: [],
351
- capabilityIds: []
352
- },
353
- {
354
- id: "operations.resources",
355
- label: "Resources",
356
- path: "/operations/resources",
357
- surfaceType: "list",
358
- enabled: true,
359
- featureId: "operations",
360
- featureIds: ["operations"],
361
- entityIds: [],
362
- resourceIds: [],
363
- capabilityIds: []
364
- },
365
- {
366
- id: "operations.command-queue",
367
- label: "Command Queue",
368
- path: "/operations/command-queue",
369
- surfaceType: "list",
370
- enabled: true,
371
- featureId: "operations",
372
- featureIds: ["operations"],
373
- entityIds: [],
374
- resourceIds: [],
375
- capabilityIds: []
376
- },
377
- {
378
- id: "operations.sessions",
379
- label: "Sessions",
380
- path: "/operations/sessions",
381
- surfaceType: "page",
382
- enabled: false,
383
- featureId: "operations",
384
- featureIds: ["operations"],
385
- entityIds: [],
386
- resourceIds: [],
387
- capabilityIds: []
388
- },
389
- {
390
- id: "operations.task-scheduler",
391
- label: "Task Scheduler",
392
- path: "/operations/task-scheduler",
393
- surfaceType: "page",
394
- enabled: true,
395
- featureId: "operations",
396
- featureIds: ["operations"],
397
- entityIds: [],
398
- resourceIds: [],
399
- capabilityIds: []
400
- },
401
- {
402
- id: "monitoring.activity-log",
403
- label: "Activity Log",
404
- path: "/monitoring/activity-log",
405
- surfaceType: "list",
406
- enabled: true,
407
- featureId: "monitoring",
408
- featureIds: ["monitoring"],
409
- entityIds: [],
410
- resourceIds: [],
411
- capabilityIds: []
412
- },
413
- {
414
- id: "monitoring.execution-logs",
415
- label: "Execution Logs",
416
- path: "/monitoring/execution-logs",
417
- surfaceType: "list",
418
- enabled: true,
419
- featureId: "monitoring",
420
- featureIds: ["monitoring"],
421
- entityIds: [],
422
- resourceIds: [],
423
- capabilityIds: []
424
- },
425
- {
426
- id: "monitoring.execution-health",
427
- label: "Execution Health",
428
- path: "/monitoring/execution-health",
429
- surfaceType: "dashboard",
430
- enabled: true,
431
- featureId: "monitoring",
432
- featureIds: ["monitoring"],
433
- entityIds: [],
434
- resourceIds: [],
435
- capabilityIds: []
436
- },
437
- {
438
- id: "monitoring.cost-analytics",
439
- label: "Cost Analytics",
440
- path: "/monitoring/cost-analytics",
441
- surfaceType: "dashboard",
442
- enabled: false,
443
- featureId: "monitoring",
444
- featureIds: ["monitoring"],
445
- entityIds: [],
446
- resourceIds: [],
447
- capabilityIds: []
448
- },
449
- {
450
- id: "monitoring.notifications",
451
- label: "Notifications",
452
- path: "/monitoring/notifications",
453
- surfaceType: "page",
454
- enabled: true,
455
- featureId: "monitoring",
456
- featureIds: ["monitoring"],
457
- entityIds: [],
458
- resourceIds: [],
459
- capabilityIds: []
460
- },
461
- {
462
- id: "submitted-requests.list",
463
- label: "Submitted Requests",
464
- path: "/monitoring/requests",
465
- surfaceType: "list",
466
- enabled: true,
467
- featureId: "submitted-requests",
468
- featureIds: ["submitted-requests"],
469
- entityIds: ["reported_request"],
470
- resourceIds: [],
471
- capabilityIds: []
472
- },
473
- {
474
- id: "submitted-requests.detail",
475
- label: "Request Detail",
476
- path: "/monitoring/requests/:requestId",
477
- surfaceType: "detail",
478
- enabled: true,
479
- featureId: "submitted-requests",
480
- featureIds: ["submitted-requests"],
481
- entityIds: ["reported_request"],
482
- resourceIds: [],
483
- capabilityIds: []
484
- },
485
- {
486
- id: "settings.account",
487
- label: "Account",
488
- path: "/settings/account",
489
- surfaceType: "settings",
490
- enabled: true,
491
- featureId: "settings",
492
- featureIds: ["settings"],
493
- entityIds: [],
494
- resourceIds: [],
495
- capabilityIds: []
496
- },
497
- {
498
- id: "settings.appearance",
499
- label: "Appearance",
500
- path: "/settings/appearance",
501
- surfaceType: "settings",
502
- enabled: true,
503
- featureId: "settings",
504
- featureIds: ["settings"],
505
- entityIds: [],
506
- resourceIds: [],
507
- capabilityIds: []
508
- },
509
- {
510
- id: "settings.organization",
511
- label: "Organization",
512
- path: "/settings/organization",
513
- surfaceType: "settings",
514
- enabled: true,
515
- featureId: "settings",
516
- featureIds: ["settings"],
517
- entityIds: [],
518
- resourceIds: [],
519
- capabilityIds: []
520
- },
521
- {
522
- id: "settings.credentials",
523
- label: "Credentials",
524
- path: "/settings/credentials",
525
- surfaceType: "settings",
526
- enabled: true,
527
- featureId: "settings",
528
- featureIds: ["settings"],
529
- entityIds: [],
530
- resourceIds: [],
531
- capabilityIds: []
532
- },
533
- {
534
- id: "settings.api-keys",
535
- label: "API Keys",
536
- path: "/settings/api-keys",
537
- surfaceType: "settings",
538
- enabled: true,
539
- featureId: "settings",
540
- featureIds: ["settings"],
541
- entityIds: [],
542
- resourceIds: [],
543
- capabilityIds: []
544
- },
545
- {
546
- id: "settings.webhooks",
547
- label: "Webhooks",
548
- path: "/settings/webhooks",
549
- surfaceType: "settings",
550
- enabled: true,
551
- featureId: "settings",
552
- featureIds: ["settings"],
553
- entityIds: [],
554
- resourceIds: [],
555
- capabilityIds: []
556
- },
557
- {
558
- id: "settings.deployments",
559
- label: "Deployments",
560
- path: "/settings/deployments",
561
- surfaceType: "settings",
562
- enabled: true,
563
- featureId: "settings",
564
- featureIds: ["settings"],
565
- entityIds: [],
566
- resourceIds: [],
567
- capabilityIds: []
568
- }
569
- ],
570
- groups: [
571
- {
572
- id: "primary-workspace",
573
- label: "Workspace",
574
- placement: "primary",
575
- surfaceIds: ["crm.pipeline", "lead-gen.lists", PROJECTS_INDEX_SURFACE_ID]
576
- },
577
- {
578
- id: "primary-operations",
579
- label: "Operations",
580
- placement: "primary",
581
- surfaceIds: [
582
- "operations.organization-graph",
583
- "operations.command-view",
584
- "operations.overview",
585
- "operations.resources",
586
- "operations.command-queue",
587
- "operations.sessions",
588
- "operations.task-scheduler"
589
- ]
590
- },
591
- {
592
- id: "primary-monitoring",
593
- label: "Monitoring",
594
- placement: "primary",
595
- surfaceIds: [
596
- "monitoring.activity-log",
597
- "monitoring.execution-logs",
598
- "monitoring.execution-health",
599
- "monitoring.cost-analytics",
600
- "monitoring.notifications",
601
- "submitted-requests.list",
602
- "submitted-requests.detail"
603
- ]
604
- },
605
- {
606
- id: "primary-settings",
607
- label: "Settings",
608
- placement: "bottom",
609
- surfaceIds: [
610
- "settings.account",
611
- "settings.appearance",
612
- "settings.organization",
613
- "settings.credentials",
614
- "settings.api-keys",
615
- "settings.webhooks",
616
- "settings.deployments"
617
- ]
618
- }
619
- ]
620
- };
621
281
  var BusinessHoursDaySchema = z.object({
622
282
  open: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format"),
623
283
  close: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format")
@@ -1017,7 +677,7 @@ var OrganizationModelSchemaBase = z.object({
1017
677
  version: z.literal(1).default(1),
1018
678
  features: z.array(FeatureSchema).default([]),
1019
679
  branding: OrganizationModelBrandingSchema,
1020
- navigation: OrganizationModelNavigationSchema,
680
+ navigation: OrganizationModelNavigationSchema.default({ surfaces: [], groups: [] }),
1021
681
  sales: OrganizationModelSalesSchema,
1022
682
  prospecting: OrganizationModelProspectingSchema,
1023
683
  projects: OrganizationModelProjectsSchema,
@@ -1027,8 +687,7 @@ var OrganizationModelSchemaBase = z.object({
1027
687
  roles: RolesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ROLES),
1028
688
  goals: GoalsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_GOALS),
1029
689
  statuses: StatusesDomainSchema.default({ entries: [] }),
1030
- operations: OperationsDomainSchema.default({ entries: [] }),
1031
- resourceMappings: z.array(ResourceMappingSchema).default([])
690
+ operations: OperationsDomainSchema.default({ entries: [] })
1032
691
  });
1033
692
  function addIssue(ctx, path, message) {
1034
693
  ctx.addIssue({
@@ -1048,123 +707,39 @@ function collectIds(items, ctx, collectionPath, label) {
1048
707
  });
1049
708
  return itemsById;
1050
709
  }
710
+ var LEGACY_FEATURE_ALIASES = /* @__PURE__ */ new Map([
711
+ ["crm", "sales.crm"],
712
+ ["lead-gen", "sales.lead-gen"],
713
+ ["submitted-requests", "monitoring.submitted-requests"]
714
+ ]);
715
+ function hasFeature(featuresById, featureId) {
716
+ return featuresById.has(featureId) || featuresById.has(LEGACY_FEATURE_ALIASES.get(featureId) ?? "");
717
+ }
1051
718
  var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ctx) => {
1052
719
  const featuresById = collectIds(model.features, ctx, ["features"], "Feature");
1053
- const surfacesById = collectIds(model.navigation.surfaces, ctx, ["navigation", "surfaces"], "Surface");
1054
- collectIds(model.navigation.groups, ctx, ["navigation", "groups"], "Navigation group");
1055
- collectIds(model.resourceMappings, ctx, ["resourceMappings"], "Resource mapping");
1056
- const resourceMappingsByResourceId = /* @__PURE__ */ new Map();
1057
- model.resourceMappings.forEach((resourceMapping, index) => {
1058
- if (resourceMappingsByResourceId.has(resourceMapping.resourceId)) {
1059
- addIssue(
1060
- ctx,
1061
- ["resourceMappings", index, "resourceId"],
1062
- `Resource mapping resourceId "${resourceMapping.resourceId}" must be unique`
1063
- );
1064
- return;
1065
- }
1066
- resourceMappingsByResourceId.set(resourceMapping.resourceId, resourceMapping);
1067
- });
1068
- if (model.navigation.defaultSurfaceId && !surfacesById.has(model.navigation.defaultSurfaceId)) {
1069
- addIssue(
1070
- ctx,
1071
- ["navigation", "defaultSurfaceId"],
1072
- `Default surface "${model.navigation.defaultSurfaceId}" must reference a declared navigation surface`
1073
- );
1074
- }
1075
- model.navigation.groups.forEach((group, groupIndex) => {
1076
- group.surfaceIds.forEach((surfaceId, surfaceIndex) => {
1077
- if (!surfacesById.has(surfaceId)) {
1078
- addIssue(
1079
- ctx,
1080
- ["navigation", "groups", groupIndex, "surfaceIds", surfaceIndex],
1081
- `Navigation group "${group.id}" references unknown surface "${surfaceId}"`
1082
- );
1083
- }
1084
- });
1085
- });
1086
720
  model.features.forEach((feature, featureIndex) => {
1087
- feature.surfaceIds.forEach((surfaceId, surfaceIndex) => {
1088
- const surface = surfacesById.get(surfaceId);
1089
- if (!surface) {
1090
- addIssue(
1091
- ctx,
1092
- ["features", featureIndex, "surfaceIds", surfaceIndex],
1093
- `Feature "${feature.id}" references unknown surface "${surfaceId}"`
1094
- );
1095
- return;
1096
- }
1097
- if (!surface.featureIds.includes(feature.id)) {
1098
- addIssue(
1099
- ctx,
1100
- ["features", featureIndex, "surfaceIds", surfaceIndex],
1101
- `Feature "${feature.id}" references surface "${surfaceId}" but that surface does not include feature "${feature.id}"`
1102
- );
1103
- }
1104
- });
1105
- feature.resourceIds.forEach((resourceId, resourceIndex) => {
1106
- const resourceMapping = resourceMappingsByResourceId.get(resourceId);
1107
- if (!resourceMapping) {
1108
- addIssue(
1109
- ctx,
1110
- ["features", featureIndex, "resourceIds", resourceIndex],
1111
- `Feature "${feature.id}" references unknown resource "${resourceId}"`
1112
- );
1113
- return;
1114
- }
1115
- if (!resourceMapping.featureIds.includes(feature.id)) {
1116
- addIssue(
1117
- ctx,
1118
- ["features", featureIndex, "resourceIds", resourceIndex],
1119
- `Feature "${feature.id}" references resource "${resourceId}" but that resource mapping does not include feature "${feature.id}"`
1120
- );
721
+ const segments = feature.id.split(".");
722
+ if (segments.length > 1) {
723
+ const parentId = segments.slice(0, -1).join(".");
724
+ if (!featuresById.has(parentId)) {
725
+ addIssue(ctx, ["features", featureIndex, "id"], `Feature "${feature.id}" references unknown parent "${parentId}"`);
1121
726
  }
1122
- });
1123
- });
1124
- model.navigation.surfaces.forEach((surface, surfaceIndex) => {
1125
- if (surface.parentId && !surfacesById.has(surface.parentId)) {
1126
- addIssue(
1127
- ctx,
1128
- ["navigation", "surfaces", surfaceIndex, "parentId"],
1129
- `Surface "${surface.id}" references unknown parent surface "${surface.parentId}"`
1130
- );
1131
727
  }
1132
- surface.featureIds.forEach((featureId, featureIndex) => {
1133
- const feature = featuresById.get(featureId);
1134
- if (!feature) {
1135
- addIssue(
1136
- ctx,
1137
- ["navigation", "surfaces", surfaceIndex, "featureIds", featureIndex],
1138
- `Surface "${surface.id}" references unknown feature "${featureId}"`
1139
- );
1140
- return;
1141
- }
1142
- if (!feature.surfaceIds.includes(surface.id)) {
1143
- addIssue(
1144
- ctx,
1145
- ["navigation", "surfaces", surfaceIndex, "featureIds", featureIndex],
1146
- `Surface "${surface.id}" references feature "${featureId}" but that feature does not include surface "${surface.id}"`
1147
- );
1148
- }
1149
- });
1150
- surface.resourceIds.forEach((resourceId, resourceIndex) => {
1151
- const resourceMapping = resourceMappingsByResourceId.get(resourceId);
1152
- if (!resourceMapping) {
1153
- addIssue(
1154
- ctx,
1155
- ["navigation", "surfaces", surfaceIndex, "resourceIds", resourceIndex],
1156
- `Surface "${surface.id}" references unknown resource "${resourceId}"`
1157
- );
1158
- return;
1159
- }
1160
- if (!resourceMapping.surfaceIds.includes(surface.id)) {
728
+ const hasChildren = model.features.some(
729
+ (candidate) => candidate.id.startsWith(`${feature.id}.`) && candidate.id !== feature.id
730
+ );
731
+ if (hasChildren && feature.enabled) {
732
+ const hasEnabledDescendant = model.features.some(
733
+ (candidate) => candidate.id.startsWith(`${feature.id}.`) && candidate.enabled
734
+ );
735
+ if (!hasEnabledDescendant) {
1161
736
  addIssue(
1162
737
  ctx,
1163
- ["navigation", "surfaces", surfaceIndex, "resourceIds", resourceIndex],
1164
- `Surface "${surface.id}" references resource "${resourceId}" but that surface does not include resource "${surface.id}"`
738
+ ["features", featureIndex, "enabled"],
739
+ `Feature "${feature.id}" is enabled but has no enabled descendants`
1165
740
  );
1166
741
  }
1167
- });
742
+ }
1168
743
  });
1169
744
  const segmentsById = new Map(model.customers.segments.map((seg) => [seg.id, seg]));
1170
745
  model.offerings.products.forEach((product, productIndex) => {
@@ -1177,7 +752,7 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
1177
752
  );
1178
753
  }
1179
754
  });
1180
- if (product.deliveryFeatureId !== void 0 && !featuresById.has(product.deliveryFeatureId)) {
755
+ if (product.deliveryFeatureId !== void 0 && !hasFeature(featuresById, product.deliveryFeatureId)) {
1181
756
  addIssue(
1182
757
  ctx,
1183
758
  ["offerings", "products", productIndex, "deliveryFeatureId"],
@@ -1204,44 +779,56 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
1204
779
  );
1205
780
  }
1206
781
  });
1207
- model.resourceMappings.forEach((resourceMapping, resourceIndex) => {
1208
- resourceMapping.featureIds.forEach((featureId, featureIndex) => {
1209
- const feature = featuresById.get(featureId);
1210
- if (!feature) {
1211
- addIssue(
1212
- ctx,
1213
- ["resourceMappings", resourceIndex, "featureIds", featureIndex],
1214
- `Resource mapping "${resourceMapping.id}" references unknown feature "${featureId}"`
1215
- );
1216
- return;
1217
- }
1218
- if (!feature.resourceIds.includes(resourceMapping.resourceId)) {
1219
- addIssue(
1220
- ctx,
1221
- ["resourceMappings", resourceIndex, "featureIds", featureIndex],
1222
- `Resource mapping "${resourceMapping.id}" references feature "${featureId}" but that feature does not include resource "${resourceMapping.resourceId}"`
1223
- );
1224
- }
1225
- });
1226
- resourceMapping.surfaceIds.forEach((surfaceId, surfaceIndex) => {
1227
- const surface = surfacesById.get(surfaceId);
1228
- if (!surface) {
1229
- addIssue(
1230
- ctx,
1231
- ["resourceMappings", resourceIndex, "surfaceIds", surfaceIndex],
1232
- `Resource mapping "${resourceMapping.id}" references unknown surface "${surfaceId}"`
1233
- );
1234
- return;
1235
- }
1236
- if (!surface.resourceIds.includes(resourceMapping.resourceId)) {
1237
- addIssue(
1238
- ctx,
1239
- ["resourceMappings", resourceIndex, "surfaceIds", surfaceIndex],
1240
- `Resource mapping "${resourceMapping.id}" references surface "${surfaceId}" but that surface does not include resource "${resourceMapping.resourceId}"`
1241
- );
1242
- }
1243
- });
1244
- });
782
+ });
783
+ var OrganizationGraphNodeKindSchema = z.enum([
784
+ "organization",
785
+ "feature",
786
+ "surface",
787
+ "entity",
788
+ "capability",
789
+ "resource"
790
+ ]);
791
+ var OrganizationGraphEdgeKindSchema = z.enum([
792
+ "contains",
793
+ "references",
794
+ "exposes",
795
+ "maps_to",
796
+ "operates-on",
797
+ "uses"
798
+ ]);
799
+ var OrganizationGraphNodeSchema = z.object({
800
+ id: z.string().trim().min(1).max(200),
801
+ kind: OrganizationGraphNodeKindSchema,
802
+ label: LabelSchema,
803
+ sourceId: z.string().trim().min(1).max(255).optional(),
804
+ description: DescriptionSchema.optional(),
805
+ enabled: z.boolean().optional(),
806
+ featureId: z.string().trim().min(1).max(100).optional(),
807
+ resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]).optional()
808
+ });
809
+ var OrganizationGraphEdgeSchema = z.object({
810
+ id: z.string().trim().min(1).max(250),
811
+ kind: OrganizationGraphEdgeKindSchema,
812
+ sourceId: z.string().trim().min(1).max(200),
813
+ targetId: z.string().trim().min(1).max(200),
814
+ label: z.string().trim().min(1).max(120).optional(),
815
+ relationshipType: z.enum(["triggers", "uses", "approval"]).optional()
816
+ });
817
+ z.object({
818
+ version: z.literal(1),
819
+ organizationModelVersion: OrganizationModelSchema.shape.version,
820
+ nodes: z.array(OrganizationGraphNodeSchema),
821
+ edges: z.array(OrganizationGraphEdgeSchema)
822
+ });
823
+ z.object({
824
+ organizationModel: OrganizationModelSchema,
825
+ commandViewData: z.unknown().optional()
826
+ });
827
+
828
+ // src/organization-model/graph/link.ts
829
+ var LinkSchema = z.object({
830
+ nodeId: NodeIdStringSchema,
831
+ kind: OrganizationGraphEdgeKindSchema
1245
832
  });
1246
833
 
1247
834
  // src/organization-model/defaults.ts
@@ -1249,110 +836,261 @@ var DEFAULT_ORGANIZATION_MODEL = {
1249
836
  version: 1,
1250
837
  features: [
1251
838
  {
1252
- id: SALES_FEATURE_ID,
839
+ id: "dashboard",
840
+ label: "Dashboard",
841
+ enabled: true,
842
+ path: "/",
843
+ icon: "dashboard",
844
+ uiPosition: "sidebar-primary"
845
+ },
846
+ {
847
+ id: "sales",
848
+ label: "Sales",
849
+ description: "Revenue workflows and customer acquisition",
850
+ enabled: true,
851
+ color: "blue",
852
+ icon: "crm",
853
+ uiPosition: "sidebar-primary"
854
+ },
855
+ {
856
+ id: "sales.crm",
1253
857
  label: "CRM",
1254
858
  description: "Relationship pipeline and deal management",
1255
859
  enabled: true,
1256
860
  color: "blue",
1257
- entityIds: ["crm.deal"],
1258
- surfaceIds: [SALES_PIPELINE_SURFACE_ID],
1259
- resourceIds: [],
1260
- capabilityIds: ["crm.pipeline.manage"]
861
+ icon: "crm",
862
+ path: "/crm"
1261
863
  },
1262
864
  {
1263
- id: PROSPECTING_FEATURE_ID,
865
+ id: "sales.lead-gen",
1264
866
  label: "Lead Gen",
1265
867
  description: "Prospecting, qualification, and outreach preparation",
1266
868
  enabled: true,
1267
869
  color: "cyan",
1268
- entityIds: ["leadgen.list", "leadgen.company", "leadgen.contact"],
1269
- surfaceIds: [PROSPECTING_LISTS_SURFACE_ID],
1270
- resourceIds: [],
1271
- capabilityIds: ["leadgen.lists.manage"]
870
+ icon: "lead-gen",
871
+ path: "/lead-gen"
1272
872
  },
1273
873
  {
1274
- id: PROJECTS_FEATURE_ID,
874
+ id: "projects",
1275
875
  label: "Projects",
1276
876
  description: "Projects, milestones, and client work execution",
1277
877
  enabled: true,
1278
878
  color: "orange",
1279
- entityIds: ["delivery.project", "delivery.milestone", "delivery.task"],
1280
- surfaceIds: [PROJECTS_INDEX_SURFACE_ID],
1281
- resourceIds: [],
1282
- capabilityIds: [PROJECTS_VIEW_CAPABILITY_ID]
879
+ icon: "projects",
880
+ path: "/projects",
881
+ uiPosition: "sidebar-primary"
1283
882
  },
1284
883
  {
1285
- id: OPERATIONS_FEATURE_ID,
884
+ id: "operations",
1286
885
  label: "Operations",
1287
886
  description: "Operational resources, topology, and orchestration visibility",
1288
887
  enabled: true,
1289
888
  color: "violet",
1290
- entityIds: [],
1291
- surfaceIds: [
1292
- OPERATIONS_ORGANIZATION_GRAPH_SURFACE_ID,
1293
- "operations.command-view",
1294
- "operations.overview",
1295
- "operations.resources",
1296
- "operations.command-queue",
1297
- "operations.sessions",
1298
- "operations.task-scheduler"
1299
- ],
1300
- resourceIds: [],
1301
- capabilityIds: ["operations.organization-graph", "operations.command-view"]
889
+ icon: "operations",
890
+ uiPosition: "sidebar-primary"
891
+ },
892
+ {
893
+ id: "operations.graph",
894
+ label: "Organization Graph",
895
+ enabled: true,
896
+ path: "/operations/organization-graph"
897
+ },
898
+ {
899
+ id: "operations.command-view",
900
+ label: "Command View",
901
+ enabled: false,
902
+ path: "/operations/command-view"
903
+ },
904
+ {
905
+ id: "operations.overview",
906
+ label: "Overview",
907
+ enabled: true,
908
+ path: "/operations"
909
+ },
910
+ {
911
+ id: "operations.resources",
912
+ label: "Resources",
913
+ enabled: true,
914
+ path: "/operations/resources"
915
+ },
916
+ {
917
+ id: "operations.command-queue",
918
+ label: "Command Queue",
919
+ enabled: true,
920
+ path: "/operations/command-queue"
921
+ },
922
+ {
923
+ id: "operations.sessions",
924
+ label: "Sessions",
925
+ enabled: false,
926
+ path: "/operations/sessions"
927
+ },
928
+ {
929
+ id: "operations.task-scheduler",
930
+ label: "Task Scheduler",
931
+ enabled: true,
932
+ path: "/operations/task-scheduler"
1302
933
  },
1303
934
  {
1304
- id: MONITORING_FEATURE_ID,
935
+ id: "monitoring",
1305
936
  label: "Monitoring",
1306
937
  enabled: true,
1307
- entityIds: [],
1308
- surfaceIds: [
1309
- "monitoring.activity-log",
1310
- "monitoring.execution-logs",
1311
- "monitoring.execution-health",
1312
- "monitoring.cost-analytics",
1313
- "monitoring.notifications"
1314
- ],
1315
- resourceIds: [],
1316
- capabilityIds: []
938
+ uiPosition: "sidebar-primary"
1317
939
  },
1318
940
  {
1319
- id: SETTINGS_FEATURE_ID,
1320
- label: "Settings",
941
+ id: "monitoring.activity-log",
942
+ label: "Activity Log",
943
+ enabled: true,
944
+ path: "/monitoring/activity-log"
945
+ },
946
+ {
947
+ id: "monitoring.execution-logs",
948
+ label: "Execution Logs",
949
+ enabled: true,
950
+ path: "/monitoring/execution-logs"
951
+ },
952
+ {
953
+ id: "monitoring.execution-health",
954
+ label: "Execution Health",
955
+ enabled: true,
956
+ path: "/monitoring/execution-health"
957
+ },
958
+ {
959
+ id: "monitoring.cost-analytics",
960
+ label: "Cost Analytics",
961
+ enabled: false,
962
+ path: "/monitoring/cost-analytics"
963
+ },
964
+ {
965
+ id: "monitoring.notifications",
966
+ label: "Notifications",
1321
967
  enabled: true,
1322
- entityIds: [],
1323
- surfaceIds: [
1324
- "settings.account",
1325
- "settings.appearance",
1326
- "settings.organization",
1327
- "settings.credentials",
1328
- "settings.api-keys",
1329
- "settings.webhooks",
1330
- "settings.deployments"
1331
- ],
1332
- resourceIds: [],
1333
- capabilityIds: []
968
+ path: "/monitoring/notifications"
1334
969
  },
1335
970
  {
1336
- id: "submitted-requests",
971
+ id: "monitoring.submitted-requests",
1337
972
  label: "Submitted Requests",
1338
973
  enabled: true,
1339
- entityIds: ["reported_request"],
1340
- surfaceIds: ["submitted-requests.list", "submitted-requests.detail"],
1341
- resourceIds: [],
1342
- capabilityIds: []
974
+ path: "/monitoring/requests"
1343
975
  },
1344
976
  {
1345
- id: SEO_FEATURE_ID,
977
+ id: "settings",
978
+ label: "Settings",
979
+ enabled: true,
980
+ icon: "settings",
981
+ uiPosition: "sidebar-bottom"
982
+ },
983
+ {
984
+ id: "settings.account",
985
+ label: "Account",
986
+ enabled: true,
987
+ path: "/settings/account"
988
+ },
989
+ {
990
+ id: "settings.appearance",
991
+ label: "Appearance",
992
+ enabled: true,
993
+ path: "/settings/appearance"
994
+ },
995
+ {
996
+ id: "settings.organization",
997
+ label: "Organization",
998
+ enabled: true,
999
+ path: "/settings/organization"
1000
+ },
1001
+ {
1002
+ id: "settings.credentials",
1003
+ label: "Credentials",
1004
+ enabled: true,
1005
+ path: "/settings/credentials"
1006
+ },
1007
+ {
1008
+ id: "settings.api-keys",
1009
+ label: "API Keys",
1010
+ enabled: true,
1011
+ path: "/settings/api-keys"
1012
+ },
1013
+ {
1014
+ id: "settings.webhooks",
1015
+ label: "Webhooks",
1016
+ enabled: true,
1017
+ path: "/settings/webhooks"
1018
+ },
1019
+ {
1020
+ id: "settings.deployments",
1021
+ label: "Deployments",
1022
+ enabled: true,
1023
+ path: "/settings/deployments"
1024
+ },
1025
+ {
1026
+ id: "admin",
1027
+ label: "Admin",
1028
+ enabled: true,
1029
+ path: "/admin",
1030
+ icon: "settings",
1031
+ uiPosition: "sidebar-bottom",
1032
+ requiresAdmin: true
1033
+ },
1034
+ {
1035
+ id: "admin.system-health",
1036
+ label: "System Health",
1037
+ enabled: true,
1038
+ path: "/admin/system-health"
1039
+ },
1040
+ {
1041
+ id: "admin.organizations",
1042
+ label: "Organizations",
1043
+ enabled: true,
1044
+ path: "/admin/organizations"
1045
+ },
1046
+ {
1047
+ id: "admin.users",
1048
+ label: "Users",
1049
+ enabled: true,
1050
+ path: "/admin/users"
1051
+ },
1052
+ {
1053
+ id: "admin.design-showcase",
1054
+ label: "Design Showcase",
1055
+ enabled: true,
1056
+ path: "/admin/design-showcase"
1057
+ },
1058
+ {
1059
+ id: "admin.debug",
1060
+ label: "Debug",
1061
+ enabled: true,
1062
+ path: "/admin/debug"
1063
+ },
1064
+ {
1065
+ id: "archive",
1066
+ label: "Archive",
1067
+ enabled: true,
1068
+ path: "/archive",
1069
+ icon: "archive",
1070
+ uiPosition: "sidebar-bottom",
1071
+ devOnly: true
1072
+ },
1073
+ {
1074
+ id: "archive.agent-chat",
1075
+ label: "Agent Chat",
1076
+ enabled: true,
1077
+ path: "/archive/agent-chat"
1078
+ },
1079
+ {
1080
+ id: "archive.execution-runner",
1081
+ label: "Execution Runner",
1082
+ enabled: true,
1083
+ path: "/archive/execution-runner"
1084
+ },
1085
+ {
1086
+ id: "seo",
1346
1087
  label: "SEO",
1347
1088
  enabled: false,
1348
- entityIds: [],
1349
- surfaceIds: [],
1350
- resourceIds: [],
1351
- capabilityIds: []
1089
+ path: "/seo"
1352
1090
  }
1353
1091
  ],
1354
1092
  branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
1355
- navigation: DEFAULT_ORGANIZATION_MODEL_NAVIGATION,
1093
+ navigation: { surfaces: [], groups: [] },
1356
1094
  sales: DEFAULT_ORGANIZATION_MODEL_SALES,
1357
1095
  prospecting: DEFAULT_ORGANIZATION_MODEL_PROSPECTING,
1358
1096
  projects: DEFAULT_ORGANIZATION_MODEL_PROJECTS,
@@ -1362,8 +1100,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
1362
1100
  roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
1363
1101
  goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
1364
1102
  statuses: DEFAULT_ORGANIZATION_MODEL_STATUSES,
1365
- operations: DEFAULT_ORGANIZATION_MODEL_OPERATIONS,
1366
- resourceMappings: []
1103
+ operations: DEFAULT_ORGANIZATION_MODEL_OPERATIONS
1367
1104
  };
1368
1105
 
1369
1106
  // src/organization-model/resolve.ts
@@ -1388,67 +1125,38 @@ function deepMerge(base, override) {
1388
1125
  }
1389
1126
  return result;
1390
1127
  }
1391
- function normalizeInheritedNavigationGroups(model, override) {
1392
- if (override?.navigation?.surfaces === void 0 || override.navigation.groups !== void 0) {
1393
- return model;
1394
- }
1395
- const validSurfaceIds = new Set(model.navigation.surfaces.map((surface) => surface.id));
1396
- const groups = model.navigation.groups.map((group) => ({
1397
- ...group,
1398
- surfaceIds: group.surfaceIds.filter((surfaceId) => validSurfaceIds.has(surfaceId))
1399
- })).filter((group) => group.surfaceIds.length > 0);
1400
- return {
1401
- ...model,
1402
- navigation: {
1403
- ...model.navigation,
1404
- groups
1405
- }
1406
- };
1407
- }
1408
1128
  function defineOrganizationModel(model) {
1409
1129
  return model;
1410
1130
  }
1411
1131
  function resolveOrganizationModel(override) {
1412
- const merged = normalizeInheritedNavigationGroups(deepMerge(DEFAULT_ORGANIZATION_MODEL, override), override);
1132
+ const merged = deepMerge(DEFAULT_ORGANIZATION_MODEL, override);
1413
1133
  return OrganizationModelSchema.parse(merged);
1414
1134
  }
1415
1135
 
1416
1136
  // src/organization-model/foundation.ts
1417
1137
  function createFoundationOrganizationModel(override) {
1418
1138
  const canonical = resolveOrganizationModel(override);
1419
- function requireCoreSurface(surfaceId) {
1420
- const surface = canonical.navigation.surfaces.find((candidate) => candidate.id === surfaceId);
1421
- if (!surface) {
1422
- throw new Error(`Missing organization surface: ${surfaceId}`);
1139
+ function requireCoreFeature(featureId) {
1140
+ const feature = canonical.features.find((candidate) => candidate.id === featureId);
1141
+ if (!feature) {
1142
+ throw new Error(`Missing organization surface/feature: ${featureId}`);
1423
1143
  }
1424
- return surface;
1144
+ return feature;
1425
1145
  }
1426
- const operationsGraphSurface = requireCoreSurface("operations.organization-graph");
1427
- const projectsSurface = requireCoreSurface(PROJECTS_INDEX_SURFACE_ID);
1428
- const leadGenSurface = requireCoreSurface("lead-gen.lists");
1429
- const crmSurface = requireCoreSurface("crm.pipeline");
1146
+ const operationsGraphFeature = requireCoreFeature("operations.graph");
1147
+ const projectsFeature = requireCoreFeature("projects");
1148
+ const leadGenFeature = requireCoreFeature("sales.lead-gen");
1149
+ const crmFeature = requireCoreFeature("sales.crm");
1430
1150
  const navigationSurfaces = [
1431
- { ...operationsGraphSurface, id: "operations", path: "/operations", icon: "operations" },
1432
- { ...operationsGraphSurface, path: "/operations", icon: "operations" },
1433
- { ...projectsSurface, id: PROJECTS_FEATURE_ID, icon: "projects" },
1434
- { ...leadGenSurface, id: "lead-gen", icon: "lead-gen" },
1435
- { ...crmSurface, id: "crm", icon: "crm" },
1436
- {
1437
- id: "settings",
1438
- label: "Settings",
1439
- path: "/settings/account",
1440
- surfaceType: "settings",
1441
- enabled: true,
1442
- icon: "settings",
1443
- featureId: "settings",
1444
- featureIds: ["settings"],
1445
- entityIds: [],
1446
- resourceIds: [],
1447
- capabilityIds: []
1448
- }
1151
+ { ...operationsGraphFeature, id: "operations", path: "/operations", icon: "operations", surfaceType: "graph" },
1152
+ { ...operationsGraphFeature, path: "/operations", icon: "operations", surfaceType: "graph" },
1153
+ { ...projectsFeature, icon: "projects", surfaceType: "list" },
1154
+ { ...leadGenFeature, id: "lead-gen", icon: "lead-gen", surfaceType: "list" },
1155
+ { ...crmFeature, id: "crm", icon: "crm", surfaceType: "graph" },
1156
+ { ...requireCoreFeature("settings.account"), id: "settings", icon: "settings", surfaceType: "settings" }
1449
1157
  ];
1450
1158
  const homeLabel = "Dashboard";
1451
- const quickAccessSurfaceIds = ["operations", PROJECTS_FEATURE_ID, "lead-gen", "crm"];
1159
+ const quickAccessSurfaceIds = ["operations", "projects", "lead-gen", "crm"];
1452
1160
  const model = {
1453
1161
  ...canonical,
1454
1162
  navigation: {
@@ -1470,4 +1178,4 @@ function createFoundationOrganizationModel(override) {
1470
1178
  };
1471
1179
  }
1472
1180
 
1473
- export { CustomerSegmentSchema, CustomersDomainSchema, DEFAULT_ORGANIZATION_MODEL, DEFAULT_ORGANIZATION_MODEL_CUSTOMERS, DEFAULT_ORGANIZATION_MODEL_GOALS, DEFAULT_ORGANIZATION_MODEL_OFFERINGS, DEFAULT_ORGANIZATION_MODEL_OPERATIONS, DEFAULT_ORGANIZATION_MODEL_ROLES, DEFAULT_ORGANIZATION_MODEL_STATUSES, FeatureSchema, FirmographicsSchema, GoalsDomainSchema, KeyResultSchema, MONITORING_FEATURE_ID, OPERATIONS_FEATURE_ID, OPERATIONS_ORGANIZATION_GRAPH_SURFACE_ID, ObjectiveSchema, OfferingsDomainSchema, OperationEntrySchema, OperationSemanticClassSchema, OperationsDomainSchema, OrganizationModelSchema, PROJECTS_FEATURE_ID, PROJECTS_INDEX_SURFACE_ID, PROJECTS_VIEW_CAPABILITY_ID, PROSPECTING_FEATURE_ID, PROSPECTING_LISTS_SURFACE_ID, PricingModelSchema, ProductSchema, RoleSchema, RolesDomainSchema, SALES_FEATURE_ID, SALES_PIPELINE_SURFACE_ID, SEO_FEATURE_ID, SETTINGS_FEATURE_ID, StatusEntrySchema, StatusSemanticClassSchema, StatusesDomainSchema, TechStackEntrySchema, createFoundationOrganizationModel, defineOrganizationModel, resolveOrganizationModel };
1181
+ export { CustomerSegmentSchema, CustomersDomainSchema, DEFAULT_ORGANIZATION_MODEL, DEFAULT_ORGANIZATION_MODEL_CUSTOMERS, DEFAULT_ORGANIZATION_MODEL_GOALS, DEFAULT_ORGANIZATION_MODEL_OFFERINGS, DEFAULT_ORGANIZATION_MODEL_OPERATIONS, DEFAULT_ORGANIZATION_MODEL_ROLES, DEFAULT_ORGANIZATION_MODEL_STATUSES, FeatureSchema, FirmographicsSchema, GoalsDomainSchema, KeyResultSchema, LinkSchema, MONITORING_FEATURE_ID, NodeIdPathSchema, NodeIdStringSchema, OPERATIONS_FEATURE_ID, OPERATIONS_ORGANIZATION_GRAPH_SURFACE_ID, ObjectiveSchema, OfferingsDomainSchema, OperationEntrySchema, OperationSemanticClassSchema, OperationsDomainSchema, OrganizationModelSchema, PROJECTS_FEATURE_ID, PROJECTS_INDEX_SURFACE_ID, PROJECTS_VIEW_CAPABILITY_ID, PROSPECTING_FEATURE_ID, PROSPECTING_LISTS_SURFACE_ID, PricingModelSchema, ProductSchema, RoleSchema, RolesDomainSchema, SALES_FEATURE_ID, SALES_PIPELINE_SURFACE_ID, SEO_FEATURE_ID, SETTINGS_FEATURE_ID, StatusEntrySchema, StatusSemanticClassSchema, StatusesDomainSchema, TechStackEntrySchema, UiPositionSchema, createFoundationOrganizationModel, defineOrganizationModel, resolveOrganizationModel };