@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
@@ -19425,7 +19425,7 @@ var TechStackEntrySchema = z.object({
19425
19425
  */
19426
19426
  isSystemOfRecord: z.boolean().default(false)
19427
19427
  });
19428
- var ResourceMappingSchema = DisplayMetadataSchema.extend({
19428
+ DisplayMetadataSchema.extend({
19429
19429
  id: ModelIdSchema,
19430
19430
  resourceId: z.string().trim().min(1).max(255),
19431
19431
  resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]),
@@ -19584,17 +19584,20 @@ var DEFAULT_ORGANIZATION_MODEL_PROJECTS = {
19584
19584
  { id: "completed", label: "Completed", order: 9 }
19585
19585
  ]
19586
19586
  };
19587
+ var NodeIdPathSchema = z.string().trim().min(1).max(100).regex(/^([a-z0-9-]+)(\.[a-z0-9-]+)*$/, "Node IDs must be lowercase dotted paths");
19588
+ z.string().trim().min(1).max(200).regex(/^[a-z]+:([a-z0-9-]+)(\.[a-z0-9-]+)*$/, "Node references must use kind:dotted-path");
19589
+ var UiPositionSchema = z.enum(["sidebar-primary", "sidebar-bottom"]);
19587
19590
  var FeatureSchema = z.object({
19588
- id: ModelIdSchema,
19591
+ id: NodeIdPathSchema,
19589
19592
  label: LabelSchema,
19590
19593
  description: DescriptionSchema.optional(),
19591
19594
  enabled: z.boolean().default(true),
19592
- color: ColorTokenSchema.optional(),
19595
+ path: PathSchema.optional(),
19593
19596
  icon: IconNameSchema.optional(),
19594
- entityIds: ReferenceIdsSchema,
19595
- surfaceIds: ReferenceIdsSchema,
19596
- resourceIds: ReferenceIdsSchema,
19597
- capabilityIds: ReferenceIdsSchema
19597
+ color: ColorTokenSchema.optional(),
19598
+ uiPosition: UiPositionSchema.optional(),
19599
+ requiresAdmin: z.boolean().optional(),
19600
+ devOnly: z.boolean().optional()
19598
19601
  });
19599
19602
  var ProspectingLifecycleStageSchema = DisplayMetadataSchema.extend({
19600
19603
  id: ModelIdSchema,
@@ -19624,22 +19627,6 @@ var DEFAULT_ORGANIZATION_MODEL_PROSPECTING = {
19624
19627
  { id: "uploaded", label: "Uploaded", order: 4 }
19625
19628
  ]
19626
19629
  };
19627
-
19628
- // src/organization-model/contracts.ts
19629
- var PROJECTS_FEATURE_ID = "projects";
19630
- var PROJECTS_INDEX_SURFACE_ID = "projects.index";
19631
- var PROJECTS_VIEW_CAPABILITY_ID = "delivery.projects.view";
19632
- var SALES_FEATURE_ID = "crm";
19633
- var PROSPECTING_FEATURE_ID = "lead-gen";
19634
- var OPERATIONS_FEATURE_ID = "operations";
19635
- var MONITORING_FEATURE_ID = "monitoring";
19636
- var SETTINGS_FEATURE_ID = "settings";
19637
- var SEO_FEATURE_ID = "seo";
19638
- var SALES_PIPELINE_SURFACE_ID = "crm.pipeline";
19639
- var PROSPECTING_LISTS_SURFACE_ID = "lead-gen.lists";
19640
- var OPERATIONS_ORGANIZATION_GRAPH_SURFACE_ID = "operations.organization-graph";
19641
-
19642
- // src/organization-model/domains/navigation.ts
19643
19630
  var SurfaceTypeSchema = z.enum(["page", "dashboard", "graph", "detail", "list", "settings"]);
19644
19631
  var SurfaceDefinitionSchema = z.object({
19645
19632
  id: ModelIdSchema,
@@ -19667,349 +19654,6 @@ var OrganizationModelNavigationSchema = z.object({
19667
19654
  surfaces: z.array(SurfaceDefinitionSchema).default([]),
19668
19655
  groups: z.array(NavigationGroupSchema).default([])
19669
19656
  });
19670
- var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
19671
- defaultSurfaceId: "crm.pipeline",
19672
- surfaces: [
19673
- {
19674
- id: "crm.pipeline",
19675
- label: "Pipeline",
19676
- path: "/crm/pipeline",
19677
- surfaceType: "graph",
19678
- enabled: true,
19679
- featureId: "crm",
19680
- featureIds: ["crm"],
19681
- entityIds: ["crm.deal"],
19682
- resourceIds: [],
19683
- capabilityIds: ["crm.pipeline.manage"]
19684
- },
19685
- {
19686
- id: "lead-gen.lists",
19687
- label: "Lists",
19688
- path: "/lead-gen/lists",
19689
- surfaceType: "list",
19690
- enabled: true,
19691
- featureId: "lead-gen",
19692
- featureIds: ["lead-gen"],
19693
- entityIds: ["leadgen.list"],
19694
- resourceIds: [],
19695
- capabilityIds: ["leadgen.lists.manage"]
19696
- },
19697
- {
19698
- id: PROJECTS_INDEX_SURFACE_ID,
19699
- label: "Projects",
19700
- path: "/projects",
19701
- surfaceType: "list",
19702
- enabled: true,
19703
- featureId: PROJECTS_FEATURE_ID,
19704
- featureIds: [PROJECTS_FEATURE_ID],
19705
- entityIds: ["delivery.project"],
19706
- resourceIds: [],
19707
- capabilityIds: [PROJECTS_VIEW_CAPABILITY_ID]
19708
- },
19709
- {
19710
- id: "operations.organization-graph",
19711
- label: "Organization Graph",
19712
- path: "/operations/organization-graph",
19713
- surfaceType: "graph",
19714
- enabled: true,
19715
- featureId: "operations",
19716
- featureIds: ["operations"],
19717
- entityIds: [],
19718
- resourceIds: [],
19719
- capabilityIds: ["operations.organization-graph"]
19720
- },
19721
- {
19722
- id: "operations.command-view",
19723
- label: "Command View",
19724
- path: "/operations/command-view",
19725
- surfaceType: "graph",
19726
- enabled: false,
19727
- featureId: "operations",
19728
- featureIds: ["operations"],
19729
- entityIds: [],
19730
- resourceIds: [],
19731
- capabilityIds: ["operations.command-view"]
19732
- },
19733
- {
19734
- id: "operations.overview",
19735
- label: "Overview",
19736
- path: "/operations",
19737
- surfaceType: "dashboard",
19738
- enabled: true,
19739
- featureId: "operations",
19740
- featureIds: ["operations"],
19741
- entityIds: [],
19742
- resourceIds: [],
19743
- capabilityIds: []
19744
- },
19745
- {
19746
- id: "operations.resources",
19747
- label: "Resources",
19748
- path: "/operations/resources",
19749
- surfaceType: "list",
19750
- enabled: true,
19751
- featureId: "operations",
19752
- featureIds: ["operations"],
19753
- entityIds: [],
19754
- resourceIds: [],
19755
- capabilityIds: []
19756
- },
19757
- {
19758
- id: "operations.command-queue",
19759
- label: "Command Queue",
19760
- path: "/operations/command-queue",
19761
- surfaceType: "list",
19762
- enabled: true,
19763
- featureId: "operations",
19764
- featureIds: ["operations"],
19765
- entityIds: [],
19766
- resourceIds: [],
19767
- capabilityIds: []
19768
- },
19769
- {
19770
- id: "operations.sessions",
19771
- label: "Sessions",
19772
- path: "/operations/sessions",
19773
- surfaceType: "page",
19774
- enabled: false,
19775
- featureId: "operations",
19776
- featureIds: ["operations"],
19777
- entityIds: [],
19778
- resourceIds: [],
19779
- capabilityIds: []
19780
- },
19781
- {
19782
- id: "operations.task-scheduler",
19783
- label: "Task Scheduler",
19784
- path: "/operations/task-scheduler",
19785
- surfaceType: "page",
19786
- enabled: true,
19787
- featureId: "operations",
19788
- featureIds: ["operations"],
19789
- entityIds: [],
19790
- resourceIds: [],
19791
- capabilityIds: []
19792
- },
19793
- {
19794
- id: "monitoring.activity-log",
19795
- label: "Activity Log",
19796
- path: "/monitoring/activity-log",
19797
- surfaceType: "list",
19798
- enabled: true,
19799
- featureId: "monitoring",
19800
- featureIds: ["monitoring"],
19801
- entityIds: [],
19802
- resourceIds: [],
19803
- capabilityIds: []
19804
- },
19805
- {
19806
- id: "monitoring.execution-logs",
19807
- label: "Execution Logs",
19808
- path: "/monitoring/execution-logs",
19809
- surfaceType: "list",
19810
- enabled: true,
19811
- featureId: "monitoring",
19812
- featureIds: ["monitoring"],
19813
- entityIds: [],
19814
- resourceIds: [],
19815
- capabilityIds: []
19816
- },
19817
- {
19818
- id: "monitoring.execution-health",
19819
- label: "Execution Health",
19820
- path: "/monitoring/execution-health",
19821
- surfaceType: "dashboard",
19822
- enabled: true,
19823
- featureId: "monitoring",
19824
- featureIds: ["monitoring"],
19825
- entityIds: [],
19826
- resourceIds: [],
19827
- capabilityIds: []
19828
- },
19829
- {
19830
- id: "monitoring.cost-analytics",
19831
- label: "Cost Analytics",
19832
- path: "/monitoring/cost-analytics",
19833
- surfaceType: "dashboard",
19834
- enabled: false,
19835
- featureId: "monitoring",
19836
- featureIds: ["monitoring"],
19837
- entityIds: [],
19838
- resourceIds: [],
19839
- capabilityIds: []
19840
- },
19841
- {
19842
- id: "monitoring.notifications",
19843
- label: "Notifications",
19844
- path: "/monitoring/notifications",
19845
- surfaceType: "page",
19846
- enabled: true,
19847
- featureId: "monitoring",
19848
- featureIds: ["monitoring"],
19849
- entityIds: [],
19850
- resourceIds: [],
19851
- capabilityIds: []
19852
- },
19853
- {
19854
- id: "submitted-requests.list",
19855
- label: "Submitted Requests",
19856
- path: "/monitoring/requests",
19857
- surfaceType: "list",
19858
- enabled: true,
19859
- featureId: "submitted-requests",
19860
- featureIds: ["submitted-requests"],
19861
- entityIds: ["reported_request"],
19862
- resourceIds: [],
19863
- capabilityIds: []
19864
- },
19865
- {
19866
- id: "submitted-requests.detail",
19867
- label: "Request Detail",
19868
- path: "/monitoring/requests/:requestId",
19869
- surfaceType: "detail",
19870
- enabled: true,
19871
- featureId: "submitted-requests",
19872
- featureIds: ["submitted-requests"],
19873
- entityIds: ["reported_request"],
19874
- resourceIds: [],
19875
- capabilityIds: []
19876
- },
19877
- {
19878
- id: "settings.account",
19879
- label: "Account",
19880
- path: "/settings/account",
19881
- surfaceType: "settings",
19882
- enabled: true,
19883
- featureId: "settings",
19884
- featureIds: ["settings"],
19885
- entityIds: [],
19886
- resourceIds: [],
19887
- capabilityIds: []
19888
- },
19889
- {
19890
- id: "settings.appearance",
19891
- label: "Appearance",
19892
- path: "/settings/appearance",
19893
- surfaceType: "settings",
19894
- enabled: true,
19895
- featureId: "settings",
19896
- featureIds: ["settings"],
19897
- entityIds: [],
19898
- resourceIds: [],
19899
- capabilityIds: []
19900
- },
19901
- {
19902
- id: "settings.organization",
19903
- label: "Organization",
19904
- path: "/settings/organization",
19905
- surfaceType: "settings",
19906
- enabled: true,
19907
- featureId: "settings",
19908
- featureIds: ["settings"],
19909
- entityIds: [],
19910
- resourceIds: [],
19911
- capabilityIds: []
19912
- },
19913
- {
19914
- id: "settings.credentials",
19915
- label: "Credentials",
19916
- path: "/settings/credentials",
19917
- surfaceType: "settings",
19918
- enabled: true,
19919
- featureId: "settings",
19920
- featureIds: ["settings"],
19921
- entityIds: [],
19922
- resourceIds: [],
19923
- capabilityIds: []
19924
- },
19925
- {
19926
- id: "settings.api-keys",
19927
- label: "API Keys",
19928
- path: "/settings/api-keys",
19929
- surfaceType: "settings",
19930
- enabled: true,
19931
- featureId: "settings",
19932
- featureIds: ["settings"],
19933
- entityIds: [],
19934
- resourceIds: [],
19935
- capabilityIds: []
19936
- },
19937
- {
19938
- id: "settings.webhooks",
19939
- label: "Webhooks",
19940
- path: "/settings/webhooks",
19941
- surfaceType: "settings",
19942
- enabled: true,
19943
- featureId: "settings",
19944
- featureIds: ["settings"],
19945
- entityIds: [],
19946
- resourceIds: [],
19947
- capabilityIds: []
19948
- },
19949
- {
19950
- id: "settings.deployments",
19951
- label: "Deployments",
19952
- path: "/settings/deployments",
19953
- surfaceType: "settings",
19954
- enabled: true,
19955
- featureId: "settings",
19956
- featureIds: ["settings"],
19957
- entityIds: [],
19958
- resourceIds: [],
19959
- capabilityIds: []
19960
- }
19961
- ],
19962
- groups: [
19963
- {
19964
- id: "primary-workspace",
19965
- label: "Workspace",
19966
- placement: "primary",
19967
- surfaceIds: ["crm.pipeline", "lead-gen.lists", PROJECTS_INDEX_SURFACE_ID]
19968
- },
19969
- {
19970
- id: "primary-operations",
19971
- label: "Operations",
19972
- placement: "primary",
19973
- surfaceIds: [
19974
- "operations.organization-graph",
19975
- "operations.command-view",
19976
- "operations.overview",
19977
- "operations.resources",
19978
- "operations.command-queue",
19979
- "operations.sessions",
19980
- "operations.task-scheduler"
19981
- ]
19982
- },
19983
- {
19984
- id: "primary-monitoring",
19985
- label: "Monitoring",
19986
- placement: "primary",
19987
- surfaceIds: [
19988
- "monitoring.activity-log",
19989
- "monitoring.execution-logs",
19990
- "monitoring.execution-health",
19991
- "monitoring.cost-analytics",
19992
- "monitoring.notifications",
19993
- "submitted-requests.list",
19994
- "submitted-requests.detail"
19995
- ]
19996
- },
19997
- {
19998
- id: "primary-settings",
19999
- label: "Settings",
20000
- placement: "bottom",
20001
- surfaceIds: [
20002
- "settings.account",
20003
- "settings.appearance",
20004
- "settings.organization",
20005
- "settings.credentials",
20006
- "settings.api-keys",
20007
- "settings.webhooks",
20008
- "settings.deployments"
20009
- ]
20010
- }
20011
- ]
20012
- };
20013
19657
  var BusinessHoursDaySchema = z.object({
20014
19658
  open: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format"),
20015
19659
  close: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format")
@@ -20409,7 +20053,7 @@ var OrganizationModelSchemaBase = z.object({
20409
20053
  version: z.literal(1).default(1),
20410
20054
  features: z.array(FeatureSchema).default([]),
20411
20055
  branding: OrganizationModelBrandingSchema,
20412
- navigation: OrganizationModelNavigationSchema,
20056
+ navigation: OrganizationModelNavigationSchema.default({ surfaces: [], groups: [] }),
20413
20057
  sales: OrganizationModelSalesSchema,
20414
20058
  prospecting: OrganizationModelProspectingSchema,
20415
20059
  projects: OrganizationModelProjectsSchema,
@@ -20419,8 +20063,7 @@ var OrganizationModelSchemaBase = z.object({
20419
20063
  roles: RolesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ROLES),
20420
20064
  goals: GoalsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_GOALS),
20421
20065
  statuses: StatusesDomainSchema.default({ entries: [] }),
20422
- operations: OperationsDomainSchema.default({ entries: [] }),
20423
- resourceMappings: z.array(ResourceMappingSchema).default([])
20066
+ operations: OperationsDomainSchema.default({ entries: [] })
20424
20067
  });
20425
20068
  function addIssue(ctx, path, message) {
20426
20069
  ctx.addIssue({
@@ -20440,123 +20083,39 @@ function collectIds(items, ctx, collectionPath, label) {
20440
20083
  });
20441
20084
  return itemsById;
20442
20085
  }
20086
+ var LEGACY_FEATURE_ALIASES = /* @__PURE__ */ new Map([
20087
+ ["crm", "sales.crm"],
20088
+ ["lead-gen", "sales.lead-gen"],
20089
+ ["submitted-requests", "monitoring.submitted-requests"]
20090
+ ]);
20091
+ function hasFeature(featuresById, featureId) {
20092
+ return featuresById.has(featureId) || featuresById.has(LEGACY_FEATURE_ALIASES.get(featureId) ?? "");
20093
+ }
20443
20094
  var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ctx) => {
20444
20095
  const featuresById = collectIds(model.features, ctx, ["features"], "Feature");
20445
- const surfacesById = collectIds(model.navigation.surfaces, ctx, ["navigation", "surfaces"], "Surface");
20446
- collectIds(model.navigation.groups, ctx, ["navigation", "groups"], "Navigation group");
20447
- collectIds(model.resourceMappings, ctx, ["resourceMappings"], "Resource mapping");
20448
- const resourceMappingsByResourceId = /* @__PURE__ */ new Map();
20449
- model.resourceMappings.forEach((resourceMapping, index2) => {
20450
- if (resourceMappingsByResourceId.has(resourceMapping.resourceId)) {
20451
- addIssue(
20452
- ctx,
20453
- ["resourceMappings", index2, "resourceId"],
20454
- `Resource mapping resourceId "${resourceMapping.resourceId}" must be unique`
20455
- );
20456
- return;
20457
- }
20458
- resourceMappingsByResourceId.set(resourceMapping.resourceId, resourceMapping);
20459
- });
20460
- if (model.navigation.defaultSurfaceId && !surfacesById.has(model.navigation.defaultSurfaceId)) {
20461
- addIssue(
20462
- ctx,
20463
- ["navigation", "defaultSurfaceId"],
20464
- `Default surface "${model.navigation.defaultSurfaceId}" must reference a declared navigation surface`
20465
- );
20466
- }
20467
- model.navigation.groups.forEach((group, groupIndex) => {
20468
- group.surfaceIds.forEach((surfaceId, surfaceIndex) => {
20469
- if (!surfacesById.has(surfaceId)) {
20470
- addIssue(
20471
- ctx,
20472
- ["navigation", "groups", groupIndex, "surfaceIds", surfaceIndex],
20473
- `Navigation group "${group.id}" references unknown surface "${surfaceId}"`
20474
- );
20475
- }
20476
- });
20477
- });
20478
20096
  model.features.forEach((feature, featureIndex) => {
20479
- feature.surfaceIds.forEach((surfaceId, surfaceIndex) => {
20480
- const surface = surfacesById.get(surfaceId);
20481
- if (!surface) {
20482
- addIssue(
20483
- ctx,
20484
- ["features", featureIndex, "surfaceIds", surfaceIndex],
20485
- `Feature "${feature.id}" references unknown surface "${surfaceId}"`
20486
- );
20487
- return;
20488
- }
20489
- if (!surface.featureIds.includes(feature.id)) {
20490
- addIssue(
20491
- ctx,
20492
- ["features", featureIndex, "surfaceIds", surfaceIndex],
20493
- `Feature "${feature.id}" references surface "${surfaceId}" but that surface does not include feature "${feature.id}"`
20494
- );
20495
- }
20496
- });
20497
- feature.resourceIds.forEach((resourceId, resourceIndex) => {
20498
- const resourceMapping = resourceMappingsByResourceId.get(resourceId);
20499
- if (!resourceMapping) {
20500
- addIssue(
20501
- ctx,
20502
- ["features", featureIndex, "resourceIds", resourceIndex],
20503
- `Feature "${feature.id}" references unknown resource "${resourceId}"`
20504
- );
20505
- return;
20097
+ const segments = feature.id.split(".");
20098
+ if (segments.length > 1) {
20099
+ const parentId = segments.slice(0, -1).join(".");
20100
+ if (!featuresById.has(parentId)) {
20101
+ addIssue(ctx, ["features", featureIndex, "id"], `Feature "${feature.id}" references unknown parent "${parentId}"`);
20506
20102
  }
20507
- if (!resourceMapping.featureIds.includes(feature.id)) {
20508
- addIssue(
20509
- ctx,
20510
- ["features", featureIndex, "resourceIds", resourceIndex],
20511
- `Feature "${feature.id}" references resource "${resourceId}" but that resource mapping does not include feature "${feature.id}"`
20512
- );
20513
- }
20514
- });
20515
- });
20516
- model.navigation.surfaces.forEach((surface, surfaceIndex) => {
20517
- if (surface.parentId && !surfacesById.has(surface.parentId)) {
20518
- addIssue(
20519
- ctx,
20520
- ["navigation", "surfaces", surfaceIndex, "parentId"],
20521
- `Surface "${surface.id}" references unknown parent surface "${surface.parentId}"`
20522
- );
20523
20103
  }
20524
- surface.featureIds.forEach((featureId, featureIndex) => {
20525
- const feature = featuresById.get(featureId);
20526
- if (!feature) {
20527
- addIssue(
20528
- ctx,
20529
- ["navigation", "surfaces", surfaceIndex, "featureIds", featureIndex],
20530
- `Surface "${surface.id}" references unknown feature "${featureId}"`
20531
- );
20532
- return;
20533
- }
20534
- if (!feature.surfaceIds.includes(surface.id)) {
20535
- addIssue(
20536
- ctx,
20537
- ["navigation", "surfaces", surfaceIndex, "featureIds", featureIndex],
20538
- `Surface "${surface.id}" references feature "${featureId}" but that feature does not include surface "${surface.id}"`
20539
- );
20540
- }
20541
- });
20542
- surface.resourceIds.forEach((resourceId, resourceIndex) => {
20543
- const resourceMapping = resourceMappingsByResourceId.get(resourceId);
20544
- if (!resourceMapping) {
20545
- addIssue(
20546
- ctx,
20547
- ["navigation", "surfaces", surfaceIndex, "resourceIds", resourceIndex],
20548
- `Surface "${surface.id}" references unknown resource "${resourceId}"`
20549
- );
20550
- return;
20551
- }
20552
- if (!resourceMapping.surfaceIds.includes(surface.id)) {
20104
+ const hasChildren = model.features.some(
20105
+ (candidate) => candidate.id.startsWith(`${feature.id}.`) && candidate.id !== feature.id
20106
+ );
20107
+ if (hasChildren && feature.enabled) {
20108
+ const hasEnabledDescendant = model.features.some(
20109
+ (candidate) => candidate.id.startsWith(`${feature.id}.`) && candidate.enabled
20110
+ );
20111
+ if (!hasEnabledDescendant) {
20553
20112
  addIssue(
20554
20113
  ctx,
20555
- ["navigation", "surfaces", surfaceIndex, "resourceIds", resourceIndex],
20556
- `Surface "${surface.id}" references resource "${resourceId}" but that surface does not include resource "${surface.id}"`
20114
+ ["features", featureIndex, "enabled"],
20115
+ `Feature "${feature.id}" is enabled but has no enabled descendants`
20557
20116
  );
20558
20117
  }
20559
- });
20118
+ }
20560
20119
  });
20561
20120
  const segmentsById = new Map(model.customers.segments.map((seg) => [seg.id, seg]));
20562
20121
  model.offerings.products.forEach((product, productIndex) => {
@@ -20569,7 +20128,7 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
20569
20128
  );
20570
20129
  }
20571
20130
  });
20572
- if (product.deliveryFeatureId !== void 0 && !featuresById.has(product.deliveryFeatureId)) {
20131
+ if (product.deliveryFeatureId !== void 0 && !hasFeature(featuresById, product.deliveryFeatureId)) {
20573
20132
  addIssue(
20574
20133
  ctx,
20575
20134
  ["offerings", "products", productIndex, "deliveryFeatureId"],
@@ -20596,44 +20155,6 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
20596
20155
  );
20597
20156
  }
20598
20157
  });
20599
- model.resourceMappings.forEach((resourceMapping, resourceIndex) => {
20600
- resourceMapping.featureIds.forEach((featureId, featureIndex) => {
20601
- const feature = featuresById.get(featureId);
20602
- if (!feature) {
20603
- addIssue(
20604
- ctx,
20605
- ["resourceMappings", resourceIndex, "featureIds", featureIndex],
20606
- `Resource mapping "${resourceMapping.id}" references unknown feature "${featureId}"`
20607
- );
20608
- return;
20609
- }
20610
- if (!feature.resourceIds.includes(resourceMapping.resourceId)) {
20611
- addIssue(
20612
- ctx,
20613
- ["resourceMappings", resourceIndex, "featureIds", featureIndex],
20614
- `Resource mapping "${resourceMapping.id}" references feature "${featureId}" but that feature does not include resource "${resourceMapping.resourceId}"`
20615
- );
20616
- }
20617
- });
20618
- resourceMapping.surfaceIds.forEach((surfaceId, surfaceIndex) => {
20619
- const surface = surfacesById.get(surfaceId);
20620
- if (!surface) {
20621
- addIssue(
20622
- ctx,
20623
- ["resourceMappings", resourceIndex, "surfaceIds", surfaceIndex],
20624
- `Resource mapping "${resourceMapping.id}" references unknown surface "${surfaceId}"`
20625
- );
20626
- return;
20627
- }
20628
- if (!surface.resourceIds.includes(resourceMapping.resourceId)) {
20629
- addIssue(
20630
- ctx,
20631
- ["resourceMappings", resourceIndex, "surfaceIds", surfaceIndex],
20632
- `Resource mapping "${resourceMapping.id}" references surface "${surfaceId}" but that surface does not include resource "${resourceMapping.resourceId}"`
20633
- );
20634
- }
20635
- });
20636
- });
20637
20158
  });
20638
20159
 
20639
20160
  // src/organization-model/defaults.ts
@@ -20641,110 +20162,261 @@ var DEFAULT_ORGANIZATION_MODEL = {
20641
20162
  version: 1,
20642
20163
  features: [
20643
20164
  {
20644
- id: SALES_FEATURE_ID,
20165
+ id: "dashboard",
20166
+ label: "Dashboard",
20167
+ enabled: true,
20168
+ path: "/",
20169
+ icon: "dashboard",
20170
+ uiPosition: "sidebar-primary"
20171
+ },
20172
+ {
20173
+ id: "sales",
20174
+ label: "Sales",
20175
+ description: "Revenue workflows and customer acquisition",
20176
+ enabled: true,
20177
+ color: "blue",
20178
+ icon: "crm",
20179
+ uiPosition: "sidebar-primary"
20180
+ },
20181
+ {
20182
+ id: "sales.crm",
20645
20183
  label: "CRM",
20646
20184
  description: "Relationship pipeline and deal management",
20647
20185
  enabled: true,
20648
20186
  color: "blue",
20649
- entityIds: ["crm.deal"],
20650
- surfaceIds: [SALES_PIPELINE_SURFACE_ID],
20651
- resourceIds: [],
20652
- capabilityIds: ["crm.pipeline.manage"]
20187
+ icon: "crm",
20188
+ path: "/crm"
20653
20189
  },
20654
20190
  {
20655
- id: PROSPECTING_FEATURE_ID,
20191
+ id: "sales.lead-gen",
20656
20192
  label: "Lead Gen",
20657
20193
  description: "Prospecting, qualification, and outreach preparation",
20658
20194
  enabled: true,
20659
20195
  color: "cyan",
20660
- entityIds: ["leadgen.list", "leadgen.company", "leadgen.contact"],
20661
- surfaceIds: [PROSPECTING_LISTS_SURFACE_ID],
20662
- resourceIds: [],
20663
- capabilityIds: ["leadgen.lists.manage"]
20196
+ icon: "lead-gen",
20197
+ path: "/lead-gen"
20664
20198
  },
20665
20199
  {
20666
- id: PROJECTS_FEATURE_ID,
20200
+ id: "projects",
20667
20201
  label: "Projects",
20668
20202
  description: "Projects, milestones, and client work execution",
20669
20203
  enabled: true,
20670
20204
  color: "orange",
20671
- entityIds: ["delivery.project", "delivery.milestone", "delivery.task"],
20672
- surfaceIds: [PROJECTS_INDEX_SURFACE_ID],
20673
- resourceIds: [],
20674
- capabilityIds: [PROJECTS_VIEW_CAPABILITY_ID]
20205
+ icon: "projects",
20206
+ path: "/projects",
20207
+ uiPosition: "sidebar-primary"
20675
20208
  },
20676
20209
  {
20677
- id: OPERATIONS_FEATURE_ID,
20210
+ id: "operations",
20678
20211
  label: "Operations",
20679
20212
  description: "Operational resources, topology, and orchestration visibility",
20680
20213
  enabled: true,
20681
20214
  color: "violet",
20682
- entityIds: [],
20683
- surfaceIds: [
20684
- OPERATIONS_ORGANIZATION_GRAPH_SURFACE_ID,
20685
- "operations.command-view",
20686
- "operations.overview",
20687
- "operations.resources",
20688
- "operations.command-queue",
20689
- "operations.sessions",
20690
- "operations.task-scheduler"
20691
- ],
20692
- resourceIds: [],
20693
- capabilityIds: ["operations.organization-graph", "operations.command-view"]
20215
+ icon: "operations",
20216
+ uiPosition: "sidebar-primary"
20694
20217
  },
20695
20218
  {
20696
- id: MONITORING_FEATURE_ID,
20219
+ id: "operations.graph",
20220
+ label: "Organization Graph",
20221
+ enabled: true,
20222
+ path: "/operations/organization-graph"
20223
+ },
20224
+ {
20225
+ id: "operations.command-view",
20226
+ label: "Command View",
20227
+ enabled: false,
20228
+ path: "/operations/command-view"
20229
+ },
20230
+ {
20231
+ id: "operations.overview",
20232
+ label: "Overview",
20233
+ enabled: true,
20234
+ path: "/operations"
20235
+ },
20236
+ {
20237
+ id: "operations.resources",
20238
+ label: "Resources",
20239
+ enabled: true,
20240
+ path: "/operations/resources"
20241
+ },
20242
+ {
20243
+ id: "operations.command-queue",
20244
+ label: "Command Queue",
20245
+ enabled: true,
20246
+ path: "/operations/command-queue"
20247
+ },
20248
+ {
20249
+ id: "operations.sessions",
20250
+ label: "Sessions",
20251
+ enabled: false,
20252
+ path: "/operations/sessions"
20253
+ },
20254
+ {
20255
+ id: "operations.task-scheduler",
20256
+ label: "Task Scheduler",
20257
+ enabled: true,
20258
+ path: "/operations/task-scheduler"
20259
+ },
20260
+ {
20261
+ id: "monitoring",
20697
20262
  label: "Monitoring",
20698
20263
  enabled: true,
20699
- entityIds: [],
20700
- surfaceIds: [
20701
- "monitoring.activity-log",
20702
- "monitoring.execution-logs",
20703
- "monitoring.execution-health",
20704
- "monitoring.cost-analytics",
20705
- "monitoring.notifications"
20706
- ],
20707
- resourceIds: [],
20708
- capabilityIds: []
20264
+ uiPosition: "sidebar-primary"
20709
20265
  },
20710
20266
  {
20711
- id: SETTINGS_FEATURE_ID,
20712
- label: "Settings",
20267
+ id: "monitoring.activity-log",
20268
+ label: "Activity Log",
20713
20269
  enabled: true,
20714
- entityIds: [],
20715
- surfaceIds: [
20716
- "settings.account",
20717
- "settings.appearance",
20718
- "settings.organization",
20719
- "settings.credentials",
20720
- "settings.api-keys",
20721
- "settings.webhooks",
20722
- "settings.deployments"
20723
- ],
20724
- resourceIds: [],
20725
- capabilityIds: []
20270
+ path: "/monitoring/activity-log"
20726
20271
  },
20727
20272
  {
20728
- id: "submitted-requests",
20273
+ id: "monitoring.execution-logs",
20274
+ label: "Execution Logs",
20275
+ enabled: true,
20276
+ path: "/monitoring/execution-logs"
20277
+ },
20278
+ {
20279
+ id: "monitoring.execution-health",
20280
+ label: "Execution Health",
20281
+ enabled: true,
20282
+ path: "/monitoring/execution-health"
20283
+ },
20284
+ {
20285
+ id: "monitoring.cost-analytics",
20286
+ label: "Cost Analytics",
20287
+ enabled: false,
20288
+ path: "/monitoring/cost-analytics"
20289
+ },
20290
+ {
20291
+ id: "monitoring.notifications",
20292
+ label: "Notifications",
20293
+ enabled: true,
20294
+ path: "/monitoring/notifications"
20295
+ },
20296
+ {
20297
+ id: "monitoring.submitted-requests",
20729
20298
  label: "Submitted Requests",
20730
20299
  enabled: true,
20731
- entityIds: ["reported_request"],
20732
- surfaceIds: ["submitted-requests.list", "submitted-requests.detail"],
20733
- resourceIds: [],
20734
- capabilityIds: []
20300
+ path: "/monitoring/requests"
20735
20301
  },
20736
20302
  {
20737
- id: SEO_FEATURE_ID,
20303
+ id: "settings",
20304
+ label: "Settings",
20305
+ enabled: true,
20306
+ icon: "settings",
20307
+ uiPosition: "sidebar-bottom"
20308
+ },
20309
+ {
20310
+ id: "settings.account",
20311
+ label: "Account",
20312
+ enabled: true,
20313
+ path: "/settings/account"
20314
+ },
20315
+ {
20316
+ id: "settings.appearance",
20317
+ label: "Appearance",
20318
+ enabled: true,
20319
+ path: "/settings/appearance"
20320
+ },
20321
+ {
20322
+ id: "settings.organization",
20323
+ label: "Organization",
20324
+ enabled: true,
20325
+ path: "/settings/organization"
20326
+ },
20327
+ {
20328
+ id: "settings.credentials",
20329
+ label: "Credentials",
20330
+ enabled: true,
20331
+ path: "/settings/credentials"
20332
+ },
20333
+ {
20334
+ id: "settings.api-keys",
20335
+ label: "API Keys",
20336
+ enabled: true,
20337
+ path: "/settings/api-keys"
20338
+ },
20339
+ {
20340
+ id: "settings.webhooks",
20341
+ label: "Webhooks",
20342
+ enabled: true,
20343
+ path: "/settings/webhooks"
20344
+ },
20345
+ {
20346
+ id: "settings.deployments",
20347
+ label: "Deployments",
20348
+ enabled: true,
20349
+ path: "/settings/deployments"
20350
+ },
20351
+ {
20352
+ id: "admin",
20353
+ label: "Admin",
20354
+ enabled: true,
20355
+ path: "/admin",
20356
+ icon: "settings",
20357
+ uiPosition: "sidebar-bottom",
20358
+ requiresAdmin: true
20359
+ },
20360
+ {
20361
+ id: "admin.system-health",
20362
+ label: "System Health",
20363
+ enabled: true,
20364
+ path: "/admin/system-health"
20365
+ },
20366
+ {
20367
+ id: "admin.organizations",
20368
+ label: "Organizations",
20369
+ enabled: true,
20370
+ path: "/admin/organizations"
20371
+ },
20372
+ {
20373
+ id: "admin.users",
20374
+ label: "Users",
20375
+ enabled: true,
20376
+ path: "/admin/users"
20377
+ },
20378
+ {
20379
+ id: "admin.design-showcase",
20380
+ label: "Design Showcase",
20381
+ enabled: true,
20382
+ path: "/admin/design-showcase"
20383
+ },
20384
+ {
20385
+ id: "admin.debug",
20386
+ label: "Debug",
20387
+ enabled: true,
20388
+ path: "/admin/debug"
20389
+ },
20390
+ {
20391
+ id: "archive",
20392
+ label: "Archive",
20393
+ enabled: true,
20394
+ path: "/archive",
20395
+ icon: "archive",
20396
+ uiPosition: "sidebar-bottom",
20397
+ devOnly: true
20398
+ },
20399
+ {
20400
+ id: "archive.agent-chat",
20401
+ label: "Agent Chat",
20402
+ enabled: true,
20403
+ path: "/archive/agent-chat"
20404
+ },
20405
+ {
20406
+ id: "archive.execution-runner",
20407
+ label: "Execution Runner",
20408
+ enabled: true,
20409
+ path: "/archive/execution-runner"
20410
+ },
20411
+ {
20412
+ id: "seo",
20738
20413
  label: "SEO",
20739
20414
  enabled: false,
20740
- entityIds: [],
20741
- surfaceIds: [],
20742
- resourceIds: [],
20743
- capabilityIds: []
20415
+ path: "/seo"
20744
20416
  }
20745
20417
  ],
20746
20418
  branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
20747
- navigation: DEFAULT_ORGANIZATION_MODEL_NAVIGATION,
20419
+ navigation: { surfaces: [], groups: [] },
20748
20420
  sales: DEFAULT_ORGANIZATION_MODEL_SALES,
20749
20421
  prospecting: DEFAULT_ORGANIZATION_MODEL_PROSPECTING,
20750
20422
  projects: DEFAULT_ORGANIZATION_MODEL_PROJECTS,
@@ -20754,8 +20426,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
20754
20426
  roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
20755
20427
  goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
20756
20428
  statuses: DEFAULT_ORGANIZATION_MODEL_STATUSES,
20757
- operations: DEFAULT_ORGANIZATION_MODEL_OPERATIONS,
20758
- resourceMappings: []
20429
+ operations: DEFAULT_ORGANIZATION_MODEL_OPERATIONS
20759
20430
  };
20760
20431
 
20761
20432
  // src/organization-model/resolve.ts
@@ -20780,25 +20451,8 @@ function deepMerge2(base, override) {
20780
20451
  }
20781
20452
  return result;
20782
20453
  }
20783
- function normalizeInheritedNavigationGroups(model, override) {
20784
- if (override?.navigation?.surfaces === void 0 || override.navigation.groups !== void 0) {
20785
- return model;
20786
- }
20787
- const validSurfaceIds = new Set(model.navigation.surfaces.map((surface) => surface.id));
20788
- const groups = model.navigation.groups.map((group) => ({
20789
- ...group,
20790
- surfaceIds: group.surfaceIds.filter((surfaceId) => validSurfaceIds.has(surfaceId))
20791
- })).filter((group) => group.surfaceIds.length > 0);
20792
- return {
20793
- ...model,
20794
- navigation: {
20795
- ...model.navigation,
20796
- groups
20797
- }
20798
- };
20799
- }
20800
20454
  function resolveOrganizationModel(override) {
20801
- const merged = normalizeInheritedNavigationGroups(deepMerge2(DEFAULT_ORGANIZATION_MODEL, override), override);
20455
+ const merged = deepMerge2(DEFAULT_ORGANIZATION_MODEL, override);
20802
20456
  return OrganizationModelSchema.parse(merged);
20803
20457
  }
20804
20458