@elevasis/ui 2.41.0 → 2.42.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 (95) hide show
  1. package/dist/api/index.js +4 -6
  2. package/dist/app/index.css +384 -0
  3. package/dist/app/index.d.ts +5 -1
  4. package/dist/app/index.js +17 -26
  5. package/dist/auth/index.css +659 -0
  6. package/dist/auth/index.js +19 -5
  7. package/dist/charts/index.css +533 -0
  8. package/dist/charts/index.js +18 -14
  9. package/dist/{chunk-JAN2ZXN5.js → chunk-3MTAHV5M.js} +28535 -18021
  10. package/dist/{chunk-73EWE2EW.js → chunk-EDVZ3AHA.js} +1 -1
  11. package/dist/chunk-GMXGDO3I.js +244 -0
  12. package/dist/{chunk-CXY7FMUM.js → chunk-GUKY77FJ.js} +50 -4
  13. package/dist/{chunk-TE4P6OSJ.js → chunk-MA7YCY7C.js} +1 -1
  14. package/dist/{chunk-5JYKCULK.js → chunk-NZ2F5RQ4.js} +44 -2
  15. package/dist/{chunk-WF7CONXF.js → chunk-OJJK27GC.js} +658 -6
  16. package/dist/chunk-YEGMSADG.js +1781 -0
  17. package/dist/components/chat/index.js +1 -2
  18. package/dist/components/index.css +149 -149
  19. package/dist/components/index.d.ts +5 -1
  20. package/dist/components/index.js +13 -36
  21. package/dist/components/navigation/index.css +659 -0
  22. package/dist/components/navigation/index.js +25 -3
  23. package/dist/features/auth/index.js +14 -37
  24. package/dist/features/clients/index.css +149 -149
  25. package/dist/features/clients/index.js +13 -36
  26. package/dist/features/crm/index.js +13 -36
  27. package/dist/features/dashboard/index.d.ts +5 -1
  28. package/dist/features/dashboard/index.js +13 -36
  29. package/dist/features/delivery/index.js +13 -36
  30. package/dist/features/knowledge/index.css +659 -0
  31. package/dist/features/knowledge/index.js +25 -247
  32. package/dist/features/lead-gen/index.d.ts +5 -1
  33. package/dist/features/lead-gen/index.js +13 -36
  34. package/dist/features/monitoring/index.js +13 -36
  35. package/dist/features/monitoring/requests/index.js +19 -149
  36. package/dist/features/operations/index.d.ts +5 -1
  37. package/dist/features/operations/index.js +13 -36
  38. package/dist/features/seo/index.js +1 -4
  39. package/dist/features/settings/index.js +13 -36
  40. package/dist/hooks/access/index.css +659 -0
  41. package/dist/hooks/access/index.js +19 -4
  42. package/dist/hooks/delivery/index.js +13 -36
  43. package/dist/hooks/index.d.ts +5 -1
  44. package/dist/hooks/index.js +13 -36
  45. package/dist/hooks/operations/command-view/utils/transformCommandViewData.d.ts +5 -1
  46. package/dist/hooks/published.d.ts +5 -1
  47. package/dist/hooks/published.js +13 -36
  48. package/dist/index.d.ts +5 -1
  49. package/dist/index.js +14 -37
  50. package/dist/initialization/index.js +1 -1
  51. package/dist/knowledge/index.css +659 -0
  52. package/dist/knowledge/index.d.ts +5 -1
  53. package/dist/knowledge/index.js +25 -15
  54. package/dist/layout/index.css +659 -0
  55. package/dist/layout/index.js +24 -9
  56. package/dist/organization/index.js +13 -36
  57. package/dist/provider/index.css +384 -0
  58. package/dist/provider/index.d.ts +5 -1
  59. package/dist/provider/index.js +18 -21
  60. package/dist/provider/published.css +533 -0
  61. package/dist/provider/published.d.ts +5 -1
  62. package/dist/provider/published.js +18 -16
  63. package/dist/test-utils/index.js +4 -6
  64. package/dist/theme/index.js +2 -5
  65. package/dist/theme/presets/index.js +1 -2
  66. package/dist/types/index.d.ts +5 -1
  67. package/dist/utils/index.d.ts +5 -1
  68. package/dist/utils/index.js +1 -3
  69. package/package.json +3 -3
  70. package/dist/chunk-3KMDHCAR.js +0 -52
  71. package/dist/chunk-4DRI3G36.js +0 -1016
  72. package/dist/chunk-56O7QQE7.js +0 -356
  73. package/dist/chunk-5EYJ2GIN.js +0 -122
  74. package/dist/chunk-66U7JOWV.js +0 -425
  75. package/dist/chunk-6D4LCJ52.js +0 -10
  76. package/dist/chunk-6ROXVZ3L.js +0 -9
  77. package/dist/chunk-A2XN6PR2.js +0 -111
  78. package/dist/chunk-B2DZLPDL.js +0 -39
  79. package/dist/chunk-CLDCYJQT.js +0 -1
  80. package/dist/chunk-CTJBPF3Z.js +0 -734
  81. package/dist/chunk-DT3QYZVU.js +0 -23
  82. package/dist/chunk-FIMGOWOT.js +0 -3644
  83. package/dist/chunk-IIMU5YAJ.js +0 -53
  84. package/dist/chunk-JHVEA5NE.js +0 -133
  85. package/dist/chunk-L7GXUSCV.js +0 -215
  86. package/dist/chunk-NYBEU5TE.js +0 -118
  87. package/dist/chunk-QVQMOQXB.js +0 -1240
  88. package/dist/chunk-RH5VWWSC.js +0 -624
  89. package/dist/chunk-RXH4D6TY.js +0 -801
  90. package/dist/chunk-S4R2ZQS7.js +0 -2131
  91. package/dist/chunk-TYRUKGGD.js +0 -46
  92. package/dist/chunk-VAAU2Z3S.js +0 -85
  93. package/dist/chunk-WLOQ4IBG.js +0 -654
  94. package/dist/chunk-X4WBGKJQ.js +0 -138
  95. package/dist/chunk-YPWN2WQ3.js +0 -340
@@ -0,0 +1,1781 @@
1
+ import { formatDistanceToNow } from 'date-fns';
2
+ import { IconUser, IconExternalLink, IconPlug, IconBolt, IconGitBranch, IconBrain } from '@tabler/icons-react';
3
+ import { z } from 'zod';
4
+
5
+ // src/utils/dateFormatters.ts
6
+ function formatDateTime(dateString) {
7
+ if (!dateString) return "Never";
8
+ const date = new Date(dateString);
9
+ return date.toLocaleDateString("en-US", {
10
+ year: "numeric",
11
+ month: "short",
12
+ day: "numeric",
13
+ hour: "2-digit",
14
+ minute: "2-digit"
15
+ });
16
+ }
17
+ function formatDate(dateString) {
18
+ if (!dateString) return "Never";
19
+ const date = new Date(dateString);
20
+ return date.toLocaleDateString("en-US", {
21
+ year: "numeric",
22
+ month: "short",
23
+ day: "numeric"
24
+ });
25
+ }
26
+ function formatChartAxisDate(dateString) {
27
+ if (!dateString) return "";
28
+ const date = new Date(dateString);
29
+ const month = date.getMonth() + 1;
30
+ const day = date.getDate();
31
+ const hour = date.getHours();
32
+ const period = hour >= 12 ? "PM" : "AM";
33
+ const hour12 = hour % 12 || 12;
34
+ return `${month}/${day}, ${hour12}${period}`;
35
+ }
36
+ function formatRelativeTime(date) {
37
+ if (!date) return "N/A";
38
+ const dateObj = typeof date === "string" ? new Date(date) : date;
39
+ return formatDistanceToNow(dateObj, { addSuffix: true });
40
+ }
41
+ function formatTimeAgo(date) {
42
+ if (!date) return "-";
43
+ const dateObj = typeof date === "string" ? new Date(date) : date;
44
+ const diffMs = Date.now() - dateObj.getTime();
45
+ const diffMinutes = Math.floor(diffMs / (1e3 * 60));
46
+ const diffHours = Math.floor(diffMs / (1e3 * 60 * 60));
47
+ const diffDays = Math.floor(diffMs / (1e3 * 60 * 60 * 24));
48
+ if (diffMinutes < 1) return "Just now";
49
+ if (diffHours < 1) return `${diffMinutes}m ago`;
50
+ if (diffDays < 1) return `${diffHours}h ago`;
51
+ if (diffDays === 1) return "1d ago";
52
+ return `${diffDays}d ago`;
53
+ }
54
+
55
+ // src/utils/validateEmail.ts
56
+ var validateEmail = (email) => {
57
+ return /^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)+$/.test(email);
58
+ };
59
+
60
+ // src/utils/error-utils.ts
61
+ var APIClientError = class extends Error {
62
+ statusCode;
63
+ code;
64
+ requestId;
65
+ fields;
66
+ retryAfter;
67
+ constructor(message, code, statusCode, requestId, fields, retryAfter) {
68
+ super(message);
69
+ this.name = "APIClientError";
70
+ this.code = code;
71
+ this.statusCode = statusCode;
72
+ this.requestId = requestId;
73
+ this.fields = fields;
74
+ this.retryAfter = retryAfter;
75
+ }
76
+ };
77
+ function isAPIClientError(error) {
78
+ return error instanceof APIClientError;
79
+ }
80
+ function getErrorInfo(error) {
81
+ if (isAPIClientError(error)) {
82
+ return {
83
+ message: error.message,
84
+ code: error.code,
85
+ requestId: error.requestId,
86
+ statusCode: error.statusCode,
87
+ fields: error.fields,
88
+ retryAfter: error.retryAfter
89
+ };
90
+ }
91
+ if (error instanceof Error) {
92
+ return {
93
+ message: error.message
94
+ };
95
+ }
96
+ return {
97
+ message: String(error)
98
+ };
99
+ }
100
+ function getErrorTitle(code) {
101
+ if (!code) return "Error";
102
+ switch (code) {
103
+ case "VALIDATION_ERROR":
104
+ return "Validation Error";
105
+ case "AUTHENTICATION_FAILED":
106
+ return "Authentication Required";
107
+ case "FORBIDDEN":
108
+ return "Access Denied";
109
+ case "NOT_FOUND":
110
+ return "Not Found";
111
+ case "CONFLICT":
112
+ return "Conflict";
113
+ case "RATE_LIMIT_EXCEEDED":
114
+ return "Rate Limit Exceeded";
115
+ case "INTERNAL_SERVER_ERROR":
116
+ return "Server Error";
117
+ case "SERVICE_UNAVAILABLE":
118
+ return "Service Temporarily Unavailable";
119
+ default:
120
+ return "Error";
121
+ }
122
+ }
123
+ function formatErrorMessage(message, requestId, fields, retryAfter) {
124
+ let formatted = message;
125
+ if (fields && Object.keys(fields).length > 0) {
126
+ const fieldErrors = [];
127
+ for (const [field, errors] of Object.entries(fields)) {
128
+ const fieldName = field === "root" || field === "_root" ? "Request" : field;
129
+ errors.forEach((error) => {
130
+ fieldErrors.push(`\u2022 ${fieldName}: ${error}`);
131
+ });
132
+ }
133
+ if (fieldErrors.length > 0) {
134
+ formatted = fieldErrors.join("\n");
135
+ }
136
+ }
137
+ if (retryAfter) {
138
+ formatted += `
139
+
140
+ Please wait ${retryAfter} seconds before retrying.`;
141
+ }
142
+ if (requestId) {
143
+ formatted += `
144
+
145
+ Request ID: ${requestId}`;
146
+ }
147
+ return formatted;
148
+ }
149
+
150
+ // ../core/src/platform/utils/debounce.ts
151
+ function debounce(fn, wait) {
152
+ let timeoutId = null;
153
+ const debounced = (...args) => {
154
+ if (timeoutId !== null) {
155
+ clearTimeout(timeoutId);
156
+ }
157
+ timeoutId = setTimeout(() => {
158
+ fn(...args);
159
+ timeoutId = null;
160
+ }, wait);
161
+ };
162
+ debounced.cancel = () => {
163
+ if (timeoutId !== null) {
164
+ clearTimeout(timeoutId);
165
+ timeoutId = null;
166
+ }
167
+ };
168
+ return debounced;
169
+ }
170
+ var ORGANIZATION_MODEL_ICON_TOKENS = [
171
+ // Navigation / app areas
172
+ "dashboard",
173
+ "calendar",
174
+ "sales",
175
+ "crm",
176
+ "lead-gen",
177
+ "projects",
178
+ "clients",
179
+ "operations",
180
+ "monitoring",
181
+ "knowledge",
182
+ "settings",
183
+ "admin",
184
+ "archive",
185
+ "business",
186
+ "finance",
187
+ "platform",
188
+ "seo",
189
+ // Knowledge kinds
190
+ "playbook",
191
+ "strategy",
192
+ "reference",
193
+ // Resource kinds
194
+ "agent",
195
+ "workflow",
196
+ "integration",
197
+ "database",
198
+ "user",
199
+ "team",
200
+ // Integration specifics
201
+ "gmail",
202
+ "google-sheets",
203
+ "attio",
204
+ // Surface / UI views
205
+ "overview",
206
+ "command-view",
207
+ "command-queue",
208
+ "pipeline",
209
+ "lists",
210
+ "resources",
211
+ // Actions
212
+ "approve",
213
+ "reject",
214
+ "retry",
215
+ "edit",
216
+ "view",
217
+ "launch",
218
+ "message",
219
+ "message-plus",
220
+ "escalate",
221
+ "promote",
222
+ "submit",
223
+ "email",
224
+ // Status
225
+ "success",
226
+ "error",
227
+ "warning",
228
+ "info",
229
+ "pending",
230
+ // OM / UI group icons
231
+ "bolt",
232
+ "building",
233
+ "briefcase",
234
+ "apps",
235
+ "graph",
236
+ "shield",
237
+ "users",
238
+ "chart-bar",
239
+ "search"
240
+ ];
241
+ var CustomIconTokenSchema = z.string().trim().max(80).regex(
242
+ /^custom\.[a-z0-9]+(?:[-._][a-z0-9]+)*$/,
243
+ 'Custom icon tokens must start with "custom." followed by lowercase alphanumeric segments'
244
+ );
245
+ var OrganizationModelBuiltinIconTokenSchema = z.enum(ORGANIZATION_MODEL_ICON_TOKENS);
246
+ var OrganizationModelIconTokenSchema = z.union([
247
+ OrganizationModelBuiltinIconTokenSchema,
248
+ CustomIconTokenSchema
249
+ ]);
250
+
251
+ // ../core/src/organization-model/domains/shared.ts
252
+ var ModelIdSchema = z.string().trim().min(1).max(100).regex(/^[a-z0-9]+(?:[-._][a-z0-9]+)*$/, "IDs must be lowercase and use -, _, or . separators");
253
+ var LabelSchema = z.string().trim().min(1).max(120);
254
+ var DescriptionSchema = z.string().trim().min(1).max(2e3);
255
+ var ColorTokenSchema = z.string().trim().min(1).max(50);
256
+ var IconNameSchema = OrganizationModelIconTokenSchema;
257
+ var PathSchema = z.string().trim().startsWith("/").max(300);
258
+ var ReferenceIdsSchema = z.array(ModelIdSchema).default([]);
259
+ var DisplayMetadataSchema = z.object({
260
+ label: LabelSchema,
261
+ description: DescriptionSchema.optional(),
262
+ color: ColorTokenSchema.optional(),
263
+ icon: IconNameSchema.optional()
264
+ });
265
+ var TechStackEntrySchema = z.object({
266
+ /** Name of the external platform (e.g. "HubSpot", "Stripe", "Notion"). */
267
+ platform: z.string().trim().min(1).max(200),
268
+ /** Free-form description of what this integration is used for. */
269
+ purpose: z.string().trim().min(1).max(500),
270
+ /**
271
+ * Health of the credential backing this integration.
272
+ * - configured: credential present and valid
273
+ * - pending: not yet set up
274
+ * - expired: credential existed but has lapsed
275
+ * - missing: expected but not present
276
+ */
277
+ credentialStatus: z.enum(["configured", "pending", "expired", "missing"]),
278
+ /**
279
+ * Whether this integration is the primary system of record for its domain
280
+ * (e.g. HubSpot is SoR for contacts). Defaults to false.
281
+ */
282
+ isSystemOfRecord: z.boolean().default(false)
283
+ });
284
+ DisplayMetadataSchema.extend({
285
+ id: ModelIdSchema,
286
+ resourceId: z.string().trim().min(1).max(255),
287
+ resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]),
288
+ systemIds: ReferenceIdsSchema,
289
+ entityIds: ReferenceIdsSchema,
290
+ surfaceIds: ReferenceIdsSchema,
291
+ actionIds: ReferenceIdsSchema,
292
+ /** Optional tech-stack metadata for external-SaaS integrations. */
293
+ techStack: TechStackEntrySchema.optional()
294
+ });
295
+
296
+ // ../core/src/organization-model/helpers.ts
297
+ function defineDomainRecord(schema, entries) {
298
+ return Object.fromEntries(
299
+ entries.map((entry) => {
300
+ const parsed = schema.parse(entry);
301
+ return [parsed.id, parsed];
302
+ })
303
+ );
304
+ }
305
+ function childSystemsOf(system) {
306
+ return system.systems ?? system.subsystems ?? {};
307
+ }
308
+ function defaultPathFor(id) {
309
+ return `/${id.replaceAll(".", "/")}`;
310
+ }
311
+ function parentIdOf(id) {
312
+ const index = id.lastIndexOf(".");
313
+ return index === -1 ? void 0 : id.slice(0, index);
314
+ }
315
+ function findById(systems, id) {
316
+ return systems[id];
317
+ }
318
+ function findByPath(systems, path) {
319
+ return Object.values(systems).find((system) => (system.path ?? system.ui?.path ?? defaultPathFor(system.id)) === path);
320
+ }
321
+ function childrenOf(systems, id) {
322
+ const prefix = `${id}.`;
323
+ return Object.values(systems).filter(
324
+ (system) => system.id.startsWith(prefix) && !system.id.slice(prefix.length).includes(".")
325
+ );
326
+ }
327
+ function topLevel(systems) {
328
+ return Object.values(systems).filter((system) => !system.id.includes("."));
329
+ }
330
+ function ancestorsOf(systems, id) {
331
+ const segments = id.split(".");
332
+ const ids = segments.map((_, index) => segments.slice(0, index + 1).join("."));
333
+ return ids.map((ancestorId) => findById(systems, ancestorId)).filter((system) => Boolean(system));
334
+ }
335
+ function parentOf(systems, id) {
336
+ const parentId = parentIdOf(id);
337
+ return parentId ? findById(systems, parentId) : void 0;
338
+ }
339
+ function inheritedValue(systems, id, getValue) {
340
+ return ancestorsOf(systems, id).slice().reverse().map(getValue).find((value) => value !== void 0);
341
+ }
342
+ function requiresAdminFor(systems, id) {
343
+ return inheritedValue(systems, id, (system) => system.requiresAdmin) ?? false;
344
+ }
345
+ function devOnlyFor(systems, id) {
346
+ return inheritedValue(systems, id, (system) => system.devOnly || system.lifecycle === "beta" || void 0) ?? false;
347
+ }
348
+ function getSystem(model, path) {
349
+ const flatMatch = model.systems[path];
350
+ if (flatMatch !== void 0) return flatMatch;
351
+ const segments = path.split(".");
352
+ let current = model.systems;
353
+ let node;
354
+ for (const seg of segments) {
355
+ node = current[seg];
356
+ if (node === void 0) return void 0;
357
+ current = childSystemsOf(node);
358
+ }
359
+ return node;
360
+ }
361
+ function getSystemAncestors(model, path) {
362
+ const flatMatch = model.systems[path];
363
+ if (flatMatch !== void 0) {
364
+ const ancestorIds = path.split(".").map((_, index, segments2) => segments2.slice(0, index + 1).join(".")).slice(0, -1);
365
+ return [
366
+ ...ancestorIds.map((ancestorId) => model.systems[ancestorId]).filter((system) => system !== void 0),
367
+ flatMatch
368
+ ];
369
+ }
370
+ const segments = path.split(".");
371
+ const result = [];
372
+ let current = model.systems;
373
+ for (const seg of segments) {
374
+ const node = current[seg];
375
+ if (node === void 0) return [];
376
+ result.push(node);
377
+ current = childSystemsOf(node);
378
+ }
379
+ return result;
380
+ }
381
+ function listAllSystems(model) {
382
+ const results = [];
383
+ function walk(map, prefix) {
384
+ for (const [localId2, system] of Object.entries(map)) {
385
+ const fullPath = prefix ? `${prefix}.${localId2}` : localId2;
386
+ results.push({ path: fullPath, system });
387
+ const childSystems = childSystemsOf(system);
388
+ if (Object.keys(childSystems).length > 0) {
389
+ walk(childSystems, fullPath);
390
+ }
391
+ }
392
+ }
393
+ walk(model.systems, "");
394
+ return results;
395
+ }
396
+ function isPlainJsonObject(value) {
397
+ return typeof value === "object" && value !== null && !Array.isArray(value);
398
+ }
399
+ function mergeJsonConfig(base, override) {
400
+ const result = { ...base };
401
+ for (const [key, value] of Object.entries(override)) {
402
+ const existing = result[key];
403
+ result[key] = isPlainJsonObject(existing) && isPlainJsonObject(value) ? mergeJsonConfig(existing, value) : value;
404
+ }
405
+ return result;
406
+ }
407
+ function resolveSystemConfig(model, path) {
408
+ const system = getSystem(model, path);
409
+ if (system === void 0) return {};
410
+ return mergeJsonConfig({}, system.config ?? {});
411
+ }
412
+ function getResourcesForSystem(model, systemPath, options = {}) {
413
+ const { includeDescendants = false } = options;
414
+ const prefix = systemPath + ".";
415
+ return Object.values(model.resources ?? {}).filter(
416
+ (r) => r.systemPath === systemPath || includeDescendants && r.systemPath.startsWith(prefix)
417
+ );
418
+ }
419
+
420
+ // ../core/src/organization-model/domains/entities.ts
421
+ var EntityIdSchema = ModelIdSchema;
422
+ var EntityLinkKindSchema = z.enum(["belongs-to", "has-many", "has-one", "many-to-many"]).meta({ label: "Link kind" });
423
+ var EntityLinkSchema = z.object({
424
+ toEntity: EntityIdSchema.meta({ ref: "entity" }),
425
+ kind: EntityLinkKindSchema,
426
+ via: z.string().trim().min(1).max(255).optional(),
427
+ label: LabelSchema.optional()
428
+ });
429
+ var EntitySchema = z.object({
430
+ id: EntityIdSchema,
431
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
432
+ order: z.number(),
433
+ label: LabelSchema,
434
+ description: DescriptionSchema.optional(),
435
+ ownedBySystemId: ModelIdSchema.meta({ ref: "system" }),
436
+ table: z.string().trim().min(1).max(255).optional(),
437
+ rowSchema: ModelIdSchema.optional(),
438
+ stateCatalogId: ModelIdSchema.optional(),
439
+ links: z.array(EntityLinkSchema).optional()
440
+ });
441
+ var EntitiesDomainSchema = z.record(z.string(), EntitySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
442
+ message: "Each entity entry id must match its map key"
443
+ }).default({});
444
+ function defineEntities(entries) {
445
+ return defineDomainRecord(EntitySchema, entries);
446
+ }
447
+
448
+ // ../core/src/organization-model/domains/actions.ts
449
+ var ActionResourceIdSchema = z.string().trim().min(1).max(255).regex(/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*$/, "Resource IDs must use letters, numbers, -, _, or . separators");
450
+ z.enum(["slash-command", "mcp-tool", "api-endpoint", "script-execution"]).meta({ label: "Invocation kind" });
451
+ var ActionIdSchema = ModelIdSchema;
452
+ var ActionScopeSchema = z.union([
453
+ z.literal("global"),
454
+ z.object({
455
+ domain: ModelIdSchema
456
+ })
457
+ ]);
458
+ var ActionRefSchema = z.object({
459
+ actionId: ActionIdSchema.meta({ ref: "action" }),
460
+ intent: z.enum(["exposes", "consumes"]).meta({ label: "Intent" })
461
+ });
462
+ var SlashCommandInvocationSchema = z.object({
463
+ kind: z.literal("slash-command"),
464
+ command: z.string().trim().min(1).max(200).regex(/^\/[^\s].*$/, "Slash commands must start with /"),
465
+ toolFactory: ModelIdSchema.optional()
466
+ });
467
+ var McpToolInvocationSchema = z.object({
468
+ kind: z.literal("mcp-tool"),
469
+ server: ModelIdSchema,
470
+ name: ModelIdSchema
471
+ });
472
+ var ApiEndpointInvocationSchema = z.object({
473
+ kind: z.literal("api-endpoint"),
474
+ method: z.enum(["GET", "POST", "PATCH", "DELETE"]).meta({ label: "HTTP method" }),
475
+ path: z.string().trim().startsWith("/").max(500),
476
+ requestSchema: ModelIdSchema.optional(),
477
+ responseSchema: ModelIdSchema.optional()
478
+ });
479
+ var ScriptExecutionInvocationSchema = z.object({
480
+ kind: z.literal("script-execution"),
481
+ resourceId: ActionResourceIdSchema
482
+ });
483
+ var ActionInvocationSchema = z.discriminatedUnion("kind", [
484
+ SlashCommandInvocationSchema,
485
+ McpToolInvocationSchema,
486
+ ApiEndpointInvocationSchema,
487
+ ScriptExecutionInvocationSchema
488
+ ]);
489
+ var ActionSchema = z.object({
490
+ id: ActionIdSchema,
491
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
492
+ order: z.number(),
493
+ label: LabelSchema,
494
+ description: DescriptionSchema.optional(),
495
+ scope: ActionScopeSchema.default("global"),
496
+ resourceId: ActionResourceIdSchema.optional(),
497
+ affects: z.array(EntityIdSchema.meta({ ref: "entity" })).optional(),
498
+ invocations: z.array(ActionInvocationSchema).default([]),
499
+ knowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
500
+ lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
501
+ });
502
+ var ActionsDomainSchema = z.record(z.string(), ActionSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
503
+ message: "Each action entry id must match its map key"
504
+ }).default({});
505
+ var DEFAULT_ORGANIZATION_MODEL_ACTIONS = {};
506
+ function defineActions(entries) {
507
+ return defineDomainRecord(ActionSchema, entries);
508
+ }
509
+ var OntologyKindSchema = z.enum([
510
+ "object",
511
+ "link",
512
+ "action",
513
+ "catalog",
514
+ "event",
515
+ "interface",
516
+ "value-type",
517
+ "property",
518
+ "group",
519
+ "surface"
520
+ ]);
521
+ var SYSTEM_PATH_PATTERN = "[a-z0-9][a-z0-9-]*(?:\\.[a-z0-9][a-z0-9-]*)*";
522
+ var LOCAL_ID_PATTERN = "[a-z0-9][a-z0-9._-]*";
523
+ var ONTOLOGY_ID_PATTERN = `^(global|${SYSTEM_PATH_PATTERN}):(${OntologyKindSchema.options.join("|")})\\/(${LOCAL_ID_PATTERN})$`;
524
+ var ONTOLOGY_ID_REGEX = new RegExp(ONTOLOGY_ID_PATTERN);
525
+ var OntologyIdSchema = z.string().trim().min(1).max(300).regex(
526
+ ONTOLOGY_ID_REGEX,
527
+ "Ontology IDs must use <system-path>:<kind>/<local-id> or global:<kind>/<local-id>"
528
+ );
529
+ function parseOntologyId(id) {
530
+ const normalized = OntologyIdSchema.parse(id);
531
+ const match = ONTOLOGY_ID_REGEX.exec(normalized);
532
+ if (match === null) {
533
+ throw new Error(`Invalid ontology ID "${id}"`);
534
+ }
535
+ return {
536
+ id: normalized,
537
+ scope: match[1],
538
+ kind: match[2],
539
+ localId: match[3],
540
+ isGlobal: match[1] === "global"
541
+ };
542
+ }
543
+ function formatOntologyId(input) {
544
+ return OntologyIdSchema.parse(`${input.scope}:${input.kind}/${input.localId}`);
545
+ }
546
+ var OntologyReferenceListSchema = z.array(OntologyIdSchema).default([]).optional();
547
+ var OntologyRecordBaseSchema = z.object({
548
+ id: OntologyIdSchema,
549
+ label: z.string().trim().min(1).max(160).optional(),
550
+ description: z.string().trim().min(1).max(2e3).optional(),
551
+ ownerSystemId: z.string().trim().min(1).max(200).optional(),
552
+ aliases: z.array(OntologyIdSchema).optional()
553
+ }).passthrough();
554
+ var OntologyObjectTypeSchema = OntologyRecordBaseSchema.extend({
555
+ properties: z.record(z.string().trim().min(1).max(200), z.unknown()).optional(),
556
+ storage: z.record(z.string(), z.unknown()).optional()
557
+ });
558
+ var OntologyLinkTypeSchema = OntologyRecordBaseSchema.extend({
559
+ from: OntologyIdSchema,
560
+ to: OntologyIdSchema,
561
+ cardinality: z.string().trim().min(1).max(80).optional(),
562
+ via: z.string().trim().min(1).max(255).optional()
563
+ });
564
+ var OntologyActionTypeSchema = OntologyRecordBaseSchema.extend({
565
+ actsOn: OntologyReferenceListSchema,
566
+ input: z.record(z.string().trim().min(1).max(200), z.unknown()).optional(),
567
+ effects: z.array(z.record(z.string(), z.unknown())).optional()
568
+ });
569
+ var OntologyCatalogTypeSchema = OntologyRecordBaseSchema.extend({
570
+ kind: z.string().trim().min(1).max(120).optional(),
571
+ appliesTo: OntologyIdSchema.optional(),
572
+ entries: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
573
+ });
574
+ var OntologyEventTypeSchema = OntologyRecordBaseSchema.extend({
575
+ payload: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
576
+ });
577
+ var OntologyInterfaceTypeSchema = OntologyRecordBaseSchema.extend({
578
+ properties: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
579
+ });
580
+ var OntologyValueTypeSchema = OntologyRecordBaseSchema.extend({
581
+ primitive: z.string().trim().min(1).max(120).optional()
582
+ });
583
+ var OntologySharedPropertySchema = OntologyRecordBaseSchema.extend({
584
+ valueType: OntologyIdSchema.optional(),
585
+ searchable: z.boolean().optional(),
586
+ pii: z.boolean().optional()
587
+ });
588
+ var OntologyGroupSchema = OntologyRecordBaseSchema.extend({
589
+ members: OntologyReferenceListSchema
590
+ });
591
+ var OntologySurfaceTypeSchema = OntologyRecordBaseSchema.extend({
592
+ route: z.string().trim().min(1).max(500).optional()
593
+ });
594
+ var OntologyScopeSchema = z.object({
595
+ objectTypes: z.record(OntologyIdSchema, OntologyObjectTypeSchema).default({}).optional(),
596
+ linkTypes: z.record(OntologyIdSchema, OntologyLinkTypeSchema).default({}).optional(),
597
+ actionTypes: z.record(OntologyIdSchema, OntologyActionTypeSchema).default({}).optional(),
598
+ catalogTypes: z.record(OntologyIdSchema, OntologyCatalogTypeSchema).default({}).optional(),
599
+ eventTypes: z.record(OntologyIdSchema, OntologyEventTypeSchema).default({}).optional(),
600
+ interfaceTypes: z.record(OntologyIdSchema, OntologyInterfaceTypeSchema).default({}).optional(),
601
+ valueTypes: z.record(OntologyIdSchema, OntologyValueTypeSchema).default({}).optional(),
602
+ sharedProperties: z.record(OntologyIdSchema, OntologySharedPropertySchema).default({}).optional(),
603
+ groups: z.record(OntologyIdSchema, OntologyGroupSchema).default({}).optional(),
604
+ surfaces: z.record(OntologyIdSchema, OntologySurfaceTypeSchema).default({}).optional()
605
+ }).default({});
606
+ var DEFAULT_ONTOLOGY_SCOPE = {
607
+ valueTypes: {
608
+ "global:value-type/uuid": {
609
+ id: "global:value-type/uuid",
610
+ label: "UUID",
611
+ primitive: "string"
612
+ },
613
+ "global:value-type/text": {
614
+ id: "global:value-type/text",
615
+ label: "Text",
616
+ primitive: "string"
617
+ },
618
+ "global:value-type/url": {
619
+ id: "global:value-type/url",
620
+ label: "URL",
621
+ primitive: "string"
622
+ },
623
+ "global:value-type/email": {
624
+ id: "global:value-type/email",
625
+ label: "Email",
626
+ primitive: "string"
627
+ }
628
+ }
629
+ };
630
+ var SCOPE_KIND = {
631
+ objectTypes: "object",
632
+ linkTypes: "link",
633
+ actionTypes: "action",
634
+ catalogTypes: "catalog",
635
+ eventTypes: "event",
636
+ interfaceTypes: "interface",
637
+ valueTypes: "value-type",
638
+ sharedProperties: "property",
639
+ groups: "group",
640
+ surfaces: "surface"
641
+ };
642
+ var SCOPE_KEYS = Object.keys(SCOPE_KIND);
643
+ function ontologyGraphNodeId(id) {
644
+ return `ontology:${OntologyIdSchema.parse(id)}`;
645
+ }
646
+ function listResolvedOntologyRecords(index) {
647
+ return SCOPE_KEYS.flatMap((scopeKey) => {
648
+ const kind = SCOPE_KIND[scopeKey];
649
+ return Object.entries(index[scopeKey]).sort(([leftId], [rightId]) => leftId.localeCompare(rightId)).map(([id, record]) => ({
650
+ id,
651
+ kind,
652
+ record
653
+ }));
654
+ });
655
+ }
656
+ function originFromContext(context) {
657
+ return {
658
+ kind: context.kind,
659
+ source: context.source,
660
+ path: context.path,
661
+ ...context.systemPath !== void 0 ? { systemPath: context.systemPath } : {},
662
+ ...context.legacyId !== void 0 ? { legacyId: context.legacyId } : {}
663
+ };
664
+ }
665
+ function createEmptyIndex() {
666
+ return {
667
+ objectTypes: {},
668
+ linkTypes: {},
669
+ actionTypes: {},
670
+ catalogTypes: {},
671
+ eventTypes: {},
672
+ interfaceTypes: {},
673
+ valueTypes: {},
674
+ sharedProperties: {},
675
+ groups: {},
676
+ surfaces: {}
677
+ };
678
+ }
679
+ function sortResolvedOntologyIndex(index) {
680
+ const sorted = createEmptyIndex();
681
+ for (const scopeKey of SCOPE_KEYS) {
682
+ const target = sorted[scopeKey];
683
+ for (const [id, record] of Object.entries(index[scopeKey]).sort(
684
+ ([leftId], [rightId]) => leftId.localeCompare(rightId)
685
+ )) {
686
+ target[id] = record;
687
+ }
688
+ }
689
+ return sorted;
690
+ }
691
+ function childSystemsOf2(system) {
692
+ return system.systems ?? system.subsystems ?? {};
693
+ }
694
+ function addRecord(index, diagnostics, sourcesById, scopeKey, record, context) {
695
+ let parsed;
696
+ try {
697
+ parsed = parseOntologyId(record.id);
698
+ } catch {
699
+ diagnostics.push({
700
+ code: "invalid_ontology_id",
701
+ message: `Invalid ontology ID "${record.id}" from ${context.source} at ${context.path.join(".")}`,
702
+ id: record.id,
703
+ path: context.path,
704
+ source: context.source,
705
+ origin: originFromContext(context)
706
+ });
707
+ return;
708
+ }
709
+ const expectedKind = SCOPE_KIND[scopeKey];
710
+ if (parsed.kind !== expectedKind) {
711
+ diagnostics.push({
712
+ code: "ontology_kind_mismatch",
713
+ message: `Ontology ID "${record.id}" has kind "${parsed.kind}" but was authored in ${scopeKey} (${expectedKind}) at ${context.path.join(".")}`,
714
+ id: record.id,
715
+ path: context.path,
716
+ source: context.source,
717
+ origin: originFromContext(context)
718
+ });
719
+ return;
720
+ }
721
+ const existing = sourcesById.get(parsed.id);
722
+ if (existing !== void 0) {
723
+ diagnostics.push({
724
+ code: "duplicate_ontology_id",
725
+ message: `Duplicate ontology ID "${parsed.id}" from ${context.source} at ${context.path.join(".")} conflicts with ${existing.source} at ${existing.path.join(".")}`,
726
+ id: parsed.id,
727
+ path: context.path,
728
+ source: context.source,
729
+ origin: originFromContext(context),
730
+ existingSource: existing.source,
731
+ existingOrigin: originFromContext(existing)
732
+ });
733
+ return;
734
+ }
735
+ sourcesById.set(parsed.id, context);
736
+ index[scopeKey][parsed.id] = {
737
+ ...record,
738
+ origin: originFromContext(context)
739
+ };
740
+ }
741
+ function addScope(index, diagnostics, sourcesById, scope, source, path) {
742
+ if (scope === void 0) return;
743
+ for (const scopeKey of SCOPE_KEYS) {
744
+ const records = scope[scopeKey] ?? {};
745
+ for (const [key, record] of Object.entries(records)) {
746
+ addRecord(index, diagnostics, sourcesById, scopeKey, record, {
747
+ source,
748
+ path: [...path, scopeKey, key],
749
+ kind: "authored",
750
+ systemPath: source.startsWith("system:") ? source.slice("system:".length, -".ontology".length) : void 0
751
+ });
752
+ }
753
+ }
754
+ }
755
+ function legacyObjectId(entity) {
756
+ return formatOntologyId({ scope: entity.ownedBySystemId, kind: "object", localId: entity.id });
757
+ }
758
+ function legacyActionOwner(action, entities) {
759
+ const firstAffectedEntityId = action.affects?.find((entityId) => entities[entityId] !== void 0);
760
+ if (firstAffectedEntityId !== void 0) {
761
+ return entities[firstAffectedEntityId].ownedBySystemId;
762
+ }
763
+ if (typeof action.scope === "object") {
764
+ return action.scope.domain;
765
+ }
766
+ return "global";
767
+ }
768
+ function addLegacyEntityProjections(index, diagnostics, sourcesById, entities) {
769
+ for (const entity of Object.values(entities)) {
770
+ const objectType = {
771
+ id: legacyObjectId(entity),
772
+ label: entity.label,
773
+ description: entity.description,
774
+ ownerSystemId: entity.ownedBySystemId,
775
+ ...entity.table !== void 0 ? {
776
+ storage: {
777
+ kind: "table",
778
+ table: entity.table
779
+ }
780
+ } : {},
781
+ ...entity.rowSchema !== void 0 ? { rowSchema: entity.rowSchema } : {},
782
+ ...entity.stateCatalogId !== void 0 ? { stateCatalogId: entity.stateCatalogId } : {}
783
+ };
784
+ addRecord(index, diagnostics, sourcesById, "objectTypes", objectType, {
785
+ source: "legacy.entities",
786
+ path: ["entities", entity.id],
787
+ kind: "projected",
788
+ systemPath: entity.ownedBySystemId,
789
+ legacyId: entity.id
790
+ });
791
+ entity.links?.forEach((link, linkIndex) => {
792
+ const targetEntity = entities[link.toEntity];
793
+ if (targetEntity === void 0) return;
794
+ const linkType = {
795
+ id: formatOntologyId({
796
+ scope: entity.ownedBySystemId,
797
+ kind: "link",
798
+ localId: `${entity.id}-${link.toEntity}-${linkIndex}`
799
+ }),
800
+ label: link.label ?? link.kind,
801
+ ownerSystemId: entity.ownedBySystemId,
802
+ from: legacyObjectId(entity),
803
+ to: legacyObjectId(targetEntity),
804
+ cardinality: link.kind,
805
+ ...link.via !== void 0 ? { via: link.via } : {}
806
+ };
807
+ addRecord(index, diagnostics, sourcesById, "linkTypes", linkType, {
808
+ source: "legacy.entities.links",
809
+ path: ["entities", entity.id, "links", linkIndex],
810
+ kind: "projected",
811
+ systemPath: entity.ownedBySystemId,
812
+ legacyId: `${entity.id}.links.${linkIndex}`
813
+ });
814
+ });
815
+ }
816
+ }
817
+ function addLegacyActionProjections(index, diagnostics, sourcesById, actions, entities) {
818
+ for (const action of Object.values(actions)) {
819
+ const ownerSystemId = legacyActionOwner(action, entities);
820
+ const actionType = {
821
+ id: formatOntologyId({ scope: ownerSystemId, kind: "action", localId: action.id }),
822
+ label: action.label,
823
+ description: action.description,
824
+ ownerSystemId,
825
+ actsOn: action.affects?.map((entityId) => entities[entityId] ? legacyObjectId(entities[entityId]) : void 0).filter((id) => id !== void 0),
826
+ ...action.resourceId !== void 0 ? { resourceId: action.resourceId } : {},
827
+ ...action.invocations !== void 0 ? { invocations: action.invocations } : {},
828
+ ...action.lifecycle !== void 0 ? { lifecycle: action.lifecycle } : {},
829
+ legacyActionId: action.id
830
+ };
831
+ addRecord(index, diagnostics, sourcesById, "actionTypes", actionType, {
832
+ source: "legacy.actions",
833
+ path: ["actions", action.id],
834
+ kind: "projected",
835
+ systemPath: ownerSystemId,
836
+ legacyId: action.id
837
+ });
838
+ }
839
+ }
840
+ function addSystemScopes(index, diagnostics, sourcesById, systems, prefix, schemaPath) {
841
+ for (const [key, system] of Object.entries(systems)) {
842
+ const systemPath = prefix ? `${prefix}.${key}` : key;
843
+ const currentPath = [...schemaPath, key];
844
+ addScope(index, diagnostics, sourcesById, system.ontology, `system:${systemPath}.ontology`, [
845
+ ...currentPath,
846
+ "ontology"
847
+ ]);
848
+ addSystemScopes(index, diagnostics, sourcesById, childSystemsOf2(system), systemPath, [
849
+ ...currentPath,
850
+ system.systems !== void 0 ? "systems" : "subsystems"
851
+ ]);
852
+ }
853
+ }
854
+ function compileOrganizationOntology(model) {
855
+ const ontology = createEmptyIndex();
856
+ const diagnostics = [];
857
+ const sourcesById = /* @__PURE__ */ new Map();
858
+ addScope(ontology, diagnostics, sourcesById, model.ontology, "organization.ontology", ["ontology"]);
859
+ addSystemScopes(ontology, diagnostics, sourcesById, model.systems ?? {}, "", ["systems"]);
860
+ addLegacyEntityProjections(ontology, diagnostics, sourcesById, model.entities ?? {});
861
+ addLegacyActionProjections(ontology, diagnostics, sourcesById, model.actions ?? {}, model.entities ?? {});
862
+ return { ontology: sortResolvedOntologyIndex(ontology), diagnostics };
863
+ }
864
+
865
+ // ../core/src/organization-model/domains/systems.ts
866
+ var SystemKindSchema = z.enum(["product", "operational", "platform", "diagnostic"]).meta({ label: "System kind", color: "blue" });
867
+ var SystemLifecycleSchema = z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" });
868
+ var SystemStatusSchema = z.enum(["active", "deprecated", "archived"]).meta({ label: "Status", color: "teal" });
869
+ var SystemIdSchema = ModelIdSchema;
870
+ var SystemPathSchema = z.string().trim().min(1).regex(
871
+ /^[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)*$/,
872
+ 'must be a dotted lowercase path (e.g. "sales.lead-gen" or "sales.crm")'
873
+ );
874
+ var UiPositionSchema = z.enum(["sidebar-primary", "sidebar-bottom"]).meta({ label: "UI position" });
875
+ var NodeIdStringSchema = z.string().trim().min(1).max(200).regex(
876
+ /^[a-z][a-z-]*:([a-z0-9-]+)(\.[a-z0-9-]+)*(:[a-z0-9.-]+)*$/,
877
+ "Node references must use kind:dotted-path (e.g. system:sales.crm or resource:lead-gen.company.qualify)"
878
+ );
879
+ var SystemUiSchema = z.object({
880
+ path: PathSchema,
881
+ surfaces: ReferenceIdsSchema,
882
+ icon: IconNameSchema.optional(),
883
+ order: z.number().int().optional()
884
+ });
885
+ var SystemInterfaceKeySchema = ModelIdSchema;
886
+ var SystemInterfaceLifecycleSchema = z.enum(["draft", "active", "disabled", "deprecated", "archived"]).meta({ label: "System interface lifecycle", color: "teal" });
887
+ var SYSTEM_INTERFACE_PROFILES = [
888
+ {
889
+ systemPath: "sales.lead-gen",
890
+ interfaceKey: "api",
891
+ readinessProfile: "sales.lead-gen.api"
892
+ },
893
+ {
894
+ systemPath: "sales.crm",
895
+ interfaceKey: "api",
896
+ readinessProfile: "sales.crm.api"
897
+ },
898
+ {
899
+ systemPath: "sales.lead-gen",
900
+ interfaceKey: "crm-handoff",
901
+ readinessProfile: "sales.lead-gen.crm-handoff"
902
+ }
903
+ ];
904
+ var SYSTEM_INTERFACE_READINESS_PROFILES = SYSTEM_INTERFACE_PROFILES.map(
905
+ (profile) => profile.readinessProfile
906
+ );
907
+ var SystemInterfaceReadinessProfileSchema = z.enum(SYSTEM_INTERFACE_READINESS_PROFILES);
908
+ var SystemInterfaceResourceScopeSchema = z.array(ModelIdSchema).default([]);
909
+ var SystemApiInterfaceSchema = z.object({
910
+ lifecycle: SystemInterfaceLifecycleSchema.default("active"),
911
+ readinessProfile: SystemInterfaceReadinessProfileSchema.optional(),
912
+ /**
913
+ * Resource ids that participate in this API interface. This scopes readiness
914
+ * derivation without duplicating authored required/provided contract refs.
915
+ */
916
+ resourceIds: SystemInterfaceResourceScopeSchema.optional()
917
+ }).strict();
918
+ var SystemInterfaceRefSchema = z.object({
919
+ systemPath: SystemPathSchema,
920
+ interfaceKey: SystemInterfaceKeySchema
921
+ }).strict();
922
+ var JsonValueSchema = z.lazy(
923
+ () => z.union([
924
+ z.string(),
925
+ z.number(),
926
+ z.boolean(),
927
+ z.null(),
928
+ z.array(JsonValueSchema),
929
+ z.record(z.string(), JsonValueSchema)
930
+ ])
931
+ );
932
+ var SystemConfigSchema = z.record(z.string().trim().min(1).max(200), JsonValueSchema).default({}).optional();
933
+ var SystemEntrySchema = z.object({
934
+ /** Stable tenant-defined system id (e.g. "sys.lead-gen" or "sales.crm"). */
935
+ id: SystemIdSchema,
936
+ /** Human-readable system label shown in UI, governance, and operations surfaces. */
937
+ label: LabelSchema.optional(),
938
+ /** @deprecated Use label. Accepted for pre-consolidation System declarations. */
939
+ title: LabelSchema.optional(),
940
+ /** One-paragraph purpose statement for the bounded context. */
941
+ description: DescriptionSchema.optional(),
942
+ /** Closed system shape enum; catalog values remain tenant-defined. */
943
+ kind: SystemKindSchema.optional(),
944
+ /** Optional self-reference for System hierarchy. */
945
+ parentSystemId: SystemIdSchema.optional(),
946
+ /** Optional UI presence. Systems without UI omit this. */
947
+ ui: SystemUiSchema.optional(),
948
+ /** Canonical lifecycle state. Replaces Feature.enabled/devOnly and System.status. */
949
+ lifecycle: SystemLifecycleSchema.optional(),
950
+ /** Optional role responsible for this system. */
951
+ responsibleRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
952
+ /** Optional knowledge nodes that govern this system. */
953
+ governedByKnowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
954
+ /** Optional actions this system exposes or consumes. */
955
+ actions: z.array(ActionRefSchema).optional(),
956
+ /** Optional operational policies that apply to this system. */
957
+ policies: z.array(ModelIdSchema.meta({ ref: "policy" })).default([]).optional(),
958
+ /** Optional goals this system contributes to. */
959
+ drivesGoals: z.array(ModelIdSchema.meta({ ref: "goal" })).default([]).optional(),
960
+ /** Thin API runtime-boundary marker. Readiness is derived from scoped resources and topology. */
961
+ apiInterface: SystemApiInterfaceSchema.optional(),
962
+ /** @deprecated Use lifecycle. Accepted for one publish cycle. */
963
+ status: SystemStatusSchema.optional(),
964
+ /** @deprecated Use ui.path. Kept for one-cycle Feature compatibility. */
965
+ path: PathSchema.optional(),
966
+ /** @deprecated Use ui.icon. Kept for one-cycle Feature compatibility. */
967
+ icon: IconNameSchema.optional(),
968
+ /** @deprecated Feature color token, retained for one-cycle compatibility. */
969
+ color: ColorTokenSchema.optional(),
970
+ /** @deprecated UI placement hint, retained for one-cycle compatibility. */
971
+ uiPosition: UiPositionSchema.optional(),
972
+ /** @deprecated Use lifecycle. */
973
+ enabled: z.boolean().optional(),
974
+ /** @deprecated Use lifecycle: "beta". */
975
+ devOnly: z.boolean().optional(),
976
+ requiresAdmin: z.boolean().optional(),
977
+ /** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
978
+ order: z.number(),
979
+ /**
980
+ * System-local JSON settings and defaults. Strongly typed OM fields,
981
+ * secrets, credentials, and runtime state stay outside this bucket.
982
+ */
983
+ config: SystemConfigSchema,
984
+ /**
985
+ * System-owned ontology declarations. `systems` is now the canonical child
986
+ * key; this scope holds the object, action, catalog, link, event, and
987
+ * shared contract records owned by this system.
988
+ */
989
+ ontology: OntologyScopeSchema.optional(),
990
+ /**
991
+ * Recursive child systems, authored via nesting (per L11).
992
+ * The key is the local system id; the full path is computed by joining
993
+ * ancestor keys with `.` (e.g. parent key `'sales'` + child key `'crm'` → `'sales.crm'`).
994
+ * Per Phase 4: `id` and `parentSystemId` fields will be removed in favour of
995
+ * position-derived paths. Both still exist on this schema for backward compat.
996
+ */
997
+ systems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional(),
998
+ /** @deprecated Use systems. Accepted as a compatibility alias during the ontology bridge. */
999
+ subsystems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional()
1000
+ }).strict().refine((system) => system.label !== void 0 || system.title !== void 0, {
1001
+ path: ["label"],
1002
+ message: "System must provide label or title"
1003
+ }).transform((system) => {
1004
+ const normalizedSystem = system.systems !== void 0 && system.subsystems === void 0 ? { ...system, subsystems: system.systems } : system;
1005
+ if (normalizedSystem.status === void 0) return normalizedSystem;
1006
+ console.warn("[organization-model] System.status is deprecated; use System.lifecycle instead.");
1007
+ return normalizedSystem.lifecycle === void 0 ? { ...normalizedSystem, lifecycle: normalizedSystem.status } : normalizedSystem;
1008
+ });
1009
+ var SystemsDomainSchema = z.record(z.string(), SystemEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
1010
+ message: "Each system entry id must match its map key"
1011
+ }).default({});
1012
+ var DEFAULT_ORGANIZATION_MODEL_SYSTEMS = {};
1013
+
1014
+ // ../core/src/organization-model/migration-helpers.ts
1015
+ function catalogRecords(model) {
1016
+ return Object.values(compileOrganizationOntology(model).ontology.catalogTypes);
1017
+ }
1018
+ function localId(id) {
1019
+ return parseOntologyId(id).localId;
1020
+ }
1021
+ function systemScope(id, fallback) {
1022
+ return parseOntologyId(id).scope || fallback || "";
1023
+ }
1024
+ function entriesOf(catalog) {
1025
+ return Object.entries(catalog.entries ?? {}).map(([id, value]) => [
1026
+ id,
1027
+ value && typeof value === "object" && !Array.isArray(value) ? value : {}
1028
+ ]);
1029
+ }
1030
+ function stringValue(value) {
1031
+ return typeof value === "string" ? value : void 0;
1032
+ }
1033
+ function stringArray(value) {
1034
+ return Array.isArray(value) ? value.filter((item) => typeof item === "string") : [];
1035
+ }
1036
+ function numberValue(value, fallback = 0) {
1037
+ return typeof value === "number" ? value : fallback;
1038
+ }
1039
+ function stageFromEntry(entryId, entry) {
1040
+ return {
1041
+ id: entryId,
1042
+ label: stringValue(entry.label) ?? entryId,
1043
+ order: numberValue(entry.order),
1044
+ semanticClass: stringValue(entry.semanticClass) ?? "open",
1045
+ surfaceIds: stringArray(entry.surfaceIds),
1046
+ resourceIds: stringArray(entry.resourceIds),
1047
+ color: stringValue(entry.color)
1048
+ };
1049
+ }
1050
+ function appliesToLocalId(catalog) {
1051
+ const appliesTo = catalog.appliesTo;
1052
+ if (appliesTo === void 0) return void 0;
1053
+ return parseOntologyId(appliesTo).localId;
1054
+ }
1055
+ function appliesToEntityKind(catalog) {
1056
+ const id = appliesToLocalId(catalog);
1057
+ if (id === "company" || id === "contact" || id === "project" || id === "milestone" || id === "task") return id;
1058
+ if (id === "deal") return void 0;
1059
+ return void 0;
1060
+ }
1061
+ function getAllPipelines(model) {
1062
+ return catalogRecords(model).filter((catalog) => catalog.kind === "pipeline").map((catalog) => {
1063
+ const pipeline = {
1064
+ id: localId(catalog.id),
1065
+ label: catalog.label ?? localId(catalog.id),
1066
+ ...catalog.description ? { description: catalog.description } : {},
1067
+ entityId: appliesToLocalId(catalog) ?? "",
1068
+ stages: entriesOf(catalog).map(([entryId, entry]) => stageFromEntry(entryId, entry)).sort((a, b) => a.order - b.order || a.id.localeCompare(b.id))
1069
+ };
1070
+ return { systemPath: catalog.ownerSystemId ?? systemScope(catalog.id), pipeline };
1071
+ }).sort((a, b) => a.systemPath.localeCompare(b.systemPath) || a.pipeline.id.localeCompare(b.pipeline.id));
1072
+ }
1073
+ function getAllBuildTemplates(model) {
1074
+ const catalogs = catalogRecords(model);
1075
+ const stepCatalogs = new Map(
1076
+ catalogs.filter((catalog) => catalog.kind === "template-step").map((catalog) => [catalog.id, catalog])
1077
+ );
1078
+ return catalogs.filter((catalog) => catalog.kind === "template").flatMap(
1079
+ (catalog) => entriesOf(catalog).map(([templateId, templateEntry]) => {
1080
+ const stepCatalogId = stringValue(templateEntry.stepCatalog);
1081
+ const stepCatalog = stepCatalogId !== void 0 ? stepCatalogs.get(stepCatalogId) : void 0;
1082
+ const steps = stepCatalog === void 0 ? [] : entriesOf(stepCatalog).sort(
1083
+ ([leftId, left], [rightId, right]) => numberValue(left.order, Number.MAX_SAFE_INTEGER) - numberValue(right.order, Number.MAX_SAFE_INTEGER) || leftId.localeCompare(rightId)
1084
+ );
1085
+ return {
1086
+ order: numberValue(templateEntry.order, Number.MAX_SAFE_INTEGER),
1087
+ template: {
1088
+ id: templateId,
1089
+ label: stringValue(templateEntry.label) ?? templateId,
1090
+ ...stringValue(templateEntry.description) ? { description: stringValue(templateEntry.description) } : {},
1091
+ ...stringValue(templateEntry.color) ? { color: stringValue(templateEntry.color) } : {},
1092
+ steps: steps.map(([stepId, step]) => ({
1093
+ id: stepId,
1094
+ label: stringValue(step.label) ?? stepId,
1095
+ ...stringValue(step.description) ? { description: stringValue(step.description) } : {},
1096
+ ...step
1097
+ }))
1098
+ }
1099
+ };
1100
+ })
1101
+ ).sort((a, b) => a.order - b.order || a.template.id.localeCompare(b.template.id)).map(({ template }) => template);
1102
+ }
1103
+ function getAllProspectingStages(model, kind) {
1104
+ return catalogRecords(model).filter((catalog) => catalog.kind === "stage" && appliesToEntityKind(catalog) === kind).flatMap(
1105
+ (catalog) => entriesOf(catalog).map(([entryId, entry]) => ({
1106
+ id: entryId,
1107
+ label: stringValue(entry.label) ?? entryId,
1108
+ order: numberValue(entry.order),
1109
+ ...stringValue(entry.color) ? { color: stringValue(entry.color) } : {},
1110
+ ...stringValue(entry.description) ? { description: stringValue(entry.description) } : {}
1111
+ }))
1112
+ ).sort((a, b) => a.order - b.order || a.id.localeCompare(b.id));
1113
+ }
1114
+ function getLeadGenStageCatalog(model) {
1115
+ const results = {};
1116
+ for (const catalog of catalogRecords(model).filter(
1117
+ (record) => record.kind === "stage" && (record.ownerSystemId ?? systemScope(record.id)) === "sales.lead-gen"
1118
+ )) {
1119
+ const catalogEntity = appliesToEntityKind(catalog);
1120
+ if (catalogEntity !== "company" && catalogEntity !== "contact") continue;
1121
+ for (const [entryId, entry] of entriesOf(catalog)) {
1122
+ const entity = entry.entity === "contact" ? "contact" : entry.entity === "company" ? "company" : catalogEntity;
1123
+ const additionalEntities = stringArray(entry.additionalEntities).filter(
1124
+ (item) => item === "company" || item === "contact"
1125
+ );
1126
+ const recordEntity = entry.recordEntity === "company" || entry.recordEntity === "contact" ? entry.recordEntity : void 0;
1127
+ const recordStageKey = stringValue(entry.recordStageKey);
1128
+ results[entryId] = {
1129
+ key: entryId,
1130
+ label: stringValue(entry.label) ?? entryId,
1131
+ description: stringValue(entry.description) ?? "",
1132
+ order: numberValue(entry.order),
1133
+ entity,
1134
+ ...additionalEntities.length > 0 ? { additionalEntities } : {},
1135
+ ...recordEntity ? { recordEntity } : {},
1136
+ ...recordStageKey ? { recordStageKey } : {}
1137
+ };
1138
+ }
1139
+ }
1140
+ return Object.fromEntries(
1141
+ Object.entries(results).sort(([, a], [, b]) => a.order - b.order || a.key.localeCompare(b.key))
1142
+ );
1143
+ }
1144
+ function getAllProjectStatuses(model, appliesTo) {
1145
+ return catalogRecords(model).filter((catalog) => catalog.kind === "status-flow" && appliesToEntityKind(catalog) === appliesTo).flatMap(
1146
+ (catalog) => entriesOf(catalog).map(([entryId, entry]) => ({
1147
+ id: entryId,
1148
+ label: stringValue(entry.label) ?? entryId,
1149
+ order: numberValue(entry.order),
1150
+ ...stringValue(entry.color) ? { color: stringValue(entry.color) } : {},
1151
+ ...stringValue(entry.description) ? { description: stringValue(entry.description) } : {}
1152
+ }))
1153
+ ).sort((a, b) => a.order - b.order || a.id.localeCompare(b.id));
1154
+ }
1155
+
1156
+ // ../core/src/business/acquisition/ontology-validation.ts
1157
+ var LEAD_GEN_API_INTERFACE = SYSTEM_INTERFACE_PROFILES[0];
1158
+ var CRM_API_INTERFACE = SYSTEM_INTERFACE_PROFILES[1];
1159
+ var LEAD_GEN_CRM_HANDOFF_INTERFACE = SYSTEM_INTERFACE_PROFILES[2];
1160
+ LEAD_GEN_API_INTERFACE.readinessProfile;
1161
+ CRM_API_INTERFACE.readinessProfile;
1162
+ LEAD_GEN_CRM_HANDOFF_INTERFACE.readinessProfile;
1163
+ var LEAD_GEN_LIST_OBJECT_ONTOLOGY_ID = formatOntologyId({
1164
+ scope: "sales.lead-gen",
1165
+ kind: "object",
1166
+ localId: "list"
1167
+ });
1168
+ var LEAD_GEN_COMPANY_OBJECT_ONTOLOGY_ID = formatOntologyId({
1169
+ scope: "sales.lead-gen",
1170
+ kind: "object",
1171
+ localId: "company"
1172
+ });
1173
+ var LEAD_GEN_CONTACT_OBJECT_ONTOLOGY_ID = formatOntologyId({
1174
+ scope: "sales.lead-gen",
1175
+ kind: "object",
1176
+ localId: "contact"
1177
+ });
1178
+ var LEAD_GEN_BUILD_TEMPLATE_CATALOG_ONTOLOGY_ID = formatOntologyId({
1179
+ scope: "sales.lead-gen",
1180
+ kind: "catalog",
1181
+ localId: "build-template"
1182
+ });
1183
+ var LEAD_GEN_COMPANY_STAGE_CATALOG_ONTOLOGY_ID = formatOntologyId({
1184
+ scope: "sales.lead-gen",
1185
+ kind: "catalog",
1186
+ localId: "company-stage"
1187
+ });
1188
+ var LEAD_GEN_CONTACT_STAGE_CATALOG_ONTOLOGY_ID = formatOntologyId({
1189
+ scope: "sales.lead-gen",
1190
+ kind: "catalog",
1191
+ localId: "contact-stage"
1192
+ });
1193
+ var CRM_PIPELINE_CATALOG_ONTOLOGY_ID = formatOntologyId({
1194
+ scope: "sales.crm",
1195
+ kind: "catalog",
1196
+ localId: "crm.pipeline"
1197
+ });
1198
+ var LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID = formatOntologyId({
1199
+ scope: "sales.lead-gen",
1200
+ kind: "catalog",
1201
+ localId: "lead-gen.stage-catalog"
1202
+ });
1203
+ function createLeadGenStageCatalog(model) {
1204
+ return {
1205
+ id: LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID,
1206
+ label: "Lead Gen Processing Stages",
1207
+ ownerSystemId: "sales.lead-gen",
1208
+ kind: "processing-stage-catalog",
1209
+ entries: Object.fromEntries(
1210
+ Object.entries(getLeadGenStageCatalog(model)).map(([key, entry]) => [
1211
+ key,
1212
+ {
1213
+ ...entry
1214
+ }
1215
+ ])
1216
+ ),
1217
+ legacyCatalogKey: "LEAD_GEN_STAGE_CATALOG"
1218
+ };
1219
+ }
1220
+ function isPlainRecord(value) {
1221
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
1222
+ }
1223
+ function addReadinessIssue(issues, family, code, message, details = {}) {
1224
+ issues.push({
1225
+ family,
1226
+ code,
1227
+ message,
1228
+ ...details
1229
+ });
1230
+ }
1231
+ function formatInterfaceIdentity(systemPath, interfaceKey) {
1232
+ return `${systemPath}/${interfaceKey}`;
1233
+ }
1234
+ function profileForInterface(systemPath, interfaceKey, readinessProfile) {
1235
+ return readinessProfile ?? `${systemPath}.${interfaceKey}`;
1236
+ }
1237
+ function readinessMarkerPath(context) {
1238
+ return context.interfaceKey === "api" ? `systems.${context.systemPath}.apiInterface` : `systems.${context.systemPath}.derivedCrmHandoffReadiness`;
1239
+ }
1240
+ function formatSupportedReadinessProfiles() {
1241
+ return SYSTEM_INTERFACE_READINESS_PROFILES.map((profile) => `"${profile}"`).join(", ");
1242
+ }
1243
+ function getActiveScopedResources(model, resourceIds, issues, context) {
1244
+ const resources = [];
1245
+ for (const [index, resourceId] of resourceIds.entries()) {
1246
+ const resource = model.resources?.[resourceId];
1247
+ const path = `${readinessMarkerPath(context)}.resourceIds.${index}`;
1248
+ if (resource === void 0) {
1249
+ addReadinessIssue(
1250
+ issues,
1251
+ "SYSTEM_INTERFACE_NOT_READY",
1252
+ "missing-resource",
1253
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" scopes missing resource "${resourceId}".`,
1254
+ { path, ref: resourceId }
1255
+ );
1256
+ continue;
1257
+ }
1258
+ if (resource.systemPath !== context.systemPath) {
1259
+ addReadinessIssue(
1260
+ issues,
1261
+ "SYSTEM_INTERFACE_INVALID",
1262
+ "resource-system-mismatch",
1263
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" scopes resource "${resourceId}" from system "${resource.systemPath}".`,
1264
+ { path, ref: resourceId }
1265
+ );
1266
+ continue;
1267
+ }
1268
+ if (resource.status !== "active") {
1269
+ addReadinessIssue(
1270
+ issues,
1271
+ "SYSTEM_INTERFACE_NOT_READY",
1272
+ "inactive-resource",
1273
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" scopes inactive resource "${resourceId}".`,
1274
+ { path, ref: resourceId }
1275
+ );
1276
+ continue;
1277
+ }
1278
+ resources.push(resource);
1279
+ }
1280
+ return resources;
1281
+ }
1282
+ function resourceBindingIds(resources, key) {
1283
+ return new Set(resources.flatMap((resource) => resource.ontology?.[key] ?? []));
1284
+ }
1285
+ function requireScopedBinding(issues, boundIds, bindingKey, ontologyId, context) {
1286
+ if (boundIds.has(ontologyId)) return;
1287
+ addReadinessIssue(
1288
+ issues,
1289
+ "SYSTEM_INTERFACE_NOT_READY",
1290
+ "missing-resource-binding",
1291
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" has no active scoped resource with ontology.${bindingKey} binding "${ontologyId}".`,
1292
+ { path: `${readinessMarkerPath(context)}.resourceIds`, ref: ontologyId }
1293
+ );
1294
+ }
1295
+ function ontologyOwnerMatches(ontologyId, expectedSystemPath, catalog) {
1296
+ if (catalog?.ownerSystemId !== void 0) return catalog.ownerSystemId === expectedSystemPath;
1297
+ return parseOntologyId(ontologyId).scope === expectedSystemPath;
1298
+ }
1299
+ function requireObjectReadiness(issues, index, objectId, context) {
1300
+ const object = index.ontology.objectTypes[objectId];
1301
+ if (object === void 0) {
1302
+ addReadinessIssue(
1303
+ issues,
1304
+ "SYSTEM_INTERFACE_NOT_READY",
1305
+ "missing-object",
1306
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" is missing required object type "${objectId}".`,
1307
+ { ref: objectId }
1308
+ );
1309
+ return;
1310
+ }
1311
+ const ownerSystemId = object.ownerSystemId ?? parseOntologyId(objectId).scope;
1312
+ if (ownerSystemId !== context.systemPath) {
1313
+ addReadinessIssue(
1314
+ issues,
1315
+ "SYSTEM_INTERFACE_INVALID",
1316
+ "foreign-object",
1317
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" requires object "${objectId}" owned by "${ownerSystemId}".`,
1318
+ { ref: objectId }
1319
+ );
1320
+ }
1321
+ }
1322
+ function requireCatalogReadiness(issues, index, catalogId, context) {
1323
+ const catalog = index.ontology.catalogTypes[catalogId];
1324
+ if (catalog === void 0) {
1325
+ addReadinessIssue(
1326
+ issues,
1327
+ "SYSTEM_INTERFACE_NOT_READY",
1328
+ "missing-catalog",
1329
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" is missing required catalog "${catalogId}".`,
1330
+ { ref: catalogId }
1331
+ );
1332
+ return void 0;
1333
+ }
1334
+ if (context.allowForeignOwner !== true && !ontologyOwnerMatches(catalogId, context.systemPath, catalog)) {
1335
+ addReadinessIssue(
1336
+ issues,
1337
+ "SYSTEM_INTERFACE_INVALID",
1338
+ "foreign-catalog",
1339
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" requires catalog "${catalogId}" owned by "${catalog.ownerSystemId ?? parseOntologyId(catalogId).scope}".`,
1340
+ { ref: catalogId }
1341
+ );
1342
+ }
1343
+ if (Object.keys(getCatalogEntries(catalog)).length === 0) {
1344
+ addReadinessIssue(
1345
+ issues,
1346
+ "SYSTEM_INTERFACE_NOT_READY",
1347
+ "empty-catalog",
1348
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" requires catalog entries for "${catalogId}".`,
1349
+ { ref: catalogId }
1350
+ );
1351
+ }
1352
+ return catalog;
1353
+ }
1354
+ function requireLeadGenInterfaceReadiness(issues, index, resources, context) {
1355
+ const reads = resourceBindingIds(resources, "reads");
1356
+ const catalogs = resourceBindingIds(resources, "usesCatalogs");
1357
+ for (const objectId of [
1358
+ LEAD_GEN_LIST_OBJECT_ONTOLOGY_ID,
1359
+ LEAD_GEN_COMPANY_OBJECT_ONTOLOGY_ID,
1360
+ LEAD_GEN_CONTACT_OBJECT_ONTOLOGY_ID
1361
+ ]) {
1362
+ requireObjectReadiness(issues, index, objectId, context);
1363
+ requireScopedBinding(issues, reads, "reads", objectId, context);
1364
+ }
1365
+ for (const catalogId of [
1366
+ LEAD_GEN_BUILD_TEMPLATE_CATALOG_ONTOLOGY_ID,
1367
+ LEAD_GEN_COMPANY_STAGE_CATALOG_ONTOLOGY_ID,
1368
+ LEAD_GEN_CONTACT_STAGE_CATALOG_ONTOLOGY_ID
1369
+ ]) {
1370
+ requireCatalogReadiness(issues, index, catalogId, context);
1371
+ requireScopedBinding(issues, catalogs, "usesCatalogs", catalogId, context);
1372
+ }
1373
+ const templateStepCatalog = findLeadGenTemplateStepCatalog(index);
1374
+ if (templateStepCatalog === void 0) {
1375
+ addReadinessIssue(
1376
+ issues,
1377
+ "SYSTEM_INTERFACE_NOT_READY",
1378
+ "missing-template-step-catalog",
1379
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" is missing a lead-gen template-step catalog.`
1380
+ );
1381
+ } else {
1382
+ requireCatalogReadiness(issues, index, templateStepCatalog.id, context);
1383
+ requireScopedBinding(issues, catalogs, "usesCatalogs", templateStepCatalog.id, context);
1384
+ }
1385
+ const leadGenStageCatalog = requireCatalogReadiness(issues, index, LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID, context);
1386
+ return leadGenStageCatalog;
1387
+ }
1388
+ function requireCrmInterfaceReadiness(issues, index, resources, context) {
1389
+ const catalogs = resourceBindingIds(resources, "usesCatalogs");
1390
+ const crmPipelineCatalog = requireCatalogReadiness(issues, index, CRM_PIPELINE_CATALOG_ONTOLOGY_ID, context);
1391
+ requireScopedBinding(issues, catalogs, "usesCatalogs", CRM_PIPELINE_CATALOG_ONTOLOGY_ID, context);
1392
+ return crmPipelineCatalog;
1393
+ }
1394
+ function findSystemInterfaceGrant(model, consumer, provider) {
1395
+ return Object.values(model.topology?.relationships ?? {}).find((relationship) => {
1396
+ const grant = relationship.metadata?.["systemInterfaceGrant"];
1397
+ if (!isPlainRecord(grant) || !isPlainRecord(grant.consumer) || !isPlainRecord(grant.provider)) return false;
1398
+ return grant.consumer.systemPath === consumer.systemPath && grant.consumer.interfaceKey === consumer.interfaceKey && grant.provider.systemPath === provider.systemPath && grant.provider.interfaceKey === provider.interfaceKey;
1399
+ });
1400
+ }
1401
+ function requireHandoffBridgeReadiness(issues, model, context) {
1402
+ const crmResult = computeInterfaceReadiness(model, CRM_API_INTERFACE);
1403
+ if (!crmResult.ready) {
1404
+ for (const issue of crmResult.issues) {
1405
+ addReadinessIssue(
1406
+ issues,
1407
+ "SYSTEM_BRIDGE_NOT_READY",
1408
+ issue.code,
1409
+ `Provider interface ${formatInterfaceIdentity(CRM_API_INTERFACE.systemPath, CRM_API_INTERFACE.interfaceKey)} is not ready: ${issue.message}`,
1410
+ { path: issue.path, ref: issue.ref }
1411
+ );
1412
+ }
1413
+ }
1414
+ const bridgeGrant = findSystemInterfaceGrant(model, context, CRM_API_INTERFACE);
1415
+ if (bridgeGrant === void 0) {
1416
+ addReadinessIssue(
1417
+ issues,
1418
+ "SYSTEM_BRIDGE_NOT_READY",
1419
+ "missing-topology-grant",
1420
+ `System Interface "${formatInterfaceIdentity(context.systemPath, context.interfaceKey)}" requires a scoped topology grant to "${formatInterfaceIdentity(CRM_API_INTERFACE.systemPath, CRM_API_INTERFACE.interfaceKey)}".`
1421
+ );
1422
+ }
1423
+ return bridgeGrant;
1424
+ }
1425
+ function getLeadGenCrmHandoffResourceIds(model) {
1426
+ return Object.values(model.resources ?? {}).filter(
1427
+ (resource) => resource.systemPath === LEAD_GEN_CRM_HANDOFF_INTERFACE.systemPath && resource.ontology?.usesCatalogs?.includes(CRM_PIPELINE_CATALOG_ONTOLOGY_ID) === true
1428
+ ).map((resource) => resource.id);
1429
+ }
1430
+ function getSystemInterfaceReadinessMarker(model, request) {
1431
+ const system = getSystem(model, request.systemPath);
1432
+ if (system === void 0) return void 0;
1433
+ if (request.interfaceKey === LEAD_GEN_API_INTERFACE.interfaceKey) {
1434
+ return system.apiInterface;
1435
+ }
1436
+ if (request.systemPath === LEAD_GEN_CRM_HANDOFF_INTERFACE.systemPath && request.interfaceKey === LEAD_GEN_CRM_HANDOFF_INTERFACE.interfaceKey) {
1437
+ return {
1438
+ lifecycle: "active",
1439
+ readinessProfile: LEAD_GEN_CRM_HANDOFF_INTERFACE.readinessProfile,
1440
+ resourceIds: getLeadGenCrmHandoffResourceIds(model)
1441
+ };
1442
+ }
1443
+ return void 0;
1444
+ }
1445
+ function mergeLeadGenDerivedCatalogs(model) {
1446
+ const baseCatalogTypes = model.ontology?.catalogTypes ?? {};
1447
+ const derivedCatalogTypes = {};
1448
+ if (baseCatalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID] === void 0) {
1449
+ derivedCatalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID] = createLeadGenStageCatalog(model);
1450
+ }
1451
+ if (Object.keys(derivedCatalogTypes).length === 0) return model;
1452
+ return {
1453
+ ...model,
1454
+ ontology: {
1455
+ ...model.ontology ?? {},
1456
+ catalogTypes: {
1457
+ ...baseCatalogTypes,
1458
+ ...derivedCatalogTypes
1459
+ }
1460
+ }
1461
+ };
1462
+ }
1463
+ function compileBusinessOntology(model, contractId) {
1464
+ const compilation = compileOrganizationOntology(mergeLeadGenDerivedCatalogs(model));
1465
+ if (compilation.diagnostics.length > 0) {
1466
+ const summary = compilation.diagnostics.map((diagnostic) => diagnostic.message).join("; ");
1467
+ throw new Error(`${contractId} ontology validation index failed to compile: ${summary}`);
1468
+ }
1469
+ return {
1470
+ ontology: compilation.ontology,
1471
+ actionTypesByLegacyId: indexActionTypesByLegacyId(compilation.ontology.actionTypes)
1472
+ };
1473
+ }
1474
+ function tryCompileBusinessOntology(model, readinessProfile, issues) {
1475
+ try {
1476
+ return compileBusinessOntology(model, readinessProfile);
1477
+ } catch (error) {
1478
+ addReadinessIssue(
1479
+ issues,
1480
+ "SYSTEM_INTERFACE_INVALID",
1481
+ "ontology-compile-failed",
1482
+ error instanceof Error ? error.message : String(error)
1483
+ );
1484
+ return void 0;
1485
+ }
1486
+ }
1487
+ function computeInterfaceReadiness(model, request) {
1488
+ const issues = [];
1489
+ const system = getSystem(model, request.systemPath);
1490
+ const systemInterface = getSystemInterfaceReadinessMarker(model, request);
1491
+ const readinessProfile = systemInterface === void 0 ? void 0 : profileForInterface(request.systemPath, request.interfaceKey, systemInterface.readinessProfile);
1492
+ const scopedResourceIds = systemInterface?.resourceIds ?? [];
1493
+ if (system === void 0) {
1494
+ addReadinessIssue(
1495
+ issues,
1496
+ "SYSTEM_INTERFACE_MISSING",
1497
+ "missing-system",
1498
+ `System "${request.systemPath}" is missing.`,
1499
+ { ref: request.systemPath }
1500
+ );
1501
+ return { ready: false, systemPath: request.systemPath, interfaceKey: request.interfaceKey, scopedResourceIds, issues };
1502
+ }
1503
+ if (systemInterface === void 0) {
1504
+ addReadinessIssue(
1505
+ issues,
1506
+ "SYSTEM_INTERFACE_MISSING",
1507
+ "missing-interface",
1508
+ `System "${request.systemPath}" does not declare interface "${request.interfaceKey}".`,
1509
+ { path: readinessMarkerPath(request) }
1510
+ );
1511
+ return { ready: false, systemPath: request.systemPath, interfaceKey: request.interfaceKey, scopedResourceIds, issues };
1512
+ }
1513
+ if (systemInterface.lifecycle !== "active") {
1514
+ addReadinessIssue(
1515
+ issues,
1516
+ "SYSTEM_INTERFACE_DISABLED",
1517
+ "inactive-interface",
1518
+ `System Interface "${formatInterfaceIdentity(request.systemPath, request.interfaceKey)}" lifecycle is "${systemInterface.lifecycle}".`,
1519
+ { path: `${readinessMarkerPath(request)}.lifecycle` }
1520
+ );
1521
+ }
1522
+ const supportedProfile = readinessProfile !== void 0 && SYSTEM_INTERFACE_PROFILES.some((profile) => profile.readinessProfile === readinessProfile);
1523
+ if (!supportedProfile) {
1524
+ addReadinessIssue(
1525
+ issues,
1526
+ "SYSTEM_INTERFACE_INVALID",
1527
+ "unknown-readiness-profile",
1528
+ `System Interface "${formatInterfaceIdentity(request.systemPath, request.interfaceKey)}" references unknown readiness profile "${readinessProfile}". Supported profiles: ${formatSupportedReadinessProfiles()}. Custom Systems should not declare apiInterface; route custom behavior through workflows/operations plus ontology, resources, and topology.`,
1529
+ { path: `${readinessMarkerPath(request)}.readinessProfile`, ref: readinessProfile }
1530
+ );
1531
+ return {
1532
+ ready: false,
1533
+ systemPath: request.systemPath,
1534
+ interfaceKey: request.interfaceKey,
1535
+ readinessProfile,
1536
+ scopedResourceIds,
1537
+ issues
1538
+ };
1539
+ }
1540
+ if (scopedResourceIds.length === 0) {
1541
+ addReadinessIssue(
1542
+ issues,
1543
+ "SYSTEM_INTERFACE_NOT_READY",
1544
+ "missing-scoped-resources",
1545
+ `System Interface "${formatInterfaceIdentity(request.systemPath, request.interfaceKey)}" must scope at least one active resource.`,
1546
+ { path: `${readinessMarkerPath(request)}.resourceIds` }
1547
+ );
1548
+ }
1549
+ const checkedReadinessProfile = readinessProfile;
1550
+ if (checkedReadinessProfile === void 0) {
1551
+ throw new Error("Supported readiness profile unexpectedly resolved to undefined");
1552
+ }
1553
+ const resources = getActiveScopedResources(model, scopedResourceIds, issues, request);
1554
+ const index = tryCompileBusinessOntology(model, checkedReadinessProfile, issues);
1555
+ if (index !== void 0) {
1556
+ if (checkedReadinessProfile === LEAD_GEN_API_INTERFACE.readinessProfile) {
1557
+ requireLeadGenInterfaceReadiness(issues, index, resources, request);
1558
+ } else if (checkedReadinessProfile === CRM_API_INTERFACE.readinessProfile) {
1559
+ requireCrmInterfaceReadiness(issues, index, resources, request);
1560
+ } else if (checkedReadinessProfile === LEAD_GEN_CRM_HANDOFF_INTERFACE.readinessProfile) {
1561
+ requireLeadGenInterfaceReadiness(issues, index, resources, request);
1562
+ requireCrmInterfaceReadiness(issues, index, resources, { ...request, allowForeignOwner: true });
1563
+ requireHandoffBridgeReadiness(issues, model, request);
1564
+ }
1565
+ }
1566
+ return {
1567
+ ready: issues.length === 0,
1568
+ systemPath: request.systemPath,
1569
+ interfaceKey: request.interfaceKey,
1570
+ readinessProfile,
1571
+ scopedResourceIds,
1572
+ issues
1573
+ };
1574
+ }
1575
+ function findLeadGenTemplateStepCatalog(index) {
1576
+ return Object.values(index.ontology.catalogTypes).find(
1577
+ (catalog) => catalog.ownerSystemId === "sales.lead-gen" && catalog.kind === "template-step" && catalog.appliesTo === LEAD_GEN_LIST_OBJECT_ONTOLOGY_ID
1578
+ );
1579
+ }
1580
+ function indexActionTypesByLegacyId(actionTypes) {
1581
+ const byLegacyId = {};
1582
+ for (const actionType of Object.values(actionTypes)) {
1583
+ const legacyActionId = actionType["legacyActionId"];
1584
+ if (typeof legacyActionId === "string") {
1585
+ byLegacyId[legacyActionId] = actionType;
1586
+ }
1587
+ }
1588
+ return byLegacyId;
1589
+ }
1590
+ function getCatalogEntries(catalog) {
1591
+ return isPlainRecord(catalog.entries) ? catalog.entries : {};
1592
+ }
1593
+
1594
+ // ../core/src/platform/registry/resource-metadata.ts
1595
+ var resourceTypeIconNames = {
1596
+ agent: "IconBrain",
1597
+ workflow: "IconGitBranch",
1598
+ trigger: "IconBolt",
1599
+ integration: "IconPlug",
1600
+ external: "IconExternalLink",
1601
+ human: "IconUser"
1602
+ };
1603
+ var resourceTypeColors = {
1604
+ agent: "violet",
1605
+ workflow: "blue",
1606
+ trigger: "orange",
1607
+ integration: "teal",
1608
+ external: "gray",
1609
+ human: "yellow"
1610
+ };
1611
+ function getResourceIconName(type) {
1612
+ return resourceTypeIconNames[type];
1613
+ }
1614
+ function getResourceColor(type) {
1615
+ return resourceTypeColors[type];
1616
+ }
1617
+
1618
+ // ../core/src/operations/observability/utils.ts
1619
+ function getTimeRangeDates(range) {
1620
+ const end = /* @__PURE__ */ new Date();
1621
+ const start = /* @__PURE__ */ new Date();
1622
+ switch (range) {
1623
+ case "1h":
1624
+ start.setHours(start.getHours() - 1);
1625
+ break;
1626
+ case "24h":
1627
+ start.setHours(start.getHours() - 24);
1628
+ break;
1629
+ case "7d":
1630
+ start.setDate(start.getDate() - 7);
1631
+ break;
1632
+ case "30d":
1633
+ start.setDate(start.getDate() - 30);
1634
+ break;
1635
+ }
1636
+ return {
1637
+ startDate: start.toISOString(),
1638
+ endDate: end.toISOString()
1639
+ };
1640
+ }
1641
+ function getTimeRangeLabel(range) {
1642
+ switch (range) {
1643
+ case "1h":
1644
+ return "Last 1 hour";
1645
+ case "24h":
1646
+ return "Last 24 hours";
1647
+ case "7d":
1648
+ return "Last 7 days";
1649
+ case "30d":
1650
+ return "Last 30 days";
1651
+ }
1652
+ }
1653
+ function formatBucketTime(timestamp, granularity) {
1654
+ const date = new Date(timestamp);
1655
+ if (granularity === "hour") {
1656
+ return date.toLocaleTimeString("en-US", {
1657
+ hour: "2-digit",
1658
+ minute: "2-digit",
1659
+ hour12: false
1660
+ });
1661
+ }
1662
+ return date.toLocaleDateString("en-US", {
1663
+ month: "short",
1664
+ day: "numeric"
1665
+ });
1666
+ }
1667
+
1668
+ // src/utils/resource-icons.tsx
1669
+ var iconNameToComponent = {
1670
+ IconBrain,
1671
+ IconGitBranch,
1672
+ IconBolt,
1673
+ IconPlug,
1674
+ IconExternalLink,
1675
+ IconUser
1676
+ };
1677
+ function getResourceIcon(type) {
1678
+ const iconName = getResourceIconName(type);
1679
+ return iconNameToComponent[iconName];
1680
+ }
1681
+
1682
+ // src/utils/constants/api.ts
1683
+ var API_URL = import.meta.env.PROD ? "https://api.elevasis.io" : "http://localhost:5170";
1684
+
1685
+ // src/utils/constants/cache.ts
1686
+ var STALE_TIME_MONITORING = 3e4;
1687
+ var STALE_TIME_ADMIN = 6e4;
1688
+ var STALE_TIME_DEFAULT = 3e5;
1689
+ var GC_TIME_SHORT = 3e5;
1690
+ var GC_TIME_MEDIUM = 6e5;
1691
+ var GC_TIME_LONG = 18e5;
1692
+
1693
+ // src/utils/constants/polling.ts
1694
+ var REFETCH_INTERVAL_DASHBOARD = 6e4;
1695
+ var REFETCH_INTERVAL_REALTIME = 3e4;
1696
+ var REFETCH_INTERVAL_RUNNING = 2e3;
1697
+ var REFETCH_INTERVAL_RUNNING_FAST = 1e3;
1698
+
1699
+ // src/utils/constants/reconnection.ts
1700
+ var SSE_TOKEN_REFRESH_DELAY = 2e3;
1701
+ var SSE_CLOSE_GRACE_PERIOD = 5e3;
1702
+ var WS_RECONNECT_BASE_DELAY = 1e3;
1703
+ var WS_RECONNECT_MAX_DELAY = 3e4;
1704
+ var WS_MAX_RETRIES_BEFORE_ERROR = 3;
1705
+
1706
+ // src/utils/constants/ui.ts
1707
+ var PAGE_SIZE_DEFAULT = 20;
1708
+ var LIMIT_ACTIVITY_FEED = 50;
1709
+ var DEBOUNCE_FILTER = 150;
1710
+ var DEBOUNCE_SLIDER = 500;
1711
+ var OAUTH_FLOW_TIMEOUT = 3e5;
1712
+
1713
+ // src/utils/suppress-warnings.ts
1714
+ var SUPPRESSED_WARNINGS = [
1715
+ // Mantine SegmentedControl data-orientation deprecation warnings
1716
+ /Unsupported style property.*data-orientation/i,
1717
+ /Did you mean.*dataOrientation/i,
1718
+ // Recharts/Mantine Charts dimension warnings (charts work fine after layout completes)
1719
+ /The width\(-1\) and height\(-1\) of chart should be greater than 0/i
1720
+ ];
1721
+ var originalConsoleError = console.error;
1722
+ var originalConsoleWarn = console.warn;
1723
+ function suppressKnownWarnings() {
1724
+ console.error = (...args) => {
1725
+ const message = args.join(" ");
1726
+ const shouldSuppress = SUPPRESSED_WARNINGS.some((pattern) => pattern.test(message));
1727
+ if (!shouldSuppress) {
1728
+ originalConsoleError(...args);
1729
+ }
1730
+ };
1731
+ console.warn = (...args) => {
1732
+ const message = args.join(" ");
1733
+ const shouldSuppress = SUPPRESSED_WARNINGS.some((pattern) => pattern.test(message));
1734
+ if (!shouldSuppress) {
1735
+ originalConsoleWarn(...args);
1736
+ }
1737
+ };
1738
+ }
1739
+ function restoreConsole() {
1740
+ console.error = originalConsoleError;
1741
+ console.warn = originalConsoleWarn;
1742
+ }
1743
+
1744
+ // src/utils/browser-mocks.ts
1745
+ function setupMatchMedia() {
1746
+ const win = globalThis.window;
1747
+ if (typeof win === "undefined") return;
1748
+ Object.defineProperty(win, "matchMedia", {
1749
+ writable: true,
1750
+ value: (query) => ({
1751
+ matches: false,
1752
+ media: query,
1753
+ onchange: null,
1754
+ addListener: () => {
1755
+ },
1756
+ removeListener: () => {
1757
+ },
1758
+ addEventListener: () => {
1759
+ },
1760
+ removeEventListener: () => {
1761
+ },
1762
+ dispatchEvent: () => true
1763
+ })
1764
+ });
1765
+ }
1766
+ function setupResizeObserver() {
1767
+ globalThis.ResizeObserver = class ResizeObserver {
1768
+ observe() {
1769
+ }
1770
+ unobserve() {
1771
+ }
1772
+ disconnect() {
1773
+ }
1774
+ };
1775
+ }
1776
+ function setupBrowserMocks() {
1777
+ setupMatchMedia();
1778
+ setupResizeObserver();
1779
+ }
1780
+
1781
+ export { APIClientError, API_URL, ActionInvocationSchema, ActionSchema, ActionsDomainSchema, DEBOUNCE_FILTER, DEBOUNCE_SLIDER, DEFAULT_ONTOLOGY_SCOPE, DEFAULT_ORGANIZATION_MODEL_ACTIONS, DEFAULT_ORGANIZATION_MODEL_SYSTEMS, DescriptionSchema, EntitiesDomainSchema, EntitySchema, GC_TIME_LONG, GC_TIME_MEDIUM, GC_TIME_SHORT, IconNameSchema, JsonValueSchema, LEAD_GEN_API_INTERFACE, LIMIT_ACTIVITY_FEED, LabelSchema, ModelIdSchema, NodeIdStringSchema, OAUTH_FLOW_TIMEOUT, OntologyIdSchema, OntologyScopeSchema, PAGE_SIZE_DEFAULT, PathSchema, REFETCH_INTERVAL_DASHBOARD, REFETCH_INTERVAL_REALTIME, REFETCH_INTERVAL_RUNNING, REFETCH_INTERVAL_RUNNING_FAST, SSE_CLOSE_GRACE_PERIOD, SSE_TOKEN_REFRESH_DELAY, STALE_TIME_ADMIN, STALE_TIME_DEFAULT, STALE_TIME_MONITORING, SystemEntrySchema, SystemIdSchema, SystemInterfaceRefSchema, SystemLifecycleSchema, SystemPathSchema, SystemsDomainSchema, WS_MAX_RETRIES_BEFORE_ERROR, WS_RECONNECT_BASE_DELAY, WS_RECONNECT_MAX_DELAY, ancestorsOf, childrenOf, compileOrganizationOntology, computeInterfaceReadiness, debounce, defaultPathFor, defineActions, defineEntities, devOnlyFor, findById, findByPath, formatBucketTime, formatChartAxisDate, formatDate, formatDateTime, formatErrorMessage, formatRelativeTime, formatTimeAgo, getAllBuildTemplates, getAllPipelines, getAllProjectStatuses, getAllProspectingStages, getErrorInfo, getErrorTitle, getLeadGenStageCatalog, getResourceColor, getResourceIcon, getResourcesForSystem, getSystem, getSystemAncestors, getTimeRangeDates, getTimeRangeLabel, isAPIClientError, listAllSystems, listResolvedOntologyRecords, ontologyGraphNodeId, parentOf, parseOntologyId, requiresAdminFor, resolveSystemConfig, restoreConsole, setupBrowserMocks, suppressKnownWarnings, topLevel, validateEmail };