@elevasis/ui 2.40.1 → 2.41.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 (48) hide show
  1. package/dist/app/index.d.ts +108 -0
  2. package/dist/app/index.js +6 -7
  3. package/dist/auth/index.js +3 -4
  4. package/dist/charts/index.js +3 -4
  5. package/dist/{chunk-7MTWRSUZ.js → chunk-56O7QQE7.js} +1 -2
  6. package/dist/{chunk-SJNIOGVX.js → chunk-A2XN6PR2.js} +2 -3
  7. package/dist/{chunk-K7GKKETO.js → chunk-FIMGOWOT.js} +1073 -586
  8. package/dist/{chunk-RX6RSKWC.js → chunk-JAN2ZXN5.js} +105 -23
  9. package/dist/{chunk-LJDYY3XB.js → chunk-JHVEA5NE.js} +1 -1
  10. package/dist/{chunk-X7D6SUKR.js → chunk-QVQMOQXB.js} +8 -2
  11. package/dist/{chunk-IUQAP4IO.js → chunk-S4R2ZQS7.js} +1 -1
  12. package/dist/{chunk-7PHY5ONQ.js → chunk-VAAU2Z3S.js} +1 -1
  13. package/dist/{chunk-6EV47QQW.js → chunk-YPWN2WQ3.js} +1 -1
  14. package/dist/components/index.js +8 -9
  15. package/dist/components/navigation/index.js +2 -3
  16. package/dist/features/auth/index.js +9 -10
  17. package/dist/features/clients/index.js +8 -9
  18. package/dist/features/crm/index.js +8 -9
  19. package/dist/features/dashboard/index.js +8 -9
  20. package/dist/features/delivery/index.js +8 -9
  21. package/dist/features/knowledge/index.js +2 -3
  22. package/dist/features/lead-gen/index.d.ts +81 -0
  23. package/dist/features/lead-gen/index.js +8 -9
  24. package/dist/features/monitoring/index.js +8 -9
  25. package/dist/features/monitoring/requests/index.d.ts +69 -7
  26. package/dist/features/monitoring/requests/index.js +136 -15
  27. package/dist/features/operations/index.d.ts +79 -0
  28. package/dist/features/operations/index.js +8 -9
  29. package/dist/features/settings/index.js +8 -9
  30. package/dist/hooks/access/index.js +2 -3
  31. package/dist/hooks/delivery/index.js +8 -9
  32. package/dist/hooks/index.d.ts +18 -6
  33. package/dist/hooks/index.js +8 -9
  34. package/dist/hooks/published.d.ts +18 -6
  35. package/dist/hooks/published.js +8 -9
  36. package/dist/index.d.ts +151 -7
  37. package/dist/index.js +8 -9
  38. package/dist/knowledge/index.d.ts +81 -0
  39. package/dist/knowledge/index.js +5 -5
  40. package/dist/layout/index.d.ts +18 -2
  41. package/dist/layout/index.js +3 -1
  42. package/dist/organization/index.js +8 -9
  43. package/dist/provider/index.d.ts +120 -1
  44. package/dist/provider/index.js +5 -6
  45. package/dist/provider/published.d.ts +121 -2
  46. package/dist/provider/published.js +4 -5
  47. package/package.json +4 -4
  48. package/dist/chunk-J3FLIZY4.js +0 -423
@@ -1,6 +1,7 @@
1
- import { OntologyScopeSchema, OntologyIdSchema, DEFAULT_ONTOLOGY_SCOPE, compileOrganizationOntology, listResolvedOntologyRecords, listAllSystems, defineDomainRecord, ontologyGraphNodeId, parseOntologyId, getAllProspectingStages, getAllPipelines, getAllProjectStatuses, getLeadGenStageCatalog, getAllBuildTemplates } from './chunk-RH5VWWSC.js';
2
- import { IconMail, IconSend, IconFileText, IconClock, IconArrowUp, IconMessageCircle, IconRocket, IconEye, IconEdit, IconAlertTriangle, IconRefresh, IconX, IconCheck, IconShieldLock, IconActivity, IconTopologyStar3, IconApps, IconBriefcase, IconBuilding, IconBolt, IconSearch, IconChartBar, IconUsers, IconInfoCircle, IconDatabase, IconGitBranch, IconDashboard, IconBuildingStore, IconUser, IconPlug, IconBrain, IconTargetArrow, IconBook, IconLayoutGrid, IconArchive, IconSettings, IconTool, IconCalendar } from '@tabler/icons-react';
1
+ import { OntologyScopeSchema, OntologyIdSchema, DEFAULT_ONTOLOGY_SCOPE, compileOrganizationOntology, listResolvedOntologyRecords, listAllSystems, defineDomainRecord, ontologyGraphNodeId, parseOntologyId, getAllProspectingStages, getAllPipelines, getAllProjectStatuses, getLeadGenStageCatalog, getAllBuildTemplates, devOnlyFor, requiresAdminFor, topLevel, parentOf, ancestorsOf, childrenOf, findById, findByPath, defaultPathFor } from './chunk-RH5VWWSC.js';
2
+ import { IconMail, IconSend, IconFileText, IconClock, IconArrowUp, IconMessageCircle, IconRocket, IconEye, IconEdit, IconAlertTriangle, IconRefresh, IconX, IconCheck, IconShieldLock, IconActivity, IconTopologyStar3, IconApps, IconBriefcase, IconBuilding, IconBolt, IconSearch, IconChartBar, IconUsers, IconInfoCircle, IconMessagePlus, IconDatabase, IconGitBranch, IconDashboard, IconBuildingStore, IconUser, IconPlug, IconBrain, IconTargetArrow, IconBook, IconLayoutGrid, IconArchive, IconSettings, IconTool, IconCalendar } from '@tabler/icons-react';
3
3
  import { jsx } from 'react/jsx-runtime';
4
+ import { createContext, useContext, useMemo, useCallback } from 'react';
4
5
  import { z } from 'zod';
5
6
 
6
7
  var DEFAULT_SEMANTIC_ICON_REGISTRY = {
@@ -44,6 +45,8 @@ var DEFAULT_SEMANTIC_ICON_REGISTRY = {
44
45
  pipeline: IconGitBranch,
45
46
  lists: IconFileText,
46
47
  resources: IconDatabase,
48
+ // Topbar action tokens
49
+ "message-plus": IconMessagePlus,
47
50
  // Actions
48
51
  approve: IconCheck,
49
52
  reject: IconX,
@@ -143,6 +146,85 @@ function SemanticIcon({
143
146
  }
144
147
  );
145
148
  }
149
+
150
+ // ../core/src/organization-model/cross-ref.ts
151
+ var ONTOLOGY_REFERENCE_KEY_KINDS = {
152
+ valueType: "value-type",
153
+ catalogType: "catalog",
154
+ objectType: "object",
155
+ eventType: "event",
156
+ actionType: "action",
157
+ linkType: "link",
158
+ interfaceType: "interface",
159
+ propertyType: "property",
160
+ groupType: "group",
161
+ surfaceType: "surface",
162
+ stepCatalog: "catalog"
163
+ };
164
+ function buildOmCrossRefIndex(model) {
165
+ const systemsById = /* @__PURE__ */ new Map();
166
+ for (const { path, system } of listAllSystems(model)) {
167
+ systemsById.set(path, system);
168
+ systemsById.set(system.id, system);
169
+ }
170
+ const resourceIds = new Set(Object.keys(model.resources ?? {}));
171
+ const knowledgeIds = new Set(Object.keys(model.knowledge ?? {}));
172
+ const roleIds = new Set(Object.keys(model.roles ?? {}));
173
+ const goalIds = new Set(Object.keys(model.goals ?? {}));
174
+ const actionIds = new Set(Object.keys(model.actions ?? {}));
175
+ const customerSegmentIds = new Set(Object.keys(model.customers ?? {}));
176
+ const offeringIds = new Set(Object.keys(model.offerings ?? {}));
177
+ const ontologyCompilation = compileOrganizationOntology(model);
178
+ const ontologyIndexByKind = {
179
+ object: ontologyCompilation.ontology.objectTypes,
180
+ link: ontologyCompilation.ontology.linkTypes,
181
+ action: ontologyCompilation.ontology.actionTypes,
182
+ catalog: ontologyCompilation.ontology.catalogTypes,
183
+ event: ontologyCompilation.ontology.eventTypes,
184
+ interface: ontologyCompilation.ontology.interfaceTypes,
185
+ "value-type": ontologyCompilation.ontology.valueTypes,
186
+ property: ontologyCompilation.ontology.sharedProperties,
187
+ group: ontologyCompilation.ontology.groups,
188
+ surface: ontologyCompilation.ontology.surfaces
189
+ };
190
+ const ontologyIds = new Set(Object.values(ontologyIndexByKind).flatMap((index) => Object.keys(index)));
191
+ const stageIds = /* @__PURE__ */ new Set();
192
+ for (const catalog of Object.values(ontologyCompilation.ontology.catalogTypes)) {
193
+ if (catalog.kind !== "stage") continue;
194
+ const entries = catalog.entries;
195
+ if (entries !== void 0) {
196
+ for (const stageId of Object.keys(entries)) {
197
+ stageIds.add(stageId);
198
+ }
199
+ }
200
+ }
201
+ return {
202
+ systemsById,
203
+ resourceIds,
204
+ knowledgeIds,
205
+ roleIds,
206
+ goalIds,
207
+ actionIds,
208
+ customerSegmentIds,
209
+ offeringIds,
210
+ ontologyIds,
211
+ ontologyIndexByKind,
212
+ stageIds
213
+ };
214
+ }
215
+ function knowledgeTargetExists(index, kind, id) {
216
+ if (kind === "system") return index.systemsById.has(id);
217
+ if (kind === "resource") return index.resourceIds.has(id);
218
+ if (kind === "knowledge") return index.knowledgeIds.has(id);
219
+ if (kind === "stage") return index.stageIds.has(id);
220
+ if (kind === "action") return index.actionIds.has(id);
221
+ if (kind === "role") return index.roleIds.has(id);
222
+ if (kind === "goal") return index.goalIds.has(id);
223
+ if (kind === "customer-segment") return index.customerSegmentIds.has(id);
224
+ if (kind === "offering") return index.offeringIds.has(id);
225
+ if (kind === "ontology") return index.ontologyIds.has(id);
226
+ return false;
227
+ }
146
228
  var ORGANIZATION_MODEL_ICON_TOKENS = [
147
229
  // Navigation / app areas
148
230
  "dashboard",
@@ -192,6 +274,7 @@ var ORGANIZATION_MODEL_ICON_TOKENS = [
192
274
  "view",
193
275
  "launch",
194
276
  "message",
277
+ "message-plus",
195
278
  "escalate",
196
279
  "promote",
197
280
  "submit",
@@ -268,7 +351,325 @@ DisplayMetadataSchema.extend({
268
351
  techStack: TechStackEntrySchema.optional()
269
352
  });
270
353
 
271
- // ../core/src/organization-model/domains/entities.ts
354
+ // ../core/src/organization-model/domains/branding.ts
355
+ var OrganizationModelBrandingSchema = z.object({
356
+ /**
357
+ * @deprecated Prefer `identity.organizationName`; branding retains it for back-compat.
358
+ * Legacy tenants that have not set `identity.organizationName` fall back to this field.
359
+ */
360
+ organizationName: LabelSchema,
361
+ /**
362
+ * @deprecated Prefer `identity.productName`; branding retains it for back-compat.
363
+ * Legacy tenants that have not set `identity.productName` fall back to this field.
364
+ */
365
+ productName: LabelSchema,
366
+ /**
367
+ * @deprecated Prefer `identity.shortName`; branding retains it for back-compat.
368
+ * Legacy tenants that have not set `identity.shortName` fall back to this field.
369
+ */
370
+ shortName: z.string().trim().min(1).max(40),
371
+ /**
372
+ * @deprecated Prefer `identity.description`; branding retains it for back-compat.
373
+ * Legacy tenants that have not set `identity.description` fall back to this field.
374
+ */
375
+ description: DescriptionSchema.optional(),
376
+ logos: z.object({
377
+ light: z.string().trim().min(1).max(2048).optional(),
378
+ dark: z.string().trim().min(1).max(2048).optional()
379
+ }).default({}),
380
+ /**
381
+ * Brand voice — how the organization communicates. Plain-language description
382
+ * of tone, register, and personality (e.g. "Direct and human — no jargon").
383
+ * Max 280 characters.
384
+ */
385
+ voice: z.string().trim().max(280).optional(),
386
+ /**
387
+ * Brand tagline or positioning statement — the memorable one-liner that
388
+ * captures the brand's promise or differentiator. Max 200 characters.
389
+ */
390
+ tagline: z.string().trim().max(200).optional(),
391
+ /**
392
+ * Core brand values — an ordered list of principles the organization stands
393
+ * for (e.g. ["Transparency", "Craftsmanship", "Velocity"]). Each entry must
394
+ * be a non-empty trimmed string.
395
+ */
396
+ values: z.array(z.string().trim().min(1)).optional(),
397
+ /**
398
+ * ID of the active UI theme preset from the UI theme-presets registry.
399
+ * The UI layer resolves this to colors and typography via `usePresetsContext()`.
400
+ * Free-form string — validation and fallback state are handled at the UI layer.
401
+ * Min 1, max 64 characters.
402
+ */
403
+ themePresetId: z.string().trim().min(1).max(64).optional()
404
+ }).passthrough();
405
+ var DEFAULT_ORGANIZATION_MODEL_BRANDING = {
406
+ organizationName: "Default Organization",
407
+ productName: "Organization OS",
408
+ shortName: "Org OS",
409
+ logos: {}
410
+ };
411
+ var SurfaceTypeSchema = z.enum(["page", "dashboard", "graph", "detail", "list", "settings"]).meta({ label: "Surface type", color: "blue" });
412
+ var SurfaceDefinitionSchema = z.object({
413
+ id: ModelIdSchema,
414
+ label: LabelSchema,
415
+ path: PathSchema,
416
+ surfaceType: SurfaceTypeSchema,
417
+ description: DescriptionSchema.optional(),
418
+ enabled: z.boolean().default(true),
419
+ devOnly: z.boolean().optional(),
420
+ icon: IconNameSchema.optional(),
421
+ systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
422
+ entityIds: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]),
423
+ resourceIds: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]),
424
+ actionIds: z.array(ModelIdSchema.meta({ ref: "action" })).default([]),
425
+ parentId: ModelIdSchema.meta({ ref: "surface" }).optional()
426
+ });
427
+ var SidebarSurfaceTargetsSchema = z.object({
428
+ systems: z.array(ModelIdSchema.meta({ ref: "system" })).default([]).optional(),
429
+ entities: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]).optional(),
430
+ resources: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]).optional(),
431
+ actions: z.array(ModelIdSchema.meta({ ref: "action" })).default([]).optional()
432
+ }).default({});
433
+ var SidebarNodeSchema = z.lazy(
434
+ () => z.discriminatedUnion("type", [
435
+ z.object({
436
+ type: z.literal("group"),
437
+ label: LabelSchema,
438
+ description: DescriptionSchema.optional(),
439
+ icon: IconNameSchema.optional(),
440
+ order: z.number().int().optional(),
441
+ children: z.record(z.string(), SidebarNodeSchema).default({})
442
+ }),
443
+ z.object({
444
+ type: z.literal("surface"),
445
+ label: LabelSchema,
446
+ path: PathSchema,
447
+ surfaceType: SurfaceTypeSchema,
448
+ description: DescriptionSchema.optional(),
449
+ icon: IconNameSchema.optional(),
450
+ order: z.number().int().optional(),
451
+ targets: SidebarSurfaceTargetsSchema.optional(),
452
+ devOnly: z.boolean().optional(),
453
+ requiresAdmin: z.boolean().optional()
454
+ })
455
+ ])
456
+ );
457
+ var SidebarSectionSchema = z.record(z.string(), SidebarNodeSchema).default({});
458
+ var SidebarNavigationSchema = z.object({
459
+ primary: SidebarSectionSchema,
460
+ bottom: SidebarSectionSchema
461
+ }).default({ primary: {}, bottom: {} });
462
+ var TopbarActionNodeSchema = z.object({
463
+ id: ModelIdSchema,
464
+ label: LabelSchema,
465
+ tooltip: DescriptionSchema.optional(),
466
+ icon: IconNameSchema.optional(),
467
+ order: z.number().int().optional(),
468
+ enabled: z.boolean().default(true),
469
+ devOnly: z.boolean().optional(),
470
+ requiresAdmin: z.boolean().optional(),
471
+ targets: SidebarSurfaceTargetsSchema.optional()
472
+ });
473
+ var TopbarSectionSchema = z.record(z.string(), TopbarActionNodeSchema).default({});
474
+ var OrganizationModelNavigationSchema = z.object({
475
+ sidebar: SidebarNavigationSchema,
476
+ topbar: TopbarSectionSchema
477
+ }).default({ sidebar: { primary: {}, bottom: {} }, topbar: {} });
478
+ function getSortedSidebarEntries(nodes) {
479
+ return Object.entries(nodes).sort(([leftId, left], [rightId, right]) => {
480
+ const orderDelta = (left.order ?? Number.MAX_SAFE_INTEGER) - (right.order ?? Number.MAX_SAFE_INTEGER);
481
+ return orderDelta === 0 ? leftId.localeCompare(rightId) : orderDelta;
482
+ });
483
+ }
484
+ z.object({
485
+ id: ModelIdSchema,
486
+ label: LabelSchema,
487
+ placement: z.string().trim().min(1).max(50),
488
+ surfaceIds: z.array(ModelIdSchema.meta({ ref: "surface" })).default([])
489
+ });
490
+ var BusinessHoursDaySchema = z.object({
491
+ open: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format"),
492
+ close: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format")
493
+ });
494
+ var BusinessHoursSchema = z.object({
495
+ monday: BusinessHoursDaySchema.optional(),
496
+ tuesday: BusinessHoursDaySchema.optional(),
497
+ wednesday: BusinessHoursDaySchema.optional(),
498
+ thursday: BusinessHoursDaySchema.optional(),
499
+ friday: BusinessHoursDaySchema.optional(),
500
+ saturday: BusinessHoursDaySchema.optional(),
501
+ sunday: BusinessHoursDaySchema.optional()
502
+ }).default({});
503
+ var IdentityDomainSchema = z.object({
504
+ /** Why the organization exists — one or two plain-language sentences. */
505
+ mission: z.string().trim().max(1e3).default(""),
506
+ /** Long-term direction the organization is moving toward. */
507
+ vision: z.string().trim().max(1e3).default(""),
508
+ /** Legal registered name of the entity. */
509
+ legalName: z.string().trim().max(200).default(""),
510
+ /**
511
+ * Type of legal entity (e.g. "LLC", "Corporation", "Sole Proprietor",
512
+ * "Non-profit"). Free-form string so it covers any jurisdiction.
513
+ */
514
+ entityType: z.string().trim().max(100).default(""),
515
+ /**
516
+ * Primary jurisdiction of registration or operation
517
+ * (e.g. "United States – Delaware", "Canada – Ontario").
518
+ */
519
+ jurisdiction: z.string().trim().max(200).default(""),
520
+ /**
521
+ * Industry category — broad classification (e.g. "Marketing Agency",
522
+ * "Software / SaaS", "Professional Services").
523
+ */
524
+ industryCategory: z.string().trim().max(200).default(""),
525
+ /**
526
+ * Geographic focus — where the organization primarily operates or serves
527
+ * (e.g. "North America", "Global", "Southeast Asia").
528
+ */
529
+ geographicFocus: z.string().trim().max(200).default(""),
530
+ /**
531
+ * IANA timezone identifier for the organization's primary operating timezone
532
+ * (e.g. "America/Los_Angeles", "Europe/London", "UTC").
533
+ */
534
+ timeZone: z.string().trim().max(100).default("UTC"),
535
+ /** Typical operating hours per day of week. Empty object means not configured. */
536
+ businessHours: BusinessHoursSchema,
537
+ /**
538
+ * Long-form markdown capturing client context, problem narrative, and domain
539
+ * background. Populated by /setup; surfaced to agents as organizational context.
540
+ * Optional — many projects have no external client.
541
+ */
542
+ clientBrief: z.string().trim().default(""),
543
+ /**
544
+ * Display name of the organization as shown to end users.
545
+ * Recommended placement for display naming — prefer this over the deprecated
546
+ * `branding.organizationName`. Falls back to `branding.organizationName` for
547
+ * legacy tenants that have not yet migrated.
548
+ */
549
+ organizationName: LabelSchema.optional(),
550
+ /**
551
+ * Display name of the primary product or platform.
552
+ * Recommended placement for display naming — prefer this over the deprecated
553
+ * `branding.productName`. Falls back to `branding.productName` for legacy tenants.
554
+ */
555
+ productName: LabelSchema.optional(),
556
+ /**
557
+ * Short abbreviated name used in space-constrained UI surfaces (max 40 chars).
558
+ * Recommended placement for display naming — prefer this over the deprecated
559
+ * `branding.shortName`. Falls back to `branding.shortName` for legacy tenants.
560
+ */
561
+ shortName: z.string().trim().min(1).max(40).optional(),
562
+ /**
563
+ * Plain-language description of the organization for display and discovery.
564
+ * Recommended placement for display naming — prefer this over the deprecated
565
+ * `branding.description`. Falls back to `branding.description` for legacy tenants.
566
+ */
567
+ description: DescriptionSchema.optional()
568
+ }).passthrough();
569
+ var DEFAULT_ORGANIZATION_MODEL_IDENTITY = {
570
+ mission: "",
571
+ vision: "",
572
+ legalName: "",
573
+ entityType: "",
574
+ jurisdiction: "",
575
+ industryCategory: "",
576
+ geographicFocus: "",
577
+ timeZone: "UTC",
578
+ businessHours: {},
579
+ clientBrief: ""
580
+ };
581
+ var FirmographicsSchema = z.object({
582
+ /** Industry vertical (e.g. "Marketing Agency", "Legal", "Real Estate"). */
583
+ industry: z.string().trim().max(200).optional(),
584
+ /**
585
+ * Company headcount band (e.g. "1–10", "11–50", "51–200", "200+").
586
+ * Free-form string to accommodate any band notation.
587
+ */
588
+ companySize: z.string().trim().max(100).optional(),
589
+ /**
590
+ * Primary geographic region the segment operates in or is targeted from
591
+ * (e.g. "North America", "Europe", "Global").
592
+ */
593
+ region: z.string().trim().max(200).optional()
594
+ });
595
+ var CustomerSegmentSchema = z.object({
596
+ /** Stable unique identifier for the segment (e.g. "segment-smb-agencies"). */
597
+ id: z.string().trim().min(1).max(100),
598
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
599
+ order: z.number(),
600
+ /** Human-readable name shown to agents and in UI (e.g. "SMB Marketing Agencies"). */
601
+ name: z.string().trim().max(200).default(""),
602
+ /** One or two sentences describing who this segment is. */
603
+ description: z.string().trim().max(2e3).default(""),
604
+ /**
605
+ * The primary job(s) this segment is trying to get done — the goal they hire
606
+ * a product/service to accomplish. Plain-language narrative or bullet list.
607
+ */
608
+ jobsToBeDone: z.string().trim().max(2e3).default(""),
609
+ /**
610
+ * Pains — frustrations, obstacles, and risks the segment experiences
611
+ * when trying to accomplish their jobs-to-be-done.
612
+ */
613
+ pains: z.array(z.string().trim().max(500)).default([]),
614
+ /**
615
+ * Gains — outcomes and benefits the segment desires; positive motivators
616
+ * beyond merely resolving pains.
617
+ */
618
+ gains: z.array(z.string().trim().max(500)).default([]),
619
+ /** Firmographic profile for targeting and filtering. */
620
+ firmographics: FirmographicsSchema.default({}),
621
+ /**
622
+ * Value proposition — one or two sentences stating why this organization's
623
+ * offering is uniquely suited for this segment's needs.
624
+ */
625
+ valueProp: z.string().trim().max(2e3).default("")
626
+ });
627
+ var CustomersDomainSchema = z.record(z.string(), CustomerSegmentSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
628
+ message: "Each segment entry id must match its map key"
629
+ }).default({});
630
+ var DEFAULT_ORGANIZATION_MODEL_CUSTOMERS = {};
631
+ var PricingModelSchema = z.enum(["one-time", "subscription", "usage-based", "custom"]).meta({ label: "Pricing model", color: "green" });
632
+ var ProductSchema = z.object({
633
+ /** Stable unique identifier for the product (e.g. "product-starter-plan"). */
634
+ id: z.string().trim().min(1).max(100),
635
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
636
+ order: z.number(),
637
+ /** Human-readable name shown to agents and in UI (e.g. "Starter Plan"). */
638
+ name: z.string().trim().max(200).default(""),
639
+ /** One or two sentences describing what this product/service delivers. */
640
+ description: z.string().trim().max(2e3).default(""),
641
+ /**
642
+ * How this product is priced:
643
+ * - "one-time" — single purchase (setup fee, project fee)
644
+ * - "subscription" — recurring (monthly/annual SaaS, retainer)
645
+ * - "usage-based" — metered by consumption (API calls, seats)
646
+ * - "custom" — negotiated or bespoke pricing
647
+ */
648
+ pricingModel: PricingModelSchema.default("custom"),
649
+ /** Base price amount (≥ 0). Currency unit defined by `currency`. */
650
+ price: z.number().min(0).default(0),
651
+ /**
652
+ * ISO 4217 currency code (e.g. "USD", "EUR", "GBP").
653
+ * Free-form string to accommodate any currency; defaults to "USD".
654
+ */
655
+ currency: z.string().trim().max(10).default("USD"),
656
+ /**
657
+ * IDs of customer segments this product targets.
658
+ * Each id must reference a declared `customers.segments[].id`.
659
+ * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
660
+ */
661
+ targetSegmentIds: z.array(z.string().trim().min(1)).default([]),
662
+ /**
663
+ * Optional: ID of the platform system responsible for delivering this product.
664
+ * When present, must reference a declared `systems.systems[].id`.
665
+ * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
666
+ */
667
+ deliveryFeatureId: z.string().trim().min(1).optional()
668
+ });
669
+ var OfferingsDomainSchema = z.record(z.string(), ProductSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
670
+ message: "Each product entry id must match its map key"
671
+ }).default({});
672
+ var DEFAULT_ORGANIZATION_MODEL_OFFERINGS = {};
272
673
  var EntityIdSchema = ModelIdSchema;
273
674
  var EntityLinkKindSchema = z.enum(["belongs-to", "has-many", "has-one", "many-to-many"]).meta({ label: "Link kind" });
274
675
  var EntityLinkSchema = z.object({
@@ -464,122 +865,33 @@ var SystemEntrySchema = z.object({
464
865
  * System-owned ontology declarations. `systems` is now the canonical child
465
866
  * key; this scope holds the object, action, catalog, link, event, and
466
867
  * shared contract records owned by this system.
467
- */
468
- ontology: OntologyScopeSchema.optional(),
469
- /**
470
- * Recursive child systems, authored via nesting (per L11).
471
- * The key is the local system id; the full path is computed by joining
472
- * ancestor keys with `.` (e.g. parent key `'sales'` + child key `'crm'` → `'sales.crm'`).
473
- * Per Phase 4: `id` and `parentSystemId` fields will be removed in favour of
474
- * position-derived paths. Both still exist on this schema for backward compat.
475
- */
476
- systems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional(),
477
- /** @deprecated Use systems. Accepted as a compatibility alias during the ontology bridge. */
478
- subsystems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional()
479
- }).strict().refine((system) => system.label !== void 0 || system.title !== void 0, {
480
- path: ["label"],
481
- message: "System must provide label or title"
482
- }).transform((system) => {
483
- const normalizedSystem = system.systems !== void 0 && system.subsystems === void 0 ? { ...system, subsystems: system.systems } : system;
484
- if (normalizedSystem.status === void 0) return normalizedSystem;
485
- console.warn("[organization-model] System.status is deprecated; use System.lifecycle instead.");
486
- return normalizedSystem.lifecycle === void 0 ? { ...normalizedSystem, lifecycle: normalizedSystem.status } : normalizedSystem;
487
- });
488
- var SystemsDomainSchema = z.record(z.string(), SystemEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
489
- message: "Each system entry id must match its map key"
490
- }).default({});
491
- var DEFAULT_ORGANIZATION_MODEL_SYSTEMS = {};
492
- var BusinessHoursDaySchema = z.object({
493
- open: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format"),
494
- close: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format")
495
- });
496
- var BusinessHoursSchema = z.object({
497
- monday: BusinessHoursDaySchema.optional(),
498
- tuesday: BusinessHoursDaySchema.optional(),
499
- wednesday: BusinessHoursDaySchema.optional(),
500
- thursday: BusinessHoursDaySchema.optional(),
501
- friday: BusinessHoursDaySchema.optional(),
502
- saturday: BusinessHoursDaySchema.optional(),
503
- sunday: BusinessHoursDaySchema.optional()
504
- }).default({});
505
- var IdentityDomainSchema = z.object({
506
- /** Why the organization exists — one or two plain-language sentences. */
507
- mission: z.string().trim().max(1e3).default(""),
508
- /** Long-term direction the organization is moving toward. */
509
- vision: z.string().trim().max(1e3).default(""),
510
- /** Legal registered name of the entity. */
511
- legalName: z.string().trim().max(200).default(""),
512
- /**
513
- * Type of legal entity (e.g. "LLC", "Corporation", "Sole Proprietor",
514
- * "Non-profit"). Free-form string so it covers any jurisdiction.
515
- */
516
- entityType: z.string().trim().max(100).default(""),
517
- /**
518
- * Primary jurisdiction of registration or operation
519
- * (e.g. "United States – Delaware", "Canada – Ontario").
520
- */
521
- jurisdiction: z.string().trim().max(200).default(""),
522
- /**
523
- * Industry category — broad classification (e.g. "Marketing Agency",
524
- * "Software / SaaS", "Professional Services").
525
- */
526
- industryCategory: z.string().trim().max(200).default(""),
527
- /**
528
- * Geographic focus — where the organization primarily operates or serves
529
- * (e.g. "North America", "Global", "Southeast Asia").
530
- */
531
- geographicFocus: z.string().trim().max(200).default(""),
532
- /**
533
- * IANA timezone identifier for the organization's primary operating timezone
534
- * (e.g. "America/Los_Angeles", "Europe/London", "UTC").
535
- */
536
- timeZone: z.string().trim().max(100).default("UTC"),
537
- /** Typical operating hours per day of week. Empty object means not configured. */
538
- businessHours: BusinessHoursSchema,
539
- /**
540
- * Long-form markdown capturing client context, problem narrative, and domain
541
- * background. Populated by /setup; surfaced to agents as organizational context.
542
- * Optional — many projects have no external client.
543
- */
544
- clientBrief: z.string().trim().default(""),
545
- /**
546
- * Display name of the organization as shown to end users.
547
- * Recommended placement for display naming — prefer this over the deprecated
548
- * `branding.organizationName`. Falls back to `branding.organizationName` for
549
- * legacy tenants that have not yet migrated.
550
- */
551
- organizationName: LabelSchema.optional(),
552
- /**
553
- * Display name of the primary product or platform.
554
- * Recommended placement for display naming — prefer this over the deprecated
555
- * `branding.productName`. Falls back to `branding.productName` for legacy tenants.
556
- */
557
- productName: LabelSchema.optional(),
558
- /**
559
- * Short abbreviated name used in space-constrained UI surfaces (max 40 chars).
560
- * Recommended placement for display naming — prefer this over the deprecated
561
- * `branding.shortName`. Falls back to `branding.shortName` for legacy tenants.
562
- */
563
- shortName: z.string().trim().min(1).max(40).optional(),
564
- /**
565
- * Plain-language description of the organization for display and discovery.
566
- * Recommended placement for display naming — prefer this over the deprecated
567
- * `branding.description`. Falls back to `branding.description` for legacy tenants.
568
- */
569
- description: DescriptionSchema.optional()
570
- }).passthrough();
571
- var DEFAULT_ORGANIZATION_MODEL_IDENTITY = {
572
- mission: "",
573
- vision: "",
574
- legalName: "",
575
- entityType: "",
576
- jurisdiction: "",
577
- industryCategory: "",
578
- geographicFocus: "",
579
- timeZone: "UTC",
580
- businessHours: {},
581
- clientBrief: ""
582
- };
868
+ */
869
+ ontology: OntologyScopeSchema.optional(),
870
+ /**
871
+ * Recursive child systems, authored via nesting (per L11).
872
+ * The key is the local system id; the full path is computed by joining
873
+ * ancestor keys with `.` (e.g. parent key `'sales'` + child key `'crm'` → `'sales.crm'`).
874
+ * Per Phase 4: `id` and `parentSystemId` fields will be removed in favour of
875
+ * position-derived paths. Both still exist on this schema for backward compat.
876
+ */
877
+ systems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional(),
878
+ /** @deprecated Use systems. Accepted as a compatibility alias during the ontology bridge. */
879
+ subsystems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional()
880
+ }).strict().refine((system) => system.label !== void 0 || system.title !== void 0, {
881
+ path: ["label"],
882
+ message: "System must provide label or title"
883
+ }).transform((system) => {
884
+ const normalizedSystem = system.systems !== void 0 && system.subsystems === void 0 ? { ...system, subsystems: system.systems } : system;
885
+ if (normalizedSystem.status === void 0) return normalizedSystem;
886
+ console.warn("[organization-model] System.status is deprecated; use System.lifecycle instead.");
887
+ return normalizedSystem.lifecycle === void 0 ? { ...normalizedSystem, lifecycle: normalizedSystem.status } : normalizedSystem;
888
+ });
889
+ var SystemsDomainSchema = z.record(z.string(), SystemEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
890
+ message: "Each system entry id must match its map key"
891
+ }).default({});
892
+ var DEFAULT_ORGANIZATION_MODEL_SYSTEMS = {};
893
+
894
+ // ../core/src/organization-model/domains/resources.ts
583
895
  var ContractRefSchema = z.string().trim().min(1).max(500).regex(
584
896
  /^[A-Za-z0-9@](?:[A-Za-z0-9_./@-]*[A-Za-z0-9_])?\/?[A-Za-z0-9_./@-]*#[A-Za-z_$][A-Za-z0-9_$]*$/,
585
897
  "ContractRef must be in the format package/subpath#ExportName (e.g. @repo/elevasis-core/contracts/apollo-import#inputSchema)"
@@ -711,156 +1023,7 @@ function defineResources(resources) {
711
1023
  );
712
1024
  }
713
1025
 
714
- // ../core/src/organization-model/contracts.ts
715
- var PROJECTS_VIEW_ACTION_ID = "delivery.projects.view";
716
- var OrganizationModelBrandingSchema = z.object({
717
- /**
718
- * @deprecated Prefer `identity.organizationName`; branding retains it for back-compat.
719
- * Legacy tenants that have not set `identity.organizationName` fall back to this field.
720
- */
721
- organizationName: LabelSchema,
722
- /**
723
- * @deprecated Prefer `identity.productName`; branding retains it for back-compat.
724
- * Legacy tenants that have not set `identity.productName` fall back to this field.
725
- */
726
- productName: LabelSchema,
727
- /**
728
- * @deprecated Prefer `identity.shortName`; branding retains it for back-compat.
729
- * Legacy tenants that have not set `identity.shortName` fall back to this field.
730
- */
731
- shortName: z.string().trim().min(1).max(40),
732
- /**
733
- * @deprecated Prefer `identity.description`; branding retains it for back-compat.
734
- * Legacy tenants that have not set `identity.description` fall back to this field.
735
- */
736
- description: DescriptionSchema.optional(),
737
- logos: z.object({
738
- light: z.string().trim().min(1).max(2048).optional(),
739
- dark: z.string().trim().min(1).max(2048).optional()
740
- }).default({}),
741
- /**
742
- * Brand voice — how the organization communicates. Plain-language description
743
- * of tone, register, and personality (e.g. "Direct and human — no jargon").
744
- * Max 280 characters.
745
- */
746
- voice: z.string().trim().max(280).optional(),
747
- /**
748
- * Brand tagline or positioning statement — the memorable one-liner that
749
- * captures the brand's promise or differentiator. Max 200 characters.
750
- */
751
- tagline: z.string().trim().max(200).optional(),
752
- /**
753
- * Core brand values — an ordered list of principles the organization stands
754
- * for (e.g. ["Transparency", "Craftsmanship", "Velocity"]). Each entry must
755
- * be a non-empty trimmed string.
756
- */
757
- values: z.array(z.string().trim().min(1)).optional(),
758
- /**
759
- * ID of the active UI theme preset from the UI theme-presets registry.
760
- * The UI layer resolves this to colors and typography via `usePresetsContext()`.
761
- * Free-form string — validation and fallback state are handled at the UI layer.
762
- * Min 1, max 64 characters.
763
- */
764
- themePresetId: z.string().trim().min(1).max(64).optional()
765
- }).passthrough();
766
- var DEFAULT_ORGANIZATION_MODEL_BRANDING = {
767
- organizationName: "Default Organization",
768
- productName: "Organization OS",
769
- shortName: "Org OS",
770
- logos: {}
771
- };
772
- var FirmographicsSchema = z.object({
773
- /** Industry vertical (e.g. "Marketing Agency", "Legal", "Real Estate"). */
774
- industry: z.string().trim().max(200).optional(),
775
- /**
776
- * Company headcount band (e.g. "1–10", "11–50", "51–200", "200+").
777
- * Free-form string to accommodate any band notation.
778
- */
779
- companySize: z.string().trim().max(100).optional(),
780
- /**
781
- * Primary geographic region the segment operates in or is targeted from
782
- * (e.g. "North America", "Europe", "Global").
783
- */
784
- region: z.string().trim().max(200).optional()
785
- });
786
- var CustomerSegmentSchema = z.object({
787
- /** Stable unique identifier for the segment (e.g. "segment-smb-agencies"). */
788
- id: z.string().trim().min(1).max(100),
789
- /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
790
- order: z.number(),
791
- /** Human-readable name shown to agents and in UI (e.g. "SMB Marketing Agencies"). */
792
- name: z.string().trim().max(200).default(""),
793
- /** One or two sentences describing who this segment is. */
794
- description: z.string().trim().max(2e3).default(""),
795
- /**
796
- * The primary job(s) this segment is trying to get done — the goal they hire
797
- * a product/service to accomplish. Plain-language narrative or bullet list.
798
- */
799
- jobsToBeDone: z.string().trim().max(2e3).default(""),
800
- /**
801
- * Pains — frustrations, obstacles, and risks the segment experiences
802
- * when trying to accomplish their jobs-to-be-done.
803
- */
804
- pains: z.array(z.string().trim().max(500)).default([]),
805
- /**
806
- * Gains — outcomes and benefits the segment desires; positive motivators
807
- * beyond merely resolving pains.
808
- */
809
- gains: z.array(z.string().trim().max(500)).default([]),
810
- /** Firmographic profile for targeting and filtering. */
811
- firmographics: FirmographicsSchema.default({}),
812
- /**
813
- * Value proposition — one or two sentences stating why this organization's
814
- * offering is uniquely suited for this segment's needs.
815
- */
816
- valueProp: z.string().trim().max(2e3).default("")
817
- });
818
- var CustomersDomainSchema = z.record(z.string(), CustomerSegmentSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
819
- message: "Each segment entry id must match its map key"
820
- }).default({});
821
- var DEFAULT_ORGANIZATION_MODEL_CUSTOMERS = {};
822
- var PricingModelSchema = z.enum(["one-time", "subscription", "usage-based", "custom"]).meta({ label: "Pricing model", color: "green" });
823
- var ProductSchema = z.object({
824
- /** Stable unique identifier for the product (e.g. "product-starter-plan"). */
825
- id: z.string().trim().min(1).max(100),
826
- /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
827
- order: z.number(),
828
- /** Human-readable name shown to agents and in UI (e.g. "Starter Plan"). */
829
- name: z.string().trim().max(200).default(""),
830
- /** One or two sentences describing what this product/service delivers. */
831
- description: z.string().trim().max(2e3).default(""),
832
- /**
833
- * How this product is priced:
834
- * - "one-time" — single purchase (setup fee, project fee)
835
- * - "subscription" — recurring (monthly/annual SaaS, retainer)
836
- * - "usage-based" — metered by consumption (API calls, seats)
837
- * - "custom" — negotiated or bespoke pricing
838
- */
839
- pricingModel: PricingModelSchema.default("custom"),
840
- /** Base price amount (≥ 0). Currency unit defined by `currency`. */
841
- price: z.number().min(0).default(0),
842
- /**
843
- * ISO 4217 currency code (e.g. "USD", "EUR", "GBP").
844
- * Free-form string to accommodate any currency; defaults to "USD".
845
- */
846
- currency: z.string().trim().max(10).default("USD"),
847
- /**
848
- * IDs of customer segments this product targets.
849
- * Each id must reference a declared `customers.segments[].id`.
850
- * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
851
- */
852
- targetSegmentIds: z.array(z.string().trim().min(1)).default([]),
853
- /**
854
- * Optional: ID of the platform system responsible for delivering this product.
855
- * When present, must reference a declared `systems.systems[].id`.
856
- * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
857
- */
858
- deliveryFeatureId: z.string().trim().min(1).optional()
859
- });
860
- var OfferingsDomainSchema = z.record(z.string(), ProductSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
861
- message: "Each product entry id must match its map key"
862
- }).default({});
863
- var DEFAULT_ORGANIZATION_MODEL_OFFERINGS = {};
1026
+ // ../core/src/organization-model/domains/roles.ts
864
1027
  var RoleIdSchema = ModelIdSchema;
865
1028
  var HumanRoleHolderSchema = z.object({
866
1029
  kind: z.literal("human"),
@@ -952,15 +1115,99 @@ var ObjectiveSchema = z.object({
952
1115
  */
953
1116
  periodEnd: z.string().regex(ISO_DATE_REGEX, "periodEnd must be an ISO date string (YYYY-MM-DD)"),
954
1117
  /**
955
- * List of measurable outcomes that define success for this goal.
956
- * Defaults to empty array so goals can be declared before outcomes are defined.
1118
+ * List of measurable outcomes that define success for this goal.
1119
+ * Defaults to empty array so goals can be declared before outcomes are defined.
1120
+ */
1121
+ keyResults: z.array(KeyResultSchema).default([])
1122
+ });
1123
+ var GoalsDomainSchema = z.record(z.string(), ObjectiveSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
1124
+ message: "Each objective entry id must match its map key"
1125
+ }).default({});
1126
+ var DEFAULT_ORGANIZATION_MODEL_GOALS = {};
1127
+ var KnowledgeTargetKindSchema = z.enum([
1128
+ "system",
1129
+ "resource",
1130
+ "knowledge",
1131
+ "stage",
1132
+ "action",
1133
+ "role",
1134
+ "goal",
1135
+ "customer-segment",
1136
+ "offering",
1137
+ "ontology"
1138
+ ]).meta({ label: "Target kind" });
1139
+ var KnowledgeTargetRefSchema = z.object({
1140
+ kind: KnowledgeTargetKindSchema,
1141
+ // Ontology targets use the canonical '<scope>:<kind>/<local-id>' ontology id format.
1142
+ // Business-logic validation of target existence is done in OrganizationModelSchema.superRefine.
1143
+ id: z.string().trim().min(1).max(300)
1144
+ }).superRefine((target, ctx) => {
1145
+ if (target.kind !== "ontology") return;
1146
+ const result = OntologyIdSchema.safeParse(target.id);
1147
+ if (!result.success) {
1148
+ ctx.addIssue({
1149
+ code: z.ZodIssueCode.custom,
1150
+ path: ["id"],
1151
+ message: "Ontology knowledge targets must use <system-path>:<kind>/<local-id> or global:<kind>/<local-id>"
1152
+ });
1153
+ }
1154
+ });
1155
+ var LegacyKnowledgeLinkSchema = z.object({
1156
+ nodeId: z.union([NodeIdStringSchema, z.templateLiteral(["ontology:", OntologyIdSchema])])
1157
+ }).superRefine((link, ctx) => {
1158
+ const [kind] = link.nodeId.split(":");
1159
+ if (!KnowledgeTargetKindSchema.safeParse(kind).success) {
1160
+ ctx.addIssue({
1161
+ code: z.ZodIssueCode.custom,
1162
+ path: ["nodeId"],
1163
+ message: `Unknown knowledge target kind "${kind}"`
1164
+ });
1165
+ }
1166
+ });
1167
+ var CanonicalKnowledgeLinkSchema = z.object({
1168
+ target: KnowledgeTargetRefSchema
1169
+ });
1170
+ function nodeIdFromTarget(target) {
1171
+ return `${target.kind}:${target.id}`;
1172
+ }
1173
+ function targetFromNodeId(nodeId2) {
1174
+ const [kind, ...idParts] = nodeId2.split(":");
1175
+ return {
1176
+ kind: KnowledgeTargetKindSchema.parse(kind),
1177
+ id: idParts.join(":")
1178
+ };
1179
+ }
1180
+ var KnowledgeLinkSchema = z.union([CanonicalKnowledgeLinkSchema, LegacyKnowledgeLinkSchema]).transform((link) => {
1181
+ const target = "target" in link ? link.target : targetFromNodeId(link.nodeId);
1182
+ return {
1183
+ target,
1184
+ nodeId: nodeIdFromTarget(target)
1185
+ };
1186
+ });
1187
+ var OrgKnowledgeKindSchema = z.enum(["playbook", "strategy", "reference"]).meta({ label: "Knowledge kind", color: "grape" });
1188
+ var OrgKnowledgeNodeSchema = z.object({
1189
+ id: ModelIdSchema,
1190
+ kind: OrgKnowledgeKindSchema,
1191
+ title: z.string().trim().min(1).max(200),
1192
+ summary: z.string().trim().min(1).max(1e3),
1193
+ icon: IconNameSchema.optional(),
1194
+ /** Canonical documentation URL when body content is a local summary. */
1195
+ externalUrl: z.string().trim().url().max(500).optional(),
1196
+ /** Optional generated source file path for local MDX-backed knowledge nodes. */
1197
+ sourceFilePath: z.string().trim().min(1).max(500).optional(),
1198
+ /** Raw MDX string. Phase 2 will introduce a structured block format. */
1199
+ body: z.string().trim().min(1),
1200
+ /**
1201
+ * Graph links to other OM nodes this knowledge node governs.
1202
+ * Each link emits a `governs` edge: knowledge-node -> target node.
957
1203
  */
958
- keyResults: z.array(KeyResultSchema).default([])
1204
+ links: z.array(KnowledgeLinkSchema).default([]),
1205
+ /** Role identifiers that own this knowledge node. */
1206
+ ownerIds: z.array(RoleIdSchema.meta({ ref: "role" })).default([]),
1207
+ /** ISO date string (YYYY-MM-DD or full ISO 8601) of last meaningful update. */
1208
+ updatedAt: z.string().trim().min(1).max(50)
959
1209
  });
960
- var GoalsDomainSchema = z.record(z.string(), ObjectiveSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
961
- message: "Each objective entry id must match its map key"
962
- }).default({});
963
- var DEFAULT_ORGANIZATION_MODEL_GOALS = {};
1210
+ var KnowledgeDomainSchema = z.record(ModelIdSchema, OrgKnowledgeNodeSchema).default({});
964
1211
  var SecretLikeMetadataKeySchema = /(?:secret|password|passwd|token|api[-_]?key|credential|private[-_]?key)/i;
965
1212
  var SecretLikeMetadataValueSchema = /(?:sk-[A-Za-z0-9_-]{12,}|pk_live_[A-Za-z0-9_-]{12,}|eyJ[A-Za-z0-9_-]{20,}|-----BEGIN (?:RSA |OPENSSH |EC )?PRIVATE KEY-----)/;
966
1213
  z.enum([
@@ -1188,247 +1435,16 @@ var PolicySchema = z.object({
1188
1435
  actions: z.array(PolicyEffectSchema).min(1),
1189
1436
  appliesTo: PolicyApplicabilitySchema.default({
1190
1437
  systemIds: [],
1191
- actionIds: [],
1192
- resourceIds: [],
1193
- roleIds: []
1194
- }),
1195
- lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
1196
- });
1197
- var PoliciesDomainSchema = z.record(z.string(), PolicySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
1198
- message: "Each policy entry id must match its map key"
1199
- }).default({});
1200
- var DEFAULT_ORGANIZATION_MODEL_POLICIES = {};
1201
- var SurfaceTypeSchema = z.enum(["page", "dashboard", "graph", "detail", "list", "settings"]).meta({ label: "Surface type", color: "blue" });
1202
- var SurfaceDefinitionSchema = z.object({
1203
- id: ModelIdSchema,
1204
- label: LabelSchema,
1205
- path: PathSchema,
1206
- surfaceType: SurfaceTypeSchema,
1207
- description: DescriptionSchema.optional(),
1208
- enabled: z.boolean().default(true),
1209
- devOnly: z.boolean().optional(),
1210
- icon: IconNameSchema.optional(),
1211
- systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
1212
- entityIds: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]),
1213
- resourceIds: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]),
1214
- actionIds: z.array(ModelIdSchema.meta({ ref: "action" })).default([]),
1215
- parentId: ModelIdSchema.meta({ ref: "surface" }).optional()
1216
- });
1217
- var SidebarSurfaceTargetsSchema = z.object({
1218
- systems: z.array(ModelIdSchema.meta({ ref: "system" })).default([]).optional(),
1219
- entities: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]).optional(),
1220
- resources: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]).optional(),
1221
- actions: z.array(ModelIdSchema.meta({ ref: "action" })).default([]).optional()
1222
- }).default({});
1223
- var SidebarNodeSchema = z.lazy(
1224
- () => z.discriminatedUnion("type", [
1225
- z.object({
1226
- type: z.literal("group"),
1227
- label: LabelSchema,
1228
- description: DescriptionSchema.optional(),
1229
- icon: IconNameSchema.optional(),
1230
- order: z.number().int().optional(),
1231
- children: z.record(z.string(), SidebarNodeSchema).default({})
1232
- }),
1233
- z.object({
1234
- type: z.literal("surface"),
1235
- label: LabelSchema,
1236
- path: PathSchema,
1237
- surfaceType: SurfaceTypeSchema,
1238
- description: DescriptionSchema.optional(),
1239
- icon: IconNameSchema.optional(),
1240
- order: z.number().int().optional(),
1241
- targets: SidebarSurfaceTargetsSchema.optional(),
1242
- devOnly: z.boolean().optional(),
1243
- requiresAdmin: z.boolean().optional()
1244
- })
1245
- ])
1246
- );
1247
- var SidebarSectionSchema = z.record(z.string(), SidebarNodeSchema).default({});
1248
- var SidebarNavigationSchema = z.object({
1249
- primary: SidebarSectionSchema,
1250
- bottom: SidebarSectionSchema
1251
- }).default({ primary: {}, bottom: {} });
1252
- var OrganizationModelNavigationSchema = z.object({
1253
- sidebar: SidebarNavigationSchema
1254
- }).default({ sidebar: { primary: {}, bottom: {} } });
1255
- function getSortedSidebarEntries(nodes) {
1256
- return Object.entries(nodes).sort(([leftId, left], [rightId, right]) => {
1257
- const orderDelta = (left.order ?? Number.MAX_SAFE_INTEGER) - (right.order ?? Number.MAX_SAFE_INTEGER);
1258
- return orderDelta === 0 ? leftId.localeCompare(rightId) : orderDelta;
1259
- });
1260
- }
1261
- z.object({
1262
- id: ModelIdSchema,
1263
- label: LabelSchema,
1264
- placement: z.string().trim().min(1).max(50),
1265
- surfaceIds: z.array(ModelIdSchema.meta({ ref: "surface" })).default([])
1266
- });
1267
- var KnowledgeTargetKindSchema = z.enum([
1268
- "system",
1269
- "resource",
1270
- "knowledge",
1271
- "stage",
1272
- "action",
1273
- "role",
1274
- "goal",
1275
- "customer-segment",
1276
- "offering",
1277
- "ontology"
1278
- ]).meta({ label: "Target kind" });
1279
- var KnowledgeTargetRefSchema = z.object({
1280
- kind: KnowledgeTargetKindSchema,
1281
- // Ontology targets use the canonical '<scope>:<kind>/<local-id>' ontology id format.
1282
- // Business-logic validation of target existence is done in OrganizationModelSchema.superRefine.
1283
- id: z.string().trim().min(1).max(300)
1284
- }).superRefine((target, ctx) => {
1285
- if (target.kind !== "ontology") return;
1286
- const result = OntologyIdSchema.safeParse(target.id);
1287
- if (!result.success) {
1288
- ctx.addIssue({
1289
- code: z.ZodIssueCode.custom,
1290
- path: ["id"],
1291
- message: "Ontology knowledge targets must use <system-path>:<kind>/<local-id> or global:<kind>/<local-id>"
1292
- });
1293
- }
1294
- });
1295
- var LegacyKnowledgeLinkSchema = z.object({
1296
- nodeId: z.union([NodeIdStringSchema, z.templateLiteral(["ontology:", OntologyIdSchema])])
1297
- }).superRefine((link, ctx) => {
1298
- const [kind] = link.nodeId.split(":");
1299
- if (!KnowledgeTargetKindSchema.safeParse(kind).success) {
1300
- ctx.addIssue({
1301
- code: z.ZodIssueCode.custom,
1302
- path: ["nodeId"],
1303
- message: `Unknown knowledge target kind "${kind}"`
1304
- });
1305
- }
1306
- });
1307
- var CanonicalKnowledgeLinkSchema = z.object({
1308
- target: KnowledgeTargetRefSchema
1309
- });
1310
- function nodeIdFromTarget(target) {
1311
- return `${target.kind}:${target.id}`;
1312
- }
1313
- function targetFromNodeId(nodeId2) {
1314
- const [kind, ...idParts] = nodeId2.split(":");
1315
- return {
1316
- kind: KnowledgeTargetKindSchema.parse(kind),
1317
- id: idParts.join(":")
1318
- };
1319
- }
1320
- var KnowledgeLinkSchema = z.union([CanonicalKnowledgeLinkSchema, LegacyKnowledgeLinkSchema]).transform((link) => {
1321
- const target = "target" in link ? link.target : targetFromNodeId(link.nodeId);
1322
- return {
1323
- target,
1324
- nodeId: nodeIdFromTarget(target)
1325
- };
1326
- });
1327
- var OrgKnowledgeKindSchema = z.enum(["playbook", "strategy", "reference"]).meta({ label: "Knowledge kind", color: "grape" });
1328
- var OrgKnowledgeNodeSchema = z.object({
1329
- id: ModelIdSchema,
1330
- kind: OrgKnowledgeKindSchema,
1331
- title: z.string().trim().min(1).max(200),
1332
- summary: z.string().trim().min(1).max(1e3),
1333
- icon: IconNameSchema.optional(),
1334
- /** Canonical documentation URL when body content is a local summary. */
1335
- externalUrl: z.string().trim().url().max(500).optional(),
1336
- /** Optional generated source file path for local MDX-backed knowledge nodes. */
1337
- sourceFilePath: z.string().trim().min(1).max(500).optional(),
1338
- /** Raw MDX string. Phase 2 will introduce a structured block format. */
1339
- body: z.string().trim().min(1),
1340
- /**
1341
- * Graph links to other OM nodes this knowledge node governs.
1342
- * Each link emits a `governs` edge: knowledge-node -> target node.
1343
- */
1344
- links: z.array(KnowledgeLinkSchema).default([]),
1345
- /** Role identifiers that own this knowledge node. */
1346
- ownerIds: z.array(RoleIdSchema.meta({ ref: "role" })).default([]),
1347
- /** ISO date string (YYYY-MM-DD or full ISO 8601) of last meaningful update. */
1348
- updatedAt: z.string().trim().min(1).max(50)
1349
- });
1350
- var KnowledgeDomainSchema = z.record(ModelIdSchema, OrgKnowledgeNodeSchema).default({});
1351
-
1352
- // ../core/src/organization-model/cross-ref.ts
1353
- var ONTOLOGY_REFERENCE_KEY_KINDS = {
1354
- valueType: "value-type",
1355
- catalogType: "catalog",
1356
- objectType: "object",
1357
- eventType: "event",
1358
- actionType: "action",
1359
- linkType: "link",
1360
- interfaceType: "interface",
1361
- propertyType: "property",
1362
- groupType: "group",
1363
- surfaceType: "surface",
1364
- stepCatalog: "catalog"
1365
- };
1366
- function buildOmCrossRefIndex(model) {
1367
- const systemsById = /* @__PURE__ */ new Map();
1368
- for (const { path, system } of listAllSystems(model)) {
1369
- systemsById.set(path, system);
1370
- systemsById.set(system.id, system);
1371
- }
1372
- const resourceIds = new Set(Object.keys(model.resources ?? {}));
1373
- const knowledgeIds = new Set(Object.keys(model.knowledge ?? {}));
1374
- const roleIds = new Set(Object.keys(model.roles ?? {}));
1375
- const goalIds = new Set(Object.keys(model.goals ?? {}));
1376
- const actionIds = new Set(Object.keys(model.actions ?? {}));
1377
- const customerSegmentIds = new Set(Object.keys(model.customers ?? {}));
1378
- const offeringIds = new Set(Object.keys(model.offerings ?? {}));
1379
- const ontologyCompilation = compileOrganizationOntology(model);
1380
- const ontologyIndexByKind = {
1381
- object: ontologyCompilation.ontology.objectTypes,
1382
- link: ontologyCompilation.ontology.linkTypes,
1383
- action: ontologyCompilation.ontology.actionTypes,
1384
- catalog: ontologyCompilation.ontology.catalogTypes,
1385
- event: ontologyCompilation.ontology.eventTypes,
1386
- interface: ontologyCompilation.ontology.interfaceTypes,
1387
- "value-type": ontologyCompilation.ontology.valueTypes,
1388
- property: ontologyCompilation.ontology.sharedProperties,
1389
- group: ontologyCompilation.ontology.groups,
1390
- surface: ontologyCompilation.ontology.surfaces
1391
- };
1392
- const ontologyIds = new Set(Object.values(ontologyIndexByKind).flatMap((index) => Object.keys(index)));
1393
- const stageIds = /* @__PURE__ */ new Set();
1394
- for (const catalog of Object.values(ontologyCompilation.ontology.catalogTypes)) {
1395
- if (catalog.kind !== "stage") continue;
1396
- const entries = catalog.entries;
1397
- if (entries !== void 0) {
1398
- for (const stageId of Object.keys(entries)) {
1399
- stageIds.add(stageId);
1400
- }
1401
- }
1402
- }
1403
- return {
1404
- systemsById,
1405
- resourceIds,
1406
- knowledgeIds,
1407
- roleIds,
1408
- goalIds,
1409
- actionIds,
1410
- customerSegmentIds,
1411
- offeringIds,
1412
- ontologyIds,
1413
- ontologyIndexByKind,
1414
- stageIds
1415
- };
1416
- }
1417
- function knowledgeTargetExists(index, kind, id) {
1418
- if (kind === "system") return index.systemsById.has(id);
1419
- if (kind === "resource") return index.resourceIds.has(id);
1420
- if (kind === "knowledge") return index.knowledgeIds.has(id);
1421
- if (kind === "stage") return index.stageIds.has(id);
1422
- if (kind === "action") return index.actionIds.has(id);
1423
- if (kind === "role") return index.roleIds.has(id);
1424
- if (kind === "goal") return index.goalIds.has(id);
1425
- if (kind === "customer-segment") return index.customerSegmentIds.has(id);
1426
- if (kind === "offering") return index.offeringIds.has(id);
1427
- if (kind === "ontology") return index.ontologyIds.has(id);
1428
- return false;
1429
- }
1430
-
1431
- // ../core/src/organization-model/schema-refinements.ts
1438
+ actionIds: [],
1439
+ resourceIds: [],
1440
+ roleIds: []
1441
+ }),
1442
+ lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
1443
+ });
1444
+ var PoliciesDomainSchema = z.record(z.string(), PolicySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
1445
+ message: "Each policy entry id must match its map key"
1446
+ }).default({});
1447
+ var DEFAULT_ORGANIZATION_MODEL_POLICIES = {};
1432
1448
  function addIssue(ctx, path, message) {
1433
1449
  ctx.addIssue({
1434
1450
  code: z.ZodIssueCode.custom,
@@ -1533,7 +1549,7 @@ function refineOrganizationModel(model, ctx) {
1533
1549
  currentParentId = systemsById.get(currentParentId)?.parentSystemId;
1534
1550
  }
1535
1551
  });
1536
- function normalizeRoutePath(path) {
1552
+ function normalizeRoutePath2(path) {
1537
1553
  return path.length > 1 ? path.replace(/\/+$/, "") : path;
1538
1554
  }
1539
1555
  const sidebarNodeIds = /* @__PURE__ */ new Map();
@@ -1553,7 +1569,7 @@ function refineOrganizationModel(model, ctx) {
1553
1569
  return;
1554
1570
  }
1555
1571
  sidebarSurfaces.push({ id: nodeId2, node, path: nodePath });
1556
- const normalizedPath = normalizeRoutePath(node.path);
1572
+ const normalizedPath = normalizeRoutePath2(node.path);
1557
1573
  const existingSurfaceId = sidebarSurfacePaths.get(normalizedPath);
1558
1574
  if (existingSurfaceId !== void 0) {
1559
1575
  addIssue(
@@ -1882,22 +1898,22 @@ function refineOrganizationModel(model, ctx) {
1882
1898
  );
1883
1899
  }
1884
1900
  });
1885
- allSystems.forEach(({ path: systemPath, schemaPath, system }) => {
1901
+ allSystems.forEach(({ path: systemPath2, schemaPath, system }) => {
1886
1902
  system.apiInterface?.resourceIds?.forEach((resourceId, resourceIndex) => {
1887
1903
  const resource = resourcesById.get(resourceId);
1888
1904
  if (resource === void 0) {
1889
1905
  addIssue(
1890
1906
  ctx,
1891
1907
  [...schemaPath, "apiInterface", "resourceIds", resourceIndex],
1892
- `System Interface "${systemPath}/api" scopes unknown resource "${resourceId}"`
1908
+ `System Interface "${systemPath2}/api" scopes unknown resource "${resourceId}"`
1893
1909
  );
1894
1910
  return;
1895
1911
  }
1896
- if (resource.systemPath !== systemPath) {
1912
+ if (resource.systemPath !== systemPath2) {
1897
1913
  addIssue(
1898
1914
  ctx,
1899
1915
  [...schemaPath, "apiInterface", "resourceIds", resourceIndex],
1900
- `System Interface "${systemPath}/api" scopes resource "${resourceId}" from system "${resource.systemPath}"`
1916
+ `System Interface "${systemPath2}/api" scopes resource "${resourceId}" from system "${resource.systemPath}"`
1901
1917
  );
1902
1918
  }
1903
1919
  });
@@ -2054,6 +2070,9 @@ var OrganizationModelSchemaBase = z.object({
2054
2070
  });
2055
2071
  var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine(refineOrganizationModel);
2056
2072
 
2073
+ // ../core/src/organization-model/contracts.ts
2074
+ var PROJECTS_VIEW_ACTION_ID = "delivery.projects.view";
2075
+
2057
2076
  // ../core/src/organization-model/defaults.ts
2058
2077
  var DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE = {};
2059
2078
  var DEFAULT_ORGANIZATION_MODEL_ENTITIES = {};
@@ -2061,7 +2080,8 @@ var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
2061
2080
  sidebar: {
2062
2081
  primary: {},
2063
2082
  bottom: {}
2064
- }
2083
+ },
2084
+ topbar: {}
2065
2085
  };
2066
2086
  var DEFAULT_ORGANIZATION_MODEL = {
2067
2087
  version: 1,
@@ -2146,6 +2166,87 @@ function resolveOrganizationModel(override, organizationIdOrOptions, options) {
2146
2166
  const merged = mergeDefaults ? deepMerge(DEFAULT_ORGANIZATION_MODEL, override) : override ?? {};
2147
2167
  return OrganizationModelSchema.parse(merged);
2148
2168
  }
2169
+
2170
+ // ../core/src/organization-model/surface-projection.ts
2171
+ function collectSystemsById(model) {
2172
+ const systemsById = /* @__PURE__ */ new Map();
2173
+ for (const { path, system } of listAllSystems(model)) {
2174
+ systemsById.set(path, system);
2175
+ systemsById.set(system.id, system);
2176
+ }
2177
+ return systemsById;
2178
+ }
2179
+ function getSystemWithAncestors(systemsById, systemId) {
2180
+ const systems = [];
2181
+ let current = systemsById.get(systemId);
2182
+ while (current !== void 0) {
2183
+ systems.unshift(current);
2184
+ current = current.parentSystemId ? systemsById.get(current.parentSystemId) : void 0;
2185
+ }
2186
+ return systems;
2187
+ }
2188
+ function hasInheritedFlag(systemsById, systemIds, flag) {
2189
+ return systemIds.some(
2190
+ (systemId) => getSystemWithAncestors(systemsById, systemId).some((system) => system[flag] === true)
2191
+ );
2192
+ }
2193
+ function isLifecycleEnabled2(system) {
2194
+ if (system.enabled === false) return false;
2195
+ return system.lifecycle !== "deprecated" && system.lifecycle !== "archived";
2196
+ }
2197
+ function isLifecycleDevOnly(system) {
2198
+ return system.devOnly === true || system.lifecycle === "beta";
2199
+ }
2200
+ function isSystemEnabled(systemsById, systemId) {
2201
+ const systemLineage = getSystemWithAncestors(systemsById, systemId);
2202
+ return systemLineage.length > 0 && systemLineage.every(isLifecycleEnabled2);
2203
+ }
2204
+ function unique(values) {
2205
+ return [...new Set(values)];
2206
+ }
2207
+ function collectSidebarSurfaces(nodes, schemaPath, surfaces = []) {
2208
+ getSortedSidebarEntries(nodes).forEach(([id, node]) => {
2209
+ const nodePath = [...schemaPath, id];
2210
+ if (node.type === "group") {
2211
+ collectSidebarSurfaces(node.children, [...nodePath, "children"], surfaces);
2212
+ return;
2213
+ }
2214
+ surfaces.push({ id, surface: node, path: nodePath });
2215
+ });
2216
+ return surfaces;
2217
+ }
2218
+ function getSidebarSurfaces(model) {
2219
+ return [
2220
+ ...collectSidebarSurfaces(model.navigation.sidebar.primary, ["navigation", "sidebar", "primary"]),
2221
+ ...collectSidebarSurfaces(model.navigation.sidebar.bottom, ["navigation", "sidebar", "bottom"])
2222
+ ];
2223
+ }
2224
+ function projectOrganizationSurfaces(model) {
2225
+ const systemsById = collectSystemsById(model);
2226
+ return getSidebarSurfaces(model).map(({ id, surface }) => {
2227
+ const targets = surface.targets ?? {};
2228
+ const systemIds = unique((targets.systems ?? []).filter((systemId) => systemsById.has(systemId)));
2229
+ const enabled = systemIds.every((candidate) => isSystemEnabled(systemsById, candidate));
2230
+ const devOnly = surface.devOnly === true || hasInheritedFlag(systemsById, systemIds, "devOnly") || systemIds.some((candidate) => getSystemWithAncestors(systemsById, candidate).some(isLifecycleDevOnly));
2231
+ const requiresAdmin = hasInheritedFlag(systemsById, systemIds, "requiresAdmin");
2232
+ return {
2233
+ id,
2234
+ label: surface.label,
2235
+ path: surface.path,
2236
+ surfaceType: surface.surfaceType,
2237
+ ...surface.description !== void 0 ? { description: surface.description } : {},
2238
+ ...surface.icon !== void 0 ? { icon: surface.icon } : {},
2239
+ ...surface.order !== void 0 ? { order: surface.order } : {},
2240
+ systemIds,
2241
+ entityIds: [...targets.entities ?? []],
2242
+ resourceIds: [...targets.resources ?? []],
2243
+ actionIds: [...targets.actions ?? []],
2244
+ enabled,
2245
+ ...devOnly ? { devOnly } : {},
2246
+ ...surface.requiresAdmin === true || requiresAdmin ? { requiresAdmin: true } : {}
2247
+ };
2248
+ });
2249
+ }
2149
2250
  var OrganizationGraphNodeKindSchema = z.enum([
2150
2251
  "organization",
2151
2252
  "system",
@@ -3073,85 +3174,471 @@ function buildOrganizationGraph(input) {
3073
3174
  return OrganizationGraphSchema.parse(graph);
3074
3175
  }
3075
3176
 
3076
- // ../core/src/organization-model/surface-projection.ts
3077
- function collectSystemsById(model) {
3078
- const systemsById = /* @__PURE__ */ new Map();
3079
- for (const { path, system } of listAllSystems(model)) {
3080
- systemsById.set(path, system);
3081
- systemsById.set(system.id, system);
3177
+ // src/provider/resolvers/RouteResolver.ts
3178
+ function normalizeRoutePath(path) {
3179
+ const trimmedPath = path.trim();
3180
+ if (!trimmedPath || trimmedPath === "/") {
3181
+ return "/";
3082
3182
  }
3083
- return systemsById;
3183
+ return trimmedPath.replace(/\/+$/, "") || "/";
3084
3184
  }
3085
- function getSystemWithAncestors(systemsById, systemId) {
3086
- const systems = [];
3087
- let current = systemsById.get(systemId);
3088
- while (current !== void 0) {
3089
- systems.unshift(current);
3090
- current = current.parentSystemId ? systemsById.get(current.parentSystemId) : void 0;
3185
+ function isRouteMatch(currentPath, route) {
3186
+ const normalizedCurrentPath = normalizeRoutePath(currentPath);
3187
+ const normalizedRoute = normalizeRoutePath(route);
3188
+ return normalizedCurrentPath === normalizedRoute || normalizedCurrentPath.startsWith(`${normalizedRoute}/`);
3189
+ }
3190
+
3191
+ // src/provider/resolvers/NavResolver.ts
3192
+ function uniqueIds(ids) {
3193
+ return ids ? [...new Set(ids)] : [];
3194
+ }
3195
+
3196
+ // src/provider/validateManifests.ts
3197
+ function listSystemRefs(systems) {
3198
+ const refs = [];
3199
+ function walk(map, prefix = "") {
3200
+ for (const [key, system] of Object.entries(map)) {
3201
+ const path = prefix ? `${prefix}.${key}` : key;
3202
+ refs.push(path, system.id);
3203
+ const subsystems = system.subsystems;
3204
+ if (subsystems) {
3205
+ walk(subsystems, path);
3206
+ }
3207
+ }
3091
3208
  }
3092
- return systems;
3209
+ walk(systems);
3210
+ return refs;
3093
3211
  }
3094
- function hasInheritedFlag(systemsById, systemIds, flag) {
3095
- return systemIds.some(
3096
- (systemId) => getSystemWithAncestors(systemsById, systemId).some((system) => system[flag] === true)
3097
- );
3212
+ function validateManifests(manifests, organizationModel) {
3213
+ if (!organizationModel) {
3214
+ return;
3215
+ }
3216
+ const validSystemIds = /* @__PURE__ */ new Set([
3217
+ ...Object.keys(organizationModel.systems ?? {}),
3218
+ ...listSystemRefs(organizationModel.systems ?? {})
3219
+ ]);
3220
+ const errors = [];
3221
+ for (const manifest of manifests) {
3222
+ const key = manifest.key;
3223
+ const systemId = manifest.systemId;
3224
+ if (!systemId) {
3225
+ continue;
3226
+ }
3227
+ if (!validSystemIds.has(systemId)) {
3228
+ errors.push(
3229
+ `Manifest "${key}": systemId "${systemId}" is not a known system id. Valid values: ${[...validSystemIds].sort().join(", ")}`
3230
+ );
3231
+ }
3232
+ }
3233
+ if (errors.length > 0) {
3234
+ throw new Error(
3235
+ `System manifest validation failed with ${errors.length} error(s):
3236
+ ` + errors.map((e, i) => ` ${i + 1}. ${e}`).join("\n")
3237
+ );
3238
+ }
3098
3239
  }
3099
- function isLifecycleEnabled2(system) {
3240
+ var ElevasisSystemsContext = createContext(null);
3241
+
3242
+ // src/provider/sidebarProjection.ts
3243
+ function isLifecycleEnabled3(system) {
3100
3244
  if (system.enabled === false) return false;
3101
3245
  return system.lifecycle !== "deprecated" && system.lifecycle !== "archived";
3102
3246
  }
3103
- function isLifecycleDevOnly(system) {
3104
- return system.devOnly === true || system.lifecycle === "beta";
3247
+ function isSystemAccessible(systemId, context) {
3248
+ const system = context.shellModel.findById(systemId);
3249
+ if (!system || !isLifecycleEnabled3(system)) return false;
3250
+ if (!context.isSystemEnabled(systemId)) return false;
3251
+ if (context.shellModel.requiresAdminFor(systemId) && !context.isPlatformAdmin) return false;
3252
+ if (context.shellModel.devOnlyFor(systemId) && !context.isDev) return false;
3253
+ return true;
3105
3254
  }
3106
- function isSystemEnabled(systemsById, systemId) {
3107
- const systemLineage = getSystemWithAncestors(systemsById, systemId);
3108
- return systemLineage.length > 0 && systemLineage.every(isLifecycleEnabled2);
3255
+ function isSurfaceAccessible(node, context) {
3256
+ if (node.devOnly && !context.isDev) return false;
3257
+ if (node.requiresAdmin && !context.isPlatformAdmin) return false;
3258
+ const systemTargets = node.targets?.systems ?? [];
3259
+ if (systemTargets.length === 0) return true;
3260
+ return systemTargets.some((systemId) => isSystemAccessible(systemId, context));
3109
3261
  }
3110
- function unique(values) {
3111
- return [...new Set(values)];
3262
+ function iconForNode(node, context) {
3263
+ if (node.type === "surface") {
3264
+ const targetIcon = node.targets?.systems?.map((systemId) => context.shellModel.findById(systemId)?.iconComponent).find(Boolean);
3265
+ if (targetIcon) return targetIcon;
3266
+ }
3267
+ return getSemanticIconComponent(node.icon);
3112
3268
  }
3113
- function collectSidebarSurfaces(nodes, schemaPath, surfaces = []) {
3114
- getSortedSidebarEntries(nodes).forEach(([id, node]) => {
3115
- const nodePath = [...schemaPath, id];
3116
- if (node.type === "group") {
3117
- collectSidebarSurfaces(node.children, [...nodePath, "children"], surfaces);
3118
- return;
3269
+ function activeMatchPathsForSurface(node, context) {
3270
+ const targets = node.targets?.systems ?? [];
3271
+ if (targets.length !== 1) return void 0;
3272
+ const paths = context.shellModel.childrenOf(targets[0]).map((child) => child.path).filter((path) => Boolean(path && path !== node.path));
3273
+ return paths.length > 0 ? [...new Set(paths)] : void 0;
3274
+ }
3275
+ function surfaceToLinkItem(node, context, siblings) {
3276
+ if (!isSurfaceAccessible(node, context)) return void 0;
3277
+ const siblingShadows = siblings.some((sibling) => sibling !== node && sibling.path.startsWith(`${node.path}/`));
3278
+ const activeMatchPaths = activeMatchPathsForSurface(node, context);
3279
+ return {
3280
+ label: node.label,
3281
+ link: node.path,
3282
+ ...siblingShadows ? { exact: true } : {},
3283
+ ...activeMatchPaths ? { activeMatchPaths } : {}
3284
+ };
3285
+ }
3286
+ function projectNode(node, context) {
3287
+ if (node.type === "surface") {
3288
+ if (!isSurfaceAccessible(node, context)) return void 0;
3289
+ return {
3290
+ label: node.label,
3291
+ icon: iconForNode(node, context),
3292
+ link: node.path
3293
+ };
3294
+ }
3295
+ const childEntries = getSortedSidebarEntries(node.children);
3296
+ const childSurfaces = childEntries.map(([, child]) => child).filter((child) => child.type === "surface");
3297
+ const links = childEntries.flatMap(([, child]) => {
3298
+ if (child.type === "surface") {
3299
+ const link = surfaceToLinkItem(child, context, childSurfaces);
3300
+ return link ? [link] : [];
3119
3301
  }
3120
- surfaces.push({ id, surface: node, path: nodePath });
3302
+ const nestedGroup = projectNode(child, context);
3303
+ return nestedGroup?.link ? [
3304
+ {
3305
+ label: nestedGroup.label,
3306
+ link: nestedGroup.link
3307
+ }
3308
+ ] : nestedGroup?.links ?? [];
3121
3309
  });
3122
- return surfaces;
3310
+ if (links.length === 0) return void 0;
3311
+ return {
3312
+ label: node.label,
3313
+ icon: iconForNode(node, context),
3314
+ links
3315
+ };
3123
3316
  }
3124
- function getSidebarSurfaces(model) {
3125
- return [
3126
- ...collectSidebarSurfaces(model.navigation.sidebar.primary, ["navigation", "sidebar", "primary"]),
3127
- ...collectSidebarSurfaces(model.navigation.sidebar.bottom, ["navigation", "sidebar", "bottom"])
3128
- ];
3317
+ function projectSection(section, context) {
3318
+ const entries = getSortedSidebarEntries(section);
3319
+ return entries.flatMap(([, node]) => {
3320
+ const group = projectNode(node, context);
3321
+ return group ? [group] : [];
3322
+ });
3129
3323
  }
3130
- function projectOrganizationSurfaces(model) {
3131
- const systemsById = collectSystemsById(model);
3132
- return getSidebarSurfaces(model).map(({ id, surface }) => {
3133
- const targets = surface.targets ?? {};
3134
- const systemIds = unique((targets.systems ?? []).filter((systemId) => systemsById.has(systemId)));
3135
- const enabled = systemIds.every((candidate) => isSystemEnabled(systemsById, candidate));
3136
- const devOnly = surface.devOnly === true || hasInheritedFlag(systemsById, systemIds, "devOnly") || systemIds.some((candidate) => getSystemWithAncestors(systemsById, candidate).some(isLifecycleDevOnly));
3137
- const requiresAdmin = hasInheritedFlag(systemsById, systemIds, "requiresAdmin");
3324
+ function projectSidebarLinks({
3325
+ shellModel,
3326
+ organizationModel,
3327
+ isSystemEnabled: isSystemEnabled2,
3328
+ isPlatformAdmin = false,
3329
+ isDev = false,
3330
+ section
3331
+ }) {
3332
+ const context = {
3333
+ shellModel,
3334
+ isSystemEnabled: isSystemEnabled2,
3335
+ isPlatformAdmin,
3336
+ isDev
3337
+ };
3338
+ const sidebar = organizationModel?.navigation.sidebar;
3339
+ if (!sidebar) return [];
3340
+ if (section) {
3341
+ return projectSection(sidebar[section], context);
3342
+ }
3343
+ return [...projectSection(sidebar.primary, context), ...projectSection(sidebar.bottom, context)];
3344
+ }
3345
+
3346
+ // src/provider/topbarProjection.ts
3347
+ function isTopbarActionVisible(node, context) {
3348
+ if (node.enabled === false) return false;
3349
+ if (node.devOnly && !context.isDev) return false;
3350
+ if (node.requiresAdmin && !context.isPlatformAdmin) return false;
3351
+ return true;
3352
+ }
3353
+ function resolveTopbarAction(node, index) {
3354
+ return {
3355
+ id: node.id,
3356
+ label: node.label,
3357
+ tooltip: node.tooltip,
3358
+ icon: getSemanticIconComponent(node.icon),
3359
+ order: node.order ?? index
3360
+ };
3361
+ }
3362
+ function projectTopbarActions(topbar, modules, context) {
3363
+ const modulesByKey = new Map(modules.map((m) => [m.key, m]));
3364
+ const entries = Object.values(topbar);
3365
+ const visibleNodes = entries.filter((node) => isTopbarActionVisible(node, context));
3366
+ visibleNodes.sort((a, b) => {
3367
+ const aOrder = a.order ?? Number.MAX_SAFE_INTEGER;
3368
+ const bOrder = b.order ?? Number.MAX_SAFE_INTEGER;
3369
+ if (aOrder !== bOrder) return aOrder - bOrder;
3370
+ return a.id.localeCompare(b.id);
3371
+ });
3372
+ const result = [];
3373
+ for (let i = 0; i < visibleNodes.length; i++) {
3374
+ const node = visibleNodes[i];
3375
+ const module = modulesByKey.get(node.id);
3376
+ if (!module) continue;
3377
+ result.push({
3378
+ node: resolveTopbarAction(node, i),
3379
+ render: module.render
3380
+ });
3381
+ }
3382
+ return result;
3383
+ }
3384
+ function useElevasisSystems() {
3385
+ const context = useContext(ElevasisSystemsContext);
3386
+ if (!context) {
3387
+ throw new Error(
3388
+ "useElevasisSystems must be used within an ElevasisSystemsProvider. Wrap your app (or the relevant subtree) with <ElevasisSystemsProvider>."
3389
+ );
3390
+ }
3391
+ return context;
3392
+ }
3393
+ function useOptionalElevasisSystems() {
3394
+ return useContext(ElevasisSystemsContext);
3395
+ }
3396
+ function defaultSystems(organizationModel) {
3397
+ if (!organizationModel) return [];
3398
+ return listAllSystems(organizationModel).map(({ path, system }) => ({ ...system, id: path }));
3399
+ }
3400
+ function systemPath(system) {
3401
+ return system.ui?.path ?? system.path ?? defaultPathFor(system.id);
3402
+ }
3403
+ function systemLabel(system) {
3404
+ return system.label ?? system.title ?? system.id;
3405
+ }
3406
+ function moduleSystemId(module) {
3407
+ return module.systemId ?? module.key;
3408
+ }
3409
+ function isLifecycleEnabled4(system) {
3410
+ if (system.enabled === false) return false;
3411
+ return system.lifecycle !== "deprecated" && system.lifecycle !== "archived";
3412
+ }
3413
+ function isOrganizationModelSystemEnabled(organizationModel, systemId) {
3414
+ const system = defaultSystems(organizationModel).find((candidate) => candidate.id === systemId);
3415
+ return system ? isLifecycleEnabled4(system) : void 0;
3416
+ }
3417
+ function resolveSystemModules(systems, isSystemEnabled2) {
3418
+ return systems.map((system) => {
3419
+ const systemId = system.systemId;
3420
+ const accessKey = systemId ?? system.key;
3138
3421
  return {
3139
- id,
3140
- label: surface.label,
3141
- path: surface.path,
3142
- surfaceType: surface.surfaceType,
3143
- ...surface.description !== void 0 ? { description: surface.description } : {},
3144
- ...surface.icon !== void 0 ? { icon: surface.icon } : {},
3145
- ...surface.order !== void 0 ? { order: surface.order } : {},
3146
- systemIds,
3147
- entityIds: [...targets.entities ?? []],
3148
- resourceIds: [...targets.resources ?? []],
3149
- actionIds: [...targets.actions ?? []],
3150
- enabled,
3151
- ...devOnly ? { devOnly } : {},
3152
- ...surface.requiresAdmin === true || requiresAdmin ? { requiresAdmin: true } : {}
3422
+ ...system,
3423
+ systemId,
3424
+ access: {
3425
+ systemKey: system.key,
3426
+ systemId,
3427
+ enabled: isSystemEnabled2(accessKey)
3428
+ },
3429
+ semantics: {
3430
+ capabilityIds: uniqueIds(system.capabilityIds ?? [])
3431
+ }
3153
3432
  };
3154
3433
  });
3155
3434
  }
3435
+ function buildShellSystems(organizationModel, modules) {
3436
+ const iconBySystemId = new Map(
3437
+ modules.flatMap((module) => module.systemId ? [[moduleSystemId(module), module.icon]] : [])
3438
+ );
3439
+ return defaultSystems(organizationModel).map((system) => ({
3440
+ ...system,
3441
+ label: systemLabel(system),
3442
+ path: systemPath(system),
3443
+ iconComponent: iconBySystemId.get(system.id)
3444
+ }));
3445
+ }
3446
+ function createShellModel(systems) {
3447
+ const systemsRecord = Object.fromEntries(systems.map((s) => [s.id, s]));
3448
+ return {
3449
+ systems,
3450
+ findByPath: (path) => findByPath(systemsRecord, normalizeRoutePath(path)),
3451
+ findById: (id) => findById(systemsRecord, id),
3452
+ childrenOf: (id) => childrenOf(systemsRecord, id),
3453
+ ancestorsOf: (id) => ancestorsOf(systemsRecord, id),
3454
+ parentOf: (id) => parentOf(systemsRecord, id),
3455
+ topLevel: () => topLevel(systemsRecord),
3456
+ requiresAdminFor: (id) => requiresAdminFor(systemsRecord, id),
3457
+ devOnlyFor: (id) => devOnlyFor(systemsRecord, id)
3458
+ };
3459
+ }
3460
+ function resolveOrganizationGraphSystem(systems, shellModel) {
3461
+ for (const system of systems) {
3462
+ const graphBridge = system.organizationGraph;
3463
+ if (!graphBridge) continue;
3464
+ const systemId = graphBridge.systemId;
3465
+ if (!systemId) continue;
3466
+ const node = shellModel.findById(systemId);
3467
+ return {
3468
+ available: Boolean(node),
3469
+ systemId,
3470
+ systemPath: node ? systemPath(node) : void 0
3471
+ };
3472
+ }
3473
+ return {
3474
+ available: false
3475
+ };
3476
+ }
3477
+ function findMatchingNode(shellModel, currentPath) {
3478
+ const normalizedPath = normalizeRoutePath(currentPath);
3479
+ const exact = shellModel.findByPath(normalizedPath);
3480
+ if (exact) return exact;
3481
+ return [...shellModel.systems].filter((system) => {
3482
+ const path = normalizeRoutePath(systemPath(system));
3483
+ return path !== "/" && isRouteMatch(normalizedPath, path);
3484
+ }).sort((a, b) => systemPath(b).length - systemPath(a).length)[0];
3485
+ }
3486
+ function ownsNode(module, node) {
3487
+ if (!node || !module.systemId) return false;
3488
+ return node.id === module.systemId || node.id.startsWith(`${module.systemId}.`);
3489
+ }
3490
+ function ownsRoutePrefix(module, normalizedPath) {
3491
+ return (module.routePrefixes ?? []).some((prefix) => isRouteMatch(normalizedPath, normalizeRoutePath(prefix)));
3492
+ }
3493
+ function resolveRoute(systems, shellModel, currentPath, disabledSubsectionPaths) {
3494
+ const node = findMatchingNode(shellModel, currentPath);
3495
+ const normalizedPath = normalizeRoutePath(currentPath);
3496
+ if (disabledSubsectionPaths.some((disabledPath) => isRouteMatch(normalizedPath, disabledPath))) {
3497
+ return {
3498
+ status: "hidden",
3499
+ path: currentPath,
3500
+ node
3501
+ };
3502
+ }
3503
+ const system = systems.find((candidate) => ownsNode(candidate, node)) ?? systems.filter((candidate) => ownsRoutePrefix(candidate, normalizedPath)).sort(
3504
+ (a, b) => Math.max(...(b.routePrefixes ?? []).map((prefix) => prefix.length)) - Math.max(...(a.routePrefixes ?? []).map((prefix) => prefix.length))
3505
+ )[0];
3506
+ if (!system) {
3507
+ return {
3508
+ status: "unmatched",
3509
+ path: currentPath,
3510
+ node
3511
+ };
3512
+ }
3513
+ return {
3514
+ status: "matched",
3515
+ path: currentPath,
3516
+ system,
3517
+ node
3518
+ };
3519
+ }
3520
+ function ElevasisSystemsProvider({
3521
+ systems,
3522
+ topbarActions,
3523
+ organizationModel,
3524
+ timeRange,
3525
+ operationsApiUrl,
3526
+ operationsSSEManager,
3527
+ deliveryApiUrl,
3528
+ deliverySSEManager,
3529
+ disabledSubsectionPaths = [],
3530
+ children
3531
+ }) {
3532
+ const activeSystems = systems ?? [];
3533
+ const resolvedOrganizationModel = useMemo(() => {
3534
+ if (!organizationModel) {
3535
+ return void 0;
3536
+ }
3537
+ return {
3538
+ ...organizationModel,
3539
+ knowledge: organizationModel.knowledge ?? {}
3540
+ };
3541
+ }, [organizationModel]);
3542
+ useMemo(() => validateManifests(activeSystems, resolvedOrganizationModel), [activeSystems, resolvedOrganizationModel]);
3543
+ const hasResolvedSystem = useCallback(
3544
+ (key) => {
3545
+ const organizationModelSystemEnabled = isOrganizationModelSystemEnabled(resolvedOrganizationModel, key);
3546
+ return organizationModelSystemEnabled ?? true;
3547
+ },
3548
+ [resolvedOrganizationModel]
3549
+ );
3550
+ const shellSystems = useMemo(
3551
+ () => buildShellSystems(resolvedOrganizationModel, activeSystems),
3552
+ [resolvedOrganizationModel, activeSystems]
3553
+ );
3554
+ const shellModel = useMemo(() => createShellModel(shellSystems), [shellSystems]);
3555
+ const normalizedDisabledSubsectionPaths = useMemo(
3556
+ () => [...new Set(disabledSubsectionPaths.map((path) => normalizeRoutePath(path)))],
3557
+ [disabledSubsectionPaths]
3558
+ );
3559
+ const resolvedSystems = useMemo(
3560
+ () => resolveSystemModules(activeSystems, hasResolvedSystem),
3561
+ [activeSystems, hasResolvedSystem]
3562
+ );
3563
+ const enabledResolvedSystems = useMemo(
3564
+ () => resolvedSystems.filter((system) => system.access.enabled),
3565
+ [resolvedSystems]
3566
+ );
3567
+ const organizationGraph = useMemo(
3568
+ () => resolveOrganizationGraphSystem(enabledResolvedSystems, shellModel),
3569
+ [enabledResolvedSystems, shellModel]
3570
+ );
3571
+ const getResolvedSystem = useCallback(
3572
+ (key) => resolvedSystems.find((system) => system.key === key),
3573
+ [resolvedSystems]
3574
+ );
3575
+ const isSystemEnabled2 = useCallback((key) => hasResolvedSystem(key), [hasResolvedSystem]);
3576
+ const getSidebarLinks = useCallback(
3577
+ (options = {}) => projectSidebarLinks({
3578
+ shellModel,
3579
+ organizationModel: resolvedOrganizationModel,
3580
+ isSystemEnabled: isSystemEnabled2,
3581
+ ...options
3582
+ }),
3583
+ [shellModel, resolvedOrganizationModel, isSystemEnabled2]
3584
+ );
3585
+ const activeTopbarActions = topbarActions ?? [];
3586
+ const getTopbarActions = useCallback(
3587
+ (options = {}) => projectTopbarActions(resolvedOrganizationModel?.navigation.topbar ?? {}, activeTopbarActions, {
3588
+ isPlatformAdmin: options.isPlatformAdmin ?? false,
3589
+ isDev: options.isDev ?? false
3590
+ }),
3591
+ [resolvedOrganizationModel, activeTopbarActions]
3592
+ );
3593
+ const resolveRouteByPath = useCallback(
3594
+ (path) => resolveRoute(enabledResolvedSystems, shellModel, path, normalizedDisabledSubsectionPaths),
3595
+ [enabledResolvedSystems, shellModel, normalizedDisabledSubsectionPaths]
3596
+ );
3597
+ const shellRuntime = useMemo(
3598
+ () => ({
3599
+ resolveRoute: resolveRouteByPath
3600
+ }),
3601
+ [resolveRouteByPath]
3602
+ );
3603
+ const value = useMemo(
3604
+ () => ({
3605
+ shellModel,
3606
+ shellRuntime,
3607
+ getSidebarLinks,
3608
+ getTopbarActions,
3609
+ enabledResolvedSystems,
3610
+ resolvedSystems,
3611
+ organizationGraph,
3612
+ organizationModel: resolvedOrganizationModel,
3613
+ timeRange,
3614
+ operationsApiUrl,
3615
+ operationsSSEManager,
3616
+ deliveryApiUrl,
3617
+ deliverySSEManager,
3618
+ disabledSubsectionPaths: normalizedDisabledSubsectionPaths,
3619
+ isSystemEnabled: isSystemEnabled2,
3620
+ getResolvedSystem
3621
+ }),
3622
+ [
3623
+ shellModel,
3624
+ shellRuntime,
3625
+ enabledResolvedSystems,
3626
+ resolvedSystems,
3627
+ organizationGraph,
3628
+ resolvedOrganizationModel,
3629
+ timeRange,
3630
+ operationsApiUrl,
3631
+ operationsSSEManager,
3632
+ deliveryApiUrl,
3633
+ deliverySSEManager,
3634
+ normalizedDisabledSubsectionPaths,
3635
+ isSystemEnabled2,
3636
+ getResolvedSystem,
3637
+ getSidebarLinks,
3638
+ getTopbarActions
3639
+ ]
3640
+ );
3641
+ return /* @__PURE__ */ jsx(ElevasisSystemsContext.Provider, { value, children });
3642
+ }
3156
3643
 
3157
- export { ActionSchema, AgentResourceEntrySchema, DEFAULT_ORGANIZATION_MODEL, DEFAULT_SEMANTIC_ICON_REGISTRY, EntitySchema, IdentityDomainSchema, IntegrationResourceEntrySchema, OrgKnowledgeNodeSchema, PROJECTS_VIEW_ACTION_ID, PolicySchema, RoleSchema, ScriptResourceEntrySchema, SemanticIcon, SurfaceDefinitionSchema, SystemEntrySchema, WorkflowResourceEntrySchema, buildOrganizationGraph, defineActions, defineEntities, defineResources, defineTopology, extendSemanticIconRegistry, getSemanticIconComponent, getSortedSidebarEntries, projectOrganizationSurfaces, resolveOrganizationModel, resolveSemanticIconComponent, topologyRef, topologyRelationship };
3644
+ export { ActionSchema, AgentResourceEntrySchema, DEFAULT_ORGANIZATION_MODEL, DEFAULT_SEMANTIC_ICON_REGISTRY, ElevasisSystemsProvider, EntitySchema, IdentityDomainSchema, IntegrationResourceEntrySchema, OrgKnowledgeNodeSchema, PROJECTS_VIEW_ACTION_ID, PolicySchema, RoleSchema, ScriptResourceEntrySchema, SemanticIcon, SurfaceDefinitionSchema, SystemEntrySchema, WorkflowResourceEntrySchema, buildOrganizationGraph, defineActions, defineEntities, defineResources, defineTopology, extendSemanticIconRegistry, getSemanticIconComponent, getSortedSidebarEntries, projectOrganizationSurfaces, resolveOrganizationModel, resolveSemanticIconComponent, topologyRef, topologyRelationship, useElevasisSystems, useOptionalElevasisSystems };