@elevasis/ui 2.33.2 → 2.35.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 (116) hide show
  1. package/dist/api/index.d.ts +9 -2
  2. package/dist/api/index.js +3 -3
  3. package/dist/app/index.css +452 -0
  4. package/dist/app/index.d.ts +1255 -8
  5. package/dist/app/index.js +151 -13
  6. package/dist/charts/index.js +3 -6
  7. package/dist/chunk-26HFM4MH.js +41449 -0
  8. package/dist/{chunk-52K5RFDH.js → chunk-4U3XAWCN.js} +1328 -2492
  9. package/dist/{chunk-ND5TDV2J.js → chunk-57OZ3AEG.js} +1 -1
  10. package/dist/{chunk-E4WQGJNS.js → chunk-7FPLLSHN.js} +14 -1
  11. package/dist/{chunk-RQA2EVN3.js → chunk-AKW7KISS.js} +39 -3
  12. package/dist/chunk-AUDNF2Q7.js +2050 -0
  13. package/dist/{chunk-TYRUKGGD.js → chunk-GX6XBRRF.js} +1 -2
  14. package/dist/{chunk-V6SZ4ECN.js → chunk-LUYVRATI.js} +257 -6
  15. package/dist/{chunk-X4WBGKJQ.js → chunk-R3VCBZDC.js} +50 -3
  16. package/dist/chunk-SIQ3P4OR.js +1764 -0
  17. package/dist/{chunk-Z2K2EAPL.js → chunk-VDOOGGBA.js} +5 -6
  18. package/dist/{chunk-3FV6HBXS.js → chunk-WF7CONXF.js} +23 -23
  19. package/dist/chunk-YYX7OPZQ.js +25 -0
  20. package/dist/components/index.d.ts +69 -92
  21. package/dist/components/index.js +20 -3216
  22. package/dist/components/navigation/index.js +25 -7
  23. package/dist/execution/index.d.ts +9 -9
  24. package/dist/execution/index.js +1 -2
  25. package/dist/features/auth/index.js +23 -2
  26. package/dist/features/clients/index.js +20 -31
  27. package/dist/features/crm/index.js +20 -35
  28. package/dist/features/dashboard/index.d.ts +68 -91
  29. package/dist/features/dashboard/index.js +20 -33
  30. package/dist/features/delivery/index.js +20 -35
  31. package/dist/features/knowledge/index.js +25 -11
  32. package/dist/features/lead-gen/index.d.ts +9 -9
  33. package/dist/features/lead-gen/index.js +20 -36
  34. package/dist/features/monitoring/index.js +20 -35
  35. package/dist/features/monitoring/requests/index.js +20 -30
  36. package/dist/features/operations/index.d.ts +197 -188
  37. package/dist/features/operations/index.js +18 -42
  38. package/dist/features/seo/index.js +3 -4
  39. package/dist/features/settings/index.js +20 -32
  40. package/dist/graph/index.js +1 -1
  41. package/dist/hooks/delivery/index.js +30 -2
  42. package/dist/hooks/index.d.ts +105 -112
  43. package/dist/hooks/index.js +20 -26
  44. package/dist/hooks/operations/command-view/utils/transformCommandViewData.d.ts +55 -62
  45. package/dist/hooks/published.d.ts +105 -112
  46. package/dist/hooks/published.js +20 -25
  47. package/dist/index.css +532 -532
  48. package/dist/index.d.ts +10261 -6793
  49. package/dist/index.js +22 -31
  50. package/dist/knowledge/index.d.ts +51 -59
  51. package/dist/knowledge/index.js +40 -211
  52. package/dist/{knowledge-search-index-VMAW7FLR.js → knowledge-search-index-ORIJCEZX.js} +3 -3
  53. package/dist/layout/index.js +4 -10
  54. package/dist/organization/index.js +27 -2
  55. package/dist/provider/index.d.ts +71 -52
  56. package/dist/provider/index.js +20 -20
  57. package/dist/provider/published.d.ts +39 -47
  58. package/dist/provider/published.js +20 -15
  59. package/dist/test-utils/index.d.ts +2 -0
  60. package/dist/test-utils/index.js +16 -4
  61. package/dist/test-utils/setup.js +38 -0
  62. package/dist/theme/index.js +2 -3
  63. package/dist/theme/presets/index.d.ts +28 -3
  64. package/dist/theme/presets/index.js +1 -1
  65. package/dist/typeform/index.js +1 -2049
  66. package/dist/types/index.d.ts +88 -95
  67. package/dist/utils/index.d.ts +46 -69
  68. package/dist/utils/index.js +1 -1
  69. package/dist/zustand/index.d.ts +21 -8
  70. package/dist/zustand/index.js +32 -1
  71. package/package.json +5 -5
  72. package/dist/chunk-2ZZ72TAB.js +0 -2281
  73. package/dist/chunk-32I2RCGC.js +0 -85
  74. package/dist/chunk-3MEXPLWT.js +0 -265
  75. package/dist/chunk-3ZMAGTWF.js +0 -18
  76. package/dist/chunk-44I4LOH6.js +0 -1593
  77. package/dist/chunk-4DYOXEH6.js +0 -951
  78. package/dist/chunk-7M2VOCYN.js +0 -1
  79. package/dist/chunk-A4VDJJCV.js +0 -1864
  80. package/dist/chunk-BZZCNLT6.js +0 -12
  81. package/dist/chunk-CLDCYJQT.js +0 -1
  82. package/dist/chunk-E565XMTQ.js +0 -17
  83. package/dist/chunk-EPTHX4VZ.js +0 -749
  84. package/dist/chunk-GWGQI6V4.js +0 -447
  85. package/dist/chunk-HUJCU55S.js +0 -159
  86. package/dist/chunk-IBWMR4TI.js +0 -469
  87. package/dist/chunk-IIMU5YAJ.js +0 -53
  88. package/dist/chunk-IOXOPMYS.js +0 -145
  89. package/dist/chunk-J2UD7BOH.js +0 -347
  90. package/dist/chunk-JA5ECJJB.js +0 -387
  91. package/dist/chunk-JFL3GRD4.js +0 -39
  92. package/dist/chunk-KW7ZNQD7.js +0 -126
  93. package/dist/chunk-LGKLC5MG.js +0 -44
  94. package/dist/chunk-N55DVMAG.js +0 -14
  95. package/dist/chunk-O56ESZCQ.js +0 -1874
  96. package/dist/chunk-OIBHQH5Q.js +0 -96
  97. package/dist/chunk-PDHTXPSF.js +0 -12
  98. package/dist/chunk-QDFJSUG3.js +0 -13
  99. package/dist/chunk-R2XR4FCV.js +0 -48
  100. package/dist/chunk-R66W5UDG.js +0 -26
  101. package/dist/chunk-RYTEQBAO.js +0 -37
  102. package/dist/chunk-SZHARWKU.js +0 -15
  103. package/dist/chunk-T3J6U77J.js +0 -12056
  104. package/dist/chunk-TBVLQRXT.js +0 -68
  105. package/dist/chunk-TGVAIWIL.js +0 -1778
  106. package/dist/chunk-TKAYX2SP.js +0 -204
  107. package/dist/chunk-TUMSNGTX.js +0 -35
  108. package/dist/chunk-VGU4ZFYZ.js +0 -4752
  109. package/dist/chunk-VNAZTCHA.js +0 -65
  110. package/dist/chunk-VNFR57DF.js +0 -87
  111. package/dist/chunk-WKW6B5ID.js +0 -29
  112. package/dist/chunk-XCYKC6OZ.js +0 -1
  113. package/dist/chunk-XZGSCABI.js +0 -383
  114. package/dist/chunk-ZMK5Z6KE.js +0 -5198
  115. /package/dist/{chunk-2RJMVWFJ.js → chunk-GEFWMU26.js} +0 -0
  116. /package/dist/{chunk-22UVE3RA.js → chunk-HENXLGVD.js} +0 -0
@@ -1,6 +1,148 @@
1
+ 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';
2
+ import { jsx } from 'react/jsx-runtime';
1
3
  import { z } from 'zod';
2
4
 
3
- // ../core/src/organization-model/ontology.ts
5
+ // src/icons/registry.tsx
6
+ var DEFAULT_SEMANTIC_ICON_REGISTRY = {
7
+ // Navigation / app areas
8
+ dashboard: IconDashboard,
9
+ calendar: IconCalendar,
10
+ sales: IconChartBar,
11
+ crm: IconBuildingStore,
12
+ "lead-gen": IconTargetArrow,
13
+ projects: IconBriefcase,
14
+ clients: IconUsers,
15
+ operations: IconTool,
16
+ monitoring: IconChartBar,
17
+ knowledge: IconBrain,
18
+ settings: IconSettings,
19
+ admin: IconShieldLock,
20
+ archive: IconArchive,
21
+ business: IconBriefcase,
22
+ finance: IconChartBar,
23
+ platform: IconLayoutGrid,
24
+ seo: IconSearch,
25
+ // Knowledge kinds
26
+ playbook: IconBook,
27
+ strategy: IconTargetArrow,
28
+ reference: IconFileText,
29
+ // Resource kinds
30
+ agent: IconBrain,
31
+ workflow: IconGitBranch,
32
+ integration: IconPlug,
33
+ database: IconDatabase,
34
+ user: IconUser,
35
+ team: IconUsers,
36
+ // Integration specifics
37
+ gmail: IconMail,
38
+ "google-sheets": IconDatabase,
39
+ attio: IconBuildingStore,
40
+ // Surface / UI views
41
+ overview: IconDashboard,
42
+ "command-view": IconTopologyStar3,
43
+ "command-queue": IconSend,
44
+ pipeline: IconGitBranch,
45
+ lists: IconFileText,
46
+ resources: IconDatabase,
47
+ // Actions
48
+ approve: IconCheck,
49
+ reject: IconX,
50
+ retry: IconRefresh,
51
+ edit: IconEdit,
52
+ view: IconEye,
53
+ launch: IconRocket,
54
+ message: IconMessageCircle,
55
+ escalate: IconAlertTriangle,
56
+ promote: IconArrowUp,
57
+ submit: IconSend,
58
+ email: IconMail,
59
+ // Status
60
+ success: IconCheck,
61
+ error: IconX,
62
+ warning: IconAlertTriangle,
63
+ info: IconInfoCircle,
64
+ pending: IconClock,
65
+ // OM / UI group icons
66
+ bolt: IconBolt,
67
+ building: IconBuilding,
68
+ briefcase: IconBriefcase,
69
+ apps: IconApps,
70
+ graph: IconTopologyStar3,
71
+ shield: IconShieldLock,
72
+ users: IconUsers,
73
+ "chart-bar": IconChartBar,
74
+ search: IconSearch,
75
+ // UI-only om.* group tokens (not in the core enum — kept for registry lookup
76
+ // by components that reference them directly via extendSemanticIconRegistry)
77
+ "om.quick-access": IconBolt,
78
+ "om.profile": IconBuilding,
79
+ "om.business-model": IconBriefcase,
80
+ "om.systems": IconApps,
81
+ "om.graph": IconTopologyStar3,
82
+ "om.governance-wiring": IconShieldLock,
83
+ // Graph node-kind fallback tokens (used internally by knowledge-tree helpers)
84
+ "entity.record": IconActivity,
85
+ "event.lifecycle": IconActivity,
86
+ "policy.governance": IconShieldLock,
87
+ // Compatibility aliases for existing command queue payloads.
88
+ IconCheck,
89
+ IconX,
90
+ IconRefresh,
91
+ IconAlertTriangle,
92
+ IconEdit,
93
+ IconEye,
94
+ IconRocket,
95
+ IconMessageCircle,
96
+ IconArrowUp,
97
+ IconClock,
98
+ IconFileText,
99
+ IconSend,
100
+ IconMail
101
+ };
102
+ var semanticIconRegistry = { ...DEFAULT_SEMANTIC_ICON_REGISTRY };
103
+ function extendSemanticIconRegistry(overrides) {
104
+ semanticIconRegistry = { ...semanticIconRegistry, ...overrides };
105
+ }
106
+ function getSemanticIconComponent(token, fallbackToken) {
107
+ const icon = resolveSemanticIconComponent(token);
108
+ if (icon) return icon;
109
+ if (fallbackToken && semanticIconRegistry[fallbackToken]) return semanticIconRegistry[fallbackToken];
110
+ return IconInfoCircle;
111
+ }
112
+ function resolveSemanticIconComponent(token) {
113
+ if (!token) return null;
114
+ return semanticIconRegistry[token] ?? null;
115
+ }
116
+ function SemanticIcon({
117
+ token,
118
+ fallbackToken,
119
+ size = 16,
120
+ stroke = 1.8,
121
+ className,
122
+ style,
123
+ "aria-hidden": ariaHidden = true
124
+ }) {
125
+ const Icon = getSemanticIconComponent(token, fallbackToken);
126
+ return /* @__PURE__ */ jsx(
127
+ "span",
128
+ {
129
+ className,
130
+ "aria-hidden": ariaHidden,
131
+ style: {
132
+ display: "inline-flex",
133
+ alignItems: "center",
134
+ justifyContent: "center",
135
+ width: size,
136
+ height: size,
137
+ minWidth: size,
138
+ color: "currentColor",
139
+ flexShrink: 0,
140
+ ...style
141
+ },
142
+ children: /* @__PURE__ */ jsx(Icon, { size, stroke })
143
+ }
144
+ );
145
+ }
4
146
  var OntologyKindSchema = z.enum([
5
147
  "object",
6
148
  "link",
@@ -332,40 +474,6 @@ function addLegacyActionProjections(index, diagnostics, sourcesById, actions, en
332
474
  });
333
475
  }
334
476
  }
335
- function addSystemContentProjections(index, diagnostics, sourcesById, systemPath, system, schemaPath) {
336
- const content = system.content ?? {};
337
- for (const [localId, node] of Object.entries(content)) {
338
- if (node.kind !== "schema") continue;
339
- const entries = Object.fromEntries(
340
- Object.entries(content).filter(([, candidate]) => candidate.parentContentId === localId).map(([entryId, candidate]) => [
341
- entryId,
342
- {
343
- label: candidate.label ?? entryId,
344
- type: candidate.type,
345
- ...candidate.description !== void 0 ? { description: candidate.description } : {},
346
- ...candidate.data !== void 0 ? candidate.data : {}
347
- }
348
- ])
349
- );
350
- const catalogType = {
351
- id: formatOntologyId({ scope: systemPath, kind: "catalog", localId }),
352
- label: node.label ?? localId,
353
- description: node.description,
354
- ownerSystemId: systemPath,
355
- kind: node.type,
356
- ...typeof node.data?.["entityId"] === "string" ? { appliesTo: formatOntologyId({ scope: systemPath, kind: "object", localId: node.data["entityId"] }) } : {},
357
- ...Object.keys(entries).length > 0 ? { entries } : {},
358
- ...node.data !== void 0 ? { data: node.data } : {}
359
- };
360
- addRecord(index, diagnostics, sourcesById, "catalogTypes", catalogType, {
361
- source: "legacy.system.content",
362
- path: [...schemaPath, "content", localId],
363
- kind: "projected",
364
- systemPath,
365
- legacyId: `${systemPath}:${localId}`
366
- });
367
- }
368
- }
369
477
  function addSystemScopes(index, diagnostics, sourcesById, systems, prefix, schemaPath) {
370
478
  for (const [key, system] of Object.entries(systems)) {
371
479
  const systemPath = prefix ? `${prefix}.${key}` : key;
@@ -374,7 +482,6 @@ function addSystemScopes(index, diagnostics, sourcesById, systems, prefix, schem
374
482
  ...currentPath,
375
483
  "ontology"
376
484
  ]);
377
- addSystemContentProjections(index, diagnostics, sourcesById, systemPath, system, currentPath);
378
485
  addSystemScopes(index, diagnostics, sourcesById, childSystemsOf(system), systemPath, [
379
486
  ...currentPath,
380
487
  system.systems !== void 0 ? "systems" : "subsystems"
@@ -399,6 +506,7 @@ var ORGANIZATION_MODEL_ICON_TOKENS = [
399
506
  "crm",
400
507
  "lead-gen",
401
508
  "projects",
509
+ "clients",
402
510
  "operations",
403
511
  "monitoring",
404
512
  "knowledge",
@@ -698,265 +806,7 @@ var ActionSchema = z.object({
698
806
  var ActionsDomainSchema = z.record(z.string(), ActionSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
699
807
  message: "Each action entry id must match its map key"
700
808
  }).default({});
701
- var LEAD_GEN_ACTION_ENTRY_INPUTS = [
702
- {
703
- id: "lead-gen.company.source",
704
- order: 10,
705
- label: "Source companies",
706
- description: "Import source companies from a list provider.",
707
- scope: { domain: "sales" },
708
- resourceId: "lgn-import-workflow",
709
- invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/source" }]
710
- },
711
- {
712
- id: "lead-gen.company.apollo-import",
713
- order: 20,
714
- label: "Import from Apollo",
715
- description: "Pull companies and seed contact data from an Apollo search or list.",
716
- scope: { domain: "sales" },
717
- resourceId: "lgn-01c-apollo-import-workflow",
718
- invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/apollo-import" }]
719
- },
720
- {
721
- id: "lead-gen.contact.discover",
722
- order: 30,
723
- label: "Discover contact emails",
724
- description: "Find email addresses for contacts at qualified companies.",
725
- scope: { domain: "sales" },
726
- resourceId: "lgn-04-email-discovery-workflow",
727
- invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/discover" }]
728
- },
729
- {
730
- id: "lead-gen.contact.verify-email",
731
- order: 40,
732
- label: "Verify emails",
733
- description: "Check email deliverability before outreach.",
734
- scope: { domain: "sales" },
735
- resourceId: "lgn-05-email-verification-workflow",
736
- invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/verify-email" }]
737
- },
738
- {
739
- id: "lead-gen.company.apify-crawl",
740
- order: 50,
741
- label: "Crawl websites",
742
- description: "Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis.",
743
- scope: { domain: "sales" },
744
- resourceId: "lgn-02a-apify-website-crawl-workflow",
745
- invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/apify-crawl" }]
746
- },
747
- {
748
- id: "lead-gen.company.website-extract",
749
- order: 60,
750
- label: "Extract website signals",
751
- description: "Scrape and analyze company websites for qualification signals.",
752
- scope: { domain: "sales" },
753
- resourceId: "lgn-02-website-extract-workflow",
754
- invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/website-extract" }]
755
- },
756
- {
757
- id: "lead-gen.company.qualify",
758
- order: 70,
759
- label: "Qualify companies",
760
- description: "Score and filter companies against the ICP rubric.",
761
- scope: { domain: "sales" },
762
- resourceId: "lgn-03-company-qualification-workflow",
763
- invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/qualify" }]
764
- },
765
- {
766
- id: "lead-gen.company.dtc-subscription-qualify",
767
- order: 80,
768
- label: "Qualify DTC subscription fit",
769
- description: "Classify subscription potential and consumable-product fit for DTC brands.",
770
- scope: { domain: "sales" },
771
- resourceId: "lgn-03b-dtc-subscription-score-workflow",
772
- invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/dtc-subscription-qualify" }]
773
- },
774
- {
775
- id: "lead-gen.contact.apollo-decision-maker-enrich",
776
- order: 90,
777
- label: "Enrich decision-makers",
778
- description: "Find and enrich qualified contacts at qualified companies via Apollo.",
779
- scope: { domain: "sales" },
780
- resourceId: "lgn-04b-apollo-decision-maker-enrich-workflow",
781
- invocations: [
782
- { kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/apollo-decision-maker-enrich" }
783
- ]
784
- },
785
- {
786
- id: "lead-gen.contact.personalize",
787
- order: 100,
788
- label: "Personalize outreach",
789
- description: "Generate personalized opening lines for each contact.",
790
- scope: { domain: "sales" },
791
- resourceId: "ist-personalization-workflow",
792
- invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/personalize" }]
793
- },
794
- {
795
- id: "lead-gen.review.outreach-ready",
796
- order: 110,
797
- label: "Upload to outreach",
798
- description: "Upload approved contacts to the outreach sequence after QC review.",
799
- scope: { domain: "sales" },
800
- resourceId: "ist-upload-contacts-workflow",
801
- invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/review/outreach-ready" }]
802
- },
803
- {
804
- id: "lead-gen.export.list",
805
- order: 120,
806
- label: "Export lead list",
807
- description: "Export approved leads as a downloadable lead list.",
808
- scope: { domain: "sales" },
809
- resourceId: "lgn-06-export-list-workflow",
810
- invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/export/list" }]
811
- },
812
- {
813
- id: "lead-gen.company.cleanup",
814
- order: 130,
815
- label: "Clean up companies",
816
- description: "Remove disqualified or duplicate companies from the list.",
817
- scope: { domain: "sales" },
818
- resourceId: "lgn-company-cleanup-workflow",
819
- invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/cleanup" }]
820
- }
821
- ];
822
- var LEAD_GEN_ACTION_ENTRIES = Object.fromEntries(
823
- LEAD_GEN_ACTION_ENTRY_INPUTS.map((action) => {
824
- const parsed = ActionSchema.parse(action);
825
- return [parsed.id, parsed];
826
- })
827
- );
828
- var CRM_ACTION_ENTRY_INPUTS = [
829
- {
830
- id: "send_reply",
831
- order: 210,
832
- label: "Send Reply",
833
- description: "Send a contextual reply for an active CRM deal.",
834
- scope: { domain: "sales" },
835
- resourceId: "crm-send-reply-workflow",
836
- affects: ["crm.deal"]
837
- },
838
- {
839
- id: "send_link",
840
- order: 220,
841
- label: "Send Booking Link",
842
- description: "Send a booking link to move a deal toward a scheduled call.",
843
- scope: { domain: "sales" },
844
- resourceId: "crm-send-booking-link-workflow",
845
- affects: ["crm.deal"]
846
- },
847
- {
848
- id: "send_nudge",
849
- order: 230,
850
- label: "Send Nudge",
851
- description: "Send a follow-up nudge for a stalled CRM deal.",
852
- scope: { domain: "sales" },
853
- resourceId: "crm-send-nudge-workflow",
854
- affects: ["crm.deal"]
855
- },
856
- {
857
- id: "rebook",
858
- order: 240,
859
- label: "Rebook",
860
- description: "Rebook a missed or rescheduled CRM appointment.",
861
- scope: { domain: "sales" },
862
- resourceId: "crm-rebook-workflow",
863
- affects: ["crm.deal"]
864
- },
865
- {
866
- id: "move_to_proposal",
867
- order: 250,
868
- label: "Move to Proposal",
869
- description: "Advance a qualified CRM deal into the proposal stage.",
870
- scope: { domain: "sales" },
871
- resourceId: "move_to_proposal-workflow",
872
- affects: ["crm.deal"]
873
- },
874
- {
875
- id: "move_to_closing",
876
- order: 260,
877
- label: "Move to Closing",
878
- description: "Advance a proposal-stage CRM deal into closing.",
879
- scope: { domain: "sales" },
880
- resourceId: "move_to_closing-workflow",
881
- affects: ["crm.deal"]
882
- },
883
- {
884
- id: "move_to_closed_won",
885
- order: 270,
886
- label: "Close Won",
887
- description: "Mark a CRM deal as closed won.",
888
- scope: { domain: "sales" },
889
- resourceId: "move_to_closed_won-workflow",
890
- affects: ["crm.deal"]
891
- },
892
- {
893
- id: "move_to_closed_lost",
894
- order: 280,
895
- label: "Close Lost",
896
- description: "Mark a CRM deal as closed lost.",
897
- scope: { domain: "sales" },
898
- resourceId: "move_to_closed_lost-workflow",
899
- affects: ["crm.deal"]
900
- },
901
- {
902
- id: "move_to_nurturing",
903
- order: 290,
904
- label: "Move to Nurturing",
905
- description: "Move a CRM deal into nurturing for future follow-up.",
906
- scope: { domain: "sales" },
907
- resourceId: "move_to_nurturing-workflow",
908
- affects: ["crm.deal"]
909
- }
910
- ];
911
- var CRM_ACTION_ENTRIES = Object.fromEntries(
912
- CRM_ACTION_ENTRY_INPUTS.map((action) => {
913
- const parsed = ActionSchema.parse(action);
914
- return [parsed.id, parsed];
915
- })
916
- );
917
- var DEFAULT_ORGANIZATION_MODEL_ACTIONS = {
918
- ...LEAD_GEN_ACTION_ENTRIES,
919
- ...CRM_ACTION_ENTRIES
920
- };
921
- var ContentNodeBaseSchema = z.object({
922
- /** Human-readable label for the content node. */
923
- label: z.string().trim().min(1).max(120).meta({ label: "Label" }),
924
- /** Optional one-paragraph description. */
925
- description: z.string().trim().min(1).max(2e3).optional().meta({ label: "Description" }),
926
- /** Optional display order within the system content map. */
927
- order: z.number().int().optional().meta({ label: "Order" }),
928
- /**
929
- * Local NodeId of the parent content node within the SAME system.
930
- * Per B4/L9: MUST resolve to a sibling in the same `system.content` map.
931
- * Per L19: parent and child MUST share the same `kind` (meta-category).
932
- */
933
- parentContentId: z.string().trim().min(1).max(200).optional().meta({ label: "Parent content id" })
934
- });
935
- var ContentNodeSchema = ContentNodeBaseSchema.extend({
936
- /** Meta-category (e.g. 'schema', 'config', 'knowledge', tenant-defined). */
937
- kind: z.string().trim().min(1).max(100).meta({ label: "Kind" }),
938
- /** Specific family within the meta-category (e.g. 'pipeline', 'kv'). */
939
- type: z.string().trim().min(1).max(100).meta({ label: "Type" }),
940
- /** Payload data; validated against registered payloadSchema when (kind, type) is known. */
941
- data: z.record(z.string(), z.unknown()).optional().meta({ label: "Data" })
942
- });
943
- z.object({
944
- /** Meta-category (tenant-defined or registry-shipped). */
945
- kind: z.string().trim().min(1).max(100).meta({ label: "Kind" }),
946
- /** Specific family within the meta-category. */
947
- type: z.string().trim().min(1).max(100).meta({ label: "Type" }),
948
- /** Human-readable label shown in the KB tree and describe views. */
949
- label: z.string().trim().min(1).max(120).meta({ label: "Label" }),
950
- /** Optional description. */
951
- description: z.string().trim().min(1).max(2e3).optional().meta({ label: "Description" }),
952
- /**
953
- * Which KB tree group this extension renders in.
954
- * Per L6: 'business-model' places it alongside Customers / Offerings / Goals.
955
- */
956
- treeGroup: z.union([z.enum(["profile", "business-model", "systems", "graph", "governance-wiring"]), z.string().min(1).max(100)]).meta({ label: "Tree group" }),
957
- /** Untyped payload; shape governed by the registered payloadSchema when available. */
958
- data: z.record(z.string(), z.unknown()).optional().meta({ label: "Data" })
959
- });
809
+ var DEFAULT_ORGANIZATION_MODEL_ACTIONS = {};
960
810
 
961
811
  // ../core/src/organization-model/domains/systems.ts
962
812
  var SystemKindSchema = z.enum(["product", "operational", "platform", "diagnostic"]).meta({ label: "System kind", color: "blue" });
@@ -970,7 +820,7 @@ var SystemPathSchema = z.string().trim().min(1).regex(
970
820
  var UiPositionSchema = z.enum(["sidebar-primary", "sidebar-bottom"]).meta({ label: "UI position" });
971
821
  var NodeIdStringSchema = z.string().trim().min(1).max(200).regex(
972
822
  /^[a-z][a-z-]*:([a-z0-9-]+)(\.[a-z0-9-]+)*(:[a-z0-9.-]+)*$/,
973
- "Node references must use kind:dotted-path (e.g. system:sales.crm or content-node:sales.crm:pipeline-id)"
823
+ "Node references must use kind:dotted-path (e.g. system:sales.crm or resource:lead-gen.company.qualify)"
974
824
  );
975
825
  var SystemUiSchema = z.object({
976
826
  path: PathSchema,
@@ -1044,13 +894,6 @@ var SystemEntrySchema = z.object({
1044
894
  * shared contract records owned by this system.
1045
895
  */
1046
896
  ontology: OntologyScopeSchema.optional(),
1047
- /**
1048
- * @deprecated Compatibility-only bridge for old tenant content nodes and
1049
- * migration readers. New schema/catalog authoring belongs in ontology;
1050
- * new system-local settings belong in config. Bridge nodes are keyed by
1051
- * local NodeId and may still project to content-node:* graph IDs.
1052
- */
1053
- content: z.record(z.string().trim().min(1).max(200), ContentNodeSchema).optional(),
1054
897
  /**
1055
898
  * Recursive child systems, authored via nesting (per L11).
1056
899
  * The key is the local system id; the full path is computed by joining
@@ -1061,7 +904,7 @@ var SystemEntrySchema = z.object({
1061
904
  systems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional(),
1062
905
  /** @deprecated Use systems. Accepted as a compatibility alias during the ontology bridge. */
1063
906
  subsystems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional()
1064
- }).refine((system) => system.label !== void 0 || system.title !== void 0, {
907
+ }).strict().refine((system) => system.label !== void 0 || system.title !== void 0, {
1065
908
  path: ["label"],
1066
909
  message: "System must provide label or title"
1067
910
  }).transform((system) => {
@@ -1140,6 +983,10 @@ var DEFAULT_ORGANIZATION_MODEL_IDENTITY = {
1140
983
  businessHours: {},
1141
984
  clientBrief: ""
1142
985
  };
986
+ var ContractRefSchema = z.string().trim().min(1).max(500).regex(
987
+ /^[A-Za-z0-9@](?:[A-Za-z0-9_./@-]*[A-Za-z0-9_])?\/?[A-Za-z0-9_./@-]*#[A-Za-z_$][A-Za-z0-9_$]*$/,
988
+ "ContractRef must be in the format package/subpath#ExportName (e.g. @repo/elevasis-core/contracts/apollo-import#inputSchema)"
989
+ );
1143
990
  z.enum(["workflow", "agent", "integration", "script"]).meta({ label: "Resource kind", color: "orange" });
1144
991
  var ResourceGovernanceStatusSchema = z.enum(["active", "deprecated", "archived"]).meta({ label: "Governance status", color: "teal" });
1145
992
  var AgentKindSchema = z.enum(["orchestrator", "specialist", "utility", "platform"]).meta({ label: "Agent kind", color: "violet" });
@@ -1168,7 +1015,20 @@ var ResourceOntologyBindingSchema = z.object({
1168
1015
  reads: z.array(OntologyIdSchema).optional(),
1169
1016
  writes: z.array(OntologyIdSchema).optional(),
1170
1017
  usesCatalogs: z.array(OntologyIdSchema).optional(),
1171
- emits: z.array(OntologyIdSchema).optional()
1018
+ emits: z.array(OntologyIdSchema).optional(),
1019
+ /**
1020
+ * Optional typed contract binding for this resource's workflow I/O.
1021
+ * Each ref is a `package/subpath#ExportName` string that resolves to a
1022
+ * Zod schema in `@repo/elevasis-core` (or the consumer's equivalent package).
1023
+ *
1024
+ * Absence of this field preserves all existing behavior — it is additive + optional.
1025
+ * Tier-1 validation (schema.ts): ref-string shape only (browser-safe, no imports).
1026
+ * Tier-2 validation (om:verify): intra-package typed-map resolution asserts ZodType.
1027
+ */
1028
+ contract: z.object({
1029
+ input: ContractRefSchema.optional(),
1030
+ output: ContractRefSchema.optional()
1031
+ }).optional()
1172
1032
  }).superRefine((binding, ctx) => {
1173
1033
  if (binding.primaryAction === void 0) return;
1174
1034
  if (binding.actions?.includes(binding.primaryAction)) return;
@@ -1248,6 +1108,11 @@ var ResourcesDomainSchema = z.record(z.string(), ResourceEntrySchema).refine((re
1248
1108
  message: "Each resource entry id must match its map key"
1249
1109
  }).default({});
1250
1110
  var DEFAULT_ORGANIZATION_MODEL_RESOURCES = {};
1111
+ function defineResources(resources) {
1112
+ return Object.fromEntries(
1113
+ Object.entries(resources).map(([key, resource]) => [key, ResourceEntrySchema.parse(resource)])
1114
+ );
1115
+ }
1251
1116
 
1252
1117
  // ../core/src/organization-model/helpers.ts
1253
1118
  function childSystemsOf2(system) {
@@ -1319,8 +1184,8 @@ function getSystemAncestors(model, path) {
1319
1184
  function listAllSystems(model) {
1320
1185
  const results = [];
1321
1186
  function walk(map, prefix) {
1322
- for (const [localId, system] of Object.entries(map)) {
1323
- const fullPath = prefix ? `${prefix}.${localId}` : localId;
1187
+ for (const [localId2, system] of Object.entries(map)) {
1188
+ const fullPath = prefix ? `${prefix}.${localId2}` : localId2;
1324
1189
  results.push({ path: fullPath, system });
1325
1190
  const childSystems = childSystemsOf2(system);
1326
1191
  if (Object.keys(childSystems).length > 0) {
@@ -1331,15 +1196,6 @@ function listAllSystems(model) {
1331
1196
  walk(model.systems, "");
1332
1197
  return results;
1333
1198
  }
1334
- function getContent(model, qualifiedId) {
1335
- const colonIndex = qualifiedId.indexOf(":");
1336
- if (colonIndex === -1) return void 0;
1337
- const systemPath = qualifiedId.slice(0, colonIndex);
1338
- const localId = qualifiedId.slice(colonIndex + 1);
1339
- if (!systemPath || !localId) return void 0;
1340
- const system = getSystem(model, systemPath);
1341
- return system?.content?.[localId];
1342
- }
1343
1199
  function isPlainJsonObject(value) {
1344
1200
  return typeof value === "object" && value !== null && !Array.isArray(value);
1345
1201
  }
@@ -1354,15 +1210,7 @@ function mergeJsonConfig(base, override) {
1354
1210
  function resolveSystemConfig(model, path) {
1355
1211
  const system = getSystem(model, path);
1356
1212
  if (system === void 0) return {};
1357
- let resolved = {};
1358
- for (const node of Object.values(system.content ?? {})) {
1359
- if (node.kind !== "config" || node.type !== "kv") continue;
1360
- const entries = node.data?.entries;
1361
- if (isPlainJsonObject(entries)) {
1362
- resolved = mergeJsonConfig(resolved, entries);
1363
- }
1364
- }
1365
- return mergeJsonConfig(resolved, system.config ?? {});
1213
+ return mergeJsonConfig({}, system.config ?? {});
1366
1214
  }
1367
1215
  function getResourcesForSystem(model, systemPath, options = {}) {
1368
1216
  const { includeDescendants = false } = options;
@@ -1371,893 +1219,207 @@ function getResourcesForSystem(model, systemPath, options = {}) {
1371
1219
  (r) => r.systemPath === systemPath || includeDescendants && r.systemPath.startsWith(prefix)
1372
1220
  );
1373
1221
  }
1374
- DisplayMetadataSchema.extend({
1375
- id: ModelIdSchema,
1376
- order: z.number().min(0)
1377
- });
1378
- var RecordColumnConfigSchema = z.object({
1379
- key: ModelIdSchema,
1380
- label: z.string().trim().min(1).max(120),
1381
- path: z.string().trim().min(1).max(500),
1382
- width: z.union([z.number().positive(), z.string().trim().min(1).max(100)]).optional(),
1383
- renderType: z.enum(["text", "badge", "datetime", "count", "json"]).optional(),
1384
- badgeColor: z.string().trim().min(1).max(40).optional()
1385
- });
1386
- var RecordColumnsConfigSchema = z.object({
1387
- company: z.array(RecordColumnConfigSchema).optional(),
1388
- contact: z.array(RecordColumnConfigSchema).optional()
1389
- }).refine((columns) => Boolean(columns.company?.length || columns.contact?.length), {
1390
- message: "recordColumns must include at least one entity column set"
1391
- });
1392
- var CredentialRequirementSchema = z.object({
1393
- key: ModelIdSchema,
1394
- provider: ModelIdSchema,
1395
- credentialType: z.enum(["api-key", "api-key-secret", "oauth", "webhook-secret"]),
1396
- label: z.string().trim().min(1).max(120),
1397
- required: z.boolean(),
1398
- selectionMode: z.enum(["single", "multiple"]).optional(),
1399
- inputPath: z.string().trim().min(1).max(500),
1400
- verifyOnRun: z.boolean().optional()
1222
+
1223
+ // ../core/src/organization-model/migration-helpers.ts
1224
+ function catalogRecords(model) {
1225
+ return Object.values(compileOrganizationOntology(model).ontology.catalogTypes);
1226
+ }
1227
+ function localId(id) {
1228
+ return parseOntologyId(id).localId;
1229
+ }
1230
+ function systemScope(id, fallback) {
1231
+ return parseOntologyId(id).scope || fallback || "";
1232
+ }
1233
+ function entriesOf(catalog) {
1234
+ return Object.entries(catalog.entries ?? {}).map(([id, value]) => [
1235
+ id,
1236
+ value && typeof value === "object" && !Array.isArray(value) ? value : {}
1237
+ ]);
1238
+ }
1239
+ function stringValue(value) {
1240
+ return typeof value === "string" ? value : void 0;
1241
+ }
1242
+ function stringArray(value) {
1243
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
1244
+ }
1245
+ function numberValue(value, fallback = 0) {
1246
+ return typeof value === "number" ? value : fallback;
1247
+ }
1248
+ function stageFromEntry(entryId, entry) {
1249
+ return {
1250
+ id: entryId,
1251
+ label: stringValue(entry.label) ?? entryId,
1252
+ order: numberValue(entry.order),
1253
+ semanticClass: stringValue(entry.semanticClass) ?? "open",
1254
+ surfaceIds: stringArray(entry.surfaceIds),
1255
+ resourceIds: stringArray(entry.resourceIds),
1256
+ color: stringValue(entry.color)
1257
+ };
1258
+ }
1259
+ function appliesToLocalId(catalog) {
1260
+ const appliesTo = catalog.appliesTo;
1261
+ if (appliesTo === void 0) return void 0;
1262
+ return parseOntologyId(appliesTo).localId;
1263
+ }
1264
+ function appliesToEntityKind(catalog) {
1265
+ const id = appliesToLocalId(catalog);
1266
+ if (id === "company" || id === "contact" || id === "project" || id === "milestone" || id === "task") return id;
1267
+ if (id === "deal") return void 0;
1268
+ return void 0;
1269
+ }
1270
+ function getAllPipelines(model) {
1271
+ return catalogRecords(model).filter((catalog) => catalog.kind === "pipeline").map((catalog) => {
1272
+ const pipeline = {
1273
+ id: localId(catalog.id),
1274
+ label: catalog.label ?? localId(catalog.id),
1275
+ ...catalog.description ? { description: catalog.description } : {},
1276
+ entityId: appliesToLocalId(catalog) ?? "",
1277
+ stages: entriesOf(catalog).map(([entryId, entry]) => stageFromEntry(entryId, entry)).sort((a, b) => a.order - b.order || a.id.localeCompare(b.id))
1278
+ };
1279
+ return { systemPath: catalog.ownerSystemId ?? systemScope(catalog.id), pipeline };
1280
+ }).sort((a, b) => a.systemPath.localeCompare(b.systemPath) || a.pipeline.id.localeCompare(b.pipeline.id));
1281
+ }
1282
+ function getAllBuildTemplates(model) {
1283
+ const catalogs = catalogRecords(model);
1284
+ const stepCatalogs = new Map(
1285
+ catalogs.filter((catalog) => catalog.kind === "template-step").map((catalog) => [catalog.id, catalog])
1286
+ );
1287
+ return catalogs.filter((catalog) => catalog.kind === "template").flatMap(
1288
+ (catalog) => entriesOf(catalog).map(([templateId, templateEntry]) => {
1289
+ const stepCatalogId = stringValue(templateEntry.stepCatalog);
1290
+ const stepCatalog = stepCatalogId !== void 0 ? stepCatalogs.get(stepCatalogId) : void 0;
1291
+ const steps = stepCatalog === void 0 ? [] : entriesOf(stepCatalog);
1292
+ return {
1293
+ id: templateId,
1294
+ label: stringValue(templateEntry.label) ?? templateId,
1295
+ ...stringValue(templateEntry.description) ? { description: stringValue(templateEntry.description) } : {},
1296
+ ...stringValue(templateEntry.color) ? { color: stringValue(templateEntry.color) } : {},
1297
+ steps: steps.map(([stepId, step]) => ({
1298
+ id: stepId,
1299
+ label: stringValue(step.label) ?? stepId,
1300
+ ...stringValue(step.description) ? { description: stringValue(step.description) } : {},
1301
+ ...step
1302
+ }))
1303
+ };
1304
+ })
1305
+ ).sort((a, b) => a.id.localeCompare(b.id));
1306
+ }
1307
+ function getAllProspectingStages(model, kind) {
1308
+ return catalogRecords(model).filter((catalog) => catalog.kind === "stage" && appliesToEntityKind(catalog) === kind).flatMap(
1309
+ (catalog) => entriesOf(catalog).map(([entryId, entry]) => ({
1310
+ id: entryId,
1311
+ label: stringValue(entry.label) ?? entryId,
1312
+ order: numberValue(entry.order),
1313
+ ...stringValue(entry.color) ? { color: stringValue(entry.color) } : {},
1314
+ ...stringValue(entry.description) ? { description: stringValue(entry.description) } : {}
1315
+ }))
1316
+ ).sort((a, b) => a.order - b.order || a.id.localeCompare(b.id));
1317
+ }
1318
+ function getLeadGenStageCatalog(model) {
1319
+ const results = {};
1320
+ for (const catalog of catalogRecords(model).filter(
1321
+ (record) => record.kind === "stage" && (record.ownerSystemId ?? systemScope(record.id)) === "sales.lead-gen"
1322
+ )) {
1323
+ const catalogEntity = appliesToEntityKind(catalog);
1324
+ if (catalogEntity !== "company" && catalogEntity !== "contact") continue;
1325
+ for (const [entryId, entry] of entriesOf(catalog)) {
1326
+ const entity = entry.entity === "contact" ? "contact" : entry.entity === "company" ? "company" : catalogEntity;
1327
+ const additionalEntities = stringArray(entry.additionalEntities).filter(
1328
+ (item) => item === "company" || item === "contact"
1329
+ );
1330
+ const recordEntity = entry.recordEntity === "company" || entry.recordEntity === "contact" ? entry.recordEntity : void 0;
1331
+ const recordStageKey = stringValue(entry.recordStageKey);
1332
+ results[entryId] = {
1333
+ key: entryId,
1334
+ label: stringValue(entry.label) ?? entryId,
1335
+ description: stringValue(entry.description) ?? "",
1336
+ order: numberValue(entry.order),
1337
+ entity,
1338
+ ...additionalEntities.length > 0 ? { additionalEntities } : {},
1339
+ ...recordEntity ? { recordEntity } : {},
1340
+ ...recordStageKey ? { recordStageKey } : {}
1341
+ };
1342
+ }
1343
+ }
1344
+ return Object.fromEntries(
1345
+ Object.entries(results).sort(([, a], [, b]) => a.order - b.order || a.key.localeCompare(b.key))
1346
+ );
1347
+ }
1348
+ function getAllProjectStatuses(model, appliesTo) {
1349
+ return catalogRecords(model).filter((catalog) => catalog.kind === "status-flow" && appliesToEntityKind(catalog) === appliesTo).flatMap(
1350
+ (catalog) => entriesOf(catalog).map(([entryId, entry]) => ({
1351
+ id: entryId,
1352
+ label: stringValue(entry.label) ?? entryId,
1353
+ order: numberValue(entry.order),
1354
+ ...stringValue(entry.color) ? { color: stringValue(entry.color) } : {},
1355
+ ...stringValue(entry.description) ? { description: stringValue(entry.description) } : {}
1356
+ }))
1357
+ ).sort((a, b) => a.order - b.order || a.id.localeCompare(b.id));
1358
+ }
1359
+
1360
+ // ../core/src/organization-model/contracts.ts
1361
+ var PROJECTS_VIEW_ACTION_ID = "delivery.projects.view";
1362
+ var OrganizationModelBrandingSchema = z.object({
1363
+ organizationName: LabelSchema,
1364
+ productName: LabelSchema,
1365
+ shortName: z.string().trim().min(1).max(40),
1366
+ description: DescriptionSchema.optional(),
1367
+ logos: z.object({
1368
+ light: z.string().trim().min(1).max(2048).optional(),
1369
+ dark: z.string().trim().min(1).max(2048).optional()
1370
+ }).default({})
1401
1371
  });
1402
- var ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
1403
- id: ModelIdSchema,
1404
- primaryEntity: z.enum(["company", "contact"]),
1405
- outputs: z.array(z.enum(["company", "contact", "export"])).min(1),
1406
- stageKey: ModelIdSchema,
1407
- recordEntity: z.enum(["company", "contact"]).optional(),
1408
- recordsStageKey: ModelIdSchema.optional(),
1409
- recordSourceStageKey: ModelIdSchema.optional(),
1410
- dependsOn: z.array(ModelIdSchema).optional(),
1411
- dependencyMode: z.literal("per-record-eligibility"),
1412
- actionKey: ModelIdSchema,
1413
- defaultBatchSize: z.number().int().positive(),
1414
- maxBatchSize: z.number().int().positive(),
1415
- recordColumns: RecordColumnsConfigSchema.optional(),
1416
- credentialRequirements: z.array(CredentialRequirementSchema).optional()
1417
- }).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
1418
- message: "defaultBatchSize must be less than or equal to maxBatchSize",
1419
- path: ["defaultBatchSize"]
1372
+ var DEFAULT_ORGANIZATION_MODEL_BRANDING = {
1373
+ organizationName: "Default Organization",
1374
+ productName: "Organization OS",
1375
+ shortName: "Org OS",
1376
+ logos: {}
1377
+ };
1378
+ var FirmographicsSchema = z.object({
1379
+ /** Industry vertical (e.g. "Marketing Agency", "Legal", "Real Estate"). */
1380
+ industry: z.string().trim().max(200).optional(),
1381
+ /**
1382
+ * Company headcount band (e.g. "1–10", "11–50", "51–200", "200+").
1383
+ * Free-form string to accommodate any band notation.
1384
+ */
1385
+ companySize: z.string().trim().max(100).optional(),
1386
+ /**
1387
+ * Primary geographic region the segment operates in or is targeted from
1388
+ * (e.g. "North America", "Europe", "Global").
1389
+ */
1390
+ region: z.string().trim().max(200).optional()
1420
1391
  });
1421
- DisplayMetadataSchema.extend({
1422
- id: ModelIdSchema,
1423
- steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
1424
- });
1425
- var DTC_RECORD_COLUMNS = {
1426
- populated: {
1427
- company: [
1428
- { key: "name", label: "Company", path: "company.name" },
1429
- { key: "domain", label: "Domain", path: "company.domain" },
1430
- { key: "employee-count", label: "Employees", path: "company.numEmployees", renderType: "count" },
1431
- { key: "apollo-industry", label: "Apollo industry", path: "company.category" },
1432
- { key: "location", label: "Location", path: "company.locationState" }
1433
- ]
1434
- },
1435
- crawled: {
1436
- company: [
1437
- { key: "name", label: "Company", path: "company.name" },
1438
- { key: "domain", label: "Domain", path: "company.domain" },
1439
- { key: "page-count", label: "Pages", path: "company.enrichmentData.websiteCrawl.pageCount", renderType: "count" },
1440
- { key: "crawl-status", label: "Crawl status", path: "processingState.crawled.status", renderType: "badge" }
1441
- ]
1442
- },
1443
- extracted: {
1444
- company: [
1445
- { key: "name", label: "Company", path: "company.name" },
1446
- { key: "domain", label: "Domain", path: "company.domain" },
1447
- { key: "description", label: "Description", path: "company.enrichmentData.websiteCrawl.companyDescription" },
1448
- { key: "services", label: "Services", path: "company.enrichmentData.websiteCrawl.services", renderType: "json" },
1449
- {
1450
- key: "automation-gaps",
1451
- label: "Automation gaps",
1452
- path: "company.enrichmentData.websiteCrawl.automationGaps",
1453
- renderType: "json"
1454
- },
1455
- {
1456
- key: "contact-count",
1457
- label: "Contacts",
1458
- path: "company.enrichmentData.websiteCrawl.emailCount",
1459
- renderType: "count"
1460
- }
1461
- ]
1462
- },
1463
- qualified: {
1464
- company: [
1465
- { key: "name", label: "Company", path: "company.name" },
1466
- { key: "domain", label: "Domain", path: "company.domain" },
1467
- { key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
1468
- { key: "signals", label: "Signals", path: "company.qualificationSignals", renderType: "json" },
1469
- {
1470
- key: "disqualified-reason",
1471
- label: "Disqualified reason",
1472
- path: "processingState.qualified.data.disqualifiedReason"
1473
- }
1474
- ]
1475
- },
1476
- decisionMakers: {
1477
- contact: [
1478
- { key: "name", label: "Name", path: "contact.name" },
1479
- { key: "title", label: "Title", path: "contact.title" },
1480
- { key: "email", label: "Email", path: "contact.email" },
1481
- { key: "linkedin", label: "LinkedIn", path: "contact.linkedinUrl" },
1482
- {
1483
- key: "priority-score",
1484
- label: "Priority",
1485
- path: "contact.enrichmentData.apollo.priorityScore",
1486
- renderType: "badge"
1487
- }
1488
- ]
1489
- },
1490
- uploaded: {
1491
- company: [
1492
- { key: "name", label: "Company", path: "company.name" },
1493
- { key: "domain", label: "Domain", path: "company.domain" },
1494
- {
1495
- key: "contacts",
1496
- label: "Contacts",
1497
- path: "company.enrichmentData.approvedLeadListExport.contacts",
1498
- renderType: "json"
1499
- },
1500
- { key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
1501
- {
1502
- key: "approval",
1503
- label: "Approval",
1504
- path: "company.enrichmentData.approvedLeadListExport.approvalStatus",
1505
- renderType: "badge"
1506
- }
1507
- ]
1508
- }
1509
- };
1510
- Object.values(LEAD_GEN_ACTION_ENTRIES);
1511
- var PROSPECTING_STEPS = {
1512
- localServices: {
1513
- sourceCompanies: {
1514
- id: "source-companies",
1515
- label: "Companies found",
1516
- primaryEntity: "company",
1517
- outputs: ["company"],
1518
- stageKey: "populated",
1519
- dependencyMode: "per-record-eligibility",
1520
- actionKey: "lead-gen.company.source",
1521
- defaultBatchSize: 100,
1522
- maxBatchSize: 250
1523
- },
1524
- analyzeWebsites: {
1525
- id: "analyze-websites",
1526
- label: "Websites analyzed",
1527
- primaryEntity: "company",
1528
- outputs: ["company"],
1529
- stageKey: "extracted",
1530
- dependsOn: ["source-companies"],
1531
- dependencyMode: "per-record-eligibility",
1532
- actionKey: "lead-gen.company.website-extract",
1533
- defaultBatchSize: 50,
1534
- maxBatchSize: 100
1535
- },
1536
- qualifyCompanies: {
1537
- id: "qualify-companies",
1538
- label: "Companies qualified",
1539
- primaryEntity: "company",
1540
- outputs: ["company"],
1541
- stageKey: "qualified",
1542
- dependsOn: ["analyze-websites"],
1543
- dependencyMode: "per-record-eligibility",
1544
- actionKey: "lead-gen.company.qualify",
1545
- defaultBatchSize: 100,
1546
- maxBatchSize: 250
1547
- },
1548
- findContacts: {
1549
- id: "find-contacts",
1550
- label: "Decision-makers found",
1551
- primaryEntity: "contact",
1552
- outputs: ["contact"],
1553
- stageKey: "discovered",
1554
- dependsOn: ["qualify-companies"],
1555
- dependencyMode: "per-record-eligibility",
1556
- actionKey: "lead-gen.contact.discover",
1557
- defaultBatchSize: 50,
1558
- maxBatchSize: 100
1559
- },
1560
- verifyEmails: {
1561
- id: "verify-emails",
1562
- label: "Emails verified",
1563
- primaryEntity: "contact",
1564
- outputs: ["contact"],
1565
- stageKey: "verified",
1566
- dependsOn: ["find-contacts"],
1567
- dependencyMode: "per-record-eligibility",
1568
- actionKey: "lead-gen.contact.verify-email",
1569
- defaultBatchSize: 100,
1570
- maxBatchSize: 500
1571
- },
1572
- personalize: {
1573
- id: "personalize",
1574
- label: "Personalize",
1575
- primaryEntity: "contact",
1576
- outputs: ["contact"],
1577
- stageKey: "personalized",
1578
- dependsOn: ["verify-emails"],
1579
- dependencyMode: "per-record-eligibility",
1580
- actionKey: "lead-gen.contact.personalize",
1581
- defaultBatchSize: 25,
1582
- maxBatchSize: 100
1583
- },
1584
- review: {
1585
- id: "review",
1586
- label: "Reviewed and exported",
1587
- primaryEntity: "contact",
1588
- outputs: ["export"],
1589
- stageKey: "uploaded",
1590
- dependsOn: ["personalize"],
1591
- dependencyMode: "per-record-eligibility",
1592
- actionKey: "lead-gen.review.outreach-ready",
1593
- defaultBatchSize: 25,
1594
- maxBatchSize: 100
1595
- }
1596
- },
1597
- dtcApolloClickup: {
1598
- importApolloSearch: {
1599
- id: "import-apollo-search",
1600
- label: "Companies found",
1601
- description: "Pull companies and seed contact data from a predefined Apollo search or list.",
1602
- primaryEntity: "company",
1603
- outputs: ["company", "contact"],
1604
- stageKey: "populated",
1605
- dependencyMode: "per-record-eligibility",
1606
- actionKey: "lead-gen.company.apollo-import",
1607
- defaultBatchSize: 250,
1608
- maxBatchSize: 1e3,
1609
- recordColumns: DTC_RECORD_COLUMNS.populated,
1610
- credentialRequirements: [
1611
- {
1612
- key: "apollo",
1613
- provider: "apollo",
1614
- credentialType: "api-key-secret",
1615
- label: "Apollo API key",
1616
- required: true,
1617
- selectionMode: "single",
1618
- inputPath: "credential"
1619
- }
1620
- ]
1621
- },
1622
- apifyCrawl: {
1623
- id: "apify-crawl",
1624
- label: "Websites crawled",
1625
- description: "Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis. Overwrites the synthetic seed Apollo Import wrote with real page content.",
1626
- primaryEntity: "company",
1627
- outputs: ["company"],
1628
- stageKey: "crawled",
1629
- dependsOn: ["import-apollo-search"],
1630
- dependencyMode: "per-record-eligibility",
1631
- actionKey: "lead-gen.company.apify-crawl",
1632
- defaultBatchSize: 50,
1633
- maxBatchSize: 100,
1634
- recordColumns: DTC_RECORD_COLUMNS.crawled,
1635
- credentialRequirements: [
1636
- {
1637
- key: "apify",
1638
- provider: "apify",
1639
- credentialType: "api-key-secret",
1640
- label: "Apify API token",
1641
- required: true,
1642
- selectionMode: "single",
1643
- inputPath: "credential",
1644
- verifyOnRun: true
1645
- }
1646
- ]
1647
- },
1648
- analyzeWebsites: {
1649
- id: "analyze-websites",
1650
- label: "Websites analyzed",
1651
- description: "Extract subscription, product, retention, and tech-stack signals from each brand website.",
1652
- primaryEntity: "company",
1653
- outputs: ["company"],
1654
- stageKey: "extracted",
1655
- dependsOn: ["apify-crawl"],
1656
- dependencyMode: "per-record-eligibility",
1657
- actionKey: "lead-gen.company.website-extract",
1658
- defaultBatchSize: 50,
1659
- maxBatchSize: 100,
1660
- recordColumns: DTC_RECORD_COLUMNS.extracted
1661
- },
1662
- scoreDtcFit: {
1663
- id: "score-dtc-fit",
1664
- label: "Companies qualified",
1665
- description: "Classify subscription potential, consumable-product fit, retention maturity, and disqualifiers.",
1666
- primaryEntity: "company",
1667
- outputs: ["company"],
1668
- stageKey: "qualified",
1669
- dependsOn: ["analyze-websites"],
1670
- dependencyMode: "per-record-eligibility",
1671
- actionKey: "lead-gen.company.dtc-subscription-qualify",
1672
- defaultBatchSize: 100,
1673
- maxBatchSize: 250,
1674
- recordColumns: DTC_RECORD_COLUMNS.qualified
1675
- },
1676
- enrichDecisionMakers: {
1677
- id: "enrich-decision-makers",
1678
- label: "Decision-makers found",
1679
- description: "Use Apollo to find qualified contacts at qualified companies - founders, retention leads, lifecycle leads, and marketing owners.",
1680
- primaryEntity: "company",
1681
- outputs: ["contact"],
1682
- stageKey: "decision-makers-enriched",
1683
- recordEntity: "contact",
1684
- dependsOn: ["score-dtc-fit"],
1685
- dependencyMode: "per-record-eligibility",
1686
- actionKey: "lead-gen.contact.apollo-decision-maker-enrich",
1687
- defaultBatchSize: 100,
1688
- maxBatchSize: 250,
1689
- recordColumns: DTC_RECORD_COLUMNS.decisionMakers,
1690
- credentialRequirements: [
1691
- {
1692
- key: "apollo",
1693
- provider: "apollo",
1694
- credentialType: "api-key-secret",
1695
- label: "Apollo API key",
1696
- required: true,
1697
- selectionMode: "single",
1698
- inputPath: "credential"
1699
- }
1700
- ]
1701
- },
1702
- reviewAndExport: {
1703
- id: "review-and-export",
1704
- label: "Reviewed and exported",
1705
- description: "Operator QC approves or rejects qualified companies, then approved records are exported as a lead list with unverified emails.",
1706
- primaryEntity: "company",
1707
- outputs: ["export"],
1708
- stageKey: "uploaded",
1709
- recordsStageKey: "uploaded",
1710
- recordSourceStageKey: "qualified",
1711
- dependsOn: ["enrich-decision-makers"],
1712
- dependencyMode: "per-record-eligibility",
1713
- actionKey: "lead-gen.export.list",
1714
- defaultBatchSize: 100,
1715
- maxBatchSize: 250,
1716
- recordColumns: DTC_RECORD_COLUMNS.uploaded,
1717
- credentialRequirements: [
1718
- {
1719
- key: "clickup",
1720
- provider: "clickup",
1721
- credentialType: "api-key-secret",
1722
- label: "ClickUp API token",
1723
- required: true,
1724
- selectionMode: "single",
1725
- inputPath: "clickupCredential",
1726
- verifyOnRun: true
1727
- }
1728
- ]
1729
- }
1730
- }
1731
- };
1732
-
1733
- // ../core/src/organization-model/catalogs/lead-gen.ts
1734
- var LEAD_GEN_STAGE_CATALOG = {
1735
- // Prospecting - company population
1736
- scraped: {
1737
- key: "scraped",
1738
- label: "Scraped",
1739
- description: "Company was scraped from a source directory (Apify actor run).",
1740
- order: 1,
1741
- entity: "company"
1742
- },
1743
- populated: {
1744
- key: "populated",
1745
- label: "Companies found",
1746
- description: "Companies have been found and added to the lead-gen list.",
1747
- order: 2,
1748
- entity: "company"
1749
- },
1750
- crawled: {
1751
- key: "crawled",
1752
- label: "Websites crawled",
1753
- description: "Company websites have been crawled (e.g. via Apify) and raw page content stored for downstream LLM analysis.",
1754
- order: 2.5,
1755
- entity: "company"
1756
- },
1757
- extracted: {
1758
- key: "extracted",
1759
- label: "Websites analyzed",
1760
- description: "Company websites have been analyzed for business signals.",
1761
- order: 3,
1762
- entity: "company"
1763
- },
1764
- enriched: {
1765
- key: "enriched",
1766
- label: "Enriched",
1767
- description: "Company or contact enriched with third-party data (e.g. Tomba, Anymailfinder).",
1768
- order: 4,
1769
- entity: "company"
1770
- },
1771
- "decision-makers-enriched": {
1772
- key: "decision-makers-enriched",
1773
- label: "Decision-makers found",
1774
- description: "Decision-maker contacts discovered and attached to a qualified company.",
1775
- order: 6,
1776
- entity: "company",
1777
- recordEntity: "contact",
1778
- recordStageKey: "discovered"
1779
- },
1780
- // Prospecting - contact discovery
1781
- discovered: {
1782
- key: "discovered",
1783
- label: "Decision-makers found",
1784
- description: "Decision-maker contact details have been found.",
1785
- order: 5,
1786
- entity: "contact"
1787
- },
1788
- verified: {
1789
- key: "verified",
1790
- label: "Emails verified",
1791
- description: "Contact email addresses have been checked for deliverability.",
1792
- order: 7,
1793
- entity: "contact"
1794
- },
1795
- // Qualification
1796
- qualified: {
1797
- key: "qualified",
1798
- label: "Companies qualified",
1799
- description: "Companies have been scored against the qualification criteria.",
1800
- order: 8,
1801
- entity: "company"
1802
- },
1803
- // Outreach
1804
- personalized: {
1805
- key: "personalized",
1806
- label: "Personalized",
1807
- description: "Outreach message personalized for the contact (Instantly personalization workflow).",
1808
- order: 9,
1809
- entity: "contact"
1810
- },
1811
- uploaded: {
1812
- key: "uploaded",
1813
- label: "Reviewed and exported",
1814
- description: "Approved records have been reviewed and exported for handoff.",
1815
- order: 10,
1816
- entity: "company",
1817
- additionalEntities: ["contact"]
1818
- },
1819
- interested: {
1820
- key: "interested",
1821
- label: "Interested",
1822
- description: "Contact replied with a positive signal (Instantly reply-handler transition).",
1823
- order: 11,
1824
- entity: "contact"
1825
- }
1826
- };
1827
- var SalesStageSemanticClassSchema = z.enum(["open", "active", "nurturing", "closed_won", "closed_lost"]);
1828
- var SalesStageSchema = DisplayMetadataSchema.extend({
1829
- id: ModelIdSchema,
1830
- order: z.number().int().min(0),
1831
- semanticClass: SalesStageSemanticClassSchema,
1832
- surfaceIds: ReferenceIdsSchema,
1833
- resourceIds: ReferenceIdsSchema
1834
- });
1835
- z.object({
1836
- id: ModelIdSchema,
1837
- label: z.string().trim().min(1).max(120),
1838
- description: DescriptionSchema.optional(),
1839
- entityId: ModelIdSchema,
1840
- stages: z.array(SalesStageSchema).min(1)
1841
- });
1842
- function findPipeline(definitions, pipelineKey) {
1843
- return definitions.find((def) => def.pipelineKey === pipelineKey);
1844
- }
1845
- var CRM_DISCOVERY_REPLIED_STATE = {
1846
- stateKey: "discovery_replied",
1847
- label: "Discovery Replied"
1848
- };
1849
- var CRM_DISCOVERY_LINK_SENT_STATE = {
1850
- stateKey: "discovery_link_sent",
1851
- label: "Discovery Link Sent"
1852
- };
1853
- var CRM_DISCOVERY_NUDGING_STATE = {
1854
- stateKey: "discovery_nudging",
1855
- label: "Discovery Nudging"
1856
- };
1857
- var CRM_DISCOVERY_BOOKING_CANCELLED_STATE = {
1858
- stateKey: "discovery_booking_cancelled",
1859
- label: "Discovery Booking Cancelled"
1860
- };
1861
- var CRM_REPLY_SENT_STATE = {
1862
- stateKey: "reply_sent",
1863
- label: "Reply Sent"
1864
- };
1865
- var CRM_FOLLOWUP_1_SENT_STATE = {
1866
- stateKey: "followup_1_sent",
1867
- label: "Follow-up 1 Sent"
1868
- };
1869
- var CRM_FOLLOWUP_2_SENT_STATE = {
1870
- stateKey: "followup_2_sent",
1871
- label: "Follow-up 2 Sent"
1872
- };
1873
- var CRM_FOLLOWUP_3_SENT_STATE = {
1874
- stateKey: "followup_3_sent",
1875
- label: "Follow-up 3 Sent"
1876
- };
1877
- var CRM_PIPELINE_DEFINITION = {
1878
- pipelineKey: "crm",
1879
- label: "CRM",
1880
- entityKey: "crm.deal",
1881
- stages: [
1882
- {
1883
- stageKey: "interested",
1884
- label: "Interested",
1885
- color: "blue",
1886
- states: [
1887
- CRM_DISCOVERY_REPLIED_STATE,
1888
- CRM_DISCOVERY_LINK_SENT_STATE,
1889
- CRM_DISCOVERY_NUDGING_STATE,
1890
- CRM_DISCOVERY_BOOKING_CANCELLED_STATE,
1891
- CRM_REPLY_SENT_STATE,
1892
- CRM_FOLLOWUP_1_SENT_STATE,
1893
- CRM_FOLLOWUP_2_SENT_STATE,
1894
- CRM_FOLLOWUP_3_SENT_STATE
1895
- ]
1896
- },
1897
- { stageKey: "proposal", label: "Proposal", color: "yellow", states: [] },
1898
- { stageKey: "closing", label: "Closing", color: "orange", states: [] },
1899
- { stageKey: "closed_won", label: "Closed Won", color: "green", states: [] },
1900
- { stageKey: "closed_lost", label: "Closed Lost", color: "red", states: [] },
1901
- { stageKey: "nurturing", label: "Nurturing", color: "grape", states: [] }
1902
- ]
1903
- };
1904
- var CRM_PRIORITY_BUCKETS = [
1905
- { bucketKey: "needs_response", label: "Needs Response", rank: 10, color: "red" },
1906
- { bucketKey: "follow_up_due", label: "Follow-up Due", rank: 20, color: "orange" },
1907
- { bucketKey: "waiting", label: "Waiting", rank: 30, color: "blue" },
1908
- { bucketKey: "stale", label: "Stale", rank: 40, color: "gray" },
1909
- { bucketKey: "closed_low", label: "Closed", rank: 50, color: "dark" }
1910
- ];
1911
- var DEFAULT_CRM_PRIORITY_RULE_CONFIG = {
1912
- buckets: CRM_PRIORITY_BUCKETS,
1913
- closedStageKeys: ["closed_won", "closed_lost"],
1914
- followUpAfterDaysByStateKey: {
1915
- discovery_link_sent: 3,
1916
- discovery_nudging: 2,
1917
- reply_sent: 3,
1918
- followup_1_sent: 3,
1919
- followup_2_sent: 5,
1920
- followup_3_sent: 7
1921
- },
1922
- staleAfterDays: 14
1923
- };
1924
- var PENDING_STATE = { stateKey: "pending", label: "Pending" };
1925
- var ACQ_LIST_MEMBERS_LEAD_GEN_PIPELINE = {
1926
- pipelineKey: "lead-gen",
1927
- label: "Lead Generation",
1928
- entityKey: "acq.list-member",
1929
- stages: [
1930
- {
1931
- stageKey: "outreach",
1932
- label: "Outreach",
1933
- states: [
1934
- PENDING_STATE,
1935
- { stateKey: "personalized", label: "Personalized" },
1936
- { stateKey: "uploaded", label: "Uploaded" },
1937
- { stateKey: "interested", label: "Interested" }
1938
- ]
1939
- },
1940
- {
1941
- stageKey: "prospecting",
1942
- label: "Prospecting",
1943
- states: [
1944
- PENDING_STATE,
1945
- { stateKey: "discovered", label: "Discovered" },
1946
- { stateKey: "verified", label: "Verified" }
1947
- ]
1948
- },
1949
- {
1950
- stageKey: "qualification",
1951
- label: "Qualification",
1952
- states: [PENDING_STATE]
1953
- }
1954
- ]
1955
- };
1956
- var ACQ_LIST_COMPANIES_LEAD_GEN_PIPELINE = {
1957
- pipelineKey: "lead-gen",
1958
- label: "Lead Generation",
1959
- entityKey: "acq.list-company",
1960
- stages: [
1961
- {
1962
- stageKey: "outreach",
1963
- label: "Outreach",
1964
- states: [PENDING_STATE, { stateKey: "uploaded", label: "Uploaded" }]
1965
- },
1966
- {
1967
- stageKey: "prospecting",
1968
- label: "Prospecting",
1969
- states: [
1970
- PENDING_STATE,
1971
- { stateKey: "populated", label: "Populated" },
1972
- { stateKey: "extracted", label: "Extracted" }
1973
- ]
1974
- },
1975
- {
1976
- stageKey: "qualification",
1977
- label: "Qualification",
1978
- states: [PENDING_STATE, { stateKey: "qualified", label: "Qualified" }]
1979
- }
1980
- ]
1981
- };
1982
- var LEAD_GEN_PIPELINE_DEFINITIONS = {
1983
- "acq.list-member": [ACQ_LIST_MEMBERS_LEAD_GEN_PIPELINE],
1984
- "acq.list-company": [ACQ_LIST_COMPANIES_LEAD_GEN_PIPELINE]
1985
- };
1986
-
1987
- // ../core/src/organization-model/contracts.ts
1988
- var PROJECTS_VIEW_ACTION_ID = "delivery.projects.view";
1989
-
1990
- // ../core/src/organization-model/content-kinds/registry.ts
1991
- function defineContentType(def) {
1992
- return def;
1993
- }
1994
- var PipelinePayloadSchema = z.object({
1995
- /**
1996
- * Local NodeId of the entity this pipeline applies to (e.g. 'crm.deal').
1997
- * `.meta({ ref: 'entity' })` enables SchemaDrivenFieldList to render a
1998
- * clickable graph link to the referenced entity node.
1999
- */
2000
- entityId: z.string().trim().min(1).max(200).meta({ label: "Entity", ref: "entity", hint: "The entity type this pipeline tracks" }),
2001
- /**
2002
- * Optional Kanban column color token for UI rendering.
2003
- */
2004
- kanbanColor: z.string().trim().min(1).max(40).optional().meta({ label: "Kanban color", hint: "UI color token" })
2005
- });
2006
- var pipelineKind = defineContentType({
2007
- kind: "schema",
2008
- type: "pipeline",
2009
- label: "Pipeline",
2010
- description: "A named progression pipeline that applies to a specific entity type.",
2011
- payloadSchema: PipelinePayloadSchema,
2012
- parentTypes: []
2013
- });
2014
- var StagePayloadSchema = z.object({
2015
- /**
2016
- * Semantic classification for this stage.
2017
- * Drives color, icon, and CRM-priority logic in consuming views.
2018
- * Optional — prospecting stages use data.entityKind instead.
2019
- * Enum aligned with SalesStageSemanticClassSchema (sales.ts).
2020
- */
2021
- semanticClass: z.enum(["open", "active", "nurturing", "closed_won", "closed_lost", "won", "lost", "closed"]).optional().meta({ label: "Semantic class", hint: "Semantic meaning of this stage", color: "blue" })
2022
- });
2023
- var stageKind = defineContentType({
2024
- kind: "schema",
2025
- type: "stage",
2026
- label: "Stage",
2027
- description: "A stage within a pipeline. Must be parented under a schema:pipeline content node.",
2028
- payloadSchema: StagePayloadSchema,
2029
- parentTypes: ["schema:pipeline"]
2030
- });
2031
- var TemplatePayloadSchema = z.object({
2032
- /**
2033
- * Optional description surfaced in the KB describe view and tooling.
2034
- */
2035
- description: z.string().trim().min(1).max(2e3).optional().meta({ label: "Description", hint: "What this template is used for" })
2036
- });
2037
- var templateKind = defineContentType({
2038
- kind: "schema",
2039
- type: "template",
2040
- label: "Template",
2041
- description: "A named build template (e.g. a prospecting pipeline sequence).",
2042
- payloadSchema: TemplatePayloadSchema,
2043
- parentTypes: []
2044
- });
2045
- var TemplateStepPayloadSchema = z.object({
2046
- /**
2047
- * Which entity type this step primarily operates on.
2048
- */
2049
- primaryEntity: z.enum(["company", "contact"]).meta({ label: "Primary entity", hint: "Entity type this step processes", color: "blue" }),
2050
- /**
2051
- * Action key identifying the workflow action executed by this step.
2052
- * `.meta({ ref: 'action' })` enables SchemaDrivenFieldList to render a
2053
- * clickable graph link.
2054
- */
2055
- actionKey: z.string().trim().min(1).max(200).meta({ label: "Action", ref: "action", hint: "Workflow action executed by this step" }),
2056
- /**
2057
- * IDs of sibling step local NodeIds this step depends on.
2058
- */
2059
- dependsOn: z.array(z.string().trim().min(1).max(200)).optional().meta({ label: "Depends on", hint: "Local NodeIds of prerequisite steps" })
2060
- });
2061
- var templateStepKind = defineContentType({
2062
- kind: "schema",
2063
- type: "template-step",
2064
- label: "Template Step",
2065
- description: "A step within a build template. Must be parented under a schema:template content node.",
2066
- payloadSchema: TemplateStepPayloadSchema,
2067
- parentTypes: ["schema:template"]
2068
- });
2069
- var StatusFlowPayloadSchema = z.object({
2070
- /**
2071
- * Which entity scope this status flow governs.
2072
- */
2073
- appliesTo: z.enum(["project", "milestone", "task"]).meta({ label: "Applies to", hint: "Entity scope governed by this status flow", color: "blue" })
2074
- });
2075
- var statusFlowKind = defineContentType({
2076
- kind: "schema",
2077
- type: "status-flow",
2078
- label: "Status Flow",
2079
- description: "A named set of statuses governing a project, milestone, or task entity.",
2080
- payloadSchema: StatusFlowPayloadSchema,
2081
- parentTypes: []
2082
- });
2083
- var StatusPayloadSchema = z.object({
2084
- /**
2085
- * Semantic classification string for this status.
2086
- * Free-form to allow tenant-defined classifications (e.g. 'active', 'blocked',
2087
- * 'completed'). Used by UI to apply color and icon fallbacks.
2088
- * Optional — status nodes may omit this when the label is self-descriptive.
2089
- */
2090
- semanticClass: z.string().trim().min(1).max(100).optional().meta({ label: "Semantic class", hint: "Semantic meaning of this status (e.g. active, blocked, completed)" }),
2091
- /**
2092
- * Optional UI color token override for this status.
2093
- */
2094
- color: z.string().trim().min(1).max(40).optional().meta({ label: "Color", hint: "UI color token" })
2095
- });
2096
- var statusKind = defineContentType({
2097
- kind: "schema",
2098
- type: "status",
2099
- label: "Status",
2100
- description: "A single status within a status flow. Must be parented under a schema:status-flow content node.",
2101
- payloadSchema: StatusPayloadSchema,
2102
- parentTypes: ["schema:status-flow"]
2103
- });
2104
- var ConfigKvPayloadSchema = z.object({
2105
- /**
2106
- * Flat key-value entries. Values are JSON primitives.
2107
- * Keys are short identifiers (e.g. 'maxBatchSize', 'featureEnabled').
2108
- */
2109
- entries: z.record(z.string().trim().min(1).max(200), z.union([z.string(), z.number(), z.boolean(), z.null()])).meta({ label: "Entries", hint: "Key-value configuration entries (string, number, boolean, or null values)" })
2110
- });
2111
- var configKvKind = defineContentType({
2112
- kind: "config",
2113
- type: "kv",
2114
- label: "Key-Value Config",
2115
- description: "A flat key-value configuration store co-located with a system. Values are JSON primitives.",
2116
- payloadSchema: ConfigKvPayloadSchema,
2117
- parentTypes: []
2118
- });
2119
-
2120
- // ../core/src/organization-model/content-kinds/index.ts
2121
- var CONTENT_KIND_REGISTRY = {
2122
- "schema:pipeline": pipelineKind,
2123
- "schema:stage": stageKind,
2124
- "schema:template": templateKind,
2125
- "schema:template-step": templateStepKind,
2126
- "schema:status-flow": statusFlowKind,
2127
- "schema:status": statusKind,
2128
- "config:kv": configKvKind
2129
- };
2130
- function lookupContentType(kind, type) {
2131
- const key = `${kind}:${type}`;
2132
- return CONTENT_KIND_REGISTRY[key];
2133
- }
2134
- var OrganizationModelBrandingSchema = z.object({
2135
- organizationName: LabelSchema,
2136
- productName: LabelSchema,
2137
- shortName: z.string().trim().min(1).max(40),
2138
- description: DescriptionSchema.optional(),
2139
- logos: z.object({
2140
- light: z.string().trim().min(1).max(2048).optional(),
2141
- dark: z.string().trim().min(1).max(2048).optional()
2142
- }).default({})
2143
- });
2144
- var DEFAULT_ORGANIZATION_MODEL_BRANDING = {
2145
- organizationName: "Default Organization",
2146
- productName: "Elevasis",
2147
- shortName: "Elevasis",
2148
- logos: {}
2149
- };
2150
- var SurfaceTypeSchema = z.enum(["page", "dashboard", "graph", "detail", "list", "settings"]).meta({ label: "Surface type", color: "blue" });
2151
- var SurfaceDefinitionSchema = z.object({
2152
- id: ModelIdSchema,
2153
- label: LabelSchema,
2154
- path: PathSchema,
2155
- surfaceType: SurfaceTypeSchema,
2156
- description: DescriptionSchema.optional(),
2157
- enabled: z.boolean().default(true),
2158
- devOnly: z.boolean().optional(),
2159
- icon: IconNameSchema.optional(),
2160
- systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
2161
- entityIds: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]),
2162
- resourceIds: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]),
2163
- actionIds: z.array(ModelIdSchema.meta({ ref: "action" })).default([]),
2164
- parentId: ModelIdSchema.meta({ ref: "surface" }).optional()
2165
- });
2166
- var SidebarSurfaceTargetsSchema = z.object({
2167
- systems: z.array(ModelIdSchema.meta({ ref: "system" })).default([]).optional(),
2168
- entities: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]).optional(),
2169
- resources: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]).optional(),
2170
- actions: z.array(ModelIdSchema.meta({ ref: "action" })).default([]).optional()
2171
- }).default({});
2172
- var SidebarNodeSchema = z.lazy(
2173
- () => z.discriminatedUnion("type", [
2174
- z.object({
2175
- type: z.literal("group"),
2176
- label: LabelSchema,
2177
- description: DescriptionSchema.optional(),
2178
- icon: IconNameSchema.optional(),
2179
- order: z.number().int().optional(),
2180
- children: z.record(z.string(), SidebarNodeSchema).default({})
2181
- }),
2182
- z.object({
2183
- type: z.literal("surface"),
2184
- label: LabelSchema,
2185
- path: PathSchema,
2186
- surfaceType: SurfaceTypeSchema,
2187
- description: DescriptionSchema.optional(),
2188
- icon: IconNameSchema.optional(),
2189
- order: z.number().int().optional(),
2190
- targets: SidebarSurfaceTargetsSchema.optional(),
2191
- devOnly: z.boolean().optional(),
2192
- requiresAdmin: z.boolean().optional()
2193
- })
2194
- ])
2195
- );
2196
- var SidebarSectionSchema = z.record(z.string(), SidebarNodeSchema).default({});
2197
- var SidebarNavigationSchema = z.object({
2198
- primary: SidebarSectionSchema,
2199
- bottom: SidebarSectionSchema
2200
- }).default({ primary: {}, bottom: {} });
2201
- var OrganizationModelNavigationSchema = z.object({
2202
- sidebar: SidebarNavigationSchema
2203
- }).default({ sidebar: { primary: {}, bottom: {} } });
2204
- function getSortedSidebarEntries(nodes) {
2205
- return Object.entries(nodes).sort(([leftId, left], [rightId, right]) => {
2206
- const orderDelta = (left.order ?? Number.MAX_SAFE_INTEGER) - (right.order ?? Number.MAX_SAFE_INTEGER);
2207
- return orderDelta === 0 ? leftId.localeCompare(rightId) : orderDelta;
2208
- });
2209
- }
2210
- z.object({
2211
- id: ModelIdSchema,
2212
- label: LabelSchema,
2213
- placement: z.string().trim().min(1).max(50),
2214
- surfaceIds: z.array(ModelIdSchema.meta({ ref: "surface" })).default([])
2215
- });
2216
- var FirmographicsSchema = z.object({
2217
- /** Industry vertical (e.g. "Marketing Agency", "Legal", "Real Estate"). */
2218
- industry: z.string().trim().max(200).optional(),
2219
- /**
2220
- * Company headcount band (e.g. "1–10", "11–50", "51–200", "200+").
2221
- * Free-form string to accommodate any band notation.
2222
- */
2223
- companySize: z.string().trim().max(100).optional(),
2224
- /**
2225
- * Primary geographic region the segment operates in or is targeted from
2226
- * (e.g. "North America", "Europe", "Global").
2227
- */
2228
- region: z.string().trim().max(200).optional()
2229
- });
2230
- var CustomerSegmentSchema = z.object({
2231
- /** Stable unique identifier for the segment (e.g. "segment-smb-agencies"). */
2232
- id: z.string().trim().min(1).max(100),
2233
- /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
2234
- order: z.number(),
2235
- /** Human-readable name shown to agents and in UI (e.g. "SMB Marketing Agencies"). */
2236
- name: z.string().trim().max(200).default(""),
2237
- /** One or two sentences describing who this segment is. */
2238
- description: z.string().trim().max(2e3).default(""),
2239
- /**
2240
- * The primary job(s) this segment is trying to get done — the goal they hire
2241
- * a product/service to accomplish. Plain-language narrative or bullet list.
2242
- */
2243
- jobsToBeDone: z.string().trim().max(2e3).default(""),
2244
- /**
2245
- * Pains — frustrations, obstacles, and risks the segment experiences
2246
- * when trying to accomplish their jobs-to-be-done.
2247
- */
2248
- pains: z.array(z.string().trim().max(500)).default([]),
2249
- /**
2250
- * Gains — outcomes and benefits the segment desires; positive motivators
2251
- * beyond merely resolving pains.
2252
- */
2253
- gains: z.array(z.string().trim().max(500)).default([]),
2254
- /** Firmographic profile for targeting and filtering. */
2255
- firmographics: FirmographicsSchema.default({}),
2256
- /**
2257
- * Value proposition — one or two sentences stating why this organization's
2258
- * offering is uniquely suited for this segment's needs.
2259
- */
2260
- valueProp: z.string().trim().max(2e3).default("")
1392
+ var CustomerSegmentSchema = z.object({
1393
+ /** Stable unique identifier for the segment (e.g. "segment-smb-agencies"). */
1394
+ id: z.string().trim().min(1).max(100),
1395
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
1396
+ order: z.number(),
1397
+ /** Human-readable name shown to agents and in UI (e.g. "SMB Marketing Agencies"). */
1398
+ name: z.string().trim().max(200).default(""),
1399
+ /** One or two sentences describing who this segment is. */
1400
+ description: z.string().trim().max(2e3).default(""),
1401
+ /**
1402
+ * The primary job(s) this segment is trying to get done — the goal they hire
1403
+ * a product/service to accomplish. Plain-language narrative or bullet list.
1404
+ */
1405
+ jobsToBeDone: z.string().trim().max(2e3).default(""),
1406
+ /**
1407
+ * Pains — frustrations, obstacles, and risks the segment experiences
1408
+ * when trying to accomplish their jobs-to-be-done.
1409
+ */
1410
+ pains: z.array(z.string().trim().max(500)).default([]),
1411
+ /**
1412
+ * Gains — outcomes and benefits the segment desires; positive motivators
1413
+ * beyond merely resolving pains.
1414
+ */
1415
+ gains: z.array(z.string().trim().max(500)).default([]),
1416
+ /** Firmographic profile for targeting and filtering. */
1417
+ firmographics: FirmographicsSchema.default({}),
1418
+ /**
1419
+ * Value proposition one or two sentences stating why this organization's
1420
+ * offering is uniquely suited for this segment's needs.
1421
+ */
1422
+ valueProp: z.string().trim().max(2e3).default("")
2261
1423
  });
2262
1424
  var CustomersDomainSchema = z.record(z.string(), CustomerSegmentSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
2263
1425
  message: "Each segment entry id must match its map key"
@@ -2405,84 +1567,6 @@ var GoalsDomainSchema = z.record(z.string(), ObjectiveSchema).refine((record) =>
2405
1567
  message: "Each objective entry id must match its map key"
2406
1568
  }).default({});
2407
1569
  var DEFAULT_ORGANIZATION_MODEL_GOALS = {};
2408
- var KnowledgeTargetKindSchema = z.enum([
2409
- "system",
2410
- "resource",
2411
- "knowledge",
2412
- "stage",
2413
- "action",
2414
- "role",
2415
- "goal",
2416
- "customer-segment",
2417
- "offering",
2418
- "ontology",
2419
- // D4: content nodes are a valid knowledge target after compound-domain data moved into system.content
2420
- "content-node"
2421
- ]).meta({ label: "Target kind" });
2422
- var KnowledgeTargetRefSchema = z.object({
2423
- kind: KnowledgeTargetKindSchema,
2424
- // D4: content-node targets use a qualified id format '<system-path>:<local-content-id>'.
2425
- // Ontology targets use the canonical '<scope>:<kind>/<local-id>' ontology id format.
2426
- // Business-logic validation of target existence is done in OrganizationModelSchema.superRefine.
2427
- id: z.string().trim().min(1).max(300)
2428
- }).superRefine((target, ctx) => {
2429
- if (target.kind !== "ontology") return;
2430
- const result = OntologyIdSchema.safeParse(target.id);
2431
- if (!result.success) {
2432
- ctx.addIssue({
2433
- code: z.ZodIssueCode.custom,
2434
- path: ["id"],
2435
- message: "Ontology knowledge targets must use <system-path>:<kind>/<local-id> or global:<kind>/<local-id>"
2436
- });
2437
- }
2438
- });
2439
- var LegacyKnowledgeLinkSchema = z.object({
2440
- nodeId: z.union([NodeIdStringSchema, z.templateLiteral(["ontology:", OntologyIdSchema])])
2441
- });
2442
- var CanonicalKnowledgeLinkSchema = z.object({
2443
- target: KnowledgeTargetRefSchema
2444
- });
2445
- function nodeIdFromTarget(target) {
2446
- return `${target.kind}:${target.id}`;
2447
- }
2448
- function targetFromNodeId(nodeId2) {
2449
- const [kind, ...idParts] = nodeId2.split(":");
2450
- return {
2451
- kind: KnowledgeTargetKindSchema.parse(kind),
2452
- id: idParts.join(":")
2453
- };
2454
- }
2455
- var KnowledgeLinkSchema = z.union([CanonicalKnowledgeLinkSchema, LegacyKnowledgeLinkSchema]).transform((link) => {
2456
- const target = "target" in link ? link.target : targetFromNodeId(link.nodeId);
2457
- return {
2458
- target,
2459
- nodeId: nodeIdFromTarget(target)
2460
- };
2461
- });
2462
- var OrgKnowledgeKindSchema = z.enum(["playbook", "strategy", "reference"]).meta({ label: "Knowledge kind", color: "grape" });
2463
- var OrgKnowledgeNodeSchema = z.object({
2464
- id: ModelIdSchema,
2465
- kind: OrgKnowledgeKindSchema,
2466
- title: z.string().trim().min(1).max(200),
2467
- summary: z.string().trim().min(1).max(1e3),
2468
- icon: IconNameSchema.optional(),
2469
- /** Canonical documentation URL when body content is a local summary. */
2470
- externalUrl: z.string().trim().url().max(500).optional(),
2471
- /** Optional generated source file path for local MDX-backed knowledge nodes. */
2472
- sourceFilePath: z.string().trim().min(1).max(500).optional(),
2473
- /** Raw MDX string. Phase 2 will introduce a structured block format. */
2474
- body: z.string().trim().min(1),
2475
- /**
2476
- * Graph links to other OM nodes this knowledge node governs.
2477
- * Each link emits a `governs` edge: knowledge-node -> target node.
2478
- */
2479
- links: z.array(KnowledgeLinkSchema).default([]),
2480
- /** Role identifiers that own this knowledge node. */
2481
- ownerIds: z.array(RoleIdSchema.meta({ ref: "role" })).default([]),
2482
- /** ISO date string (YYYY-MM-DD or full ISO 8601) of last meaningful update. */
2483
- updatedAt: z.string().trim().min(1).max(50)
2484
- });
2485
- var KnowledgeDomainSchema = z.record(ModelIdSchema, OrgKnowledgeNodeSchema).default({});
2486
1570
  var SecretLikeMetadataKeySchema = /(?:secret|password|passwd|token|api[-_]?key|credential|private[-_]?key)/i;
2487
1571
  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-----)/;
2488
1572
  z.enum([
@@ -2550,6 +1634,90 @@ var DEFAULT_ORGANIZATION_MODEL_TOPOLOGY = {
2550
1634
  version: 1,
2551
1635
  relationships: {}
2552
1636
  };
1637
+ function idFrom(input) {
1638
+ return typeof input === "string" ? input : input.id;
1639
+ }
1640
+ function parseRef(kind, id) {
1641
+ return OmTopologyNodeRefSchema.parse({ kind, id });
1642
+ }
1643
+ function isNodeRef(input) {
1644
+ return OmTopologyNodeRefSchema.safeParse(input).success;
1645
+ }
1646
+ function isResourceEntry(input) {
1647
+ if (typeof input !== "object" || input === null) return false;
1648
+ const candidate = input;
1649
+ return typeof candidate.id === "string" && typeof candidate.systemPath === "string" && typeof candidate.status === "string" && ["workflow", "agent", "integration", "script"].includes(String(candidate.kind));
1650
+ }
1651
+ var topologyRef = {
1652
+ system: (system) => parseRef("system", idFrom(system)),
1653
+ resource: (resource) => parseRef("resource", idFrom(resource)),
1654
+ ontology: (record) => parseRef("ontology", idFrom(record)),
1655
+ policy: (policy) => parseRef("policy", idFrom(policy)),
1656
+ role: (role) => parseRef("role", idFrom(role)),
1657
+ trigger: (trigger) => parseRef("trigger", idFrom(trigger)),
1658
+ humanCheckpoint: (checkpoint) => parseRef("humanCheckpoint", idFrom(checkpoint)),
1659
+ externalResource: (externalResource) => parseRef("externalResource", idFrom(externalResource))
1660
+ };
1661
+ var topologyRelationship = {
1662
+ triggers: (from, to, options = {}) => defineTopologyRelationship({
1663
+ ...options,
1664
+ from,
1665
+ kind: "triggers",
1666
+ to
1667
+ }),
1668
+ uses: (from, to, options = {}) => defineTopologyRelationship({
1669
+ ...options,
1670
+ from,
1671
+ kind: "uses",
1672
+ to
1673
+ }),
1674
+ approval: (from, to, options = {}) => defineTopologyRelationship({
1675
+ ...options,
1676
+ from,
1677
+ kind: "approval",
1678
+ to
1679
+ }),
1680
+ usesIntegration: (from, integration, options = {}) => defineTopologyRelationship({
1681
+ required: true,
1682
+ ...options,
1683
+ from,
1684
+ kind: "uses",
1685
+ to: integration
1686
+ }),
1687
+ requestsApproval: (from, checkpoint, options = {}) => defineTopologyRelationship({
1688
+ required: true,
1689
+ ...options,
1690
+ from,
1691
+ kind: "approval",
1692
+ to: topologyRef.humanCheckpoint(checkpoint)
1693
+ }),
1694
+ checkpointRoutesTo: (checkpoint, to, options = {}) => defineTopologyRelationship({
1695
+ required: true,
1696
+ ...options,
1697
+ from: topologyRef.humanCheckpoint(checkpoint),
1698
+ kind: "triggers",
1699
+ to
1700
+ })
1701
+ };
1702
+ function compileTopologyNodeRef(input) {
1703
+ if (isNodeRef(input)) return input;
1704
+ if (isResourceEntry(input)) return topologyRef.resource(input);
1705
+ throw new Error("Topology node refs must be typed node objects or serializable { kind, id } refs");
1706
+ }
1707
+ function defineTopologyRelationship(input) {
1708
+ return OmTopologyRelationshipSchema.parse({
1709
+ ...input,
1710
+ from: compileTopologyNodeRef(input.from),
1711
+ to: compileTopologyNodeRef(input.to)
1712
+ });
1713
+ }
1714
+ function defineTopology(relationships) {
1715
+ const entries = Array.isArray(relationships) ? relationships.map((relationship, index) => [`relationship-${index + 1}`, relationship]) : Object.entries(relationships);
1716
+ return OmTopologyDomainSchema.parse({
1717
+ version: 1,
1718
+ relationships: Object.fromEntries(entries.map(([key, relationship]) => [key, defineTopologyRelationship(relationship)]))
1719
+ });
1720
+ }
2553
1721
  var PolicyIdSchema = ModelIdSchema;
2554
1722
  var PolicyApplicabilitySchema = z.object({
2555
1723
  systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
@@ -2623,84 +1791,241 @@ var PolicySchema = z.object({
2623
1791
  }),
2624
1792
  lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
2625
1793
  });
2626
- var PoliciesDomainSchema = z.record(z.string(), PolicySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
2627
- message: "Each policy entry id must match its map key"
2628
- }).default({});
2629
- var DEFAULT_ORGANIZATION_MODEL_POLICIES = {};
1794
+ var PoliciesDomainSchema = z.record(z.string(), PolicySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
1795
+ message: "Each policy entry id must match its map key"
1796
+ }).default({});
1797
+ var DEFAULT_ORGANIZATION_MODEL_POLICIES = {};
1798
+ var SurfaceTypeSchema = z.enum(["page", "dashboard", "graph", "detail", "list", "settings"]).meta({ label: "Surface type", color: "blue" });
1799
+ var SurfaceDefinitionSchema = z.object({
1800
+ id: ModelIdSchema,
1801
+ label: LabelSchema,
1802
+ path: PathSchema,
1803
+ surfaceType: SurfaceTypeSchema,
1804
+ description: DescriptionSchema.optional(),
1805
+ enabled: z.boolean().default(true),
1806
+ devOnly: z.boolean().optional(),
1807
+ icon: IconNameSchema.optional(),
1808
+ systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
1809
+ entityIds: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]),
1810
+ resourceIds: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]),
1811
+ actionIds: z.array(ModelIdSchema.meta({ ref: "action" })).default([]),
1812
+ parentId: ModelIdSchema.meta({ ref: "surface" }).optional()
1813
+ });
1814
+ var SidebarSurfaceTargetsSchema = z.object({
1815
+ systems: z.array(ModelIdSchema.meta({ ref: "system" })).default([]).optional(),
1816
+ entities: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]).optional(),
1817
+ resources: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]).optional(),
1818
+ actions: z.array(ModelIdSchema.meta({ ref: "action" })).default([]).optional()
1819
+ }).default({});
1820
+ var SidebarNodeSchema = z.lazy(
1821
+ () => z.discriminatedUnion("type", [
1822
+ z.object({
1823
+ type: z.literal("group"),
1824
+ label: LabelSchema,
1825
+ description: DescriptionSchema.optional(),
1826
+ icon: IconNameSchema.optional(),
1827
+ order: z.number().int().optional(),
1828
+ children: z.record(z.string(), SidebarNodeSchema).default({})
1829
+ }),
1830
+ z.object({
1831
+ type: z.literal("surface"),
1832
+ label: LabelSchema,
1833
+ path: PathSchema,
1834
+ surfaceType: SurfaceTypeSchema,
1835
+ description: DescriptionSchema.optional(),
1836
+ icon: IconNameSchema.optional(),
1837
+ order: z.number().int().optional(),
1838
+ targets: SidebarSurfaceTargetsSchema.optional(),
1839
+ devOnly: z.boolean().optional(),
1840
+ requiresAdmin: z.boolean().optional()
1841
+ })
1842
+ ])
1843
+ );
1844
+ var SidebarSectionSchema = z.record(z.string(), SidebarNodeSchema).default({});
1845
+ var SidebarNavigationSchema = z.object({
1846
+ primary: SidebarSectionSchema,
1847
+ bottom: SidebarSectionSchema
1848
+ }).default({ primary: {}, bottom: {} });
1849
+ var OrganizationModelNavigationSchema = z.object({
1850
+ sidebar: SidebarNavigationSchema
1851
+ }).default({ sidebar: { primary: {}, bottom: {} } });
1852
+ function getSortedSidebarEntries(nodes) {
1853
+ return Object.entries(nodes).sort(([leftId, left], [rightId, right]) => {
1854
+ const orderDelta = (left.order ?? Number.MAX_SAFE_INTEGER) - (right.order ?? Number.MAX_SAFE_INTEGER);
1855
+ return orderDelta === 0 ? leftId.localeCompare(rightId) : orderDelta;
1856
+ });
1857
+ }
1858
+ z.object({
1859
+ id: ModelIdSchema,
1860
+ label: LabelSchema,
1861
+ placement: z.string().trim().min(1).max(50),
1862
+ surfaceIds: z.array(ModelIdSchema.meta({ ref: "surface" })).default([])
1863
+ });
1864
+ var KnowledgeTargetKindSchema = z.enum([
1865
+ "system",
1866
+ "resource",
1867
+ "knowledge",
1868
+ "stage",
1869
+ "action",
1870
+ "role",
1871
+ "goal",
1872
+ "customer-segment",
1873
+ "offering",
1874
+ "ontology"
1875
+ ]).meta({ label: "Target kind" });
1876
+ var KnowledgeTargetRefSchema = z.object({
1877
+ kind: KnowledgeTargetKindSchema,
1878
+ // Ontology targets use the canonical '<scope>:<kind>/<local-id>' ontology id format.
1879
+ // Business-logic validation of target existence is done in OrganizationModelSchema.superRefine.
1880
+ id: z.string().trim().min(1).max(300)
1881
+ }).superRefine((target, ctx) => {
1882
+ if (target.kind !== "ontology") return;
1883
+ const result = OntologyIdSchema.safeParse(target.id);
1884
+ if (!result.success) {
1885
+ ctx.addIssue({
1886
+ code: z.ZodIssueCode.custom,
1887
+ path: ["id"],
1888
+ message: "Ontology knowledge targets must use <system-path>:<kind>/<local-id> or global:<kind>/<local-id>"
1889
+ });
1890
+ }
1891
+ });
1892
+ var LegacyKnowledgeLinkSchema = z.object({
1893
+ nodeId: z.union([NodeIdStringSchema, z.templateLiteral(["ontology:", OntologyIdSchema])])
1894
+ }).superRefine((link, ctx) => {
1895
+ const [kind] = link.nodeId.split(":");
1896
+ if (!KnowledgeTargetKindSchema.safeParse(kind).success) {
1897
+ ctx.addIssue({
1898
+ code: z.ZodIssueCode.custom,
1899
+ path: ["nodeId"],
1900
+ message: `Unknown knowledge target kind "${kind}"`
1901
+ });
1902
+ }
1903
+ });
1904
+ var CanonicalKnowledgeLinkSchema = z.object({
1905
+ target: KnowledgeTargetRefSchema
1906
+ });
1907
+ function nodeIdFromTarget(target) {
1908
+ return `${target.kind}:${target.id}`;
1909
+ }
1910
+ function targetFromNodeId(nodeId2) {
1911
+ const [kind, ...idParts] = nodeId2.split(":");
1912
+ return {
1913
+ kind: KnowledgeTargetKindSchema.parse(kind),
1914
+ id: idParts.join(":")
1915
+ };
1916
+ }
1917
+ var KnowledgeLinkSchema = z.union([CanonicalKnowledgeLinkSchema, LegacyKnowledgeLinkSchema]).transform((link) => {
1918
+ const target = "target" in link ? link.target : targetFromNodeId(link.nodeId);
1919
+ return {
1920
+ target,
1921
+ nodeId: nodeIdFromTarget(target)
1922
+ };
1923
+ });
1924
+ var OrgKnowledgeKindSchema = z.enum(["playbook", "strategy", "reference"]).meta({ label: "Knowledge kind", color: "grape" });
1925
+ var OrgKnowledgeNodeSchema = z.object({
1926
+ id: ModelIdSchema,
1927
+ kind: OrgKnowledgeKindSchema,
1928
+ title: z.string().trim().min(1).max(200),
1929
+ summary: z.string().trim().min(1).max(1e3),
1930
+ icon: IconNameSchema.optional(),
1931
+ /** Canonical documentation URL when body content is a local summary. */
1932
+ externalUrl: z.string().trim().url().max(500).optional(),
1933
+ /** Optional generated source file path for local MDX-backed knowledge nodes. */
1934
+ sourceFilePath: z.string().trim().min(1).max(500).optional(),
1935
+ /** Raw MDX string. Phase 2 will introduce a structured block format. */
1936
+ body: z.string().trim().min(1),
1937
+ /**
1938
+ * Graph links to other OM nodes this knowledge node governs.
1939
+ * Each link emits a `governs` edge: knowledge-node -> target node.
1940
+ */
1941
+ links: z.array(KnowledgeLinkSchema).default([]),
1942
+ /** Role identifiers that own this knowledge node. */
1943
+ ownerIds: z.array(RoleIdSchema.meta({ ref: "role" })).default([]),
1944
+ /** ISO date string (YYYY-MM-DD or full ISO 8601) of last meaningful update. */
1945
+ updatedAt: z.string().trim().min(1).max(50)
1946
+ });
1947
+ var KnowledgeDomainSchema = z.record(ModelIdSchema, OrgKnowledgeNodeSchema).default({});
2630
1948
 
2631
- // ../core/src/organization-model/schema.ts
2632
- z.enum([
2633
- "branding",
2634
- "identity",
2635
- "customers",
2636
- "offerings",
2637
- "roles",
2638
- "goals",
2639
- "systems",
2640
- "ontology",
2641
- "resources",
2642
- "topology",
2643
- "actions",
2644
- "entities",
2645
- "policies",
2646
- "knowledge"
2647
- ]);
2648
- var OrganizationModelDomainMetadataSchema = z.object({
2649
- version: z.literal(1).default(1),
2650
- lastModified: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "lastModified must be an ISO date string (YYYY-MM-DD)")
2651
- });
2652
- var DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA = {
2653
- branding: { version: 1, lastModified: "2026-05-10" },
2654
- identity: { version: 1, lastModified: "2026-05-10" },
2655
- customers: { version: 1, lastModified: "2026-05-10" },
2656
- offerings: { version: 1, lastModified: "2026-05-10" },
2657
- roles: { version: 1, lastModified: "2026-05-10" },
2658
- goals: { version: 1, lastModified: "2026-05-10" },
2659
- systems: { version: 1, lastModified: "2026-05-10" },
2660
- ontology: { version: 1, lastModified: "2026-05-14" },
2661
- resources: { version: 1, lastModified: "2026-05-10" },
2662
- topology: { version: 1, lastModified: "2026-05-14" },
2663
- actions: { version: 1, lastModified: "2026-05-10" },
2664
- entities: { version: 1, lastModified: "2026-05-10" },
2665
- policies: { version: 1, lastModified: "2026-05-10" },
2666
- knowledge: { version: 1, lastModified: "2026-05-10" }
1949
+ // ../core/src/organization-model/cross-ref.ts
1950
+ var ONTOLOGY_REFERENCE_KEY_KINDS = {
1951
+ valueType: "value-type",
1952
+ catalogType: "catalog",
1953
+ objectType: "object",
1954
+ eventType: "event",
1955
+ actionType: "action",
1956
+ linkType: "link",
1957
+ interfaceType: "interface",
1958
+ propertyType: "property",
1959
+ groupType: "group",
1960
+ surfaceType: "surface",
1961
+ stepCatalog: "catalog"
2667
1962
  };
2668
- var OrganizationModelDomainMetadataByDomainSchema = z.object({
2669
- branding: OrganizationModelDomainMetadataSchema,
2670
- identity: OrganizationModelDomainMetadataSchema,
2671
- customers: OrganizationModelDomainMetadataSchema,
2672
- offerings: OrganizationModelDomainMetadataSchema,
2673
- roles: OrganizationModelDomainMetadataSchema,
2674
- goals: OrganizationModelDomainMetadataSchema,
2675
- systems: OrganizationModelDomainMetadataSchema,
2676
- ontology: OrganizationModelDomainMetadataSchema,
2677
- resources: OrganizationModelDomainMetadataSchema,
2678
- topology: OrganizationModelDomainMetadataSchema,
2679
- actions: OrganizationModelDomainMetadataSchema,
2680
- entities: OrganizationModelDomainMetadataSchema,
2681
- policies: OrganizationModelDomainMetadataSchema,
2682
- knowledge: OrganizationModelDomainMetadataSchema
2683
- }).partial().default(DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA).transform((metadata) => ({ ...DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA, ...metadata }));
2684
- var OrganizationModelSchemaBase = z.object({
2685
- version: z.literal(1).default(1),
2686
- domainMetadata: OrganizationModelDomainMetadataByDomainSchema,
2687
- branding: OrganizationModelBrandingSchema,
2688
- navigation: OrganizationModelNavigationSchema,
2689
- identity: IdentityDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_IDENTITY),
2690
- customers: CustomersDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_CUSTOMERS),
2691
- offerings: OfferingsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_OFFERINGS),
2692
- roles: RolesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ROLES),
2693
- goals: GoalsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_GOALS),
2694
- systems: SystemsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_SYSTEMS),
2695
- ontology: OntologyScopeSchema.default(DEFAULT_ONTOLOGY_SCOPE),
2696
- resources: ResourcesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_RESOURCES),
2697
- topology: OmTopologyDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_TOPOLOGY),
2698
- actions: ActionsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ACTIONS),
2699
- entities: EntitiesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ENTITIES),
2700
- policies: PoliciesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_POLICIES),
2701
- // D3: flat Record<id, OrgKnowledgeNode> — no wrapper object
2702
- knowledge: KnowledgeDomainSchema.default({})
2703
- });
1963
+ function buildOmCrossRefIndex(model) {
1964
+ const systemsById = /* @__PURE__ */ new Map();
1965
+ for (const { path, system } of listAllSystems(model)) {
1966
+ systemsById.set(path, system);
1967
+ systemsById.set(system.id, system);
1968
+ }
1969
+ const resourceIds = new Set(Object.keys(model.resources ?? {}));
1970
+ const knowledgeIds = new Set(Object.keys(model.knowledge ?? {}));
1971
+ const roleIds = new Set(Object.keys(model.roles ?? {}));
1972
+ const goalIds = new Set(Object.keys(model.goals ?? {}));
1973
+ const actionIds = new Set(Object.keys(model.actions ?? {}));
1974
+ const customerSegmentIds = new Set(Object.keys(model.customers ?? {}));
1975
+ const offeringIds = new Set(Object.keys(model.offerings ?? {}));
1976
+ const ontologyCompilation = compileOrganizationOntology(model);
1977
+ const ontologyIndexByKind = {
1978
+ object: ontologyCompilation.ontology.objectTypes,
1979
+ link: ontologyCompilation.ontology.linkTypes,
1980
+ action: ontologyCompilation.ontology.actionTypes,
1981
+ catalog: ontologyCompilation.ontology.catalogTypes,
1982
+ event: ontologyCompilation.ontology.eventTypes,
1983
+ interface: ontologyCompilation.ontology.interfaceTypes,
1984
+ "value-type": ontologyCompilation.ontology.valueTypes,
1985
+ property: ontologyCompilation.ontology.sharedProperties,
1986
+ group: ontologyCompilation.ontology.groups,
1987
+ surface: ontologyCompilation.ontology.surfaces
1988
+ };
1989
+ const ontologyIds = new Set(Object.values(ontologyIndexByKind).flatMap((index) => Object.keys(index)));
1990
+ const stageIds = /* @__PURE__ */ new Set();
1991
+ for (const catalog of Object.values(ontologyCompilation.ontology.catalogTypes)) {
1992
+ if (catalog.kind !== "stage") continue;
1993
+ const entries = catalog.entries;
1994
+ if (entries !== void 0) {
1995
+ for (const stageId of Object.keys(entries)) {
1996
+ stageIds.add(stageId);
1997
+ }
1998
+ }
1999
+ }
2000
+ return {
2001
+ systemsById,
2002
+ resourceIds,
2003
+ knowledgeIds,
2004
+ roleIds,
2005
+ goalIds,
2006
+ actionIds,
2007
+ customerSegmentIds,
2008
+ offeringIds,
2009
+ ontologyIds,
2010
+ ontologyIndexByKind,
2011
+ stageIds
2012
+ };
2013
+ }
2014
+ function knowledgeTargetExists(index, kind, id) {
2015
+ if (kind === "system") return index.systemsById.has(id);
2016
+ if (kind === "resource") return index.resourceIds.has(id);
2017
+ if (kind === "knowledge") return index.knowledgeIds.has(id);
2018
+ if (kind === "stage") return index.stageIds.has(id);
2019
+ if (kind === "action") return index.actionIds.has(id);
2020
+ if (kind === "role") return index.roleIds.has(id);
2021
+ if (kind === "goal") return index.goalIds.has(id);
2022
+ if (kind === "customer-segment") return index.customerSegmentIds.has(id);
2023
+ if (kind === "offering") return index.offeringIds.has(id);
2024
+ if (kind === "ontology") return index.ontologyIds.has(id);
2025
+ return false;
2026
+ }
2027
+
2028
+ // ../core/src/organization-model/schema-refinements.ts
2704
2029
  function addIssue(ctx, path, message) {
2705
2030
  ctx.addIssue({
2706
2031
  code: z.ZodIssueCode.custom,
@@ -2731,7 +2056,7 @@ function isKnowledgeKindCompatibleWithTarget(knowledgeKind, targetKind) {
2731
2056
  function isRecord(value) {
2732
2057
  return typeof value === "object" && value !== null && !Array.isArray(value);
2733
2058
  }
2734
- var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ctx) => {
2059
+ function refineOrganizationModel(model, ctx) {
2735
2060
  function collectAllSystems(systems, prefix = "", schemaPath = ["systems"]) {
2736
2061
  const result = [];
2737
2062
  for (const [key, system] of Object.entries(systems)) {
@@ -2741,7 +2066,10 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
2741
2066
  const childSystems = system.systems ?? system.subsystems;
2742
2067
  if (childSystems !== void 0) {
2743
2068
  result.push(
2744
- ...collectAllSystems(childSystems, path, [...currentSchemaPath, system.systems !== void 0 ? "systems" : "subsystems"])
2069
+ ...collectAllSystems(childSystems, path, [
2070
+ ...currentSchemaPath,
2071
+ system.systems !== void 0 ? "systems" : "subsystems"
2072
+ ])
2745
2073
  );
2746
2074
  }
2747
2075
  }
@@ -2762,7 +2090,9 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
2762
2090
  `System "${system.id}" references unknown parent "${system.parentSystemId}"`
2763
2091
  );
2764
2092
  }
2765
- const hasChildren = Object.keys(system.systems ?? system.subsystems ?? {}).length > 0 || allSystems.some((candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes("."));
2093
+ const hasChildren = Object.keys(system.systems ?? system.subsystems ?? {}).length > 0 || allSystems.some(
2094
+ (candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes(".")
2095
+ );
2766
2096
  const contributesRoutePath = system.ui?.path !== void 0 || system.path !== void 0 || !hasChildren;
2767
2097
  if (contributesRoutePath) {
2768
2098
  const effectivePath = system.ui?.path ?? system.path ?? defaultSystemPathFor(path);
@@ -2784,11 +2114,7 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
2784
2114
  (candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes(".") && isLifecycleEnabled(candidate.system.lifecycle, candidate.system.enabled)
2785
2115
  );
2786
2116
  if (!hasEnabledDescendant) {
2787
- addIssue(
2788
- ctx,
2789
- [...schemaPath, "lifecycle"],
2790
- `System "${path}" is active but has no active descendants`
2791
- );
2117
+ addIssue(ctx, [...schemaPath, "lifecycle"], `System "${path}" is active but has no active descendants`);
2792
2118
  }
2793
2119
  }
2794
2120
  });
@@ -2902,7 +2228,7 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
2902
2228
  });
2903
2229
  });
2904
2230
  Object.values(model.entities).forEach((entity) => {
2905
- if (!systemsById.has(entity.ownedBySystemId)) {
2231
+ if (systemsById.size > 0 && !systemsById.has(entity.ownedBySystemId)) {
2906
2232
  addIssue(
2907
2233
  ctx,
2908
2234
  ["entities", entity.id, "ownedBySystemId"],
@@ -3020,23 +2346,9 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
3020
2346
  }
3021
2347
  });
3022
2348
  });
3023
- const stageIds = /* @__PURE__ */ new Set();
3024
- const actionIds = new Set(Object.keys(model.actions));
3025
- const offeringsById = new Map(Object.entries(model.offerings));
2349
+ const idx = buildOmCrossRefIndex(model);
2350
+ const { ontologyIndexByKind, ontologyIds } = idx;
3026
2351
  const ontologyCompilation = compileOrganizationOntology(model);
3027
- const ontologyIndexByKind = {
3028
- object: ontologyCompilation.ontology.objectTypes,
3029
- link: ontologyCompilation.ontology.linkTypes,
3030
- action: ontologyCompilation.ontology.actionTypes,
3031
- catalog: ontologyCompilation.ontology.catalogTypes,
3032
- event: ontologyCompilation.ontology.eventTypes,
3033
- interface: ontologyCompilation.ontology.interfaceTypes,
3034
- "value-type": ontologyCompilation.ontology.valueTypes,
3035
- property: ontologyCompilation.ontology.sharedProperties,
3036
- group: ontologyCompilation.ontology.groups,
3037
- surface: ontologyCompilation.ontology.surfaces
3038
- };
3039
- const ontologyIds = new Set(Object.values(ontologyIndexByKind).flatMap((index) => Object.keys(index)));
3040
2352
  function topologyTargetExists(ref) {
3041
2353
  if (ref.kind === "system") return systemsById.has(ref.id);
3042
2354
  if (ref.kind === "resource") return resourcesById.has(ref.id);
@@ -3056,19 +2368,6 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
3056
2368
  );
3057
2369
  });
3058
2370
  });
3059
- const ontologyReferenceKeyKinds = {
3060
- valueType: "value-type",
3061
- catalogType: "catalog",
3062
- objectType: "object",
3063
- eventType: "event",
3064
- actionType: "action",
3065
- linkType: "link",
3066
- interfaceType: "interface",
3067
- propertyType: "property",
3068
- groupType: "group",
3069
- surfaceType: "surface",
3070
- stepCatalog: "catalog"
3071
- };
3072
2371
  function validateKnownOntologyReferences(ownerId, value, path, seen = /* @__PURE__ */ new WeakSet()) {
3073
2372
  if (Array.isArray(value)) {
3074
2373
  value.forEach((entry, index) => validateKnownOntologyReferences(ownerId, entry, [...path, index], seen));
@@ -3078,7 +2377,7 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
3078
2377
  if (seen.has(value)) return;
3079
2378
  seen.add(value);
3080
2379
  Object.entries(value).forEach(([key, entry]) => {
3081
- const expectedKind = ontologyReferenceKeyKinds[key];
2380
+ const expectedKind = ONTOLOGY_REFERENCE_KEY_KINDS[key];
3082
2381
  if (expectedKind !== void 0) {
3083
2382
  if (typeof entry !== "string") {
3084
2383
  addIssue(ctx, [...path, key], `Ontology record "${ownerId}" ${key} must be an ontology ID string`);
@@ -3139,22 +2438,9 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
3139
2438
  );
3140
2439
  }
3141
2440
  });
3142
- function knowledgeTargetExists(kind, id) {
3143
- if (kind === "system") return systemsById.has(id);
3144
- if (kind === "resource") return resourcesById.has(id);
3145
- if (kind === "knowledge") return knowledgeById.has(id);
3146
- if (kind === "stage") return stageIds.has(id);
3147
- if (kind === "action") return actionIds.has(id);
3148
- if (kind === "role") return rolesById.has(id);
3149
- if (kind === "goal") return goalsById.has(id);
3150
- if (kind === "customer-segment") return segmentsById.has(id);
3151
- if (kind === "offering") return offeringsById.has(id);
3152
- if (kind === "ontology") return ontologyIds.has(id);
3153
- return false;
3154
- }
3155
2441
  Object.entries(model.knowledge).forEach(([nodeId2, node]) => {
3156
2442
  node.links.forEach((link, linkIndex) => {
3157
- if (!knowledgeTargetExists(link.target.kind, link.target.id)) {
2443
+ if (!knowledgeTargetExists(idx, link.target.kind, link.target.id)) {
3158
2444
  addIssue(
3159
2445
  ctx,
3160
2446
  ["knowledge", nodeId2, "links", linkIndex, "target"],
@@ -3199,13 +2485,7 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
3199
2485
  if (ontologyIndexByKind[expectedKind][ontologyId] === void 0) {
3200
2486
  addIssue(
3201
2487
  ctx,
3202
- [
3203
- "resources",
3204
- resourceId,
3205
- "ontology",
3206
- bindingKey,
3207
- ...Array.isArray(ids) ? [ontologyIndex] : []
3208
- ],
2488
+ ["resources", resourceId, "ontology", bindingKey, ...Array.isArray(ids) ? [ontologyIndex] : []],
3209
2489
  `Resource "${resourceId}" ontology binding "${bindingKey}" references unknown ${expectedKind} ontology ID "${ontologyId}"`
3210
2490
  );
3211
2491
  }
@@ -3220,6 +2500,23 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
3220
2500
  validateResourceOntologyBinding(resource.id, "writes", "object", binding.writes);
3221
2501
  validateResourceOntologyBinding(resource.id, "usesCatalogs", "catalog", binding.usesCatalogs);
3222
2502
  validateResourceOntologyBinding(resource.id, "emits", "event", binding.emits);
2503
+ if (binding.contract !== void 0) {
2504
+ const contractEntries = [
2505
+ ["input", binding.contract.input],
2506
+ ["output", binding.contract.output]
2507
+ ];
2508
+ for (const [side, ref] of contractEntries) {
2509
+ if (ref === void 0) continue;
2510
+ const result = ContractRefSchema.safeParse(ref);
2511
+ if (!result.success) {
2512
+ addIssue(
2513
+ ctx,
2514
+ ["resources", resource.id, "ontology", "contract", side],
2515
+ `Resource "${resource.id}" contract.${side} "${ref}" is not a valid ContractRef (expected "package/subpath#ExportName")`
2516
+ );
2517
+ }
2518
+ }
2519
+ }
3223
2520
  });
3224
2521
  Object.values(model.roles).forEach((role) => {
3225
2522
  if (role.heldBy === void 0) return;
@@ -3254,84 +2551,178 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
3254
2551
  }
3255
2552
  });
3256
2553
  });
3257
- function validateSystemContent(system, systemPath) {
3258
- const childSystems = system.systems ?? system.subsystems;
3259
- const childKey = system.systems !== void 0 ? "systems" : "subsystems";
3260
- const content = system.content;
3261
- if (content === void 0 || Object.keys(content).length === 0) {
3262
- if (childSystems !== void 0) {
3263
- Object.entries(childSystems).forEach(([childLocalId, child]) => {
3264
- validateSystemContent(child, [...systemPath, childKey, childLocalId]);
3265
- });
2554
+ for (const diagnostic of ontologyCompilation.diagnostics) {
2555
+ addIssue(ctx, diagnostic.path, diagnostic.message);
2556
+ }
2557
+ }
2558
+
2559
+ // ../core/src/organization-model/schema.ts
2560
+ z.enum([
2561
+ "branding",
2562
+ "identity",
2563
+ "customers",
2564
+ "offerings",
2565
+ "roles",
2566
+ "goals",
2567
+ "systems",
2568
+ "ontology",
2569
+ "resources",
2570
+ "topology",
2571
+ "actions",
2572
+ "entities",
2573
+ "policies",
2574
+ "knowledge"
2575
+ ]);
2576
+ var OrganizationModelDomainMetadataSchema = z.object({
2577
+ version: z.literal(1).default(1),
2578
+ lastModified: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "lastModified must be an ISO date string (YYYY-MM-DD)")
2579
+ });
2580
+ var DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA = {
2581
+ branding: { version: 1, lastModified: "2026-05-10" },
2582
+ identity: { version: 1, lastModified: "2026-05-10" },
2583
+ customers: { version: 1, lastModified: "2026-05-10" },
2584
+ offerings: { version: 1, lastModified: "2026-05-10" },
2585
+ roles: { version: 1, lastModified: "2026-05-10" },
2586
+ goals: { version: 1, lastModified: "2026-05-10" },
2587
+ systems: { version: 1, lastModified: "2026-05-10" },
2588
+ ontology: { version: 1, lastModified: "2026-05-14" },
2589
+ resources: { version: 1, lastModified: "2026-05-10" },
2590
+ topology: { version: 1, lastModified: "2026-05-14" },
2591
+ actions: { version: 1, lastModified: "2026-05-10" },
2592
+ entities: { version: 1, lastModified: "2026-05-10" },
2593
+ policies: { version: 1, lastModified: "2026-05-10" },
2594
+ knowledge: { version: 1, lastModified: "2026-05-10" }
2595
+ };
2596
+ var OrganizationModelDomainMetadataByDomainSchema = z.object({
2597
+ branding: OrganizationModelDomainMetadataSchema,
2598
+ identity: OrganizationModelDomainMetadataSchema,
2599
+ customers: OrganizationModelDomainMetadataSchema,
2600
+ offerings: OrganizationModelDomainMetadataSchema,
2601
+ roles: OrganizationModelDomainMetadataSchema,
2602
+ goals: OrganizationModelDomainMetadataSchema,
2603
+ systems: OrganizationModelDomainMetadataSchema,
2604
+ ontology: OrganizationModelDomainMetadataSchema,
2605
+ resources: OrganizationModelDomainMetadataSchema,
2606
+ topology: OrganizationModelDomainMetadataSchema,
2607
+ actions: OrganizationModelDomainMetadataSchema,
2608
+ entities: OrganizationModelDomainMetadataSchema,
2609
+ policies: OrganizationModelDomainMetadataSchema,
2610
+ knowledge: OrganizationModelDomainMetadataSchema
2611
+ }).partial().default(DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA).transform((metadata) => ({ ...DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA, ...metadata }));
2612
+ var OrganizationModelSchemaBase = z.object({
2613
+ version: z.literal(1).default(1),
2614
+ domainMetadata: OrganizationModelDomainMetadataByDomainSchema,
2615
+ branding: OrganizationModelBrandingSchema.default(DEFAULT_ORGANIZATION_MODEL_BRANDING),
2616
+ navigation: OrganizationModelNavigationSchema,
2617
+ identity: IdentityDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_IDENTITY),
2618
+ customers: CustomersDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_CUSTOMERS),
2619
+ offerings: OfferingsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_OFFERINGS),
2620
+ roles: RolesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ROLES),
2621
+ goals: GoalsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_GOALS),
2622
+ systems: SystemsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_SYSTEMS),
2623
+ ontology: OntologyScopeSchema.default(DEFAULT_ONTOLOGY_SCOPE),
2624
+ resources: ResourcesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_RESOURCES),
2625
+ topology: OmTopologyDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_TOPOLOGY),
2626
+ actions: ActionsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ACTIONS),
2627
+ entities: EntitiesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ENTITIES),
2628
+ policies: PoliciesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_POLICIES),
2629
+ // D3: flat Record<id, OrgKnowledgeNode> — no wrapper object
2630
+ knowledge: KnowledgeDomainSchema.default({})
2631
+ });
2632
+ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine(refineOrganizationModel);
2633
+
2634
+ // ../core/src/organization-model/defaults.ts
2635
+ var DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE = {};
2636
+ var DEFAULT_ORGANIZATION_MODEL_ENTITIES2 = {};
2637
+ var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
2638
+ sidebar: {
2639
+ primary: {},
2640
+ bottom: {}
2641
+ }
2642
+ };
2643
+ var DEFAULT_ORGANIZATION_MODEL = {
2644
+ version: 1,
2645
+ domainMetadata: DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA,
2646
+ branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
2647
+ navigation: DEFAULT_ORGANIZATION_MODEL_NAVIGATION,
2648
+ identity: DEFAULT_ORGANIZATION_MODEL_IDENTITY,
2649
+ customers: DEFAULT_ORGANIZATION_MODEL_CUSTOMERS,
2650
+ offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
2651
+ roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
2652
+ goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
2653
+ // Generic empty systems map. Elevasis-specific systems (platform, sales, sales.crm,
2654
+ // sales.lead-gen, monitoring, settings, admin, etc.) have been relocated to
2655
+ // `@repo/elevasis-core/src/organization-model/systems.ts` via `canonicalOrganizationModel`.
2656
+ // Tenant OM configs supply their own systems via `resolveOrganizationModel`.
2657
+ systems: {},
2658
+ ontology: DEFAULT_ONTOLOGY_SCOPE,
2659
+ resources: DEFAULT_ORGANIZATION_MODEL_RESOURCES,
2660
+ topology: DEFAULT_ORGANIZATION_MODEL_TOPOLOGY,
2661
+ // Generic empty actions map. Elevasis-specific action entries have been relocated to
2662
+ // `@repo/elevasis-core/src/organization-model/actions.ts`.
2663
+ actions: {},
2664
+ entities: DEFAULT_ORGANIZATION_MODEL_ENTITIES2,
2665
+ policies: DEFAULT_ORGANIZATION_MODEL_POLICIES,
2666
+ knowledge: DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE
2667
+ };
2668
+
2669
+ // ../core/src/organization-model/resolve.ts
2670
+ function isPlainObject(value) {
2671
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2672
+ }
2673
+ function collectNestedSystemPaths(systems, prefix = "") {
2674
+ const paths = /* @__PURE__ */ new Set();
2675
+ for (const [key, value] of Object.entries(systems)) {
2676
+ if (!isPlainObject(value)) continue;
2677
+ const path = prefix ? `${prefix}.${key}` : key;
2678
+ for (const childKey of ["systems", "subsystems"]) {
2679
+ const childSystems = value[childKey];
2680
+ if (!isPlainObject(childSystems)) continue;
2681
+ for (const childPath of collectNestedSystemPaths(childSystems, path)) {
2682
+ paths.add(childPath);
3266
2683
  }
3267
- return;
3268
2684
  }
3269
- Object.entries(content).forEach(([localId, node]) => {
3270
- if (node.parentContentId !== void 0 && !(node.parentContentId in content)) {
3271
- addIssue(
3272
- ctx,
3273
- [...systemPath, "content", localId, "parentContentId"],
3274
- `Content node "${localId}" parentContentId "${node.parentContentId}" does not resolve within the same system`
3275
- );
3276
- }
3277
- });
3278
- Object.entries(content).forEach(([localId, node]) => {
3279
- const visited = /* @__PURE__ */ new Set();
3280
- let currentId = node.parentContentId;
3281
- while (currentId !== void 0) {
3282
- if (currentId === localId || visited.has(currentId)) {
3283
- addIssue(
3284
- ctx,
3285
- [...systemPath, "content", localId, "parentContentId"],
3286
- `Content node "${localId}" has a parentContentId cycle`
3287
- );
3288
- break;
3289
- }
3290
- visited.add(currentId);
3291
- currentId = content[currentId]?.parentContentId;
3292
- }
3293
- });
3294
- Object.entries(content).forEach(([localId, node]) => {
3295
- const childDef = lookupContentType(node.kind, node.type);
3296
- if (childDef !== void 0 && node.data !== void 0) {
3297
- const result = childDef.payloadSchema.safeParse(node.data);
3298
- if (!result.success) {
3299
- addIssue(
3300
- ctx,
3301
- [...systemPath, "content", localId, "data"],
3302
- `Content node "${localId}" (${node.kind}:${node.type}) data failed payload validation: ${result.error.message}`
3303
- );
3304
- }
3305
- }
3306
- if (node.parentContentId !== void 0 && childDef !== void 0) {
3307
- const parentNode = content[node.parentContentId];
3308
- if (parentNode !== void 0) {
3309
- const parentDef = lookupContentType(parentNode.kind, parentNode.type);
3310
- if (parentDef !== void 0 && childDef.kind !== parentDef.kind) {
3311
- addIssue(
3312
- ctx,
3313
- [...systemPath, "content", localId, "parentContentId"],
3314
- `Content node "${localId}" kind "${childDef.kind}" cannot parent under "${node.parentContentId}" kind "${parentDef.kind}": parentContentId must be same-meta-kind (per L19)`
3315
- );
3316
- }
3317
- }
3318
- }
3319
- });
3320
- if (childSystems !== void 0) {
3321
- Object.entries(childSystems).forEach(([childLocalId, child]) => {
3322
- validateSystemContent(child, [...systemPath, childKey, childLocalId]);
3323
- });
2685
+ if (prefix !== "") {
2686
+ paths.add(path);
3324
2687
  }
3325
2688
  }
3326
- Object.entries(model.systems).forEach(([systemKey, system]) => {
3327
- validateSystemContent(system, ["systems", systemKey]);
3328
- });
3329
- for (const diagnostic of ontologyCompilation.diagnostics) {
3330
- addIssue(ctx, diagnostic.path, diagnostic.message);
2689
+ return paths;
2690
+ }
2691
+ function pruneFlatSystemDescendantCollisions(base, override) {
2692
+ const result = { ...base };
2693
+ for (const nestedPath of collectNestedSystemPaths(override)) {
2694
+ delete result[nestedPath];
3331
2695
  }
3332
- });
3333
-
3334
- // ../core/src/organization-model/graph/schema.ts
2696
+ return result;
2697
+ }
2698
+ function deepMerge(base, override) {
2699
+ if (override === void 0) {
2700
+ return base;
2701
+ }
2702
+ if (Array.isArray(base)) {
2703
+ return override ?? base;
2704
+ }
2705
+ if (!isPlainObject(base) || !isPlainObject(override)) {
2706
+ return override ?? base;
2707
+ }
2708
+ const result = { ...base };
2709
+ for (const [key, value] of Object.entries(override)) {
2710
+ if (value === void 0) continue;
2711
+ const existing = result[key];
2712
+ if (key === "systems" && isPlainObject(existing) && isPlainObject(value)) {
2713
+ result[key] = deepMerge(pruneFlatSystemDescendantCollisions(existing, value), value);
2714
+ continue;
2715
+ }
2716
+ result[key] = isPlainObject(existing) && isPlainObject(value) ? deepMerge(existing, value) : value;
2717
+ }
2718
+ return result;
2719
+ }
2720
+ function resolveOrganizationModel(override, organizationIdOrOptions, options) {
2721
+ const resolvedOptions = typeof organizationIdOrOptions === "object" ? organizationIdOrOptions : options;
2722
+ const mergeDefaults = resolvedOptions?.mergeDefaults ?? true;
2723
+ const merged = mergeDefaults ? deepMerge(DEFAULT_ORGANIZATION_MODEL, override) : override ?? {};
2724
+ return OrganizationModelSchema.parse(merged);
2725
+ }
3335
2726
  var OrganizationGraphNodeKindSchema = z.enum([
3336
2727
  "organization",
3337
2728
  "system",
@@ -3348,9 +2739,8 @@ var OrganizationGraphNodeKindSchema = z.enum([
3348
2739
  "goal",
3349
2740
  "surface",
3350
2741
  "navigation-group",
3351
- // Phase 3 preview Phase 4 populates via graph projection of system.content entries.
3352
- "ontology",
3353
- "content-node"
2742
+ // Ontology records are projected from compiled System.ontology scopes.
2743
+ "ontology"
3354
2744
  ]);
3355
2745
  var OrganizationGraphEdgeKindSchema = z.enum([
3356
2746
  "contains",
@@ -3401,112 +2791,6 @@ var BuildOrganizationGraphInputSchema = z.object({
3401
2791
  commandViewData: z.unknown().optional()
3402
2792
  });
3403
2793
 
3404
- // ../core/src/organization-model/migration-helpers.ts
3405
- function getAllPipelines(model) {
3406
- const results = [];
3407
- for (const { path: systemPath, system } of listAllSystems(model)) {
3408
- const content = system.content ?? {};
3409
- for (const [localId, node] of Object.entries(content)) {
3410
- if (node.kind !== "schema" || node.type !== "pipeline") continue;
3411
- const data = node.data ?? {};
3412
- const stages = Object.entries(content).filter(([, s]) => s.kind === "schema" && s.type === "stage" && s.parentContentId === localId).map(([stageLocalId, s]) => {
3413
- const sd = s.data ?? {};
3414
- return {
3415
- id: stageLocalId,
3416
- label: s.label ?? stageLocalId,
3417
- order: typeof sd.order === "number" ? sd.order : 0,
3418
- semanticClass: sd.semanticClass ?? "open",
3419
- surfaceIds: Array.isArray(sd.surfaceIds) ? sd.surfaceIds : [],
3420
- resourceIds: Array.isArray(sd.resourceIds) ? sd.resourceIds : [],
3421
- color: typeof sd.color === "string" ? sd.color : void 0
3422
- };
3423
- }).sort((a, b) => a.order - b.order);
3424
- const pipeline = {
3425
- id: localId,
3426
- label: node.label ?? localId,
3427
- entityId: typeof data.entityId === "string" ? data.entityId : "",
3428
- stages,
3429
- ...typeof node.description === "string" ? { description: node.description } : {}
3430
- };
3431
- results.push({ systemPath, pipeline });
3432
- }
3433
- }
3434
- return results;
3435
- }
3436
- function getAllBuildTemplates(model) {
3437
- const results = [];
3438
- for (const { system } of listAllSystems(model)) {
3439
- const content = system.content ?? {};
3440
- for (const [localId, node] of Object.entries(content)) {
3441
- if (node.kind !== "schema" || node.type !== "template") continue;
3442
- const nd = node.data ?? {};
3443
- const steps = Object.entries(content).filter(([, s]) => s.kind === "schema" && s.type === "template-step" && s.parentContentId === localId).map(([stepLocalId, s]) => {
3444
- const sd = s.data ?? {};
3445
- return {
3446
- id: stepLocalId,
3447
- label: s.label ?? stepLocalId,
3448
- ...s.description ? { description: s.description } : {},
3449
- // Pass through all data fields — template-step payload is richer than Pipeline;
3450
- // Bridge readers preserve the historical shape for round-trip fidelity.
3451
- ...sd
3452
- };
3453
- });
3454
- results.push({
3455
- id: localId,
3456
- label: node.label ?? localId,
3457
- ...node.description ? { description: node.description } : {},
3458
- ...typeof nd.color === "string" ? { color: nd.color } : {},
3459
- // BuildTemplate requires steps array — cast via spread; Wave 4 adds type-safe assertions.
3460
- steps
3461
- });
3462
- }
3463
- }
3464
- return results;
3465
- }
3466
- function getAllProspectingStages(model, kind) {
3467
- const results = [];
3468
- for (const { system } of listAllSystems(model)) {
3469
- const content = system.content ?? {};
3470
- for (const [localId, node] of Object.entries(content)) {
3471
- if (node.kind !== "schema" || node.type !== "stage") continue;
3472
- const sd = node.data ?? {};
3473
- if (sd.entityKind !== kind) continue;
3474
- results.push({
3475
- id: localId,
3476
- label: node.label ?? localId,
3477
- order: typeof sd.order === "number" ? sd.order : 0,
3478
- ...typeof sd.color === "string" ? { color: sd.color } : {},
3479
- ...node.description ? { description: node.description } : {}
3480
- });
3481
- }
3482
- }
3483
- return results.sort((a, b) => a.order - b.order);
3484
- }
3485
- function getAllProjectStatuses(model, appliesTo) {
3486
- const results = [];
3487
- for (const { system } of listAllSystems(model)) {
3488
- const content = system.content ?? {};
3489
- for (const [flowLocalId, flowNode] of Object.entries(content)) {
3490
- if (flowNode.kind !== "schema" || flowNode.type !== "status-flow") continue;
3491
- const fd = flowNode.data ?? {};
3492
- if (fd.appliesTo !== appliesTo) continue;
3493
- for (const [statusLocalId, statusNode] of Object.entries(content)) {
3494
- if (statusNode.kind !== "schema" || statusNode.type !== "status") continue;
3495
- if (statusNode.parentContentId !== flowLocalId) continue;
3496
- const sd = statusNode.data ?? {};
3497
- results.push({
3498
- id: statusLocalId,
3499
- label: statusNode.label ?? statusLocalId,
3500
- order: typeof sd.order === "number" ? sd.order : 0,
3501
- ...typeof sd.color === "string" ? { color: sd.color } : {},
3502
- ...statusNode.description ? { description: statusNode.description } : {}
3503
- });
3504
- }
3505
- }
3506
- }
3507
- return results.sort((a, b) => a.order - b.order);
3508
- }
3509
-
3510
2794
  // ../core/src/organization-model/graph/build.ts
3511
2795
  function nodeId(kind, sourceId) {
3512
2796
  return kind === "organization" ? "organization-model" : `${kind}:${sourceId ?? ""}`;
@@ -3979,7 +3263,7 @@ function buildOrganizationGraph(input) {
3979
3263
  }
3980
3264
  if (entity.stateCatalogId === "lead-gen.company" || entity.stateCatalogId === "lead-gen.contact") {
3981
3265
  const leadGenEntity = entity.stateCatalogId === "lead-gen.company" ? "company" : "contact";
3982
- for (const stage of Object.values(LEAD_GEN_STAGE_CATALOG).sort(
3266
+ for (const stage of Object.values(getLeadGenStageCatalog(organizationModel)).sort(
3983
3267
  (a, b) => a.order - b.order || a.key.localeCompare(b.key)
3984
3268
  )) {
3985
3269
  if (stage.entity !== leadGenEntity && !(stage.additionalEntities ?? []).includes(leadGenEntity)) continue;
@@ -4283,49 +3567,6 @@ function buildOrganizationGraph(input) {
4283
3567
  targetId: id
4284
3568
  });
4285
3569
  }
4286
- for (const { path, system } of listAllSystems(organizationModel).sort((a, b) => a.path.localeCompare(b.path))) {
4287
- const contentMap = system.content ?? {};
4288
- const systemSpineId = nodeId("system", path);
4289
- for (const [localId, contentNode] of Object.entries(contentMap).sort(([a], [b]) => a.localeCompare(b))) {
4290
- const contentNodeGraphId = `content-node:${path}:${localId}`;
4291
- pushUniqueNode(nodes, nodeIds, {
4292
- id: contentNodeGraphId,
4293
- kind: "content-node",
4294
- label: contentNode.label,
4295
- sourceId: `${path}:${localId}`,
4296
- description: contentNode.description
4297
- // Spread contentKind and contentType into attributes; the node schema
4298
- // does not have custom attribute slots, so we encode them in the label
4299
- // suffix for now. The actual kind/type are recoverable from sourceId +
4300
- // the registry lookup by consumers.
4301
- });
4302
- pushUniqueEdge(edges, edgeIds, {
4303
- id: edgeId("contains", systemSpineId, contentNodeGraphId, "system-content"),
4304
- kind: "contains",
4305
- sourceId: systemSpineId,
4306
- targetId: contentNodeGraphId
4307
- });
4308
- if (contentNode.parentContentId) {
4309
- const parentContentNodeGraphId = `content-node:${path}:${contentNode.parentContentId}`;
4310
- pushUniqueEdge(edges, edgeIds, {
4311
- id: edgeId("contains", parentContentNodeGraphId, contentNodeGraphId, "content-parent"),
4312
- kind: "contains",
4313
- sourceId: parentContentNodeGraphId,
4314
- targetId: contentNodeGraphId
4315
- });
4316
- }
4317
- if (contentNode.kind === "schema" && contentNode.type === "pipeline" && contentNode.data && typeof contentNode.data["entityId"] === "string") {
4318
- const targetEntityId = nodeId("entity", contentNode.data["entityId"]);
4319
- pushUniqueEdge(edges, edgeIds, {
4320
- id: edgeId("references", contentNodeGraphId, targetEntityId, "pipeline-entity"),
4321
- kind: "references",
4322
- sourceId: contentNodeGraphId,
4323
- targetId: targetEntityId,
4324
- label: "applies to entity"
4325
- });
4326
- }
4327
- }
4328
- }
4329
3570
  for (const template of getAllBuildTemplates(organizationModel).sort((a, b) => a.id.localeCompare(b.id))) {
4330
3571
  const steps = template.steps;
4331
3572
  const stepById = new Map(steps.map((s) => [s.id, s]));
@@ -4409,865 +3650,460 @@ function buildOrganizationGraph(input) {
4409
3650
  return OrganizationGraphSchema.parse(graph);
4410
3651
  }
4411
3652
 
4412
- // ../core/src/organization-model/defaults.ts
4413
- var DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE = {};
4414
- var DEFAULT_ORGANIZATION_MODEL_ENTITIES2 = DEFAULT_ORGANIZATION_MODEL_ENTITIES;
4415
- var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
4416
- sidebar: {
4417
- primary: {
4418
- dashboard: {
4419
- type: "surface",
4420
- label: "Dashboard",
4421
- path: "/",
4422
- surfaceType: "dashboard",
4423
- icon: "dashboard",
4424
- order: 10,
4425
- targets: { systems: ["dashboard"] }
4426
- },
4427
- business: {
4428
- type: "group",
4429
- label: "Business",
4430
- icon: "briefcase",
4431
- order: 20,
4432
- children: {
4433
- sales: {
4434
- type: "surface",
4435
- label: "Sales",
4436
- path: "/sales",
4437
- surfaceType: "page",
4438
- icon: "sales",
4439
- order: 10,
4440
- targets: { systems: ["sales"] }
4441
- },
4442
- clients: {
4443
- type: "surface",
4444
- label: "Clients",
4445
- path: "/clients",
4446
- surfaceType: "list",
4447
- icon: "projects",
4448
- order: 20,
4449
- targets: { systems: ["clients"] }
4450
- },
4451
- projects: {
4452
- type: "surface",
4453
- label: "Projects",
4454
- path: "/projects",
4455
- surfaceType: "page",
4456
- icon: "projects",
4457
- order: 30,
4458
- targets: { systems: ["projects"] }
4459
- }
4460
- }
4461
- },
4462
- operations: {
4463
- type: "group",
4464
- label: "Operations",
4465
- icon: "operations",
4466
- order: 30,
4467
- children: {
4468
- "operations-overview": {
4469
- type: "surface",
4470
- label: "Overview",
4471
- path: "/operations",
4472
- surfaceType: "page",
4473
- order: 10,
4474
- targets: { systems: ["operations.overview"] }
4475
- },
4476
- "operations-systems": {
4477
- type: "surface",
4478
- label: "Systems",
4479
- path: "/operations/systems",
4480
- surfaceType: "page",
4481
- order: 20,
4482
- targets: { systems: ["operations"] }
4483
- },
4484
- "operations-resources": {
4485
- type: "surface",
4486
- label: "Resources",
4487
- path: "/operations/resources",
4488
- surfaceType: "list",
4489
- order: 30,
4490
- targets: { systems: ["operations.resources"] }
4491
- },
4492
- "operations-command-queue": {
4493
- type: "surface",
4494
- label: "Command Queue",
4495
- path: "/operations/command-queue",
4496
- surfaceType: "list",
4497
- order: 40,
4498
- targets: { systems: ["operations.command-queue"] }
4499
- },
4500
- "operations-task-scheduler": {
4501
- type: "surface",
4502
- label: "Task Scheduler",
4503
- path: "/operations/task-scheduler",
4504
- surfaceType: "list",
4505
- order: 50,
4506
- targets: { systems: ["operations.task-scheduler"] }
4507
- }
4508
- }
4509
- },
4510
- monitoring: {
4511
- type: "group",
4512
- label: "Monitoring",
4513
- icon: "monitoring",
4514
- order: 40,
4515
- children: {
4516
- "monitoring-overview": {
4517
- type: "surface",
4518
- label: "Overview",
4519
- path: "/monitoring",
4520
- surfaceType: "page",
4521
- order: 10,
4522
- targets: { systems: ["monitoring"] }
4523
- },
4524
- "monitoring-calendar": {
4525
- type: "surface",
4526
- label: "Calendar",
4527
- path: "/monitoring/calendar",
4528
- surfaceType: "page",
4529
- order: 20,
4530
- targets: { systems: ["monitoring.calendar"] }
4531
- },
4532
- "monitoring-activity-log": {
4533
- type: "surface",
4534
- label: "Activity Log",
4535
- path: "/monitoring/activity-log",
4536
- surfaceType: "list",
4537
- order: 30,
4538
- targets: { systems: ["monitoring.activity-log"] }
4539
- },
4540
- "monitoring-execution-logs": {
4541
- type: "surface",
4542
- label: "Execution Logs",
4543
- path: "/monitoring/execution-logs",
4544
- surfaceType: "list",
4545
- order: 40,
4546
- targets: { systems: ["monitoring.execution-logs"] }
4547
- },
4548
- "monitoring-execution-health": {
4549
- type: "surface",
4550
- label: "Execution Health",
4551
- path: "/monitoring/execution-health",
4552
- surfaceType: "dashboard",
4553
- order: 50,
4554
- targets: { systems: ["monitoring.execution-health"] }
4555
- },
4556
- "monitoring-notifications": {
4557
- type: "surface",
4558
- label: "Notifications",
4559
- path: "/monitoring/notifications",
4560
- surfaceType: "list",
4561
- order: 60,
4562
- targets: { systems: ["monitoring.notifications"] }
4563
- },
4564
- "monitoring-requests": {
4565
- type: "surface",
4566
- label: "Requests",
4567
- path: "/monitoring/requests",
4568
- surfaceType: "list",
4569
- order: 70,
4570
- targets: { systems: ["monitoring.submitted-requests"] }
4571
- }
4572
- }
3653
+ // ../core/src/organization-model/surface-projection.ts
3654
+ function collectSystemsById(model) {
3655
+ const systemsById = /* @__PURE__ */ new Map();
3656
+ for (const { path, system } of listAllSystems(model)) {
3657
+ systemsById.set(path, system);
3658
+ systemsById.set(system.id, system);
3659
+ }
3660
+ return systemsById;
3661
+ }
3662
+ function getSystemWithAncestors(systemsById, systemId) {
3663
+ const systems = [];
3664
+ let current = systemsById.get(systemId);
3665
+ while (current !== void 0) {
3666
+ systems.unshift(current);
3667
+ current = current.parentSystemId ? systemsById.get(current.parentSystemId) : void 0;
3668
+ }
3669
+ return systems;
3670
+ }
3671
+ function hasInheritedFlag(systemsById, systemIds, flag) {
3672
+ return systemIds.some(
3673
+ (systemId) => getSystemWithAncestors(systemsById, systemId).some((system) => system[flag] === true)
3674
+ );
3675
+ }
3676
+ function isLifecycleEnabled2(system) {
3677
+ if (system.enabled === false) return false;
3678
+ return system.lifecycle !== "deprecated" && system.lifecycle !== "archived";
3679
+ }
3680
+ function isLifecycleDevOnly(system) {
3681
+ return system.devOnly === true || system.lifecycle === "beta";
3682
+ }
3683
+ function isSystemEnabled(systemsById, systemId) {
3684
+ const systemLineage = getSystemWithAncestors(systemsById, systemId);
3685
+ return systemLineage.length > 0 && systemLineage.every(isLifecycleEnabled2);
3686
+ }
3687
+ function unique(values) {
3688
+ return [...new Set(values)];
3689
+ }
3690
+ function collectSidebarSurfaces(nodes, schemaPath, surfaces = []) {
3691
+ getSortedSidebarEntries(nodes).forEach(([id, node]) => {
3692
+ const nodePath = [...schemaPath, id];
3693
+ if (node.type === "group") {
3694
+ collectSidebarSurfaces(node.children, [...nodePath, "children"], surfaces);
3695
+ return;
3696
+ }
3697
+ surfaces.push({ id, surface: node, path: nodePath });
3698
+ });
3699
+ return surfaces;
3700
+ }
3701
+ function getSidebarSurfaces(model) {
3702
+ return [
3703
+ ...collectSidebarSurfaces(model.navigation.sidebar.primary, ["navigation", "sidebar", "primary"]),
3704
+ ...collectSidebarSurfaces(model.navigation.sidebar.bottom, ["navigation", "sidebar", "bottom"])
3705
+ ];
3706
+ }
3707
+ function projectOrganizationSurfaces(model) {
3708
+ const systemsById = collectSystemsById(model);
3709
+ return getSidebarSurfaces(model).map(({ id, surface }) => {
3710
+ const targets = surface.targets ?? {};
3711
+ const systemIds = unique((targets.systems ?? []).filter((systemId) => systemsById.has(systemId)));
3712
+ const enabled = systemIds.every((candidate) => isSystemEnabled(systemsById, candidate));
3713
+ const devOnly = surface.devOnly === true || hasInheritedFlag(systemsById, systemIds, "devOnly") || systemIds.some((candidate) => getSystemWithAncestors(systemsById, candidate).some(isLifecycleDevOnly));
3714
+ const requiresAdmin = hasInheritedFlag(systemsById, systemIds, "requiresAdmin");
3715
+ return {
3716
+ id,
3717
+ label: surface.label,
3718
+ path: surface.path,
3719
+ surfaceType: surface.surfaceType,
3720
+ ...surface.description !== void 0 ? { description: surface.description } : {},
3721
+ ...surface.icon !== void 0 ? { icon: surface.icon } : {},
3722
+ ...surface.order !== void 0 ? { order: surface.order } : {},
3723
+ systemIds,
3724
+ entityIds: [...targets.entities ?? []],
3725
+ resourceIds: [...targets.resources ?? []],
3726
+ actionIds: [...targets.actions ?? []],
3727
+ enabled,
3728
+ ...devOnly ? { devOnly } : {},
3729
+ ...surface.requiresAdmin === true || requiresAdmin ? { requiresAdmin: true } : {}
3730
+ };
3731
+ });
3732
+ }
3733
+ var SalesStageSemanticClassSchema = z.enum(["open", "active", "nurturing", "closed_won", "closed_lost"]);
3734
+ var SalesStageSchema = DisplayMetadataSchema.extend({
3735
+ id: ModelIdSchema,
3736
+ order: z.number().int().min(0),
3737
+ semanticClass: SalesStageSemanticClassSchema,
3738
+ surfaceIds: ReferenceIdsSchema,
3739
+ resourceIds: ReferenceIdsSchema
3740
+ });
3741
+ z.object({
3742
+ id: ModelIdSchema,
3743
+ label: z.string().trim().min(1).max(120),
3744
+ description: DescriptionSchema.optional(),
3745
+ entityId: ModelIdSchema,
3746
+ stages: z.array(SalesStageSchema).min(1)
3747
+ });
3748
+ function findPipeline(definitions, pipelineKey) {
3749
+ return definitions.find((def) => def.pipelineKey === pipelineKey);
3750
+ }
3751
+ DisplayMetadataSchema.extend({
3752
+ id: ModelIdSchema,
3753
+ order: z.number().min(0)
3754
+ });
3755
+ var RecordColumnConfigSchema = z.object({
3756
+ key: ModelIdSchema,
3757
+ label: z.string().trim().min(1).max(120),
3758
+ path: z.string().trim().min(1).max(500),
3759
+ width: z.union([z.number().positive(), z.string().trim().min(1).max(100)]).optional(),
3760
+ renderType: z.enum(["text", "badge", "datetime", "count", "json"]).optional(),
3761
+ badgeColor: z.string().trim().min(1).max(40).optional()
3762
+ });
3763
+ var RecordColumnsConfigSchema = z.object({
3764
+ company: z.array(RecordColumnConfigSchema).optional(),
3765
+ contact: z.array(RecordColumnConfigSchema).optional()
3766
+ }).refine((columns) => Boolean(columns.company?.length || columns.contact?.length), {
3767
+ message: "recordColumns must include at least one entity column set"
3768
+ });
3769
+ var CredentialRequirementSchema = z.object({
3770
+ key: ModelIdSchema,
3771
+ provider: ModelIdSchema,
3772
+ credentialType: z.enum(["api-key", "api-key-secret", "oauth", "webhook-secret"]),
3773
+ label: z.string().trim().min(1).max(120),
3774
+ required: z.boolean(),
3775
+ selectionMode: z.enum(["single", "multiple"]).optional(),
3776
+ inputPath: z.string().trim().min(1).max(500),
3777
+ verifyOnRun: z.boolean().optional()
3778
+ });
3779
+ var ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
3780
+ id: ModelIdSchema,
3781
+ primaryEntity: z.enum(["company", "contact"]),
3782
+ outputs: z.array(z.enum(["company", "contact", "export"])).min(1),
3783
+ stageKey: ModelIdSchema,
3784
+ recordEntity: z.enum(["company", "contact"]).optional(),
3785
+ recordsStageKey: ModelIdSchema.optional(),
3786
+ recordSourceStageKey: ModelIdSchema.optional(),
3787
+ dependsOn: z.array(ModelIdSchema).optional(),
3788
+ dependencyMode: z.literal("per-record-eligibility"),
3789
+ actionKey: ModelIdSchema,
3790
+ defaultBatchSize: z.number().int().positive(),
3791
+ maxBatchSize: z.number().int().positive(),
3792
+ recordColumns: RecordColumnsConfigSchema.optional(),
3793
+ credentialRequirements: z.array(CredentialRequirementSchema).optional()
3794
+ }).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
3795
+ message: "defaultBatchSize must be less than or equal to maxBatchSize",
3796
+ path: ["defaultBatchSize"]
3797
+ });
3798
+ DisplayMetadataSchema.extend({
3799
+ id: ModelIdSchema,
3800
+ steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
3801
+ });
3802
+ var DTC_RECORD_COLUMNS = {
3803
+ populated: {
3804
+ company: [
3805
+ { key: "name", label: "Company", path: "company.name" },
3806
+ { key: "domain", label: "Domain", path: "company.domain" },
3807
+ { key: "employee-count", label: "Employees", path: "company.numEmployees", renderType: "count" },
3808
+ { key: "apollo-industry", label: "Apollo industry", path: "company.category" },
3809
+ { key: "location", label: "Location", path: "company.locationState" }
3810
+ ]
3811
+ },
3812
+ crawled: {
3813
+ company: [
3814
+ { key: "name", label: "Company", path: "company.name" },
3815
+ { key: "domain", label: "Domain", path: "company.domain" },
3816
+ { key: "page-count", label: "Pages", path: "company.enrichmentData.websiteCrawl.pageCount", renderType: "count" },
3817
+ { key: "crawl-status", label: "Crawl status", path: "processingState.crawled.status", renderType: "badge" }
3818
+ ]
3819
+ },
3820
+ extracted: {
3821
+ company: [
3822
+ { key: "name", label: "Company", path: "company.name" },
3823
+ { key: "domain", label: "Domain", path: "company.domain" },
3824
+ { key: "description", label: "Description", path: "company.enrichmentData.websiteCrawl.companyDescription" },
3825
+ { key: "services", label: "Services", path: "company.enrichmentData.websiteCrawl.services", renderType: "json" },
3826
+ {
3827
+ key: "automation-gaps",
3828
+ label: "Automation gaps",
3829
+ path: "company.enrichmentData.websiteCrawl.automationGaps",
3830
+ renderType: "json"
4573
3831
  },
4574
- knowledge: {
4575
- type: "surface",
4576
- label: "Knowledge Base",
4577
- path: "/knowledge",
4578
- surfaceType: "page",
4579
- icon: "knowledge",
4580
- order: 50
3832
+ {
3833
+ key: "contact-count",
3834
+ label: "Contacts",
3835
+ path: "company.enrichmentData.websiteCrawl.emailCount",
3836
+ renderType: "count"
4581
3837
  }
4582
- },
4583
- bottom: {
4584
- settings: {
4585
- type: "group",
4586
- label: "Settings",
4587
- icon: "settings",
4588
- order: 10,
4589
- children: {
4590
- "settings-account": {
4591
- type: "surface",
4592
- label: "Account",
4593
- path: "/settings/account",
4594
- surfaceType: "settings",
4595
- order: 10,
4596
- targets: { systems: ["settings.account"] }
4597
- },
4598
- "settings-appearance": {
4599
- type: "surface",
4600
- label: "Appearance",
4601
- path: "/settings/appearance",
4602
- surfaceType: "settings",
4603
- order: 20,
4604
- targets: { systems: ["settings.appearance"] }
4605
- },
4606
- "settings-roles": {
4607
- type: "surface",
4608
- label: "My Roles",
4609
- path: "/settings/roles",
4610
- surfaceType: "settings",
4611
- order: 30,
4612
- targets: { systems: ["settings.roles"] }
4613
- },
4614
- "settings-organization": {
4615
- type: "surface",
4616
- label: "Organization",
4617
- path: "/settings/organization",
4618
- surfaceType: "settings",
4619
- order: 40,
4620
- targets: { systems: ["settings.organization"] }
4621
- },
4622
- "settings-credentials": {
4623
- type: "surface",
4624
- label: "Credentials",
4625
- path: "/settings/credentials",
4626
- surfaceType: "settings",
4627
- order: 50,
4628
- targets: { systems: ["settings.credentials"] }
4629
- },
4630
- "settings-api-keys": {
4631
- type: "surface",
4632
- label: "API Keys",
4633
- path: "/settings/api-keys",
4634
- surfaceType: "settings",
4635
- order: 60,
4636
- targets: { systems: ["settings.api-keys"] }
4637
- },
4638
- "settings-webhooks": {
4639
- type: "surface",
4640
- label: "Webhooks",
4641
- path: "/settings/webhooks",
4642
- surfaceType: "settings",
4643
- order: 70,
4644
- targets: { systems: ["settings.webhooks"] }
4645
- },
4646
- "settings-deployments": {
4647
- type: "surface",
4648
- label: "Deployments",
4649
- path: "/settings/deployments",
4650
- surfaceType: "settings",
4651
- order: 80,
4652
- targets: { systems: ["settings.deployments"] }
4653
- }
4654
- }
3838
+ ]
3839
+ },
3840
+ qualified: {
3841
+ company: [
3842
+ { key: "name", label: "Company", path: "company.name" },
3843
+ { key: "domain", label: "Domain", path: "company.domain" },
3844
+ { key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
3845
+ { key: "signals", label: "Signals", path: "company.qualificationSignals", renderType: "json" },
3846
+ {
3847
+ key: "disqualified-reason",
3848
+ label: "Disqualified reason",
3849
+ path: "processingState.qualified.data.disqualifiedReason"
3850
+ }
3851
+ ]
3852
+ },
3853
+ decisionMakers: {
3854
+ contact: [
3855
+ { key: "name", label: "Name", path: "contact.name" },
3856
+ { key: "title", label: "Title", path: "contact.title" },
3857
+ { key: "email", label: "Email", path: "contact.email" },
3858
+ { key: "linkedin", label: "LinkedIn", path: "contact.linkedinUrl" },
3859
+ {
3860
+ key: "priority-score",
3861
+ label: "Priority",
3862
+ path: "contact.enrichmentData.apollo.priorityScore",
3863
+ renderType: "badge"
3864
+ }
3865
+ ]
3866
+ },
3867
+ uploaded: {
3868
+ company: [
3869
+ { key: "name", label: "Company", path: "company.name" },
3870
+ { key: "domain", label: "Domain", path: "company.domain" },
3871
+ {
3872
+ key: "contacts",
3873
+ label: "Contacts",
3874
+ path: "company.enrichmentData.approvedLeadListExport.contacts",
3875
+ renderType: "json"
4655
3876
  },
4656
- admin: {
4657
- type: "group",
4658
- label: "Admin",
4659
- icon: "admin",
4660
- order: 20,
4661
- children: {
4662
- "admin-dashboard": {
4663
- type: "surface",
4664
- label: "Dashboard",
4665
- path: "/admin/dashboard",
4666
- surfaceType: "dashboard",
4667
- order: 10,
4668
- targets: { systems: ["admin"] },
4669
- requiresAdmin: true
4670
- },
4671
- "admin-system-health": {
4672
- type: "surface",
4673
- label: "System Health",
4674
- path: "/admin/system-health",
4675
- surfaceType: "dashboard",
4676
- order: 20,
4677
- targets: { systems: ["admin.system-health"] },
4678
- requiresAdmin: true
4679
- },
4680
- "admin-organizations": {
4681
- type: "surface",
4682
- label: "Organizations",
4683
- path: "/admin/organizations",
4684
- surfaceType: "list",
4685
- order: 30,
4686
- targets: { systems: ["admin.organizations"] },
4687
- requiresAdmin: true
4688
- },
4689
- "admin-users": {
4690
- type: "surface",
4691
- label: "Users",
4692
- path: "/admin/users",
4693
- surfaceType: "list",
4694
- order: 40,
4695
- targets: { systems: ["admin.users"] },
4696
- requiresAdmin: true
4697
- },
4698
- "admin-design-showcase": {
4699
- type: "surface",
4700
- label: "Design Showcase",
4701
- path: "/admin/design-showcase",
4702
- surfaceType: "page",
4703
- order: 50,
4704
- targets: { systems: ["admin.design-showcase"] },
4705
- requiresAdmin: true
4706
- },
4707
- "admin-debug": {
4708
- type: "surface",
4709
- label: "Debug",
4710
- path: "/admin/debug",
4711
- surfaceType: "page",
4712
- order: 60,
4713
- targets: { systems: ["admin.debug"] },
4714
- requiresAdmin: true
4715
- }
4716
- }
3877
+ { key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
3878
+ {
3879
+ key: "approval",
3880
+ label: "Approval",
3881
+ path: "company.enrichmentData.approvedLeadListExport.approvalStatus",
3882
+ renderType: "badge"
4717
3883
  }
4718
- }
3884
+ ]
4719
3885
  }
4720
3886
  };
4721
- var DEFAULT_ORGANIZATION_MODEL = {
4722
- version: 1,
4723
- domainMetadata: DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA,
4724
- branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
4725
- navigation: DEFAULT_ORGANIZATION_MODEL_NAVIGATION,
4726
- identity: DEFAULT_ORGANIZATION_MODEL_IDENTITY,
4727
- customers: DEFAULT_ORGANIZATION_MODEL_CUSTOMERS,
4728
- offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
4729
- roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
4730
- goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
4731
- systems: {
4732
- dashboard: {
4733
- id: "dashboard",
4734
- order: 10,
4735
- label: "Dashboard",
4736
- enabled: true,
4737
- lifecycle: "active",
4738
- path: "/",
4739
- icon: "dashboard"
4740
- },
4741
- platform: {
4742
- id: "platform",
4743
- order: 30,
4744
- label: "Platform",
4745
- description: "Elevasis platform architecture, capabilities, and implementation patterns",
4746
- enabled: true,
4747
- lifecycle: "active",
4748
- color: "cyan",
4749
- icon: "platform"
4750
- },
4751
- finance: {
4752
- id: "finance",
4753
- order: 40,
4754
- label: "Finance",
4755
- description: "Finance operations, accounting, billing, reconciliation, and tax prep",
4756
- enabled: true,
4757
- lifecycle: "active",
4758
- color: "green",
4759
- icon: "finance"
4760
- },
4761
- sales: {
4762
- id: "sales",
4763
- order: 60,
4764
- label: "Sales",
4765
- description: "Revenue workflows and customer acquisition",
4766
- enabled: true,
4767
- lifecycle: "active",
4768
- color: "blue",
4769
- icon: "sales",
4770
- path: "/sales"
4771
- },
4772
- "sales.crm": {
4773
- id: "sales.crm",
4774
- order: 70,
4775
- label: "CRM",
4776
- description: "Relationship pipeline and deal management",
4777
- enabled: true,
4778
- lifecycle: "active",
4779
- actions: Object.values(CRM_ACTION_ENTRIES).map((action) => ({
4780
- actionId: action.id,
4781
- intent: "exposes"
4782
- })),
4783
- color: "blue",
4784
- icon: "crm",
4785
- path: "/crm"
4786
- },
4787
- "sales.lead-gen": {
4788
- id: "sales.lead-gen",
4789
- order: 80,
4790
- label: "Lead Gen",
4791
- description: "Prospecting, qualification, and outreach preparation",
4792
- enabled: true,
4793
- lifecycle: "active",
4794
- actions: Object.values(LEAD_GEN_ACTION_ENTRIES).map((action) => ({
4795
- actionId: action.id,
4796
- intent: "exposes"
4797
- })),
4798
- color: "cyan",
4799
- icon: "lead-gen",
4800
- path: "/lead-gen"
4801
- },
4802
- projects: {
4803
- id: "projects",
4804
- order: 90,
4805
- label: "Projects",
4806
- description: "Projects, milestones, and client work execution",
4807
- enabled: true,
4808
- lifecycle: "active",
4809
- color: "orange",
4810
- icon: "projects",
4811
- path: "/projects"
4812
- },
4813
- clients: {
4814
- id: "clients",
4815
- order: 100,
4816
- label: "Clients",
4817
- description: "Client relationships, accounts, and business context",
4818
- enabled: true,
4819
- lifecycle: "active",
4820
- color: "orange",
4821
- icon: "projects",
4822
- path: "/clients"
4823
- },
4824
- operations: {
4825
- id: "operations",
4826
- order: 110,
4827
- label: "Operations",
4828
- description: "Operational resources, topology, and orchestration visibility",
4829
- enabled: true,
4830
- lifecycle: "active",
4831
- color: "violet",
4832
- icon: "operations"
4833
- },
4834
- "knowledge.command-view": {
4835
- id: "knowledge.command-view",
4836
- order: 120,
4837
- label: "Command View",
4838
- enabled: true,
4839
- lifecycle: "active",
4840
- path: "/knowledge/command-view",
4841
- devOnly: true
4842
- },
4843
- "operations.overview": {
4844
- id: "operations.overview",
4845
- order: 130,
4846
- label: "Overview",
4847
- enabled: true,
4848
- lifecycle: "active",
4849
- path: "/operations"
4850
- },
4851
- "operations.resources": {
4852
- id: "operations.resources",
4853
- order: 140,
4854
- label: "Resources",
4855
- enabled: true,
4856
- lifecycle: "active",
4857
- path: "/operations/resources"
4858
- },
4859
- "operations.command-queue": {
4860
- id: "operations.command-queue",
4861
- order: 150,
4862
- label: "Command Queue",
4863
- enabled: true,
4864
- lifecycle: "active",
4865
- path: "/operations/command-queue"
4866
- },
4867
- "operations.sessions": {
4868
- id: "operations.sessions",
4869
- order: 160,
4870
- label: "Sessions",
4871
- enabled: false,
4872
- lifecycle: "deprecated",
4873
- path: "/operations/sessions"
4874
- },
4875
- "operations.task-scheduler": {
4876
- id: "operations.task-scheduler",
4877
- order: 170,
4878
- label: "Task Scheduler",
4879
- enabled: true,
4880
- lifecycle: "active",
4881
- path: "/operations/task-scheduler"
4882
- },
4883
- monitoring: {
4884
- id: "monitoring",
4885
- order: 180,
4886
- label: "Monitoring",
4887
- enabled: true,
4888
- lifecycle: "active"
4889
- },
4890
- "monitoring.calendar": {
4891
- id: "monitoring.calendar",
4892
- order: 190,
4893
- label: "Calendar",
4894
- description: "Google Calendar events and agenda views",
4895
- enabled: true,
4896
- lifecycle: "active",
4897
- path: "/monitoring/calendar",
4898
- icon: "calendar"
4899
- },
4900
- "monitoring.activity-log": {
4901
- id: "monitoring.activity-log",
4902
- order: 200,
4903
- label: "Activity Log",
4904
- enabled: true,
4905
- lifecycle: "active",
4906
- path: "/monitoring/activity-log"
4907
- },
4908
- "monitoring.execution-logs": {
4909
- id: "monitoring.execution-logs",
4910
- order: 210,
4911
- label: "Execution Logs",
4912
- enabled: true,
4913
- lifecycle: "active",
4914
- path: "/monitoring/execution-logs"
4915
- },
4916
- "monitoring.execution-health": {
4917
- id: "monitoring.execution-health",
4918
- order: 220,
4919
- label: "Execution Health",
4920
- enabled: true,
4921
- lifecycle: "active",
4922
- path: "/monitoring/execution-health"
4923
- },
4924
- "monitoring.cost-analytics": {
4925
- id: "monitoring.cost-analytics",
4926
- order: 230,
4927
- label: "Cost Analytics",
4928
- enabled: false,
4929
- lifecycle: "deprecated",
4930
- path: "/monitoring/cost-analytics"
4931
- },
4932
- "monitoring.notifications": {
4933
- id: "monitoring.notifications",
4934
- order: 240,
4935
- label: "Notifications",
4936
- enabled: true,
4937
- lifecycle: "active",
4938
- path: "/monitoring/notifications"
4939
- },
4940
- "monitoring.submitted-requests": {
4941
- id: "monitoring.submitted-requests",
4942
- order: 250,
4943
- label: "Submitted Requests",
4944
- enabled: true,
4945
- lifecycle: "active",
4946
- path: "/monitoring/requests"
4947
- },
4948
- settings: {
4949
- id: "settings",
4950
- order: 260,
4951
- label: "Settings",
4952
- enabled: true,
4953
- lifecycle: "active",
4954
- icon: "settings"
4955
- },
4956
- "settings.account": {
4957
- id: "settings.account",
4958
- order: 270,
4959
- label: "Account",
4960
- enabled: true,
4961
- lifecycle: "active",
4962
- path: "/settings/account"
4963
- },
4964
- "settings.appearance": {
4965
- id: "settings.appearance",
4966
- order: 280,
4967
- label: "Appearance",
4968
- enabled: true,
4969
- lifecycle: "active",
4970
- path: "/settings/appearance"
4971
- },
4972
- "settings.roles": {
4973
- id: "settings.roles",
4974
- order: 290,
4975
- label: "My Roles",
4976
- enabled: true,
4977
- lifecycle: "active",
4978
- path: "/settings/roles"
4979
- },
4980
- "settings.organization": {
4981
- id: "settings.organization",
4982
- order: 300,
4983
- label: "Organization",
4984
- enabled: true,
4985
- lifecycle: "active",
4986
- path: "/settings/organization"
4987
- },
4988
- "settings.credentials": {
4989
- id: "settings.credentials",
4990
- order: 310,
4991
- label: "Credentials",
4992
- enabled: true,
4993
- lifecycle: "active",
4994
- path: "/settings/credentials"
4995
- },
4996
- "settings.api-keys": {
4997
- id: "settings.api-keys",
4998
- order: 320,
4999
- label: "API Keys",
5000
- enabled: true,
5001
- lifecycle: "active",
5002
- path: "/settings/api-keys"
5003
- },
5004
- "settings.webhooks": {
5005
- id: "settings.webhooks",
5006
- order: 330,
5007
- label: "Webhooks",
5008
- enabled: true,
5009
- lifecycle: "active",
5010
- path: "/settings/webhooks"
5011
- },
5012
- "settings.deployments": {
5013
- id: "settings.deployments",
5014
- order: 340,
5015
- label: "Deployments",
5016
- enabled: true,
5017
- lifecycle: "active",
5018
- path: "/settings/deployments"
5019
- },
5020
- admin: {
5021
- id: "admin",
5022
- order: 350,
5023
- label: "Admin",
5024
- enabled: true,
5025
- lifecycle: "active",
5026
- path: "/admin",
5027
- icon: "admin",
5028
- requiresAdmin: true
3887
+ var PROSPECTING_STEPS = {
3888
+ localServices: {
3889
+ sourceCompanies: {
3890
+ id: "source-companies",
3891
+ label: "Companies found",
3892
+ primaryEntity: "company",
3893
+ outputs: ["company"],
3894
+ stageKey: "populated",
3895
+ dependencyMode: "per-record-eligibility",
3896
+ actionKey: "lead-gen.company.source",
3897
+ defaultBatchSize: 100,
3898
+ maxBatchSize: 250
5029
3899
  },
5030
- "admin.system-health": {
5031
- id: "admin.system-health",
5032
- order: 360,
5033
- label: "System Health",
5034
- enabled: true,
5035
- lifecycle: "active",
5036
- path: "/admin/system-health"
3900
+ analyzeWebsites: {
3901
+ id: "analyze-websites",
3902
+ label: "Websites analyzed",
3903
+ primaryEntity: "company",
3904
+ outputs: ["company"],
3905
+ stageKey: "extracted",
3906
+ dependsOn: ["source-companies"],
3907
+ dependencyMode: "per-record-eligibility",
3908
+ actionKey: "lead-gen.company.website-extract",
3909
+ defaultBatchSize: 50,
3910
+ maxBatchSize: 100
5037
3911
  },
5038
- "admin.organizations": {
5039
- id: "admin.organizations",
5040
- order: 370,
5041
- label: "Organizations",
5042
- enabled: true,
5043
- lifecycle: "active",
5044
- path: "/admin/organizations"
3912
+ qualifyCompanies: {
3913
+ id: "qualify-companies",
3914
+ label: "Companies qualified",
3915
+ primaryEntity: "company",
3916
+ outputs: ["company"],
3917
+ stageKey: "qualified",
3918
+ dependsOn: ["analyze-websites"],
3919
+ dependencyMode: "per-record-eligibility",
3920
+ actionKey: "lead-gen.company.qualify",
3921
+ defaultBatchSize: 100,
3922
+ maxBatchSize: 250
5045
3923
  },
5046
- "admin.users": {
5047
- id: "admin.users",
5048
- order: 380,
5049
- label: "Users",
5050
- enabled: true,
5051
- lifecycle: "active",
5052
- path: "/admin/users"
3924
+ findContacts: {
3925
+ id: "find-contacts",
3926
+ label: "Decision-makers found",
3927
+ primaryEntity: "contact",
3928
+ outputs: ["contact"],
3929
+ stageKey: "discovered",
3930
+ dependsOn: ["qualify-companies"],
3931
+ dependencyMode: "per-record-eligibility",
3932
+ actionKey: "lead-gen.contact.discover",
3933
+ defaultBatchSize: 50,
3934
+ maxBatchSize: 100
5053
3935
  },
5054
- "admin.design-showcase": {
5055
- id: "admin.design-showcase",
5056
- order: 390,
5057
- label: "Design Showcase",
5058
- enabled: true,
5059
- lifecycle: "active",
5060
- path: "/admin/design-showcase"
3936
+ verifyEmails: {
3937
+ id: "verify-emails",
3938
+ label: "Emails verified",
3939
+ primaryEntity: "contact",
3940
+ outputs: ["contact"],
3941
+ stageKey: "verified",
3942
+ dependsOn: ["find-contacts"],
3943
+ dependencyMode: "per-record-eligibility",
3944
+ actionKey: "lead-gen.contact.verify-email",
3945
+ defaultBatchSize: 100,
3946
+ maxBatchSize: 500
5061
3947
  },
5062
- "admin.debug": {
5063
- id: "admin.debug",
5064
- order: 400,
5065
- label: "Debug",
5066
- enabled: true,
5067
- lifecycle: "active",
5068
- path: "/admin/debug"
3948
+ personalize: {
3949
+ id: "personalize",
3950
+ label: "Personalize",
3951
+ primaryEntity: "contact",
3952
+ outputs: ["contact"],
3953
+ stageKey: "personalized",
3954
+ dependsOn: ["verify-emails"],
3955
+ dependencyMode: "per-record-eligibility",
3956
+ actionKey: "lead-gen.contact.personalize",
3957
+ defaultBatchSize: 25,
3958
+ maxBatchSize: 100
5069
3959
  },
5070
- archive: {
5071
- id: "archive",
5072
- order: 410,
5073
- label: "Archive",
5074
- enabled: true,
5075
- lifecycle: "active",
5076
- path: "/archive",
5077
- icon: "archive",
5078
- devOnly: true
3960
+ review: {
3961
+ id: "review",
3962
+ label: "Reviewed and exported",
3963
+ primaryEntity: "contact",
3964
+ outputs: ["export"],
3965
+ stageKey: "uploaded",
3966
+ dependsOn: ["personalize"],
3967
+ dependencyMode: "per-record-eligibility",
3968
+ actionKey: "lead-gen.review.outreach-ready",
3969
+ defaultBatchSize: 25,
3970
+ maxBatchSize: 100
3971
+ }
3972
+ },
3973
+ dtcApolloClickup: {
3974
+ importApolloSearch: {
3975
+ id: "import-apollo-search",
3976
+ label: "Companies found",
3977
+ description: "Pull companies and seed contact data from a predefined Apollo search or list.",
3978
+ primaryEntity: "company",
3979
+ outputs: ["company", "contact"],
3980
+ stageKey: "populated",
3981
+ dependencyMode: "per-record-eligibility",
3982
+ actionKey: "lead-gen.company.apollo-import",
3983
+ defaultBatchSize: 250,
3984
+ maxBatchSize: 1e3,
3985
+ recordColumns: DTC_RECORD_COLUMNS.populated,
3986
+ credentialRequirements: [
3987
+ {
3988
+ key: "apollo",
3989
+ provider: "apollo",
3990
+ credentialType: "api-key-secret",
3991
+ label: "Apollo API key",
3992
+ required: true,
3993
+ selectionMode: "single",
3994
+ inputPath: "credential"
3995
+ }
3996
+ ]
5079
3997
  },
5080
- "archive.agent-chat": {
5081
- id: "archive.agent-chat",
5082
- order: 420,
5083
- label: "Agent Chat",
5084
- enabled: true,
5085
- lifecycle: "active",
5086
- path: "/archive/agent-chat"
3998
+ apifyCrawl: {
3999
+ id: "apify-crawl",
4000
+ label: "Websites crawled",
4001
+ description: "Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis. Overwrites the synthetic seed Apollo Import wrote with real page content.",
4002
+ primaryEntity: "company",
4003
+ outputs: ["company"],
4004
+ stageKey: "crawled",
4005
+ dependsOn: ["import-apollo-search"],
4006
+ dependencyMode: "per-record-eligibility",
4007
+ actionKey: "lead-gen.company.apify-crawl",
4008
+ defaultBatchSize: 50,
4009
+ maxBatchSize: 100,
4010
+ recordColumns: DTC_RECORD_COLUMNS.crawled,
4011
+ credentialRequirements: [
4012
+ {
4013
+ key: "apify",
4014
+ provider: "apify",
4015
+ credentialType: "api-key-secret",
4016
+ label: "Apify API token",
4017
+ required: true,
4018
+ selectionMode: "single",
4019
+ inputPath: "credential",
4020
+ verifyOnRun: true
4021
+ }
4022
+ ]
5087
4023
  },
5088
- "archive.execution-runner": {
5089
- id: "archive.execution-runner",
5090
- order: 430,
5091
- label: "Execution Runner",
5092
- enabled: true,
5093
- lifecycle: "active",
5094
- path: "/archive/execution-runner"
4024
+ analyzeWebsites: {
4025
+ id: "analyze-websites",
4026
+ label: "Websites analyzed",
4027
+ description: "Extract subscription, product, retention, and tech-stack signals from each brand website.",
4028
+ primaryEntity: "company",
4029
+ outputs: ["company"],
4030
+ stageKey: "extracted",
4031
+ dependsOn: ["apify-crawl"],
4032
+ dependencyMode: "per-record-eligibility",
4033
+ actionKey: "lead-gen.company.website-extract",
4034
+ defaultBatchSize: 50,
4035
+ maxBatchSize: 100,
4036
+ recordColumns: DTC_RECORD_COLUMNS.extracted
5095
4037
  },
5096
- seo: {
5097
- id: "seo",
5098
- order: 440,
5099
- label: "SEO",
5100
- enabled: false,
5101
- lifecycle: "deprecated",
5102
- path: "/seo"
4038
+ scoreDtcFit: {
4039
+ id: "score-dtc-fit",
4040
+ label: "Companies qualified",
4041
+ description: "Classify subscription potential, consumable-product fit, retention maturity, and disqualifiers.",
4042
+ primaryEntity: "company",
4043
+ outputs: ["company"],
4044
+ stageKey: "qualified",
4045
+ dependsOn: ["analyze-websites"],
4046
+ dependencyMode: "per-record-eligibility",
4047
+ actionKey: "lead-gen.company.dtc-subscription-qualify",
4048
+ defaultBatchSize: 100,
4049
+ maxBatchSize: 250,
4050
+ recordColumns: DTC_RECORD_COLUMNS.qualified
5103
4051
  },
5104
- knowledge: {
5105
- id: "knowledge",
5106
- order: 450,
5107
- label: "Knowledge",
5108
- description: "Operational knowledge, playbooks, and strategy docs",
5109
- enabled: true,
5110
- lifecycle: "active",
5111
- color: "teal",
5112
- icon: "knowledge"
4052
+ enrichDecisionMakers: {
4053
+ id: "enrich-decision-makers",
4054
+ label: "Decision-makers found",
4055
+ description: "Use Apollo to find qualified contacts at qualified companies - founders, retention leads, lifecycle leads, and marketing owners.",
4056
+ primaryEntity: "company",
4057
+ outputs: ["contact"],
4058
+ stageKey: "decision-makers-enriched",
4059
+ recordEntity: "contact",
4060
+ dependsOn: ["score-dtc-fit"],
4061
+ dependencyMode: "per-record-eligibility",
4062
+ actionKey: "lead-gen.contact.apollo-decision-maker-enrich",
4063
+ defaultBatchSize: 100,
4064
+ maxBatchSize: 250,
4065
+ recordColumns: DTC_RECORD_COLUMNS.decisionMakers,
4066
+ credentialRequirements: [
4067
+ {
4068
+ key: "apollo",
4069
+ provider: "apollo",
4070
+ credentialType: "api-key-secret",
4071
+ label: "Apollo API key",
4072
+ required: true,
4073
+ selectionMode: "single",
4074
+ inputPath: "credential"
4075
+ }
4076
+ ]
5113
4077
  },
5114
- "knowledge.base": {
5115
- id: "knowledge.base",
5116
- order: 460,
5117
- label: "Knowledge Base",
5118
- enabled: true,
5119
- lifecycle: "active",
5120
- path: "/knowledge"
5121
- }
5122
- },
5123
- ontology: DEFAULT_ONTOLOGY_SCOPE,
5124
- resources: DEFAULT_ORGANIZATION_MODEL_RESOURCES,
5125
- topology: DEFAULT_ORGANIZATION_MODEL_TOPOLOGY,
5126
- actions: DEFAULT_ORGANIZATION_MODEL_ACTIONS,
5127
- entities: DEFAULT_ORGANIZATION_MODEL_ENTITIES2,
5128
- policies: DEFAULT_ORGANIZATION_MODEL_POLICIES,
5129
- // Phase 4 (D1): statuses top-level field removed; bridge status mirrors may
5130
- // still project from System.content, but primary authoring belongs in ontology.
5131
- knowledge: DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE
5132
- };
5133
-
5134
- // ../core/src/organization-model/resolve.ts
5135
- function isPlainObject(value) {
5136
- return typeof value === "object" && value !== null && !Array.isArray(value);
5137
- }
5138
- function collectNestedSystemPaths(systems, prefix = "") {
5139
- const paths = /* @__PURE__ */ new Set();
5140
- for (const [key, value] of Object.entries(systems)) {
5141
- if (!isPlainObject(value)) continue;
5142
- const path = prefix ? `${prefix}.${key}` : key;
5143
- for (const childKey of ["systems", "subsystems"]) {
5144
- const childSystems = value[childKey];
5145
- if (!isPlainObject(childSystems)) continue;
5146
- for (const childPath of collectNestedSystemPaths(childSystems, path)) {
5147
- paths.add(childPath);
5148
- }
5149
- }
5150
- if (prefix !== "") {
5151
- paths.add(path);
5152
- }
5153
- }
5154
- return paths;
5155
- }
5156
- function pruneFlatSystemDescendantCollisions(base, override) {
5157
- const result = { ...base };
5158
- for (const nestedPath of collectNestedSystemPaths(override)) {
5159
- delete result[nestedPath];
5160
- }
5161
- return result;
5162
- }
5163
- function deepMerge(base, override) {
5164
- if (override === void 0) {
5165
- return base;
5166
- }
5167
- if (Array.isArray(base)) {
5168
- return override ?? base;
5169
- }
5170
- if (!isPlainObject(base) || !isPlainObject(override)) {
5171
- return override ?? base;
5172
- }
5173
- const result = { ...base };
5174
- for (const [key, value] of Object.entries(override)) {
5175
- if (value === void 0) continue;
5176
- const existing = result[key];
5177
- if (key === "systems" && isPlainObject(existing) && isPlainObject(value)) {
5178
- result[key] = deepMerge(pruneFlatSystemDescendantCollisions(existing, value), value);
5179
- continue;
4078
+ reviewAndExport: {
4079
+ id: "review-and-export",
4080
+ label: "Reviewed and exported",
4081
+ description: "Operator QC approves or rejects qualified companies, then approved records are exported as a lead list with unverified emails.",
4082
+ primaryEntity: "company",
4083
+ outputs: ["export"],
4084
+ stageKey: "uploaded",
4085
+ recordsStageKey: "uploaded",
4086
+ recordSourceStageKey: "qualified",
4087
+ dependsOn: ["enrich-decision-makers"],
4088
+ dependencyMode: "per-record-eligibility",
4089
+ actionKey: "lead-gen.export.list",
4090
+ defaultBatchSize: 100,
4091
+ maxBatchSize: 250,
4092
+ recordColumns: DTC_RECORD_COLUMNS.uploaded,
4093
+ credentialRequirements: [
4094
+ {
4095
+ key: "clickup",
4096
+ provider: "clickup",
4097
+ credentialType: "api-key-secret",
4098
+ label: "ClickUp API token",
4099
+ required: true,
4100
+ selectionMode: "single",
4101
+ inputPath: "clickupCredential",
4102
+ verifyOnRun: true
4103
+ }
4104
+ ]
5180
4105
  }
5181
- result[key] = isPlainObject(existing) && isPlainObject(value) ? deepMerge(existing, value) : value;
5182
- }
5183
- return result;
5184
- }
5185
- function resolveOrganizationModel(override, organizationIdOrOptions, options) {
5186
- const resolvedOptions = typeof organizationIdOrOptions === "object" ? organizationIdOrOptions : options;
5187
- const mergeDefaults = resolvedOptions?.mergeDefaults ?? true;
5188
- const merged = mergeDefaults ? deepMerge(DEFAULT_ORGANIZATION_MODEL, override) : override ?? {};
5189
- return OrganizationModelSchema.parse(merged);
5190
- }
5191
-
5192
- // ../core/src/organization-model/surface-projection.ts
5193
- function collectSystemsById(model) {
5194
- const systemsById = /* @__PURE__ */ new Map();
5195
- for (const { path, system } of listAllSystems(model)) {
5196
- systemsById.set(path, system);
5197
- systemsById.set(system.id, system);
5198
- }
5199
- return systemsById;
5200
- }
5201
- function getSystemWithAncestors(systemsById, systemId) {
5202
- const systems = [];
5203
- let current = systemsById.get(systemId);
5204
- while (current !== void 0) {
5205
- systems.unshift(current);
5206
- current = current.parentSystemId ? systemsById.get(current.parentSystemId) : void 0;
5207
4106
  }
5208
- return systems;
5209
- }
5210
- function hasInheritedFlag(systemsById, systemIds, flag) {
5211
- return systemIds.some(
5212
- (systemId) => getSystemWithAncestors(systemsById, systemId).some((system) => system[flag] === true)
5213
- );
5214
- }
5215
- function isLifecycleEnabled2(system) {
5216
- if (system.enabled === false) return false;
5217
- return system.lifecycle !== "deprecated" && system.lifecycle !== "archived";
5218
- }
5219
- function isLifecycleDevOnly(system) {
5220
- return system.devOnly === true || system.lifecycle === "beta";
5221
- }
5222
- function isSystemEnabled(systemsById, systemId) {
5223
- const systemLineage = getSystemWithAncestors(systemsById, systemId);
5224
- return systemLineage.length > 0 && systemLineage.every(isLifecycleEnabled2);
5225
- }
5226
- function unique(values) {
5227
- return [...new Set(values)];
5228
- }
5229
- function collectSidebarSurfaces(nodes, schemaPath, surfaces = []) {
5230
- getSortedSidebarEntries(nodes).forEach(([id, node]) => {
5231
- const nodePath = [...schemaPath, id];
5232
- if (node.type === "group") {
5233
- collectSidebarSurfaces(node.children, [...nodePath, "children"], surfaces);
5234
- return;
5235
- }
5236
- surfaces.push({ id, surface: node, path: nodePath });
5237
- });
5238
- return surfaces;
5239
- }
5240
- function getSidebarSurfaces(model) {
5241
- return [
5242
- ...collectSidebarSurfaces(model.navigation.sidebar.primary, ["navigation", "sidebar", "primary"]),
5243
- ...collectSidebarSurfaces(model.navigation.sidebar.bottom, ["navigation", "sidebar", "bottom"])
5244
- ];
5245
- }
5246
- function projectOrganizationSurfaces(model) {
5247
- const systemsById = collectSystemsById(model);
5248
- return getSidebarSurfaces(model).map(({ id, surface }) => {
5249
- const targets = surface.targets ?? {};
5250
- const systemIds = unique((targets.systems ?? []).filter((systemId) => systemsById.has(systemId)));
5251
- const enabled = systemIds.every((candidate) => isSystemEnabled(systemsById, candidate));
5252
- const devOnly = surface.devOnly === true || hasInheritedFlag(systemsById, systemIds, "devOnly") || systemIds.some((candidate) => getSystemWithAncestors(systemsById, candidate).some(isLifecycleDevOnly));
5253
- const requiresAdmin = hasInheritedFlag(systemsById, systemIds, "requiresAdmin");
5254
- return {
5255
- id,
5256
- label: surface.label,
5257
- path: surface.path,
5258
- surfaceType: surface.surfaceType,
5259
- ...surface.description !== void 0 ? { description: surface.description } : {},
5260
- ...surface.icon !== void 0 ? { icon: surface.icon } : {},
5261
- ...surface.order !== void 0 ? { order: surface.order } : {},
5262
- systemIds,
5263
- entityIds: [...targets.entities ?? []],
5264
- resourceIds: [...targets.resources ?? []],
5265
- actionIds: [...targets.actions ?? []],
5266
- enabled,
5267
- ...devOnly ? { devOnly } : {},
5268
- ...surface.requiresAdmin === true || requiresAdmin ? { requiresAdmin: true } : {}
5269
- };
5270
- });
5271
- }
4107
+ };
5272
4108
 
5273
- export { ActionSchema, AgentResourceEntrySchema, CRM_DISCOVERY_BOOKING_CANCELLED_STATE, CRM_DISCOVERY_LINK_SENT_STATE, CRM_DISCOVERY_NUDGING_STATE, CRM_DISCOVERY_REPLIED_STATE, CRM_PIPELINE_DEFINITION, CRM_PRIORITY_BUCKETS, DEFAULT_CRM_PRIORITY_RULE_CONFIG, DEFAULT_ORGANIZATION_MODEL, EntitySchema, IdentityDomainSchema, IntegrationResourceEntrySchema, LEAD_GEN_PIPELINE_DEFINITIONS, LEAD_GEN_STAGE_CATALOG, OntologyIdSchema, PROJECTS_VIEW_ACTION_ID, PROSPECTING_STEPS, PolicySchema, RoleSchema, SalesStageSchema, ScriptResourceEntrySchema, SurfaceDefinitionSchema, SystemEntrySchema, WorkflowResourceEntrySchema, ancestorsOf, buildOrganizationGraph, childrenOf, compileOrganizationOntology, defaultPathFor, devOnlyFor, findById, findByPath, findPipeline, formatOntologyId, getContent, getResourcesForSystem, getSortedSidebarEntries, getSystem, getSystemAncestors, listAllSystems, lookupContentType, ontologyGraphNodeId, parentOf, parseOntologyId, projectOrganizationSurfaces, requiresAdminFor, resolveOrganizationModel, resolveSystemConfig, topLevel };
4109
+ export { ActionSchema, AgentResourceEntrySchema, DEFAULT_SEMANTIC_ICON_REGISTRY, EntitySchema, IdentityDomainSchema, IntegrationResourceEntrySchema, OntologyIdSchema, OrgKnowledgeNodeSchema, PROJECTS_VIEW_ACTION_ID, PROSPECTING_STEPS, PolicySchema, RoleSchema, ScriptResourceEntrySchema, SemanticIcon, SurfaceDefinitionSchema, SystemEntrySchema, WorkflowResourceEntrySchema, ancestorsOf, buildOrganizationGraph, childrenOf, compileOrganizationOntology, defaultPathFor, defineResources, defineTopology, devOnlyFor, extendSemanticIconRegistry, findById, findByPath, findPipeline, getLeadGenStageCatalog, getResourcesForSystem, getSemanticIconComponent, getSortedSidebarEntries, getSystem, getSystemAncestors, listAllSystems, ontologyGraphNodeId, parentOf, parseOntologyId, projectOrganizationSurfaces, requiresAdminFor, resolveOrganizationModel, resolveSemanticIconComponent, resolveSystemConfig, topLevel, topologyRef, topologyRelationship };