@elevasis/core 0.21.0 → 0.23.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.
- package/dist/index.d.ts +2518 -2169
- package/dist/index.js +2495 -1095
- package/dist/knowledge/index.d.ts +706 -1044
- package/dist/knowledge/index.js +9 -9
- package/dist/organization-model/index.d.ts +2518 -2169
- package/dist/organization-model/index.js +2495 -1095
- package/dist/test-utils/index.d.ts +826 -1014
- package/dist/test-utils/index.js +1894 -1032
- package/package.json +3 -3
- package/src/__tests__/template-core-compatibility.test.ts +11 -79
- package/src/_gen/__tests__/__snapshots__/contracts.md.snap +852 -397
- package/src/auth/multi-tenancy/permissions.ts +20 -8
- package/src/business/README.md +2 -2
- package/src/business/acquisition/api-schemas.test.ts +175 -2
- package/src/business/acquisition/api-schemas.ts +132 -16
- package/src/business/acquisition/build-templates.test.ts +4 -4
- package/src/business/acquisition/build-templates.ts +72 -30
- package/src/business/acquisition/crm-state-actions.test.ts +13 -11
- package/src/business/acquisition/index.ts +12 -0
- package/src/business/acquisition/types.ts +7 -3
- package/src/business/clients/api-schemas.test.ts +115 -0
- package/src/business/clients/api-schemas.ts +158 -0
- package/src/business/clients/index.ts +1 -0
- package/src/business/deals/api-schemas.ts +8 -0
- package/src/business/index.ts +5 -2
- package/src/business/projects/types.ts +19 -0
- package/src/execution/engine/__tests__/fixtures/test-agents.ts +10 -8
- package/src/execution/engine/agent/core/__tests__/agent.test.ts +16 -12
- package/src/execution/engine/agent/core/__tests__/error-passthrough.test.ts +4 -3
- package/src/execution/engine/agent/core/types.ts +25 -15
- package/src/execution/engine/agent/index.ts +6 -4
- package/src/execution/engine/agent/reasoning/__tests__/request-builder.test.ts +24 -18
- package/src/execution/engine/index.ts +3 -0
- package/src/execution/engine/workflow/types.ts +9 -2
- package/src/knowledge/README.md +8 -7
- package/src/knowledge/__tests__/queries.test.ts +74 -73
- package/src/knowledge/format.ts +10 -9
- package/src/knowledge/index.ts +1 -1
- package/src/knowledge/published.ts +1 -1
- package/src/knowledge/queries.ts +26 -25
- package/src/organization-model/README.md +73 -26
- package/src/organization-model/__tests__/content-kinds-registry.test.ts +210 -0
- package/src/organization-model/__tests__/defaults.test.ts +76 -96
- package/src/organization-model/__tests__/domains/actions.test.ts +56 -0
- package/src/organization-model/__tests__/domains/customers.test.ts +299 -295
- package/src/organization-model/__tests__/domains/entities.test.ts +56 -0
- package/src/organization-model/__tests__/domains/goals.test.ts +493 -479
- package/src/organization-model/__tests__/domains/identity.test.ts +280 -279
- package/src/organization-model/__tests__/domains/navigation.test.ts +268 -212
- package/src/organization-model/__tests__/domains/offerings.test.ts +414 -419
- package/src/organization-model/__tests__/domains/policies.test.ts +323 -0
- package/src/organization-model/__tests__/domains/resource-mappings.test.ts +271 -271
- package/src/organization-model/__tests__/domains/resources.test.ts +310 -0
- package/src/organization-model/__tests__/domains/roles.test.ts +463 -347
- package/src/organization-model/__tests__/domains/statuses.test.ts +246 -243
- package/src/organization-model/__tests__/domains/systems.test.ts +209 -0
- package/src/organization-model/__tests__/flatten-additive-merge.test.ts +361 -0
- package/src/organization-model/__tests__/foundation.test.ts +74 -102
- package/src/organization-model/__tests__/get-resources-for-system.test.ts +144 -0
- package/src/organization-model/__tests__/graph.test.ts +899 -71
- package/src/organization-model/__tests__/knowledge.test.ts +209 -49
- package/src/organization-model/__tests__/lookup-helpers.test.ts +438 -0
- package/src/organization-model/__tests__/migration-helpers.test.ts +591 -0
- package/src/organization-model/__tests__/prospecting-ssot.test.ts +36 -27
- package/src/organization-model/__tests__/recursive-system-schema.test.ts +520 -0
- package/src/organization-model/__tests__/resolve.test.ts +174 -23
- package/src/organization-model/__tests__/schema.test.ts +291 -114
- package/src/organization-model/__tests__/surface-projection.test.ts +207 -97
- package/src/organization-model/catalogs/lead-gen.ts +144 -0
- package/src/organization-model/content-kinds/config.ts +36 -0
- package/src/organization-model/content-kinds/index.ts +74 -0
- package/src/organization-model/content-kinds/pipeline.ts +68 -0
- package/src/organization-model/content-kinds/registry.ts +44 -0
- package/src/organization-model/content-kinds/status.ts +71 -0
- package/src/organization-model/content-kinds/template.ts +83 -0
- package/src/organization-model/content-kinds/types.ts +117 -0
- package/src/organization-model/contracts.ts +13 -3
- package/src/organization-model/defaults.ts +499 -86
- package/src/organization-model/domains/actions.ts +239 -0
- package/src/organization-model/domains/customers.ts +78 -75
- package/src/organization-model/domains/entities.ts +144 -0
- package/src/organization-model/domains/goals.ts +83 -80
- package/src/organization-model/domains/knowledge.ts +76 -17
- package/src/organization-model/domains/navigation.ts +107 -384
- package/src/organization-model/domains/offerings.ts +71 -66
- package/src/organization-model/domains/policies.ts +102 -0
- package/src/organization-model/domains/projects.ts +14 -48
- package/src/organization-model/domains/prospecting.ts +62 -181
- package/src/organization-model/domains/resources.ts +145 -0
- package/src/organization-model/domains/roles.ts +96 -55
- package/src/organization-model/domains/sales.ts +10 -219
- package/src/organization-model/domains/shared.ts +57 -57
- package/src/organization-model/domains/statuses.ts +339 -130
- package/src/organization-model/domains/systems.ts +203 -0
- package/src/organization-model/foundation.ts +54 -67
- package/src/organization-model/graph/build.ts +682 -54
- package/src/organization-model/graph/link.ts +1 -1
- package/src/organization-model/graph/schema.ts +24 -9
- package/src/organization-model/graph/types.ts +20 -7
- package/src/organization-model/helpers.ts +231 -26
- package/src/organization-model/icons.ts +1 -0
- package/src/organization-model/index.ts +118 -5
- package/src/organization-model/migration-helpers.ts +249 -0
- package/src/organization-model/organization-graph.mdx +16 -15
- package/src/organization-model/organization-model.mdx +111 -44
- package/src/organization-model/published.ts +172 -19
- package/src/organization-model/resolve.ts +117 -54
- package/src/organization-model/schema.ts +654 -112
- package/src/organization-model/surface-projection.ts +116 -122
- package/src/organization-model/types.ts +146 -20
- package/src/platform/api/types.ts +38 -35
- package/src/platform/constants/versions.ts +1 -1
- package/src/platform/registry/__tests__/command-view.test.ts +6 -8
- package/src/platform/registry/__tests__/resource-link.test.ts +13 -8
- package/src/platform/registry/__tests__/resource-registry.integration.test.ts +16 -31
- package/src/platform/registry/__tests__/resource-registry.nested-systems.test.ts +245 -0
- package/src/platform/registry/__tests__/resource-registry.test.ts +2053 -2005
- package/src/platform/registry/__tests__/validation.test.ts +1347 -1086
- package/src/platform/registry/index.ts +14 -0
- package/src/platform/registry/resource-registry.ts +52 -2
- package/src/platform/registry/serialization.ts +241 -202
- package/src/platform/registry/serialized-types.ts +1 -0
- package/src/platform/registry/types.ts +411 -361
- package/src/platform/registry/validation.ts +745 -513
- package/src/projects/api-schemas.ts +290 -267
- package/src/reference/_generated/contracts.md +853 -397
- package/src/reference/glossary.md +23 -18
- package/src/supabase/database.types.ts +181 -0
- package/src/test-utils/test-utils.test.ts +1 -6
- package/src/organization-model/__tests__/domains/operations.test.ts +0 -203
- package/src/organization-model/domains/features.ts +0 -31
- package/src/organization-model/domains/operations.ts +0 -85
|
@@ -1,6 +1,190 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
2
|
|
|
3
3
|
// src/organization-model/schema.ts
|
|
4
|
+
|
|
5
|
+
// src/organization-model/content-kinds/registry.ts
|
|
6
|
+
function defineContentType(def) {
|
|
7
|
+
return def;
|
|
8
|
+
}
|
|
9
|
+
var ContentNodeBaseSchema = z.object({
|
|
10
|
+
/** Human-readable label for the content node. */
|
|
11
|
+
label: z.string().trim().min(1).max(120).meta({ label: "Label" }),
|
|
12
|
+
/** Optional one-paragraph description. */
|
|
13
|
+
description: z.string().trim().min(1).max(2e3).optional().meta({ label: "Description" }),
|
|
14
|
+
/** Optional display order within the system content map. */
|
|
15
|
+
order: z.number().int().optional().meta({ label: "Order" }),
|
|
16
|
+
/**
|
|
17
|
+
* Local NodeId of the parent content node within the SAME system.
|
|
18
|
+
* Per B4/L9: MUST resolve to a sibling in the same `system.content` map.
|
|
19
|
+
* Per L19: parent and child MUST share the same `kind` (meta-category).
|
|
20
|
+
*/
|
|
21
|
+
parentContentId: z.string().trim().min(1).max(200).optional().meta({ label: "Parent content id" })
|
|
22
|
+
});
|
|
23
|
+
var ContentNodeSchema = ContentNodeBaseSchema.extend({
|
|
24
|
+
/** Meta-category (e.g. 'schema', 'config', 'knowledge', tenant-defined). */
|
|
25
|
+
kind: z.string().trim().min(1).max(100).meta({ label: "Kind" }),
|
|
26
|
+
/** Specific family within the meta-category (e.g. 'pipeline', 'kv'). */
|
|
27
|
+
type: z.string().trim().min(1).max(100).meta({ label: "Type" }),
|
|
28
|
+
/** Payload data; validated against registered payloadSchema when (kind, type) is known. */
|
|
29
|
+
data: z.record(z.string(), z.unknown()).optional().meta({ label: "Data" })
|
|
30
|
+
});
|
|
31
|
+
z.object({
|
|
32
|
+
/** Meta-category (tenant-defined or registry-shipped). */
|
|
33
|
+
kind: z.string().trim().min(1).max(100).meta({ label: "Kind" }),
|
|
34
|
+
/** Specific family within the meta-category. */
|
|
35
|
+
type: z.string().trim().min(1).max(100).meta({ label: "Type" }),
|
|
36
|
+
/** Human-readable label shown in the KB tree and describe views. */
|
|
37
|
+
label: z.string().trim().min(1).max(120).meta({ label: "Label" }),
|
|
38
|
+
/** Optional description. */
|
|
39
|
+
description: z.string().trim().min(1).max(2e3).optional().meta({ label: "Description" }),
|
|
40
|
+
/**
|
|
41
|
+
* Which KB tree group this extension renders in.
|
|
42
|
+
* Per L6: 'business-model' places it alongside Customers / Offerings / Goals.
|
|
43
|
+
*/
|
|
44
|
+
treeGroup: z.union([z.enum(["profile", "business-model", "systems", "graph", "governance-wiring"]), z.string().min(1).max(100)]).meta({ label: "Tree group" }),
|
|
45
|
+
/** Untyped payload; shape governed by the registered payloadSchema when available. */
|
|
46
|
+
data: z.record(z.string(), z.unknown()).optional().meta({ label: "Data" })
|
|
47
|
+
});
|
|
48
|
+
var PipelinePayloadSchema = z.object({
|
|
49
|
+
/**
|
|
50
|
+
* Local NodeId of the entity this pipeline applies to (e.g. 'crm.deal').
|
|
51
|
+
* `.meta({ ref: 'entity' })` enables SchemaDrivenFieldList to render a
|
|
52
|
+
* clickable graph link to the referenced entity node.
|
|
53
|
+
*/
|
|
54
|
+
entityId: z.string().trim().min(1).max(200).meta({ label: "Entity", ref: "entity", hint: "The entity type this pipeline tracks" }),
|
|
55
|
+
/**
|
|
56
|
+
* Optional Kanban column color token for UI rendering.
|
|
57
|
+
*/
|
|
58
|
+
kanbanColor: z.string().trim().min(1).max(40).optional().meta({ label: "Kanban color", hint: "UI color token" })
|
|
59
|
+
});
|
|
60
|
+
var pipelineKind = defineContentType({
|
|
61
|
+
kind: "schema",
|
|
62
|
+
type: "pipeline",
|
|
63
|
+
label: "Pipeline",
|
|
64
|
+
description: "A named progression pipeline that applies to a specific entity type.",
|
|
65
|
+
payloadSchema: PipelinePayloadSchema,
|
|
66
|
+
parentTypes: []
|
|
67
|
+
});
|
|
68
|
+
var StagePayloadSchema = z.object({
|
|
69
|
+
/**
|
|
70
|
+
* Semantic classification for this stage.
|
|
71
|
+
* Drives color, icon, and CRM-priority logic in consuming views.
|
|
72
|
+
* Optional — prospecting stages use data.entityKind instead.
|
|
73
|
+
* Enum aligned with SalesStageSemanticClassSchema (sales.ts).
|
|
74
|
+
*/
|
|
75
|
+
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" })
|
|
76
|
+
});
|
|
77
|
+
var stageKind = defineContentType({
|
|
78
|
+
kind: "schema",
|
|
79
|
+
type: "stage",
|
|
80
|
+
label: "Stage",
|
|
81
|
+
description: "A stage within a pipeline. Must be parented under a schema:pipeline content node.",
|
|
82
|
+
payloadSchema: StagePayloadSchema,
|
|
83
|
+
parentTypes: ["schema:pipeline"]
|
|
84
|
+
});
|
|
85
|
+
var TemplatePayloadSchema = z.object({
|
|
86
|
+
/**
|
|
87
|
+
* Optional description surfaced in the KB describe view and tooling.
|
|
88
|
+
*/
|
|
89
|
+
description: z.string().trim().min(1).max(2e3).optional().meta({ label: "Description", hint: "What this template is used for" })
|
|
90
|
+
});
|
|
91
|
+
var templateKind = defineContentType({
|
|
92
|
+
kind: "schema",
|
|
93
|
+
type: "template",
|
|
94
|
+
label: "Template",
|
|
95
|
+
description: "A named build template (e.g. a prospecting pipeline sequence).",
|
|
96
|
+
payloadSchema: TemplatePayloadSchema,
|
|
97
|
+
parentTypes: []
|
|
98
|
+
});
|
|
99
|
+
var TemplateStepPayloadSchema = z.object({
|
|
100
|
+
/**
|
|
101
|
+
* Which entity type this step primarily operates on.
|
|
102
|
+
*/
|
|
103
|
+
primaryEntity: z.enum(["company", "contact"]).meta({ label: "Primary entity", hint: "Entity type this step processes", color: "blue" }),
|
|
104
|
+
/**
|
|
105
|
+
* Action key identifying the workflow action executed by this step.
|
|
106
|
+
* `.meta({ ref: 'action' })` enables SchemaDrivenFieldList to render a
|
|
107
|
+
* clickable graph link.
|
|
108
|
+
*/
|
|
109
|
+
actionKey: z.string().trim().min(1).max(200).meta({ label: "Action", ref: "action", hint: "Workflow action executed by this step" }),
|
|
110
|
+
/**
|
|
111
|
+
* IDs of sibling step local NodeIds this step depends on.
|
|
112
|
+
*/
|
|
113
|
+
dependsOn: z.array(z.string().trim().min(1).max(200)).optional().meta({ label: "Depends on", hint: "Local NodeIds of prerequisite steps" })
|
|
114
|
+
});
|
|
115
|
+
var templateStepKind = defineContentType({
|
|
116
|
+
kind: "schema",
|
|
117
|
+
type: "template-step",
|
|
118
|
+
label: "Template Step",
|
|
119
|
+
description: "A step within a build template. Must be parented under a schema:template content node.",
|
|
120
|
+
payloadSchema: TemplateStepPayloadSchema,
|
|
121
|
+
parentTypes: ["schema:template"]
|
|
122
|
+
});
|
|
123
|
+
var StatusFlowPayloadSchema = z.object({
|
|
124
|
+
/**
|
|
125
|
+
* Which entity scope this status flow governs.
|
|
126
|
+
*/
|
|
127
|
+
appliesTo: z.enum(["project", "milestone", "task"]).meta({ label: "Applies to", hint: "Entity scope governed by this status flow", color: "blue" })
|
|
128
|
+
});
|
|
129
|
+
var statusFlowKind = defineContentType({
|
|
130
|
+
kind: "schema",
|
|
131
|
+
type: "status-flow",
|
|
132
|
+
label: "Status Flow",
|
|
133
|
+
description: "A named set of statuses governing a project, milestone, or task entity.",
|
|
134
|
+
payloadSchema: StatusFlowPayloadSchema,
|
|
135
|
+
parentTypes: []
|
|
136
|
+
});
|
|
137
|
+
var StatusPayloadSchema = z.object({
|
|
138
|
+
/**
|
|
139
|
+
* Semantic classification string for this status.
|
|
140
|
+
* Free-form to allow tenant-defined classifications (e.g. 'active', 'blocked',
|
|
141
|
+
* 'completed'). Used by UI to apply color and icon fallbacks.
|
|
142
|
+
* Optional — status nodes may omit this when the label is self-descriptive.
|
|
143
|
+
*/
|
|
144
|
+
semanticClass: z.string().trim().min(1).max(100).optional().meta({ label: "Semantic class", hint: "Semantic meaning of this status (e.g. active, blocked, completed)" }),
|
|
145
|
+
/**
|
|
146
|
+
* Optional UI color token override for this status.
|
|
147
|
+
*/
|
|
148
|
+
color: z.string().trim().min(1).max(40).optional().meta({ label: "Color", hint: "UI color token" })
|
|
149
|
+
});
|
|
150
|
+
var statusKind = defineContentType({
|
|
151
|
+
kind: "schema",
|
|
152
|
+
type: "status",
|
|
153
|
+
label: "Status",
|
|
154
|
+
description: "A single status within a status flow. Must be parented under a schema:status-flow content node.",
|
|
155
|
+
payloadSchema: StatusPayloadSchema,
|
|
156
|
+
parentTypes: ["schema:status-flow"]
|
|
157
|
+
});
|
|
158
|
+
var ConfigKvPayloadSchema = z.object({
|
|
159
|
+
/**
|
|
160
|
+
* Flat key-value entries. Values are JSON primitives.
|
|
161
|
+
* Keys are short identifiers (e.g. 'maxBatchSize', 'featureEnabled').
|
|
162
|
+
*/
|
|
163
|
+
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)" })
|
|
164
|
+
});
|
|
165
|
+
var configKvKind = defineContentType({
|
|
166
|
+
kind: "config",
|
|
167
|
+
type: "kv",
|
|
168
|
+
label: "Key-Value Config",
|
|
169
|
+
description: "A flat key-value configuration store co-located with a system. Values are JSON primitives.",
|
|
170
|
+
payloadSchema: ConfigKvPayloadSchema,
|
|
171
|
+
parentTypes: []
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
// src/organization-model/content-kinds/index.ts
|
|
175
|
+
var CONTENT_KIND_REGISTRY = {
|
|
176
|
+
"schema:pipeline": pipelineKind,
|
|
177
|
+
"schema:stage": stageKind,
|
|
178
|
+
"schema:template": templateKind,
|
|
179
|
+
"schema:template-step": templateStepKind,
|
|
180
|
+
"schema:status-flow": statusFlowKind,
|
|
181
|
+
"schema:status": statusKind,
|
|
182
|
+
"config:kv": configKvKind
|
|
183
|
+
};
|
|
184
|
+
function lookupContentType(kind, type) {
|
|
185
|
+
const key = `${kind}:${type}`;
|
|
186
|
+
return CONTENT_KIND_REGISTRY[key];
|
|
187
|
+
}
|
|
4
188
|
var ORGANIZATION_MODEL_ICON_TOKENS = [
|
|
5
189
|
"nav.dashboard",
|
|
6
190
|
"nav.calendar",
|
|
@@ -19,6 +203,7 @@ var ORGANIZATION_MODEL_ICON_TOKENS = [
|
|
|
19
203
|
"knowledge.reference",
|
|
20
204
|
"feature.dashboard",
|
|
21
205
|
"feature.calendar",
|
|
206
|
+
"feature.business",
|
|
22
207
|
"feature.sales",
|
|
23
208
|
"feature.crm",
|
|
24
209
|
"feature.finance",
|
|
@@ -111,10 +296,10 @@ DisplayMetadataSchema.extend({
|
|
|
111
296
|
id: ModelIdSchema,
|
|
112
297
|
resourceId: z.string().trim().min(1).max(255),
|
|
113
298
|
resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]),
|
|
114
|
-
|
|
299
|
+
systemIds: ReferenceIdsSchema,
|
|
115
300
|
entityIds: ReferenceIdsSchema,
|
|
116
301
|
surfaceIds: ReferenceIdsSchema,
|
|
117
|
-
|
|
302
|
+
actionIds: ReferenceIdsSchema,
|
|
118
303
|
/** Optional tech-stack metadata for external-SaaS integrations. */
|
|
119
304
|
techStack: TechStackEntrySchema.optional()
|
|
120
305
|
});
|
|
@@ -136,654 +321,7 @@ var DEFAULT_ORGANIZATION_MODEL_BRANDING = {
|
|
|
136
321
|
shortName: "Elevasis",
|
|
137
322
|
logos: {}
|
|
138
323
|
};
|
|
139
|
-
var
|
|
140
|
-
var SalesStageSchema = DisplayMetadataSchema.extend({
|
|
141
|
-
id: ModelIdSchema,
|
|
142
|
-
order: z.number().int().min(0),
|
|
143
|
-
semanticClass: SalesStageSemanticClassSchema,
|
|
144
|
-
surfaceIds: ReferenceIdsSchema,
|
|
145
|
-
resourceIds: ReferenceIdsSchema
|
|
146
|
-
});
|
|
147
|
-
var SalesPipelineSchema = z.object({
|
|
148
|
-
id: ModelIdSchema,
|
|
149
|
-
label: z.string().trim().min(1).max(120),
|
|
150
|
-
description: DescriptionSchema.optional(),
|
|
151
|
-
entityId: ModelIdSchema,
|
|
152
|
-
stages: z.array(SalesStageSchema).min(1)
|
|
153
|
-
});
|
|
154
|
-
var OrganizationModelSalesSchema = z.object({
|
|
155
|
-
entityId: ModelIdSchema,
|
|
156
|
-
defaultPipelineId: ModelIdSchema,
|
|
157
|
-
pipelines: z.array(SalesPipelineSchema).min(1)
|
|
158
|
-
});
|
|
159
|
-
var DEFAULT_ORGANIZATION_MODEL_SALES = {
|
|
160
|
-
entityId: "crm.deal",
|
|
161
|
-
defaultPipelineId: "default",
|
|
162
|
-
pipelines: [
|
|
163
|
-
{
|
|
164
|
-
id: "default",
|
|
165
|
-
label: "Default Pipeline",
|
|
166
|
-
entityId: "crm.deal",
|
|
167
|
-
stages: [
|
|
168
|
-
{
|
|
169
|
-
id: "interested",
|
|
170
|
-
label: "Interested",
|
|
171
|
-
color: "blue",
|
|
172
|
-
order: 1,
|
|
173
|
-
semanticClass: "open",
|
|
174
|
-
surfaceIds: ["crm.pipeline"],
|
|
175
|
-
resourceIds: []
|
|
176
|
-
},
|
|
177
|
-
{
|
|
178
|
-
id: "proposal",
|
|
179
|
-
label: "Proposal",
|
|
180
|
-
color: "yellow",
|
|
181
|
-
order: 2,
|
|
182
|
-
semanticClass: "active",
|
|
183
|
-
surfaceIds: ["crm.pipeline"],
|
|
184
|
-
resourceIds: []
|
|
185
|
-
},
|
|
186
|
-
{
|
|
187
|
-
id: "closing",
|
|
188
|
-
label: "Closing",
|
|
189
|
-
color: "lime",
|
|
190
|
-
order: 3,
|
|
191
|
-
semanticClass: "active",
|
|
192
|
-
surfaceIds: ["crm.pipeline"],
|
|
193
|
-
resourceIds: []
|
|
194
|
-
},
|
|
195
|
-
{
|
|
196
|
-
id: "closed_won",
|
|
197
|
-
label: "Closed Won",
|
|
198
|
-
color: "green",
|
|
199
|
-
order: 4,
|
|
200
|
-
semanticClass: "closed_won",
|
|
201
|
-
surfaceIds: ["crm.pipeline"],
|
|
202
|
-
resourceIds: []
|
|
203
|
-
},
|
|
204
|
-
{
|
|
205
|
-
id: "closed_lost",
|
|
206
|
-
label: "Closed Lost",
|
|
207
|
-
color: "red",
|
|
208
|
-
order: 5,
|
|
209
|
-
semanticClass: "closed_lost",
|
|
210
|
-
surfaceIds: ["crm.pipeline"],
|
|
211
|
-
resourceIds: []
|
|
212
|
-
},
|
|
213
|
-
{
|
|
214
|
-
id: "nurturing",
|
|
215
|
-
label: "Nurturing",
|
|
216
|
-
color: "grape",
|
|
217
|
-
order: 6,
|
|
218
|
-
semanticClass: "nurturing",
|
|
219
|
-
surfaceIds: ["crm.pipeline"],
|
|
220
|
-
resourceIds: []
|
|
221
|
-
}
|
|
222
|
-
]
|
|
223
|
-
}
|
|
224
|
-
]
|
|
225
|
-
};
|
|
226
|
-
var LEAD_GEN_STAGE_CATALOG = {
|
|
227
|
-
// Prospecting — company population
|
|
228
|
-
scraped: {
|
|
229
|
-
key: "scraped",
|
|
230
|
-
label: "Scraped",
|
|
231
|
-
description: "Company was scraped from a source directory (Apify actor run).",
|
|
232
|
-
order: 1,
|
|
233
|
-
entity: "company"
|
|
234
|
-
},
|
|
235
|
-
populated: {
|
|
236
|
-
key: "populated",
|
|
237
|
-
label: "Companies found",
|
|
238
|
-
description: "Companies have been found and added to the lead-gen list.",
|
|
239
|
-
order: 2,
|
|
240
|
-
entity: "company"
|
|
241
|
-
},
|
|
242
|
-
crawled: {
|
|
243
|
-
key: "crawled",
|
|
244
|
-
label: "Websites crawled",
|
|
245
|
-
description: "Company websites have been crawled (e.g. via Apify) and raw page content stored for downstream LLM analysis.",
|
|
246
|
-
order: 2.5,
|
|
247
|
-
entity: "company"
|
|
248
|
-
},
|
|
249
|
-
extracted: {
|
|
250
|
-
key: "extracted",
|
|
251
|
-
label: "Websites analyzed",
|
|
252
|
-
description: "Company websites have been analyzed for business signals.",
|
|
253
|
-
order: 3,
|
|
254
|
-
entity: "company"
|
|
255
|
-
},
|
|
256
|
-
enriched: {
|
|
257
|
-
key: "enriched",
|
|
258
|
-
label: "Enriched",
|
|
259
|
-
description: "Company or contact enriched with third-party data (e.g. Tomba, Anymailfinder).",
|
|
260
|
-
order: 4,
|
|
261
|
-
entity: "company"
|
|
262
|
-
},
|
|
263
|
-
"decision-makers-enriched": {
|
|
264
|
-
key: "decision-makers-enriched",
|
|
265
|
-
label: "Decision-makers found",
|
|
266
|
-
description: "Decision-maker contacts discovered and attached to a qualified company.",
|
|
267
|
-
order: 6,
|
|
268
|
-
entity: "company",
|
|
269
|
-
recordEntity: "contact",
|
|
270
|
-
recordStageKey: "discovered"
|
|
271
|
-
},
|
|
272
|
-
// Prospecting — contact discovery
|
|
273
|
-
discovered: {
|
|
274
|
-
key: "discovered",
|
|
275
|
-
label: "Decision-makers found",
|
|
276
|
-
description: "Decision-maker contact details have been found.",
|
|
277
|
-
order: 5,
|
|
278
|
-
entity: "contact"
|
|
279
|
-
},
|
|
280
|
-
verified: {
|
|
281
|
-
key: "verified",
|
|
282
|
-
label: "Emails verified",
|
|
283
|
-
description: "Contact email addresses have been checked for deliverability.",
|
|
284
|
-
order: 7,
|
|
285
|
-
entity: "contact"
|
|
286
|
-
},
|
|
287
|
-
// Qualification
|
|
288
|
-
qualified: {
|
|
289
|
-
key: "qualified",
|
|
290
|
-
label: "Companies qualified",
|
|
291
|
-
description: "Companies have been scored against the qualification criteria.",
|
|
292
|
-
order: 8,
|
|
293
|
-
entity: "company"
|
|
294
|
-
},
|
|
295
|
-
// Outreach
|
|
296
|
-
personalized: {
|
|
297
|
-
key: "personalized",
|
|
298
|
-
label: "Personalized",
|
|
299
|
-
description: "Outreach message personalized for the contact (Instantly personalization workflow).",
|
|
300
|
-
order: 9,
|
|
301
|
-
entity: "contact"
|
|
302
|
-
},
|
|
303
|
-
uploaded: {
|
|
304
|
-
key: "uploaded",
|
|
305
|
-
label: "Reviewed and exported",
|
|
306
|
-
description: "Approved records have been reviewed and exported for handoff.",
|
|
307
|
-
order: 10,
|
|
308
|
-
entity: "company",
|
|
309
|
-
additionalEntities: ["contact"]
|
|
310
|
-
},
|
|
311
|
-
interested: {
|
|
312
|
-
key: "interested",
|
|
313
|
-
label: "Interested",
|
|
314
|
-
description: "Contact replied with a positive signal (Instantly reply-handler transition).",
|
|
315
|
-
order: 11,
|
|
316
|
-
entity: "contact"
|
|
317
|
-
}
|
|
318
|
-
};
|
|
319
|
-
var ProjectsDomainStateSchema = DisplayMetadataSchema.extend({
|
|
320
|
-
id: ModelIdSchema,
|
|
321
|
-
order: z.number().int().min(0)
|
|
322
|
-
});
|
|
323
|
-
var OrganizationModelProjectsSchema = z.object({
|
|
324
|
-
projectEntityId: ModelIdSchema,
|
|
325
|
-
milestoneEntityId: ModelIdSchema,
|
|
326
|
-
taskEntityId: ModelIdSchema,
|
|
327
|
-
projectStatuses: z.array(ProjectsDomainStateSchema).min(1),
|
|
328
|
-
milestoneStatuses: z.array(ProjectsDomainStateSchema).min(1),
|
|
329
|
-
taskStatuses: z.array(ProjectsDomainStateSchema).min(1)
|
|
330
|
-
});
|
|
331
|
-
var DEFAULT_ORGANIZATION_MODEL_PROJECTS = {
|
|
332
|
-
projectEntityId: "delivery.project",
|
|
333
|
-
milestoneEntityId: "delivery.milestone",
|
|
334
|
-
taskEntityId: "delivery.task",
|
|
335
|
-
projectStatuses: [
|
|
336
|
-
{ id: "active", label: "Active", order: 1 },
|
|
337
|
-
{ id: "on_track", label: "On Track", order: 2 },
|
|
338
|
-
{ id: "at_risk", label: "At Risk", order: 3 },
|
|
339
|
-
{ id: "blocked", label: "Blocked", order: 4 },
|
|
340
|
-
{ id: "paused", label: "Paused", order: 5 },
|
|
341
|
-
{ id: "completed", label: "Completed", order: 6 }
|
|
342
|
-
],
|
|
343
|
-
milestoneStatuses: [
|
|
344
|
-
{ id: "upcoming", label: "Upcoming", order: 1 },
|
|
345
|
-
{ id: "in_progress", label: "In Progress", order: 2 },
|
|
346
|
-
{ id: "blocked", label: "Blocked", order: 3 },
|
|
347
|
-
{ id: "overdue", label: "Overdue", order: 4 },
|
|
348
|
-
{ id: "completed", label: "Completed", order: 5 }
|
|
349
|
-
],
|
|
350
|
-
taskStatuses: [
|
|
351
|
-
{ id: "planned", label: "Planned", order: 1 },
|
|
352
|
-
{ id: "in_progress", label: "In Progress", order: 2 },
|
|
353
|
-
{ id: "blocked", label: "Blocked", order: 3 },
|
|
354
|
-
{ id: "submitted", label: "Submitted", order: 4 },
|
|
355
|
-
{ id: "approved", label: "Approved", order: 5 },
|
|
356
|
-
{ id: "revision_requested", label: "Revision Requested", order: 6 },
|
|
357
|
-
{ id: "rejected", label: "Rejected", order: 7 },
|
|
358
|
-
{ id: "cancelled", label: "Cancelled", order: 8 },
|
|
359
|
-
{ id: "completed", label: "Completed", order: 9 }
|
|
360
|
-
]
|
|
361
|
-
};
|
|
362
|
-
var NodeIdPathSchema = z.string().trim().min(1).max(100).regex(/^([a-z0-9-]+)(\.[a-z0-9-]+)*$/, "Node IDs must be lowercase dotted paths");
|
|
363
|
-
var NodeIdStringSchema = z.string().trim().min(1).max(200).regex(/^[a-z]+:([a-z0-9-]+)(\.[a-z0-9-]+)*$/, "Node references must use kind:dotted-path");
|
|
364
|
-
var UiPositionSchema = z.enum(["sidebar-primary", "sidebar-bottom"]);
|
|
365
|
-
var FeatureSchema = z.object({
|
|
366
|
-
id: NodeIdPathSchema,
|
|
367
|
-
label: LabelSchema,
|
|
368
|
-
description: DescriptionSchema.optional(),
|
|
369
|
-
enabled: z.boolean().default(true),
|
|
370
|
-
path: PathSchema.optional(),
|
|
371
|
-
icon: IconNameSchema.optional(),
|
|
372
|
-
color: ColorTokenSchema.optional(),
|
|
373
|
-
uiPosition: UiPositionSchema.optional(),
|
|
374
|
-
requiresAdmin: z.boolean().optional(),
|
|
375
|
-
devOnly: z.boolean().optional()
|
|
376
|
-
});
|
|
377
|
-
var ProspectingLifecycleStageSchema = DisplayMetadataSchema.extend({
|
|
378
|
-
id: ModelIdSchema,
|
|
379
|
-
order: z.number().min(0)
|
|
380
|
-
});
|
|
381
|
-
var RecordColumnConfigSchema = z.object({
|
|
382
|
-
key: ModelIdSchema,
|
|
383
|
-
label: z.string().trim().min(1).max(120),
|
|
384
|
-
path: z.string().trim().min(1).max(500),
|
|
385
|
-
width: z.union([z.number().positive(), z.string().trim().min(1).max(100)]).optional(),
|
|
386
|
-
renderType: z.enum(["text", "badge", "datetime", "count", "json"]).optional(),
|
|
387
|
-
badgeColor: z.string().trim().min(1).max(40).optional()
|
|
388
|
-
});
|
|
389
|
-
var RecordColumnsConfigSchema = z.object({
|
|
390
|
-
company: z.array(RecordColumnConfigSchema).optional(),
|
|
391
|
-
contact: z.array(RecordColumnConfigSchema).optional()
|
|
392
|
-
}).refine((columns) => Boolean(columns.company?.length || columns.contact?.length), {
|
|
393
|
-
message: "recordColumns must include at least one entity column set"
|
|
394
|
-
});
|
|
395
|
-
var CredentialRequirementSchema = z.object({
|
|
396
|
-
key: ModelIdSchema,
|
|
397
|
-
provider: ModelIdSchema,
|
|
398
|
-
credentialType: z.enum(["api-key", "api-key-secret", "oauth", "webhook-secret"]),
|
|
399
|
-
label: z.string().trim().min(1).max(120),
|
|
400
|
-
required: z.boolean(),
|
|
401
|
-
selectionMode: z.enum(["single", "multiple"]).optional(),
|
|
402
|
-
inputPath: z.string().trim().min(1).max(500),
|
|
403
|
-
verifyOnRun: z.boolean().optional()
|
|
404
|
-
});
|
|
405
|
-
var ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
|
|
406
|
-
id: ModelIdSchema,
|
|
407
|
-
primaryEntity: z.enum(["company", "contact"]),
|
|
408
|
-
outputs: z.array(z.enum(["company", "contact", "export"])).min(1),
|
|
409
|
-
stageKey: ModelIdSchema,
|
|
410
|
-
recordEntity: z.enum(["company", "contact"]).optional(),
|
|
411
|
-
recordsStageKey: ModelIdSchema.optional(),
|
|
412
|
-
recordSourceStageKey: ModelIdSchema.optional(),
|
|
413
|
-
dependsOn: z.array(ModelIdSchema).optional(),
|
|
414
|
-
dependencyMode: z.literal("per-record-eligibility"),
|
|
415
|
-
capabilityKey: ModelIdSchema,
|
|
416
|
-
defaultBatchSize: z.number().int().positive(),
|
|
417
|
-
maxBatchSize: z.number().int().positive(),
|
|
418
|
-
recordColumns: RecordColumnsConfigSchema.optional(),
|
|
419
|
-
credentialRequirements: z.array(CredentialRequirementSchema).optional()
|
|
420
|
-
}).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
|
|
421
|
-
message: "defaultBatchSize must be less than or equal to maxBatchSize",
|
|
422
|
-
path: ["defaultBatchSize"]
|
|
423
|
-
});
|
|
424
|
-
var ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
|
|
425
|
-
id: ModelIdSchema,
|
|
426
|
-
steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
|
|
427
|
-
});
|
|
428
|
-
var DTC_RECORD_COLUMNS = {
|
|
429
|
-
populated: {
|
|
430
|
-
company: [
|
|
431
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
432
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
433
|
-
{ key: "employee-count", label: "Employees", path: "company.numEmployees", renderType: "count" },
|
|
434
|
-
{ key: "apollo-industry", label: "Apollo industry", path: "company.category" },
|
|
435
|
-
{ key: "location", label: "Location", path: "company.locationState" }
|
|
436
|
-
]
|
|
437
|
-
},
|
|
438
|
-
crawled: {
|
|
439
|
-
company: [
|
|
440
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
441
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
442
|
-
{ key: "page-count", label: "Pages", path: "company.enrichmentData.websiteCrawl.pageCount", renderType: "count" },
|
|
443
|
-
{ key: "crawl-status", label: "Crawl status", path: "processingState.crawled.status", renderType: "badge" }
|
|
444
|
-
]
|
|
445
|
-
},
|
|
446
|
-
extracted: {
|
|
447
|
-
company: [
|
|
448
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
449
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
450
|
-
{ key: "description", label: "Description", path: "company.enrichmentData.websiteCrawl.companyDescription" },
|
|
451
|
-
{ key: "services", label: "Services", path: "company.enrichmentData.websiteCrawl.services", renderType: "json" },
|
|
452
|
-
{ key: "automation-gaps", label: "Automation gaps", path: "company.enrichmentData.websiteCrawl.automationGaps", renderType: "json" },
|
|
453
|
-
{ key: "contact-count", label: "Contacts", path: "company.enrichmentData.websiteCrawl.emailCount", renderType: "count" }
|
|
454
|
-
]
|
|
455
|
-
},
|
|
456
|
-
qualified: {
|
|
457
|
-
company: [
|
|
458
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
459
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
460
|
-
{ key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
|
|
461
|
-
{ key: "signals", label: "Signals", path: "company.qualificationSignals", renderType: "json" },
|
|
462
|
-
{ key: "disqualified-reason", label: "Disqualified reason", path: "processingState.qualified.data.disqualifiedReason" }
|
|
463
|
-
]
|
|
464
|
-
},
|
|
465
|
-
decisionMakers: {
|
|
466
|
-
contact: [
|
|
467
|
-
{ key: "name", label: "Name", path: "contact.name" },
|
|
468
|
-
{ key: "title", label: "Title", path: "contact.title" },
|
|
469
|
-
{ key: "email", label: "Email", path: "contact.email" },
|
|
470
|
-
{ key: "linkedin", label: "LinkedIn", path: "contact.linkedinUrl" },
|
|
471
|
-
{ key: "priority-score", label: "Priority", path: "contact.enrichmentData.apollo.priorityScore", renderType: "badge" }
|
|
472
|
-
]
|
|
473
|
-
},
|
|
474
|
-
uploaded: {
|
|
475
|
-
company: [
|
|
476
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
477
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
478
|
-
{ key: "contacts", label: "Contacts", path: "company.enrichmentData.approvedLeadListExport.contacts", renderType: "json" },
|
|
479
|
-
{ key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
|
|
480
|
-
{ key: "approval", label: "Approval", path: "company.enrichmentData.approvedLeadListExport.approvalStatus", renderType: "badge" }
|
|
481
|
-
]
|
|
482
|
-
}
|
|
483
|
-
};
|
|
484
|
-
z.object({
|
|
485
|
-
id: ModelIdSchema,
|
|
486
|
-
label: z.string(),
|
|
487
|
-
description: z.string(),
|
|
488
|
-
resourceId: ModelIdSchema
|
|
489
|
-
});
|
|
490
|
-
var PROSPECTING_STEPS = {
|
|
491
|
-
localServices: {
|
|
492
|
-
sourceCompanies: {
|
|
493
|
-
id: "source-companies",
|
|
494
|
-
label: "Companies found",
|
|
495
|
-
primaryEntity: "company",
|
|
496
|
-
outputs: ["company"],
|
|
497
|
-
stageKey: "populated",
|
|
498
|
-
dependencyMode: "per-record-eligibility",
|
|
499
|
-
capabilityKey: "lead-gen.company.source",
|
|
500
|
-
defaultBatchSize: 100,
|
|
501
|
-
maxBatchSize: 250
|
|
502
|
-
},
|
|
503
|
-
analyzeWebsites: {
|
|
504
|
-
id: "analyze-websites",
|
|
505
|
-
label: "Websites analyzed",
|
|
506
|
-
primaryEntity: "company",
|
|
507
|
-
outputs: ["company"],
|
|
508
|
-
stageKey: "extracted",
|
|
509
|
-
dependsOn: ["source-companies"],
|
|
510
|
-
dependencyMode: "per-record-eligibility",
|
|
511
|
-
capabilityKey: "lead-gen.company.website-extract",
|
|
512
|
-
defaultBatchSize: 50,
|
|
513
|
-
maxBatchSize: 100
|
|
514
|
-
},
|
|
515
|
-
qualifyCompanies: {
|
|
516
|
-
id: "qualify-companies",
|
|
517
|
-
label: "Companies qualified",
|
|
518
|
-
primaryEntity: "company",
|
|
519
|
-
outputs: ["company"],
|
|
520
|
-
stageKey: "qualified",
|
|
521
|
-
dependsOn: ["analyze-websites"],
|
|
522
|
-
dependencyMode: "per-record-eligibility",
|
|
523
|
-
capabilityKey: "lead-gen.company.qualify",
|
|
524
|
-
defaultBatchSize: 100,
|
|
525
|
-
maxBatchSize: 250
|
|
526
|
-
},
|
|
527
|
-
findContacts: {
|
|
528
|
-
id: "find-contacts",
|
|
529
|
-
label: "Decision-makers found",
|
|
530
|
-
primaryEntity: "contact",
|
|
531
|
-
outputs: ["contact"],
|
|
532
|
-
stageKey: "discovered",
|
|
533
|
-
dependsOn: ["qualify-companies"],
|
|
534
|
-
dependencyMode: "per-record-eligibility",
|
|
535
|
-
capabilityKey: "lead-gen.contact.discover",
|
|
536
|
-
defaultBatchSize: 50,
|
|
537
|
-
maxBatchSize: 100
|
|
538
|
-
},
|
|
539
|
-
verifyEmails: {
|
|
540
|
-
id: "verify-emails",
|
|
541
|
-
label: "Emails verified",
|
|
542
|
-
primaryEntity: "contact",
|
|
543
|
-
outputs: ["contact"],
|
|
544
|
-
stageKey: "verified",
|
|
545
|
-
dependsOn: ["find-contacts"],
|
|
546
|
-
dependencyMode: "per-record-eligibility",
|
|
547
|
-
capabilityKey: "lead-gen.contact.verify-email",
|
|
548
|
-
defaultBatchSize: 100,
|
|
549
|
-
maxBatchSize: 500
|
|
550
|
-
},
|
|
551
|
-
personalize: {
|
|
552
|
-
id: "personalize",
|
|
553
|
-
label: "Personalize",
|
|
554
|
-
primaryEntity: "contact",
|
|
555
|
-
outputs: ["contact"],
|
|
556
|
-
stageKey: "personalized",
|
|
557
|
-
dependsOn: ["verify-emails"],
|
|
558
|
-
dependencyMode: "per-record-eligibility",
|
|
559
|
-
capabilityKey: "lead-gen.contact.personalize",
|
|
560
|
-
defaultBatchSize: 25,
|
|
561
|
-
maxBatchSize: 100
|
|
562
|
-
},
|
|
563
|
-
review: {
|
|
564
|
-
id: "review",
|
|
565
|
-
label: "Reviewed and exported",
|
|
566
|
-
primaryEntity: "contact",
|
|
567
|
-
outputs: ["export"],
|
|
568
|
-
stageKey: "uploaded",
|
|
569
|
-
dependsOn: ["personalize"],
|
|
570
|
-
dependencyMode: "per-record-eligibility",
|
|
571
|
-
capabilityKey: "lead-gen.review.outreach-ready",
|
|
572
|
-
defaultBatchSize: 25,
|
|
573
|
-
maxBatchSize: 100
|
|
574
|
-
}
|
|
575
|
-
},
|
|
576
|
-
dtcApolloClickup: {
|
|
577
|
-
importApolloSearch: {
|
|
578
|
-
id: "import-apollo-search",
|
|
579
|
-
label: "Companies found",
|
|
580
|
-
description: "Pull companies and seed contact data from a predefined Apollo search or list.",
|
|
581
|
-
primaryEntity: "company",
|
|
582
|
-
outputs: ["company", "contact"],
|
|
583
|
-
stageKey: "populated",
|
|
584
|
-
dependencyMode: "per-record-eligibility",
|
|
585
|
-
capabilityKey: "lead-gen.company.apollo-import",
|
|
586
|
-
defaultBatchSize: 250,
|
|
587
|
-
maxBatchSize: 1e3,
|
|
588
|
-
recordColumns: DTC_RECORD_COLUMNS.populated,
|
|
589
|
-
credentialRequirements: [
|
|
590
|
-
{
|
|
591
|
-
key: "apollo",
|
|
592
|
-
provider: "apollo",
|
|
593
|
-
credentialType: "api-key-secret",
|
|
594
|
-
label: "Apollo API key",
|
|
595
|
-
required: true,
|
|
596
|
-
selectionMode: "single",
|
|
597
|
-
inputPath: "credential"
|
|
598
|
-
}
|
|
599
|
-
]
|
|
600
|
-
},
|
|
601
|
-
apifyCrawl: {
|
|
602
|
-
id: "apify-crawl",
|
|
603
|
-
label: "Websites crawled",
|
|
604
|
-
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.",
|
|
605
|
-
primaryEntity: "company",
|
|
606
|
-
outputs: ["company"],
|
|
607
|
-
stageKey: "crawled",
|
|
608
|
-
dependsOn: ["import-apollo-search"],
|
|
609
|
-
dependencyMode: "per-record-eligibility",
|
|
610
|
-
capabilityKey: "lead-gen.company.apify-crawl",
|
|
611
|
-
defaultBatchSize: 50,
|
|
612
|
-
maxBatchSize: 100,
|
|
613
|
-
recordColumns: DTC_RECORD_COLUMNS.crawled,
|
|
614
|
-
credentialRequirements: [
|
|
615
|
-
{
|
|
616
|
-
key: "apify",
|
|
617
|
-
provider: "apify",
|
|
618
|
-
credentialType: "api-key-secret",
|
|
619
|
-
label: "Apify API token",
|
|
620
|
-
required: true,
|
|
621
|
-
selectionMode: "single",
|
|
622
|
-
inputPath: "credential",
|
|
623
|
-
verifyOnRun: true
|
|
624
|
-
}
|
|
625
|
-
]
|
|
626
|
-
},
|
|
627
|
-
analyzeWebsites: {
|
|
628
|
-
id: "analyze-websites",
|
|
629
|
-
label: "Websites analyzed",
|
|
630
|
-
description: "Extract subscription, product, retention, and tech-stack signals from each brand website.",
|
|
631
|
-
primaryEntity: "company",
|
|
632
|
-
outputs: ["company"],
|
|
633
|
-
stageKey: "extracted",
|
|
634
|
-
dependsOn: ["apify-crawl"],
|
|
635
|
-
dependencyMode: "per-record-eligibility",
|
|
636
|
-
capabilityKey: "lead-gen.company.website-extract",
|
|
637
|
-
defaultBatchSize: 50,
|
|
638
|
-
maxBatchSize: 100,
|
|
639
|
-
recordColumns: DTC_RECORD_COLUMNS.extracted
|
|
640
|
-
},
|
|
641
|
-
scoreDtcFit: {
|
|
642
|
-
id: "score-dtc-fit",
|
|
643
|
-
label: "Companies qualified",
|
|
644
|
-
description: "Classify subscription potential, consumable-product fit, retention maturity, and disqualifiers.",
|
|
645
|
-
primaryEntity: "company",
|
|
646
|
-
outputs: ["company"],
|
|
647
|
-
stageKey: "qualified",
|
|
648
|
-
dependsOn: ["analyze-websites"],
|
|
649
|
-
dependencyMode: "per-record-eligibility",
|
|
650
|
-
capabilityKey: "lead-gen.company.dtc-subscription-qualify",
|
|
651
|
-
defaultBatchSize: 100,
|
|
652
|
-
maxBatchSize: 250,
|
|
653
|
-
recordColumns: DTC_RECORD_COLUMNS.qualified
|
|
654
|
-
},
|
|
655
|
-
enrichDecisionMakers: {
|
|
656
|
-
id: "enrich-decision-makers",
|
|
657
|
-
label: "Decision-makers found",
|
|
658
|
-
description: "Use Apollo to find qualified contacts at qualified companies - founders, retention leads, lifecycle leads, and marketing owners.",
|
|
659
|
-
primaryEntity: "company",
|
|
660
|
-
outputs: ["contact"],
|
|
661
|
-
stageKey: "decision-makers-enriched",
|
|
662
|
-
recordEntity: "contact",
|
|
663
|
-
dependsOn: ["score-dtc-fit"],
|
|
664
|
-
dependencyMode: "per-record-eligibility",
|
|
665
|
-
capabilityKey: "lead-gen.contact.apollo-decision-maker-enrich",
|
|
666
|
-
defaultBatchSize: 100,
|
|
667
|
-
maxBatchSize: 250,
|
|
668
|
-
recordColumns: DTC_RECORD_COLUMNS.decisionMakers,
|
|
669
|
-
credentialRequirements: [
|
|
670
|
-
{
|
|
671
|
-
key: "apollo",
|
|
672
|
-
provider: "apollo",
|
|
673
|
-
credentialType: "api-key-secret",
|
|
674
|
-
label: "Apollo API key",
|
|
675
|
-
required: true,
|
|
676
|
-
selectionMode: "single",
|
|
677
|
-
inputPath: "credential"
|
|
678
|
-
}
|
|
679
|
-
]
|
|
680
|
-
},
|
|
681
|
-
reviewAndExport: {
|
|
682
|
-
id: "review-and-export",
|
|
683
|
-
label: "Reviewed and exported",
|
|
684
|
-
description: "Operator QC approves or rejects qualified companies, then approved records are exported as a lead list with unverified emails.",
|
|
685
|
-
primaryEntity: "company",
|
|
686
|
-
outputs: ["export"],
|
|
687
|
-
stageKey: "uploaded",
|
|
688
|
-
recordsStageKey: "uploaded",
|
|
689
|
-
recordSourceStageKey: "qualified",
|
|
690
|
-
dependsOn: ["enrich-decision-makers"],
|
|
691
|
-
dependencyMode: "per-record-eligibility",
|
|
692
|
-
capabilityKey: "lead-gen.export.list",
|
|
693
|
-
defaultBatchSize: 100,
|
|
694
|
-
maxBatchSize: 250,
|
|
695
|
-
recordColumns: DTC_RECORD_COLUMNS.uploaded,
|
|
696
|
-
credentialRequirements: [
|
|
697
|
-
{
|
|
698
|
-
key: "clickup",
|
|
699
|
-
provider: "clickup",
|
|
700
|
-
credentialType: "api-key-secret",
|
|
701
|
-
label: "ClickUp API token",
|
|
702
|
-
required: true,
|
|
703
|
-
selectionMode: "single",
|
|
704
|
-
inputPath: "clickupCredential",
|
|
705
|
-
verifyOnRun: true
|
|
706
|
-
}
|
|
707
|
-
]
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
};
|
|
711
|
-
var OrganizationModelProspectingSchema = z.object({
|
|
712
|
-
listEntityId: ModelIdSchema,
|
|
713
|
-
companyEntityId: ModelIdSchema,
|
|
714
|
-
contactEntityId: ModelIdSchema,
|
|
715
|
-
description: DescriptionSchema.optional(),
|
|
716
|
-
companyStages: z.array(ProspectingLifecycleStageSchema).min(1),
|
|
717
|
-
contactStages: z.array(ProspectingLifecycleStageSchema).min(1),
|
|
718
|
-
defaultBuildTemplateId: ModelIdSchema,
|
|
719
|
-
buildTemplates: z.array(ProspectingBuildTemplateSchema).min(1)
|
|
720
|
-
});
|
|
721
|
-
function toProspectingLifecycleStage(stage) {
|
|
722
|
-
return {
|
|
723
|
-
id: stage.key,
|
|
724
|
-
label: stage.label,
|
|
725
|
-
order: stage.order
|
|
726
|
-
};
|
|
727
|
-
}
|
|
728
|
-
function leadGenStagesForEntity(entity) {
|
|
729
|
-
return Object.values(LEAD_GEN_STAGE_CATALOG).filter((stage) => stage.entity === entity || stage.additionalEntities?.includes(entity)).sort((a, b) => a.order - b.order).map(toProspectingLifecycleStage);
|
|
730
|
-
}
|
|
731
|
-
var DEFAULT_ORGANIZATION_MODEL_PROSPECTING = {
|
|
732
|
-
listEntityId: "leadgen.list",
|
|
733
|
-
companyEntityId: "leadgen.company",
|
|
734
|
-
contactEntityId: "leadgen.contact",
|
|
735
|
-
companyStages: leadGenStagesForEntity("company"),
|
|
736
|
-
contactStages: leadGenStagesForEntity("contact"),
|
|
737
|
-
defaultBuildTemplateId: "local-services",
|
|
738
|
-
buildTemplates: [
|
|
739
|
-
{
|
|
740
|
-
id: "local-services",
|
|
741
|
-
label: "Local Services Prospecting",
|
|
742
|
-
description: "Curated local-services list build using company sourcing, website analysis, qualification, contact discovery, verification, personalization, and review.",
|
|
743
|
-
steps: [
|
|
744
|
-
PROSPECTING_STEPS.localServices.sourceCompanies,
|
|
745
|
-
PROSPECTING_STEPS.localServices.analyzeWebsites,
|
|
746
|
-
PROSPECTING_STEPS.localServices.qualifyCompanies,
|
|
747
|
-
PROSPECTING_STEPS.localServices.findContacts,
|
|
748
|
-
PROSPECTING_STEPS.localServices.verifyEmails,
|
|
749
|
-
PROSPECTING_STEPS.localServices.personalize,
|
|
750
|
-
PROSPECTING_STEPS.localServices.review
|
|
751
|
-
]
|
|
752
|
-
},
|
|
753
|
-
{
|
|
754
|
-
id: "dtc-subscription-apollo-clickup",
|
|
755
|
-
label: "DTC Subscription Apollo Export",
|
|
756
|
-
description: "Prospecting pipeline for DTC subscription or subscription-ready brands where Apollo is the source and contact-enrichment layer, Elevasis handles company research and fit scoring, and approved leads export as an approved lead list.",
|
|
757
|
-
steps: [
|
|
758
|
-
PROSPECTING_STEPS.dtcApolloClickup.importApolloSearch,
|
|
759
|
-
PROSPECTING_STEPS.dtcApolloClickup.apifyCrawl,
|
|
760
|
-
PROSPECTING_STEPS.dtcApolloClickup.analyzeWebsites,
|
|
761
|
-
PROSPECTING_STEPS.dtcApolloClickup.scoreDtcFit,
|
|
762
|
-
PROSPECTING_STEPS.dtcApolloClickup.enrichDecisionMakers,
|
|
763
|
-
PROSPECTING_STEPS.dtcApolloClickup.reviewAndExport
|
|
764
|
-
]
|
|
765
|
-
}
|
|
766
|
-
]
|
|
767
|
-
};
|
|
768
|
-
|
|
769
|
-
// src/organization-model/contracts.ts
|
|
770
|
-
var KNOWLEDGE_FEATURE_ID = "knowledge";
|
|
771
|
-
var PROJECTS_FEATURE_ID = "projects";
|
|
772
|
-
var PROJECTS_INDEX_SURFACE_ID = "projects.index";
|
|
773
|
-
var PROJECTS_VIEW_CAPABILITY_ID = "delivery.projects.view";
|
|
774
|
-
var SALES_FEATURE_ID = "crm";
|
|
775
|
-
var PROSPECTING_FEATURE_ID = "lead-gen";
|
|
776
|
-
var OPERATIONS_FEATURE_ID = "operations";
|
|
777
|
-
var MONITORING_FEATURE_ID = "monitoring";
|
|
778
|
-
var SETTINGS_FEATURE_ID = "settings";
|
|
779
|
-
var SEO_FEATURE_ID = "seo";
|
|
780
|
-
var SALES_PIPELINE_SURFACE_ID = "crm.pipeline";
|
|
781
|
-
var PROSPECTING_LISTS_SURFACE_ID = "lead-gen.lists";
|
|
782
|
-
var OPERATIONS_COMMAND_VIEW_SURFACE_ID = "knowledge.command-view";
|
|
783
|
-
var SETTINGS_ROLES_SURFACE_ID = "settings.roles";
|
|
784
|
-
|
|
785
|
-
// src/organization-model/domains/navigation.ts
|
|
786
|
-
var SurfaceTypeSchema = z.enum(["page", "dashboard", "graph", "detail", "list", "settings"]);
|
|
324
|
+
var SurfaceTypeSchema = z.enum(["page", "dashboard", "graph", "detail", "list", "settings"]).meta({ label: "Surface type", color: "blue" });
|
|
787
325
|
var SurfaceDefinitionSchema = z.object({
|
|
788
326
|
id: ModelIdSchema,
|
|
789
327
|
label: LabelSchema,
|
|
@@ -793,23 +331,67 @@ var SurfaceDefinitionSchema = z.object({
|
|
|
793
331
|
enabled: z.boolean().default(true),
|
|
794
332
|
devOnly: z.boolean().optional(),
|
|
795
333
|
icon: IconNameSchema.optional(),
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
parentId: ModelIdSchema.optional()
|
|
334
|
+
systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
|
|
335
|
+
entityIds: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]),
|
|
336
|
+
resourceIds: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]),
|
|
337
|
+
actionIds: z.array(ModelIdSchema.meta({ ref: "action" })).default([]),
|
|
338
|
+
parentId: ModelIdSchema.meta({ ref: "surface" }).optional()
|
|
802
339
|
});
|
|
340
|
+
var SidebarSurfaceTargetsSchema = z.object({
|
|
341
|
+
systems: z.array(ModelIdSchema.meta({ ref: "system" })).default([]).optional(),
|
|
342
|
+
entities: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]).optional(),
|
|
343
|
+
resources: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]).optional(),
|
|
344
|
+
actions: z.array(ModelIdSchema.meta({ ref: "action" })).default([]).optional()
|
|
345
|
+
}).default({});
|
|
346
|
+
var SidebarNodeSchema = z.lazy(
|
|
347
|
+
() => z.discriminatedUnion("type", [
|
|
348
|
+
z.object({
|
|
349
|
+
type: z.literal("group"),
|
|
350
|
+
label: LabelSchema,
|
|
351
|
+
description: DescriptionSchema.optional(),
|
|
352
|
+
icon: IconNameSchema.optional(),
|
|
353
|
+
order: z.number().int().optional(),
|
|
354
|
+
children: z.record(z.string(), SidebarNodeSchema).default({})
|
|
355
|
+
}),
|
|
356
|
+
z.object({
|
|
357
|
+
type: z.literal("surface"),
|
|
358
|
+
label: LabelSchema,
|
|
359
|
+
path: PathSchema,
|
|
360
|
+
surfaceType: SurfaceTypeSchema,
|
|
361
|
+
description: DescriptionSchema.optional(),
|
|
362
|
+
icon: IconNameSchema.optional(),
|
|
363
|
+
order: z.number().int().optional(),
|
|
364
|
+
targets: SidebarSurfaceTargetsSchema.optional(),
|
|
365
|
+
devOnly: z.boolean().optional(),
|
|
366
|
+
requiresAdmin: z.boolean().optional()
|
|
367
|
+
})
|
|
368
|
+
])
|
|
369
|
+
);
|
|
370
|
+
var SidebarSectionSchema = z.record(z.string(), SidebarNodeSchema).default({});
|
|
371
|
+
var SidebarNavigationSchema = z.object({
|
|
372
|
+
primary: SidebarSectionSchema,
|
|
373
|
+
bottom: SidebarSectionSchema
|
|
374
|
+
}).default({ primary: {}, bottom: {} });
|
|
375
|
+
var OrganizationModelNavigationSchema = z.object({
|
|
376
|
+
sidebar: SidebarNavigationSchema
|
|
377
|
+
}).default({ sidebar: { primary: {}, bottom: {} } });
|
|
378
|
+
var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
|
|
379
|
+
sidebar: {
|
|
380
|
+
primary: {},
|
|
381
|
+
bottom: {}
|
|
382
|
+
}
|
|
383
|
+
};
|
|
384
|
+
function getSortedSidebarEntries(nodes) {
|
|
385
|
+
return Object.entries(nodes).sort(([leftId, left], [rightId, right]) => {
|
|
386
|
+
const orderDelta = (left.order ?? Number.MAX_SAFE_INTEGER) - (right.order ?? Number.MAX_SAFE_INTEGER);
|
|
387
|
+
return orderDelta === 0 ? leftId.localeCompare(rightId) : orderDelta;
|
|
388
|
+
});
|
|
389
|
+
}
|
|
803
390
|
var NavigationGroupSchema = z.object({
|
|
804
391
|
id: ModelIdSchema,
|
|
805
392
|
label: LabelSchema,
|
|
806
393
|
placement: z.string().trim().min(1).max(50),
|
|
807
|
-
surfaceIds: z.array(ModelIdSchema).default([])
|
|
808
|
-
});
|
|
809
|
-
var OrganizationModelNavigationSchema = z.object({
|
|
810
|
-
defaultSurfaceId: ModelIdSchema.optional(),
|
|
811
|
-
surfaces: z.array(SurfaceDefinitionSchema).default([]),
|
|
812
|
-
groups: z.array(NavigationGroupSchema).default([])
|
|
394
|
+
surfaceIds: z.array(ModelIdSchema.meta({ ref: "surface" })).default([])
|
|
813
395
|
});
|
|
814
396
|
var BusinessHoursDaySchema = z.object({
|
|
815
397
|
open: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format"),
|
|
@@ -894,6 +476,8 @@ var FirmographicsSchema = z.object({
|
|
|
894
476
|
var CustomerSegmentSchema = z.object({
|
|
895
477
|
/** Stable unique identifier for the segment (e.g. "segment-smb-agencies"). */
|
|
896
478
|
id: z.string().trim().min(1).max(100),
|
|
479
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
480
|
+
order: z.number(),
|
|
897
481
|
/** Human-readable name shown to agents and in UI (e.g. "SMB Marketing Agencies"). */
|
|
898
482
|
name: z.string().trim().max(200).default(""),
|
|
899
483
|
/** One or two sentences describing who this segment is. */
|
|
@@ -921,16 +505,16 @@ var CustomerSegmentSchema = z.object({
|
|
|
921
505
|
*/
|
|
922
506
|
valueProp: z.string().trim().max(2e3).default("")
|
|
923
507
|
});
|
|
924
|
-
var CustomersDomainSchema = z.
|
|
925
|
-
|
|
926
|
-
});
|
|
927
|
-
var DEFAULT_ORGANIZATION_MODEL_CUSTOMERS = {
|
|
928
|
-
|
|
929
|
-
};
|
|
930
|
-
var PricingModelSchema = z.enum(["one-time", "subscription", "usage-based", "custom"]);
|
|
508
|
+
var CustomersDomainSchema = z.record(z.string(), CustomerSegmentSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
509
|
+
message: "Each segment entry id must match its map key"
|
|
510
|
+
}).default({});
|
|
511
|
+
var DEFAULT_ORGANIZATION_MODEL_CUSTOMERS = {};
|
|
512
|
+
var PricingModelSchema = z.enum(["one-time", "subscription", "usage-based", "custom"]).meta({ label: "Pricing model", color: "green" });
|
|
931
513
|
var ProductSchema = z.object({
|
|
932
514
|
/** Stable unique identifier for the product (e.g. "product-starter-plan"). */
|
|
933
515
|
id: z.string().trim().min(1).max(100),
|
|
516
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
517
|
+
order: z.number(),
|
|
934
518
|
/** Human-readable name shown to agents and in UI (e.g. "Starter Plan"). */
|
|
935
519
|
name: z.string().trim().max(200).default(""),
|
|
936
520
|
/** One or two sentences describing what this product/service delivers. */
|
|
@@ -957,49 +541,562 @@ var ProductSchema = z.object({
|
|
|
957
541
|
*/
|
|
958
542
|
targetSegmentIds: z.array(z.string().trim().min(1)).default([]),
|
|
959
543
|
/**
|
|
960
|
-
* Optional: ID of the platform
|
|
961
|
-
* When present, must reference a declared `
|
|
544
|
+
* Optional: ID of the platform system responsible for delivering this product.
|
|
545
|
+
* When present, must reference a declared `systems.systems[].id`.
|
|
962
546
|
* Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
|
|
963
547
|
*/
|
|
964
548
|
deliveryFeatureId: z.string().trim().min(1).optional()
|
|
965
549
|
});
|
|
966
|
-
var OfferingsDomainSchema = z.
|
|
967
|
-
|
|
550
|
+
var OfferingsDomainSchema = z.record(z.string(), ProductSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
551
|
+
message: "Each product entry id must match its map key"
|
|
552
|
+
}).default({});
|
|
553
|
+
var DEFAULT_ORGANIZATION_MODEL_OFFERINGS = {};
|
|
554
|
+
var EntityIdSchema = ModelIdSchema;
|
|
555
|
+
var EntityLinkKindSchema = z.enum(["belongs-to", "has-many", "has-one", "many-to-many"]).meta({ label: "Link kind" });
|
|
556
|
+
var EntityLinkSchema = z.object({
|
|
557
|
+
toEntity: EntityIdSchema.meta({ ref: "entity" }),
|
|
558
|
+
kind: EntityLinkKindSchema,
|
|
559
|
+
via: z.string().trim().min(1).max(255).optional(),
|
|
560
|
+
label: LabelSchema.optional()
|
|
968
561
|
});
|
|
969
|
-
var
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
562
|
+
var EntitySchema = z.object({
|
|
563
|
+
id: EntityIdSchema,
|
|
564
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
565
|
+
order: z.number(),
|
|
566
|
+
label: LabelSchema,
|
|
567
|
+
description: DescriptionSchema.optional(),
|
|
568
|
+
ownedBySystemId: ModelIdSchema.meta({ ref: "system" }),
|
|
569
|
+
table: z.string().trim().min(1).max(255).optional(),
|
|
570
|
+
rowSchema: ModelIdSchema.optional(),
|
|
571
|
+
stateCatalogId: ModelIdSchema.optional(),
|
|
572
|
+
links: z.array(EntityLinkSchema).optional()
|
|
573
|
+
});
|
|
574
|
+
var EntitiesDomainSchema = z.record(z.string(), EntitySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
575
|
+
message: "Each entity entry id must match its map key"
|
|
576
|
+
}).default({});
|
|
577
|
+
var ENTITY_ENTRY_INPUTS = [
|
|
578
|
+
{
|
|
579
|
+
id: "crm.deal",
|
|
580
|
+
order: 10,
|
|
581
|
+
label: "Deal",
|
|
582
|
+
description: "A CRM opportunity or sales pipeline record.",
|
|
583
|
+
ownedBySystemId: "sales.crm",
|
|
584
|
+
table: "crm_deals",
|
|
585
|
+
stateCatalogId: "crm.pipeline",
|
|
586
|
+
links: [{ toEntity: "crm.contact", kind: "has-many", via: "deal_contacts", label: "contacts" }]
|
|
587
|
+
},
|
|
588
|
+
{
|
|
589
|
+
id: "crm.contact",
|
|
590
|
+
order: 20,
|
|
591
|
+
label: "CRM Contact",
|
|
592
|
+
description: "A person associated with a CRM relationship or deal.",
|
|
593
|
+
ownedBySystemId: "sales.crm",
|
|
594
|
+
table: "crm_contacts"
|
|
595
|
+
},
|
|
596
|
+
{
|
|
597
|
+
id: "leadgen.list",
|
|
598
|
+
order: 30,
|
|
599
|
+
label: "Lead List",
|
|
600
|
+
description: "A prospecting list that groups companies and contacts for acquisition workflows.",
|
|
601
|
+
ownedBySystemId: "sales.lead-gen",
|
|
602
|
+
table: "acq_lists",
|
|
603
|
+
links: [
|
|
604
|
+
{ toEntity: "leadgen.company", kind: "has-many", via: "acq_list_companies", label: "companies" },
|
|
605
|
+
{ toEntity: "leadgen.contact", kind: "has-many", via: "acq_list_members", label: "contacts" }
|
|
606
|
+
]
|
|
607
|
+
},
|
|
608
|
+
{
|
|
609
|
+
id: "leadgen.company",
|
|
610
|
+
order: 40,
|
|
611
|
+
label: "Lead Company",
|
|
612
|
+
description: "A company record sourced, enriched, and qualified during prospecting.",
|
|
613
|
+
ownedBySystemId: "sales.lead-gen",
|
|
614
|
+
table: "acq_list_companies",
|
|
615
|
+
stateCatalogId: "lead-gen.company",
|
|
616
|
+
links: [
|
|
617
|
+
{ toEntity: "leadgen.list", kind: "belongs-to", via: "list_id", label: "list" },
|
|
618
|
+
{ toEntity: "leadgen.contact", kind: "has-many", via: "company_id", label: "contacts" }
|
|
619
|
+
]
|
|
620
|
+
},
|
|
621
|
+
{
|
|
622
|
+
id: "leadgen.contact",
|
|
623
|
+
order: 50,
|
|
624
|
+
label: "Lead Contact",
|
|
625
|
+
description: "A prospect contact discovered or enriched during lead generation.",
|
|
626
|
+
ownedBySystemId: "sales.lead-gen",
|
|
627
|
+
table: "acq_list_members",
|
|
628
|
+
stateCatalogId: "lead-gen.contact",
|
|
629
|
+
links: [
|
|
630
|
+
{ toEntity: "leadgen.list", kind: "belongs-to", via: "list_id", label: "list" },
|
|
631
|
+
{ toEntity: "leadgen.company", kind: "belongs-to", via: "company_id", label: "company" }
|
|
632
|
+
]
|
|
633
|
+
},
|
|
634
|
+
{
|
|
635
|
+
id: "delivery.project",
|
|
636
|
+
order: 60,
|
|
637
|
+
label: "Project",
|
|
638
|
+
description: "A client delivery project.",
|
|
639
|
+
ownedBySystemId: "projects",
|
|
640
|
+
table: "projects",
|
|
641
|
+
links: [
|
|
642
|
+
{ toEntity: "delivery.milestone", kind: "has-many", via: "project_id", label: "milestones" },
|
|
643
|
+
{ toEntity: "delivery.task", kind: "has-many", via: "project_id", label: "tasks" }
|
|
644
|
+
]
|
|
645
|
+
},
|
|
646
|
+
{
|
|
647
|
+
id: "delivery.milestone",
|
|
648
|
+
order: 70,
|
|
649
|
+
label: "Milestone",
|
|
650
|
+
description: "A delivery checkpoint within a project.",
|
|
651
|
+
ownedBySystemId: "projects",
|
|
652
|
+
table: "project_milestones",
|
|
653
|
+
links: [
|
|
654
|
+
{ toEntity: "delivery.project", kind: "belongs-to", via: "project_id", label: "project" },
|
|
655
|
+
{ toEntity: "delivery.task", kind: "has-many", via: "milestone_id", label: "tasks" }
|
|
656
|
+
]
|
|
657
|
+
},
|
|
658
|
+
{
|
|
659
|
+
id: "delivery.task",
|
|
660
|
+
order: 80,
|
|
661
|
+
label: "Task",
|
|
662
|
+
description: "A delivery task that can move through the task status catalog.",
|
|
663
|
+
ownedBySystemId: "projects",
|
|
664
|
+
table: "project_tasks",
|
|
665
|
+
stateCatalogId: "delivery.task",
|
|
666
|
+
links: [
|
|
667
|
+
{ toEntity: "delivery.project", kind: "belongs-to", via: "project_id", label: "project" },
|
|
668
|
+
{ toEntity: "delivery.milestone", kind: "belongs-to", via: "milestone_id", label: "milestone" }
|
|
669
|
+
]
|
|
670
|
+
}
|
|
671
|
+
];
|
|
672
|
+
var DEFAULT_ORGANIZATION_MODEL_ENTITIES = Object.fromEntries(
|
|
673
|
+
ENTITY_ENTRY_INPUTS.map((entity) => {
|
|
674
|
+
const parsed = EntitySchema.parse(entity);
|
|
675
|
+
return [parsed.id, parsed];
|
|
676
|
+
})
|
|
677
|
+
);
|
|
678
|
+
|
|
679
|
+
// src/organization-model/domains/actions.ts
|
|
680
|
+
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");
|
|
681
|
+
var ActionInvocationKindSchema = z.enum(["slash-command", "mcp-tool", "api-endpoint", "script-execution"]).meta({ label: "Invocation kind" });
|
|
682
|
+
var ActionIdSchema = ModelIdSchema;
|
|
683
|
+
var ActionScopeSchema = z.union([
|
|
684
|
+
z.literal("global"),
|
|
685
|
+
z.object({
|
|
686
|
+
domain: ModelIdSchema
|
|
687
|
+
})
|
|
688
|
+
]);
|
|
689
|
+
var ActionRefSchema = z.object({
|
|
690
|
+
actionId: ActionIdSchema.meta({ ref: "action" }),
|
|
691
|
+
intent: z.enum(["exposes", "consumes"]).meta({ label: "Intent" })
|
|
692
|
+
});
|
|
693
|
+
var SlashCommandInvocationSchema = z.object({
|
|
694
|
+
kind: z.literal("slash-command"),
|
|
695
|
+
command: z.string().trim().min(1).max(200).regex(/^\/[^\s].*$/, "Slash commands must start with /"),
|
|
696
|
+
toolFactory: ModelIdSchema.optional()
|
|
697
|
+
});
|
|
698
|
+
var McpToolInvocationSchema = z.object({
|
|
699
|
+
kind: z.literal("mcp-tool"),
|
|
700
|
+
server: ModelIdSchema,
|
|
701
|
+
name: ModelIdSchema
|
|
702
|
+
});
|
|
703
|
+
var ApiEndpointInvocationSchema = z.object({
|
|
704
|
+
kind: z.literal("api-endpoint"),
|
|
705
|
+
method: z.enum(["GET", "POST", "PATCH", "DELETE"]).meta({ label: "HTTP method" }),
|
|
706
|
+
path: z.string().trim().startsWith("/").max(500),
|
|
707
|
+
requestSchema: ModelIdSchema.optional(),
|
|
708
|
+
responseSchema: ModelIdSchema.optional()
|
|
709
|
+
});
|
|
710
|
+
var ScriptExecutionInvocationSchema = z.object({
|
|
711
|
+
kind: z.literal("script-execution"),
|
|
712
|
+
resourceId: ActionResourceIdSchema
|
|
713
|
+
});
|
|
714
|
+
var ActionInvocationSchema = z.discriminatedUnion("kind", [
|
|
715
|
+
SlashCommandInvocationSchema,
|
|
716
|
+
McpToolInvocationSchema,
|
|
717
|
+
ApiEndpointInvocationSchema,
|
|
718
|
+
ScriptExecutionInvocationSchema
|
|
719
|
+
]);
|
|
720
|
+
var ActionSchema = z.object({
|
|
721
|
+
id: ActionIdSchema,
|
|
722
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
723
|
+
order: z.number(),
|
|
724
|
+
label: LabelSchema,
|
|
725
|
+
description: DescriptionSchema.optional(),
|
|
726
|
+
scope: ActionScopeSchema.default("global"),
|
|
727
|
+
resourceId: ActionResourceIdSchema.optional(),
|
|
728
|
+
affects: z.array(EntityIdSchema.meta({ ref: "entity" })).optional(),
|
|
729
|
+
invocations: z.array(ActionInvocationSchema).default([]),
|
|
730
|
+
knowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
|
|
731
|
+
lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
|
|
732
|
+
});
|
|
733
|
+
var ActionsDomainSchema = z.record(z.string(), ActionSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
734
|
+
message: "Each action entry id must match its map key"
|
|
735
|
+
}).default({});
|
|
736
|
+
var LEAD_GEN_ACTION_ENTRY_INPUTS = [
|
|
737
|
+
{
|
|
738
|
+
id: "lead-gen.company.source",
|
|
739
|
+
order: 10,
|
|
740
|
+
label: "Source companies",
|
|
741
|
+
description: "Import source companies from a list provider.",
|
|
742
|
+
scope: { domain: "sales" },
|
|
743
|
+
resourceId: "lgn-import-workflow",
|
|
744
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/source" }]
|
|
745
|
+
},
|
|
746
|
+
{
|
|
747
|
+
id: "lead-gen.company.apollo-import",
|
|
748
|
+
order: 20,
|
|
749
|
+
label: "Import from Apollo",
|
|
750
|
+
description: "Pull companies and seed contact data from an Apollo search or list.",
|
|
751
|
+
scope: { domain: "sales" },
|
|
752
|
+
resourceId: "lgn-01c-apollo-import-workflow",
|
|
753
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/apollo-import" }]
|
|
754
|
+
},
|
|
755
|
+
{
|
|
756
|
+
id: "lead-gen.contact.discover",
|
|
757
|
+
order: 30,
|
|
758
|
+
label: "Discover contact emails",
|
|
759
|
+
description: "Find email addresses for contacts at qualified companies.",
|
|
760
|
+
scope: { domain: "sales" },
|
|
761
|
+
resourceId: "lgn-04-email-discovery-workflow",
|
|
762
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/discover" }]
|
|
763
|
+
},
|
|
764
|
+
{
|
|
765
|
+
id: "lead-gen.contact.verify-email",
|
|
766
|
+
order: 40,
|
|
767
|
+
label: "Verify emails",
|
|
768
|
+
description: "Check email deliverability before outreach.",
|
|
769
|
+
scope: { domain: "sales" },
|
|
770
|
+
resourceId: "lgn-05-email-verification-workflow",
|
|
771
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/verify-email" }]
|
|
772
|
+
},
|
|
773
|
+
{
|
|
774
|
+
id: "lead-gen.company.apify-crawl",
|
|
775
|
+
order: 50,
|
|
776
|
+
label: "Crawl websites",
|
|
777
|
+
description: "Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis.",
|
|
778
|
+
scope: { domain: "sales" },
|
|
779
|
+
resourceId: "lgn-02a-apify-website-crawl-workflow",
|
|
780
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/apify-crawl" }]
|
|
781
|
+
},
|
|
782
|
+
{
|
|
783
|
+
id: "lead-gen.company.website-extract",
|
|
784
|
+
order: 60,
|
|
785
|
+
label: "Extract website signals",
|
|
786
|
+
description: "Scrape and analyze company websites for qualification signals.",
|
|
787
|
+
scope: { domain: "sales" },
|
|
788
|
+
resourceId: "lgn-02-website-extract-workflow",
|
|
789
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/website-extract" }]
|
|
790
|
+
},
|
|
791
|
+
{
|
|
792
|
+
id: "lead-gen.company.qualify",
|
|
793
|
+
order: 70,
|
|
794
|
+
label: "Qualify companies",
|
|
795
|
+
description: "Score and filter companies against the ICP rubric.",
|
|
796
|
+
scope: { domain: "sales" },
|
|
797
|
+
resourceId: "lgn-03-company-qualification-workflow",
|
|
798
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/qualify" }]
|
|
799
|
+
},
|
|
800
|
+
{
|
|
801
|
+
id: "lead-gen.company.dtc-subscription-qualify",
|
|
802
|
+
order: 80,
|
|
803
|
+
label: "Qualify DTC subscription fit",
|
|
804
|
+
description: "Classify subscription potential and consumable-product fit for DTC brands.",
|
|
805
|
+
scope: { domain: "sales" },
|
|
806
|
+
resourceId: "lgn-03b-dtc-subscription-score-workflow",
|
|
807
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/dtc-subscription-qualify" }]
|
|
808
|
+
},
|
|
809
|
+
{
|
|
810
|
+
id: "lead-gen.contact.apollo-decision-maker-enrich",
|
|
811
|
+
order: 90,
|
|
812
|
+
label: "Enrich decision-makers",
|
|
813
|
+
description: "Find and enrich qualified contacts at qualified companies via Apollo.",
|
|
814
|
+
scope: { domain: "sales" },
|
|
815
|
+
resourceId: "lgn-04b-apollo-decision-maker-enrich-workflow",
|
|
816
|
+
invocations: [
|
|
817
|
+
{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/apollo-decision-maker-enrich" }
|
|
818
|
+
]
|
|
819
|
+
},
|
|
820
|
+
{
|
|
821
|
+
id: "lead-gen.contact.personalize",
|
|
822
|
+
order: 100,
|
|
823
|
+
label: "Personalize outreach",
|
|
824
|
+
description: "Generate personalized opening lines for each contact.",
|
|
825
|
+
scope: { domain: "sales" },
|
|
826
|
+
resourceId: "ist-personalization-workflow",
|
|
827
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/personalize" }]
|
|
828
|
+
},
|
|
829
|
+
{
|
|
830
|
+
id: "lead-gen.review.outreach-ready",
|
|
831
|
+
order: 110,
|
|
832
|
+
label: "Upload to outreach",
|
|
833
|
+
description: "Upload approved contacts to the outreach sequence after QC review.",
|
|
834
|
+
scope: { domain: "sales" },
|
|
835
|
+
resourceId: "ist-upload-contacts-workflow",
|
|
836
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/review/outreach-ready" }]
|
|
837
|
+
},
|
|
838
|
+
{
|
|
839
|
+
id: "lead-gen.export.list",
|
|
840
|
+
order: 120,
|
|
841
|
+
label: "Export lead list",
|
|
842
|
+
description: "Export approved leads as a downloadable lead list.",
|
|
843
|
+
scope: { domain: "sales" },
|
|
844
|
+
resourceId: "lgn-06-export-list-workflow",
|
|
845
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/export/list" }]
|
|
846
|
+
},
|
|
847
|
+
{
|
|
848
|
+
id: "lead-gen.company.cleanup",
|
|
849
|
+
order: 130,
|
|
850
|
+
label: "Clean up companies",
|
|
851
|
+
description: "Remove disqualified or duplicate companies from the list.",
|
|
852
|
+
scope: { domain: "sales" },
|
|
853
|
+
resourceId: "lgn-company-cleanup-workflow",
|
|
854
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/cleanup" }]
|
|
855
|
+
}
|
|
856
|
+
];
|
|
857
|
+
var LEAD_GEN_ACTION_ENTRIES = Object.fromEntries(
|
|
858
|
+
LEAD_GEN_ACTION_ENTRY_INPUTS.map((action) => {
|
|
859
|
+
const parsed = ActionSchema.parse(action);
|
|
860
|
+
return [parsed.id, parsed];
|
|
861
|
+
})
|
|
862
|
+
);
|
|
863
|
+
var DEFAULT_ORGANIZATION_MODEL_ACTIONS = LEAD_GEN_ACTION_ENTRIES;
|
|
864
|
+
function findOrganizationActionById(id, actions = DEFAULT_ORGANIZATION_MODEL_ACTIONS) {
|
|
865
|
+
return actions[id];
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
// src/organization-model/domains/systems.ts
|
|
869
|
+
var SystemKindSchema = z.enum(["product", "operational", "platform", "diagnostic"]).meta({ label: "System kind", color: "blue" });
|
|
870
|
+
var SystemLifecycleSchema = z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" });
|
|
871
|
+
var SystemStatusSchema = z.enum(["active", "deprecated", "archived"]).meta({ label: "Status", color: "teal" });
|
|
872
|
+
var SystemIdSchema = ModelIdSchema;
|
|
873
|
+
var SystemPathSchema = z.string().trim().min(1).regex(
|
|
874
|
+
/^[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)*$/,
|
|
875
|
+
'must be a dotted lowercase path (e.g. "sales.lead-gen" or "sales.crm")'
|
|
876
|
+
);
|
|
877
|
+
var UiPositionSchema = z.enum(["sidebar-primary", "sidebar-bottom"]).meta({ label: "UI position" });
|
|
878
|
+
var NodeIdPathSchema = SystemIdSchema;
|
|
879
|
+
var NodeIdStringSchema = z.string().trim().min(1).max(200).regex(
|
|
880
|
+
/^[a-z][a-z-]*:([a-z0-9-]+)(\.[a-z0-9-]+)*(:[a-z0-9.-]+)*$/,
|
|
881
|
+
"Node references must use kind:dotted-path (e.g. system:sales.crm or content-node:sales.crm:pipeline-id)"
|
|
882
|
+
);
|
|
883
|
+
var SystemUiSchema = z.object({
|
|
884
|
+
path: PathSchema,
|
|
885
|
+
surfaces: ReferenceIdsSchema,
|
|
886
|
+
icon: IconNameSchema.optional(),
|
|
887
|
+
order: z.number().int().optional()
|
|
888
|
+
});
|
|
889
|
+
var SystemEntrySchema = z.object({
|
|
890
|
+
/** Stable tenant-defined system id (e.g. "sys.lead-gen" or "sales.crm"). */
|
|
891
|
+
id: SystemIdSchema,
|
|
892
|
+
/** Human-readable system label shown in UI, governance, and operations surfaces. */
|
|
893
|
+
label: LabelSchema.optional(),
|
|
894
|
+
/** @deprecated Use label. Accepted for pre-consolidation System declarations. */
|
|
895
|
+
title: LabelSchema.optional(),
|
|
896
|
+
/** One-paragraph purpose statement for the bounded context. */
|
|
897
|
+
description: DescriptionSchema.optional(),
|
|
898
|
+
/** Closed system shape enum; catalog values remain tenant-defined. */
|
|
899
|
+
kind: SystemKindSchema.optional(),
|
|
900
|
+
/** Optional self-reference for System hierarchy. */
|
|
901
|
+
parentSystemId: SystemIdSchema.optional(),
|
|
902
|
+
/** Optional UI presence. Systems without UI omit this. */
|
|
903
|
+
ui: SystemUiSchema.optional(),
|
|
904
|
+
/** Canonical lifecycle state. Replaces Feature.enabled/devOnly and System.status. */
|
|
905
|
+
lifecycle: SystemLifecycleSchema.optional(),
|
|
906
|
+
/** Optional role responsible for this system. */
|
|
907
|
+
responsibleRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
|
|
908
|
+
/** Optional knowledge nodes that govern this system. */
|
|
909
|
+
governedByKnowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
|
|
910
|
+
/** Optional actions this system exposes or consumes. */
|
|
911
|
+
actions: z.array(ActionRefSchema).optional(),
|
|
912
|
+
/** Optional operational policies that apply to this system. */
|
|
913
|
+
policies: z.array(ModelIdSchema.meta({ ref: "policy" })).default([]).optional(),
|
|
914
|
+
/** Optional goals this system contributes to. */
|
|
915
|
+
drivesGoals: z.array(ModelIdSchema.meta({ ref: "goal" })).default([]).optional(),
|
|
916
|
+
/** @deprecated Use lifecycle. Accepted for one publish cycle. */
|
|
917
|
+
status: SystemStatusSchema.optional(),
|
|
918
|
+
/** @deprecated Use ui.path. Kept for one-cycle Feature compatibility. */
|
|
919
|
+
path: PathSchema.optional(),
|
|
920
|
+
/** @deprecated Use ui.icon. Kept for one-cycle Feature compatibility. */
|
|
921
|
+
icon: IconNameSchema.optional(),
|
|
922
|
+
/** @deprecated Feature color token, retained for one-cycle compatibility. */
|
|
923
|
+
color: ColorTokenSchema.optional(),
|
|
924
|
+
/** @deprecated UI placement hint, retained for one-cycle compatibility. */
|
|
925
|
+
uiPosition: UiPositionSchema.optional(),
|
|
926
|
+
/** @deprecated Use lifecycle. */
|
|
927
|
+
enabled: z.boolean().optional(),
|
|
928
|
+
/** @deprecated Use lifecycle: "beta". */
|
|
929
|
+
devOnly: z.boolean().optional(),
|
|
930
|
+
requiresAdmin: z.boolean().optional(),
|
|
931
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
932
|
+
order: z.number(),
|
|
933
|
+
/**
|
|
934
|
+
* System-scoped operational data, co-located with the owning system.
|
|
935
|
+
* Per L1, L3, L13: keyed by local NodeId (the key is the local id; qualified
|
|
936
|
+
* id is `<system-path>:<local-id>`, computed by graph projection).
|
|
937
|
+
* Per L14: every ContentNode carries both `kind` and `type`.
|
|
938
|
+
* Per D2: unregistered (kind, type) pairs parse successfully.
|
|
939
|
+
*/
|
|
940
|
+
content: z.record(z.string().trim().min(1).max(200), ContentNodeSchema).optional(),
|
|
941
|
+
/**
|
|
942
|
+
* Recursive child systems, authored via nesting (per L11).
|
|
943
|
+
* The key is the local system id; the full path is computed by joining
|
|
944
|
+
* ancestor keys with `.` (e.g. parent key `'sales'` + child key `'crm'` → `'sales.crm'`).
|
|
945
|
+
* Per Phase 4: `id` and `parentSystemId` fields will be removed in favour of
|
|
946
|
+
* position-derived paths. Both still exist on this schema for backward compat.
|
|
947
|
+
*/
|
|
948
|
+
subsystems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional()
|
|
949
|
+
}).refine((system) => system.label !== void 0 || system.title !== void 0, {
|
|
950
|
+
path: ["label"],
|
|
951
|
+
message: "System must provide label or title"
|
|
952
|
+
}).transform((system) => {
|
|
953
|
+
if (system.status === void 0) return system;
|
|
954
|
+
console.warn("[organization-model] System.status is deprecated; use System.lifecycle instead.");
|
|
955
|
+
return system.lifecycle === void 0 ? { ...system, lifecycle: system.status } : system;
|
|
956
|
+
});
|
|
957
|
+
var SystemsDomainSchema = z.record(z.string(), SystemEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
958
|
+
message: "Each system entry id must match its map key"
|
|
959
|
+
}).default({});
|
|
960
|
+
var DEFAULT_ORGANIZATION_MODEL_SYSTEMS = {};
|
|
961
|
+
|
|
962
|
+
// src/organization-model/domains/resources.ts
|
|
963
|
+
var ResourceKindSchema = z.enum(["workflow", "agent", "integration", "script"]).meta({ label: "Resource kind", color: "orange" });
|
|
964
|
+
var ResourceGovernanceStatusSchema = z.enum(["active", "deprecated", "archived"]).meta({ label: "Governance status", color: "teal" });
|
|
965
|
+
var AgentKindSchema = z.enum(["orchestrator", "specialist", "utility", "platform"]).meta({ label: "Agent kind", color: "violet" });
|
|
966
|
+
var ScriptResourceLanguageSchema = z.enum(["shell", "sql", "typescript", "python"]).meta({ label: "Language" });
|
|
967
|
+
var ResourceIdSchema = z.string().trim().min(1).max(255).regex(/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*$/, "Resource IDs must use letters, numbers, -, _, or . separators");
|
|
968
|
+
var EventIdSchema = z.string().trim().min(1).max(300).regex(
|
|
969
|
+
/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*:[a-z0-9]+(?:[-._][a-z0-9]+)*$/,
|
|
970
|
+
"Event IDs must use <owner-id>:<event-key>"
|
|
971
|
+
);
|
|
972
|
+
var EventKeySchema = ModelIdSchema;
|
|
973
|
+
var EventEmissionDescriptorSchema = z.object({
|
|
974
|
+
eventKey: EventKeySchema,
|
|
975
|
+
label: z.string().trim().min(1).max(120),
|
|
976
|
+
payloadSchema: ModelIdSchema.optional(),
|
|
977
|
+
lifecycle: SystemLifecycleSchema.optional()
|
|
978
|
+
});
|
|
979
|
+
var EventDescriptorSchema = EventEmissionDescriptorSchema.extend({
|
|
980
|
+
id: EventIdSchema,
|
|
981
|
+
ownerId: z.union([ResourceIdSchema, ModelIdSchema]),
|
|
982
|
+
ownerKind: z.enum(["resource", "entity"]).meta({ label: "Owner kind" })
|
|
983
|
+
});
|
|
984
|
+
var ResourceEntryBaseSchema = z.object({
|
|
985
|
+
/** Canonical resource id; runtime resourceId derives from this value. */
|
|
986
|
+
id: ResourceIdSchema,
|
|
987
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
988
|
+
order: z.number().default(0),
|
|
989
|
+
/** Required single System membership — value is a dot-separated system path (e.g. "sales.lead-gen"). */
|
|
990
|
+
systemPath: SystemPathSchema.meta({ ref: "system" }),
|
|
991
|
+
/** Optional role responsible for maintaining this resource. */
|
|
992
|
+
ownerRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
|
|
993
|
+
status: ResourceGovernanceStatusSchema
|
|
994
|
+
});
|
|
995
|
+
var WorkflowResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
996
|
+
kind: z.literal("workflow"),
|
|
997
|
+
/** Mirrors WorkflowConfig.actionKey when the runtime workflow has one. */
|
|
998
|
+
actionKey: z.string().trim().min(1).max(255).optional(),
|
|
999
|
+
emits: z.array(EventEmissionDescriptorSchema).optional()
|
|
1000
|
+
});
|
|
1001
|
+
var AgentResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
1002
|
+
kind: z.literal("agent"),
|
|
1003
|
+
/** Mirrors code-side AgentConfig.kind. */
|
|
1004
|
+
agentKind: AgentKindSchema,
|
|
1005
|
+
/** Role this agent embodies, if any. */
|
|
1006
|
+
actsAsRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
|
|
1007
|
+
/** Mirrors AgentConfig.sessionCapable. */
|
|
1008
|
+
sessionCapable: z.boolean(),
|
|
1009
|
+
/** Broad/composite callable entry points orchestrated by this agent. */
|
|
1010
|
+
invocations: z.array(ActionInvocationSchema).default([]),
|
|
1011
|
+
emits: z.array(EventEmissionDescriptorSchema).optional()
|
|
1012
|
+
});
|
|
1013
|
+
var IntegrationResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
1014
|
+
kind: z.literal("integration"),
|
|
1015
|
+
provider: z.string().trim().min(1).max(100)
|
|
1016
|
+
});
|
|
1017
|
+
var ScriptResourceSourceSchema = z.union([
|
|
1018
|
+
z.string().trim().min(1).max(5e4),
|
|
1019
|
+
z.object({
|
|
1020
|
+
file: z.string().trim().min(1).max(500)
|
|
1021
|
+
})
|
|
1022
|
+
]);
|
|
1023
|
+
var ScriptResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
1024
|
+
kind: z.literal("script"),
|
|
1025
|
+
language: ScriptResourceLanguageSchema,
|
|
1026
|
+
source: ScriptResourceSourceSchema
|
|
1027
|
+
});
|
|
1028
|
+
var ResourceEntrySchema = z.discriminatedUnion("kind", [
|
|
1029
|
+
WorkflowResourceEntrySchema,
|
|
1030
|
+
AgentResourceEntrySchema,
|
|
1031
|
+
IntegrationResourceEntrySchema,
|
|
1032
|
+
ScriptResourceEntrySchema
|
|
1033
|
+
]);
|
|
1034
|
+
var ResourcesDomainSchema = z.record(z.string(), ResourceEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
1035
|
+
message: "Each resource entry id must match its map key"
|
|
1036
|
+
}).default({});
|
|
1037
|
+
var DEFAULT_ORGANIZATION_MODEL_RESOURCES = {};
|
|
1038
|
+
function defineResource(resource) {
|
|
1039
|
+
return ResourceEntrySchema.parse(resource);
|
|
1040
|
+
}
|
|
1041
|
+
function defineResources(resources) {
|
|
1042
|
+
return Object.fromEntries(
|
|
1043
|
+
Object.entries(resources).map(([key, resource]) => [key, ResourceEntrySchema.parse(resource)])
|
|
1044
|
+
);
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
// src/organization-model/domains/roles.ts
|
|
1048
|
+
var RoleIdSchema = ModelIdSchema;
|
|
1049
|
+
var HumanRoleHolderSchema = z.object({
|
|
1050
|
+
kind: z.literal("human"),
|
|
1051
|
+
userId: z.string().trim().min(1).max(200)
|
|
1052
|
+
});
|
|
1053
|
+
var AgentRoleHolderSchema = z.object({
|
|
1054
|
+
kind: z.literal("agent"),
|
|
1055
|
+
agentId: ResourceIdSchema.meta({ ref: "resource" })
|
|
1056
|
+
});
|
|
1057
|
+
var TeamRoleHolderSchema = z.object({
|
|
1058
|
+
kind: z.literal("team"),
|
|
1059
|
+
memberIds: z.array(z.string().trim().min(1).max(200)).min(1)
|
|
1060
|
+
});
|
|
1061
|
+
var RoleHolderSchema = z.discriminatedUnion("kind", [
|
|
1062
|
+
HumanRoleHolderSchema,
|
|
1063
|
+
AgentRoleHolderSchema,
|
|
1064
|
+
TeamRoleHolderSchema
|
|
1065
|
+
]);
|
|
1066
|
+
var RoleHoldersSchema = z.union([RoleHolderSchema, z.array(RoleHolderSchema).min(1)]);
|
|
1067
|
+
var RoleSchema = z.object({
|
|
1068
|
+
/** Stable unique identifier for the role (e.g. "role-ceo", "role-head-of-sales"). */
|
|
1069
|
+
id: RoleIdSchema,
|
|
1070
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
1071
|
+
order: z.number(),
|
|
1072
|
+
/** Human-readable title shown to agents and in UI (e.g. "CEO", "Head of Sales"). */
|
|
1073
|
+
title: z.string().trim().min(1).max(200),
|
|
1074
|
+
/**
|
|
1075
|
+
* List of responsibilities this role owns - plain-language descriptions of
|
|
1076
|
+
* what the person in this role is accountable for delivering.
|
|
1077
|
+
* Defaults to empty array so minimal role definitions stay concise.
|
|
1078
|
+
*/
|
|
1079
|
+
responsibilities: z.array(z.string().trim().max(500)).default([]),
|
|
1080
|
+
/**
|
|
984
1081
|
* Optional: ID of another role this role reports to.
|
|
985
1082
|
* When present, must reference another `roles[].id` in the same organization.
|
|
986
|
-
* Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
|
|
987
|
-
* Absence indicates a top-level role (no reporting line).
|
|
988
1083
|
*/
|
|
989
|
-
reportsToId:
|
|
1084
|
+
reportsToId: RoleIdSchema.meta({ ref: "role" }).optional(),
|
|
990
1085
|
/**
|
|
991
|
-
* Optional:
|
|
992
|
-
*
|
|
993
|
-
* any human-readable identifier. Not validated against any user registry.
|
|
1086
|
+
* Optional: human, agent, or team holder currently filling this role.
|
|
1087
|
+
* Agent holders reference OM Resource IDs and are validated at the model level.
|
|
994
1088
|
*/
|
|
995
|
-
heldBy:
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
|
|
1089
|
+
heldBy: RoleHoldersSchema.optional(),
|
|
1090
|
+
/**
|
|
1091
|
+
* Optional Systems this role is accountable for.
|
|
1092
|
+
* Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
|
|
1093
|
+
*/
|
|
1094
|
+
responsibleFor: z.array(SystemIdSchema.meta({ ref: "system" })).optional()
|
|
999
1095
|
});
|
|
1000
|
-
var
|
|
1001
|
-
|
|
1002
|
-
};
|
|
1096
|
+
var RolesDomainSchema = z.record(z.string(), RoleSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
1097
|
+
message: "Each role entry id must match its map key"
|
|
1098
|
+
}).default({});
|
|
1099
|
+
var DEFAULT_ORGANIZATION_MODEL_ROLES = {};
|
|
1003
1100
|
var KeyResultSchema = z.object({
|
|
1004
1101
|
/** Stable unique identifier for the measurable outcome (e.g. "kr-revenue-q1"). */
|
|
1005
1102
|
id: z.string().trim().min(1).max(100),
|
|
@@ -1023,6 +1120,8 @@ var ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
|
|
1023
1120
|
var ObjectiveSchema = z.object({
|
|
1024
1121
|
/** Stable unique identifier for the goal (e.g. "goal-grow-arr-q1-2026"). */
|
|
1025
1122
|
id: z.string().trim().min(1).max(100),
|
|
1123
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
1124
|
+
order: z.number(),
|
|
1026
1125
|
/** Plain-language description of what the organization wants to achieve. */
|
|
1027
1126
|
description: z.string().trim().min(1).max(1e3),
|
|
1028
1127
|
/**
|
|
@@ -1042,180 +1141,63 @@ var ObjectiveSchema = z.object({
|
|
|
1042
1141
|
*/
|
|
1043
1142
|
keyResults: z.array(KeyResultSchema).default([])
|
|
1044
1143
|
});
|
|
1045
|
-
var GoalsDomainSchema = z.
|
|
1046
|
-
|
|
1144
|
+
var GoalsDomainSchema = z.record(z.string(), ObjectiveSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
1145
|
+
message: "Each objective entry id must match its map key"
|
|
1146
|
+
}).default({});
|
|
1147
|
+
var DEFAULT_ORGANIZATION_MODEL_GOALS = {};
|
|
1148
|
+
var KnowledgeTargetKindSchema = z.enum([
|
|
1149
|
+
"system",
|
|
1150
|
+
"resource",
|
|
1151
|
+
"knowledge",
|
|
1152
|
+
"stage",
|
|
1153
|
+
"action",
|
|
1154
|
+
"role",
|
|
1155
|
+
"goal",
|
|
1156
|
+
"customer-segment",
|
|
1157
|
+
"offering",
|
|
1158
|
+
// D4: content nodes are a valid knowledge target after compound-domain data moved into system.content
|
|
1159
|
+
"content-node"
|
|
1160
|
+
]).meta({ label: "Target kind" });
|
|
1161
|
+
var KnowledgeTargetRefSchema = z.object({
|
|
1162
|
+
kind: KnowledgeTargetKindSchema,
|
|
1163
|
+
// D4: content-node targets use a qualified id format '<system-path>:<local-content-id>'
|
|
1164
|
+
// which contains a colon separator and cannot satisfy ModelIdSchema. Use a permissive
|
|
1165
|
+
// string schema here; business-logic validation of target existence is done in
|
|
1166
|
+
// OrganizationModelSchema.superRefine (knowledgeTargetExists).
|
|
1167
|
+
id: z.string().trim().min(1).max(300)
|
|
1047
1168
|
});
|
|
1048
|
-
var
|
|
1049
|
-
|
|
1050
|
-
};
|
|
1051
|
-
var OperationSemanticClassSchema = z.enum(["queue", "executions", "sessions", "notifications", "schedules"]);
|
|
1052
|
-
var OperationEntrySchema = z.object({
|
|
1053
|
-
id: z.string().trim().min(1).max(100),
|
|
1054
|
-
label: z.string().trim().min(1).max(120),
|
|
1055
|
-
semanticClass: OperationSemanticClassSchema,
|
|
1056
|
-
/** Optional reference to the feature that owns this runtime entity. */
|
|
1057
|
-
featureId: z.string().trim().min(1).max(100).optional(),
|
|
1058
|
-
/**
|
|
1059
|
-
* Optional pointer to the status semanticClass values that apply to this
|
|
1060
|
-
* entity — ties operations back to the statuses domain for vibe rendering.
|
|
1061
|
-
*/
|
|
1062
|
-
supportedStatusSemanticClass: z.array(z.string().trim().min(1).max(80)).optional()
|
|
1063
|
-
});
|
|
1064
|
-
var OperationsDomainSchema = z.object({
|
|
1065
|
-
entries: z.array(OperationEntrySchema).default([])
|
|
1066
|
-
});
|
|
1067
|
-
var DEFAULT_ORGANIZATION_MODEL_OPERATIONS = {
|
|
1068
|
-
entries: [
|
|
1069
|
-
// --- queue (HITL command queue) ---
|
|
1070
|
-
{
|
|
1071
|
-
id: "operations.queue",
|
|
1072
|
-
label: "HITL Queue",
|
|
1073
|
-
semanticClass: "queue",
|
|
1074
|
-
featureId: "operations",
|
|
1075
|
-
supportedStatusSemanticClass: ["queue"]
|
|
1076
|
-
},
|
|
1077
|
-
// --- executions (workflow / agent executions) ---
|
|
1078
|
-
{
|
|
1079
|
-
id: "operations.executions",
|
|
1080
|
-
label: "Executions",
|
|
1081
|
-
semanticClass: "executions",
|
|
1082
|
-
featureId: "operations",
|
|
1083
|
-
supportedStatusSemanticClass: ["execution"]
|
|
1084
|
-
},
|
|
1085
|
-
// --- sessions (agent conversation sessions) ---
|
|
1086
|
-
{
|
|
1087
|
-
id: "operations.sessions",
|
|
1088
|
-
label: "Sessions",
|
|
1089
|
-
semanticClass: "sessions",
|
|
1090
|
-
featureId: "operations"
|
|
1091
|
-
},
|
|
1092
|
-
// --- notifications (platform in-app notifications) ---
|
|
1093
|
-
{
|
|
1094
|
-
id: "operations.notifications",
|
|
1095
|
-
label: "Notifications",
|
|
1096
|
-
semanticClass: "notifications",
|
|
1097
|
-
featureId: "monitoring"
|
|
1098
|
-
},
|
|
1099
|
-
// --- schedules (task scheduler) ---
|
|
1100
|
-
{
|
|
1101
|
-
id: "operations.schedules",
|
|
1102
|
-
label: "Schedules",
|
|
1103
|
-
semanticClass: "schedules",
|
|
1104
|
-
featureId: "operations",
|
|
1105
|
-
supportedStatusSemanticClass: ["schedule", "schedule.run"]
|
|
1106
|
-
}
|
|
1107
|
-
]
|
|
1108
|
-
};
|
|
1109
|
-
var StatusSemanticClassSchema = z.enum([
|
|
1110
|
-
"delivery.task",
|
|
1111
|
-
"delivery.project",
|
|
1112
|
-
"delivery.milestone",
|
|
1113
|
-
"queue",
|
|
1114
|
-
"execution",
|
|
1115
|
-
"schedule",
|
|
1116
|
-
"schedule.run",
|
|
1117
|
-
"request"
|
|
1118
|
-
]);
|
|
1119
|
-
var StatusEntrySchema = z.object({
|
|
1120
|
-
id: z.string().trim().min(1).max(100),
|
|
1121
|
-
label: z.string().trim().min(1).max(120),
|
|
1122
|
-
semanticClass: StatusSemanticClassSchema,
|
|
1123
|
-
category: z.string().trim().min(1).max(80).optional()
|
|
1169
|
+
var LegacyKnowledgeLinkSchema = z.object({
|
|
1170
|
+
nodeId: NodeIdStringSchema
|
|
1124
1171
|
});
|
|
1125
|
-
var
|
|
1126
|
-
|
|
1172
|
+
var CanonicalKnowledgeLinkSchema = z.object({
|
|
1173
|
+
target: KnowledgeTargetRefSchema
|
|
1127
1174
|
});
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
|
|
1132
|
-
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
{ id: "delivery.task.completed", label: "Completed", semanticClass: "delivery.task", category: "delivery" },
|
|
1145
|
-
// --- delivery.project (ProjectStatus — 6 values) ---
|
|
1146
|
-
{ id: "delivery.project.active", label: "Active", semanticClass: "delivery.project", category: "delivery" },
|
|
1147
|
-
{ id: "delivery.project.on_track", label: "On Track", semanticClass: "delivery.project", category: "delivery" },
|
|
1148
|
-
{ id: "delivery.project.at_risk", label: "At Risk", semanticClass: "delivery.project", category: "delivery" },
|
|
1149
|
-
{ id: "delivery.project.blocked", label: "Blocked", semanticClass: "delivery.project", category: "delivery" },
|
|
1150
|
-
{ id: "delivery.project.paused", label: "Paused", semanticClass: "delivery.project", category: "delivery" },
|
|
1151
|
-
{ id: "delivery.project.completed", label: "Completed", semanticClass: "delivery.project", category: "delivery" },
|
|
1152
|
-
// --- delivery.milestone (MilestoneStatus — 5 values) ---
|
|
1153
|
-
{
|
|
1154
|
-
id: "delivery.milestone.upcoming",
|
|
1155
|
-
label: "Upcoming",
|
|
1156
|
-
semanticClass: "delivery.milestone",
|
|
1157
|
-
category: "delivery"
|
|
1158
|
-
},
|
|
1159
|
-
{
|
|
1160
|
-
id: "delivery.milestone.in_progress",
|
|
1161
|
-
label: "In Progress",
|
|
1162
|
-
semanticClass: "delivery.milestone",
|
|
1163
|
-
category: "delivery"
|
|
1164
|
-
},
|
|
1165
|
-
{
|
|
1166
|
-
id: "delivery.milestone.blocked",
|
|
1167
|
-
label: "Blocked",
|
|
1168
|
-
semanticClass: "delivery.milestone",
|
|
1169
|
-
category: "delivery"
|
|
1170
|
-
},
|
|
1171
|
-
{ id: "delivery.milestone.overdue", label: "Overdue", semanticClass: "delivery.milestone", category: "delivery" },
|
|
1172
|
-
{
|
|
1173
|
-
id: "delivery.milestone.completed",
|
|
1174
|
-
label: "Completed",
|
|
1175
|
-
semanticClass: "delivery.milestone",
|
|
1176
|
-
category: "delivery"
|
|
1177
|
-
},
|
|
1178
|
-
// --- queue (QueueTaskStatus — 5 values, maps hitl/command-queue tasks) ---
|
|
1179
|
-
{ id: "queue.pending", label: "Pending", semanticClass: "queue", category: "queue" },
|
|
1180
|
-
{ id: "queue.processing", label: "Processing", semanticClass: "queue", category: "queue" },
|
|
1181
|
-
{ id: "queue.completed", label: "Completed", semanticClass: "queue", category: "queue" },
|
|
1182
|
-
{ id: "queue.failed", label: "Failed", semanticClass: "queue", category: "queue" },
|
|
1183
|
-
{ id: "queue.expired", label: "Expired", semanticClass: "queue", category: "queue" },
|
|
1184
|
-
// --- execution (ExecutionStatus — 5 values) ---
|
|
1185
|
-
{ id: "execution.pending", label: "Pending", semanticClass: "execution", category: "execution" },
|
|
1186
|
-
{ id: "execution.running", label: "Running", semanticClass: "execution", category: "execution" },
|
|
1187
|
-
{ id: "execution.completed", label: "Completed", semanticClass: "execution", category: "execution" },
|
|
1188
|
-
{ id: "execution.failed", label: "Failed", semanticClass: "execution", category: "execution" },
|
|
1189
|
-
{ id: "execution.warning", label: "Warning", semanticClass: "execution", category: "execution" },
|
|
1190
|
-
// --- schedule (schedule status — 4 values) ---
|
|
1191
|
-
{ id: "schedule.active", label: "Active", semanticClass: "schedule", category: "schedule" },
|
|
1192
|
-
{ id: "schedule.paused", label: "Paused", semanticClass: "schedule", category: "schedule" },
|
|
1193
|
-
{ id: "schedule.completed", label: "Completed", semanticClass: "schedule", category: "schedule" },
|
|
1194
|
-
{ id: "schedule.cancelled", label: "Cancelled", semanticClass: "schedule", category: "schedule" },
|
|
1195
|
-
// --- schedule.run (schedule run status — 4 values) ---
|
|
1196
|
-
{ id: "schedule.run.running", label: "Running", semanticClass: "schedule.run", category: "schedule" },
|
|
1197
|
-
{ id: "schedule.run.completed", label: "Completed", semanticClass: "schedule.run", category: "schedule" },
|
|
1198
|
-
{ id: "schedule.run.failed", label: "Failed", semanticClass: "schedule.run", category: "schedule" },
|
|
1199
|
-
{ id: "schedule.run.cancelled", label: "Cancelled", semanticClass: "schedule.run", category: "schedule" },
|
|
1200
|
-
// --- request (RequestStatus — 4 values, maps reported_requests) ---
|
|
1201
|
-
{ id: "request.open", label: "Open", semanticClass: "request", category: "request" },
|
|
1202
|
-
{ id: "request.investigating", label: "Investigating", semanticClass: "request", category: "request" },
|
|
1203
|
-
{ id: "request.resolved", label: "Resolved", semanticClass: "request", category: "request" },
|
|
1204
|
-
{ id: "request.wont_fix", label: "Won't Fix", semanticClass: "request", category: "request" }
|
|
1205
|
-
]
|
|
1206
|
-
};
|
|
1207
|
-
var KnowledgeLinkSchema = z.object({
|
|
1208
|
-
nodeId: NodeIdStringSchema
|
|
1175
|
+
function nodeIdFromTarget(target) {
|
|
1176
|
+
return `${target.kind}:${target.id}`;
|
|
1177
|
+
}
|
|
1178
|
+
function targetFromNodeId(nodeId) {
|
|
1179
|
+
const [kind, ...idParts] = nodeId.split(":");
|
|
1180
|
+
return {
|
|
1181
|
+
kind: KnowledgeTargetKindSchema.parse(kind),
|
|
1182
|
+
id: idParts.join(":")
|
|
1183
|
+
};
|
|
1184
|
+
}
|
|
1185
|
+
var KnowledgeLinkSchema = z.union([CanonicalKnowledgeLinkSchema, LegacyKnowledgeLinkSchema]).transform((link) => {
|
|
1186
|
+
const target = "target" in link ? link.target : targetFromNodeId(link.nodeId);
|
|
1187
|
+
return {
|
|
1188
|
+
target,
|
|
1189
|
+
nodeId: nodeIdFromTarget(target)
|
|
1190
|
+
};
|
|
1209
1191
|
});
|
|
1210
|
-
var
|
|
1211
|
-
var KnowledgeDomainBindingSchema = z.string().trim().min(1).max(80);
|
|
1212
|
-
var OrgKnowledgeKindSchema = z.enum(["playbook", "strategy", "reference"]);
|
|
1192
|
+
var OrgKnowledgeKindSchema = z.enum(["playbook", "strategy", "reference"]).meta({ label: "Knowledge kind", color: "grape" });
|
|
1213
1193
|
var OrgKnowledgeNodeSchema = z.object({
|
|
1214
1194
|
id: ModelIdSchema,
|
|
1215
1195
|
kind: OrgKnowledgeKindSchema,
|
|
1216
1196
|
title: z.string().trim().min(1).max(200),
|
|
1217
1197
|
summary: z.string().trim().min(1).max(1e3),
|
|
1218
1198
|
icon: IconNameSchema.optional(),
|
|
1199
|
+
/** Canonical documentation URL when body content is a local summary. */
|
|
1200
|
+
externalUrl: z.string().trim().url().max(500).optional(),
|
|
1219
1201
|
/** Raw MDX string. Phase 2 will introduce a structured block format. */
|
|
1220
1202
|
body: z.string().trim().min(1),
|
|
1221
1203
|
/**
|
|
@@ -1223,36 +1205,154 @@ var OrgKnowledgeNodeSchema = z.object({
|
|
|
1223
1205
|
* Each link emits a `governs` edge: knowledge-node -> target node.
|
|
1224
1206
|
*/
|
|
1225
1207
|
links: z.array(KnowledgeLinkSchema).default([]),
|
|
1226
|
-
/**
|
|
1227
|
-
|
|
1228
|
-
/** Domain key used to derive fast graph->skill registries. */
|
|
1229
|
-
domain: KnowledgeDomainBindingSchema.optional(),
|
|
1230
|
-
/** Identifiers of the roles or members who own this knowledge node. */
|
|
1231
|
-
ownerIds: z.array(ModelIdSchema).default([]),
|
|
1208
|
+
/** Role identifiers that own this knowledge node. */
|
|
1209
|
+
ownerIds: z.array(RoleIdSchema.meta({ ref: "role" })).default([]),
|
|
1232
1210
|
/** ISO date string (YYYY-MM-DD or full ISO 8601) of last meaningful update. */
|
|
1233
1211
|
updatedAt: z.string().trim().min(1).max(50)
|
|
1234
1212
|
});
|
|
1235
|
-
var KnowledgeDomainSchema = z.
|
|
1236
|
-
|
|
1213
|
+
var KnowledgeDomainSchema = z.record(ModelIdSchema, OrgKnowledgeNodeSchema).default({});
|
|
1214
|
+
var PolicyIdSchema = ModelIdSchema;
|
|
1215
|
+
var PolicyApplicabilitySchema = z.object({
|
|
1216
|
+
systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
|
|
1217
|
+
actionIds: z.array(ModelIdSchema.meta({ ref: "action" })).default([]),
|
|
1218
|
+
resourceIds: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]),
|
|
1219
|
+
roleIds: z.array(ModelIdSchema.meta({ ref: "role" })).default([])
|
|
1237
1220
|
});
|
|
1221
|
+
var PolicyTriggerSchema = z.discriminatedUnion("kind", [
|
|
1222
|
+
z.object({
|
|
1223
|
+
kind: z.literal("event"),
|
|
1224
|
+
eventId: EventIdSchema.meta({ ref: "event" })
|
|
1225
|
+
}),
|
|
1226
|
+
z.object({
|
|
1227
|
+
kind: z.literal("action-invocation"),
|
|
1228
|
+
actionId: ModelIdSchema.meta({ ref: "action" })
|
|
1229
|
+
}),
|
|
1230
|
+
z.object({
|
|
1231
|
+
kind: z.literal("schedule"),
|
|
1232
|
+
cron: z.string().trim().min(1).max(120)
|
|
1233
|
+
}),
|
|
1234
|
+
z.object({
|
|
1235
|
+
kind: z.literal("manual")
|
|
1236
|
+
})
|
|
1237
|
+
]);
|
|
1238
|
+
var PolicyPredicateSchema = z.discriminatedUnion("kind", [
|
|
1239
|
+
z.object({
|
|
1240
|
+
kind: z.literal("always")
|
|
1241
|
+
}),
|
|
1242
|
+
z.object({
|
|
1243
|
+
kind: z.literal("expression"),
|
|
1244
|
+
expression: z.string().trim().min(1).max(2e3)
|
|
1245
|
+
}),
|
|
1246
|
+
z.object({
|
|
1247
|
+
kind: z.literal("threshold"),
|
|
1248
|
+
metric: ModelIdSchema,
|
|
1249
|
+
operator: z.enum(["lt", "lte", "eq", "gte", "gt"]).meta({ label: "Operator" }),
|
|
1250
|
+
value: z.number()
|
|
1251
|
+
})
|
|
1252
|
+
]);
|
|
1253
|
+
var PolicyEffectSchema = z.discriminatedUnion("kind", [
|
|
1254
|
+
z.object({
|
|
1255
|
+
kind: z.literal("require-approval"),
|
|
1256
|
+
roleId: ModelIdSchema.meta({ ref: "role" }).optional()
|
|
1257
|
+
}),
|
|
1258
|
+
z.object({
|
|
1259
|
+
kind: z.literal("invoke-action"),
|
|
1260
|
+
actionId: ModelIdSchema.meta({ ref: "action" })
|
|
1261
|
+
}),
|
|
1262
|
+
z.object({
|
|
1263
|
+
kind: z.literal("notify-role"),
|
|
1264
|
+
roleId: ModelIdSchema.meta({ ref: "role" })
|
|
1265
|
+
}),
|
|
1266
|
+
z.object({
|
|
1267
|
+
kind: z.literal("block")
|
|
1268
|
+
})
|
|
1269
|
+
]);
|
|
1270
|
+
var PolicySchema = z.object({
|
|
1271
|
+
id: PolicyIdSchema,
|
|
1272
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
1273
|
+
order: z.number(),
|
|
1274
|
+
label: LabelSchema,
|
|
1275
|
+
description: DescriptionSchema.optional(),
|
|
1276
|
+
trigger: PolicyTriggerSchema,
|
|
1277
|
+
predicate: PolicyPredicateSchema.default({ kind: "always" }),
|
|
1278
|
+
actions: z.array(PolicyEffectSchema).min(1),
|
|
1279
|
+
appliesTo: PolicyApplicabilitySchema.default({
|
|
1280
|
+
systemIds: [],
|
|
1281
|
+
actionIds: [],
|
|
1282
|
+
resourceIds: [],
|
|
1283
|
+
roleIds: []
|
|
1284
|
+
}),
|
|
1285
|
+
lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
|
|
1286
|
+
});
|
|
1287
|
+
var PoliciesDomainSchema = z.record(z.string(), PolicySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
1288
|
+
message: "Each policy entry id must match its map key"
|
|
1289
|
+
}).default({});
|
|
1290
|
+
var DEFAULT_ORGANIZATION_MODEL_POLICIES = {};
|
|
1238
1291
|
|
|
1239
1292
|
// src/organization-model/schema.ts
|
|
1293
|
+
var OrganizationModelDomainKeySchema = z.enum([
|
|
1294
|
+
"branding",
|
|
1295
|
+
"identity",
|
|
1296
|
+
"customers",
|
|
1297
|
+
"offerings",
|
|
1298
|
+
"roles",
|
|
1299
|
+
"goals",
|
|
1300
|
+
"systems",
|
|
1301
|
+
"resources",
|
|
1302
|
+
"actions",
|
|
1303
|
+
"entities",
|
|
1304
|
+
"policies",
|
|
1305
|
+
"knowledge"
|
|
1306
|
+
]);
|
|
1307
|
+
var OrganizationModelDomainMetadataSchema = z.object({
|
|
1308
|
+
version: z.literal(1).default(1),
|
|
1309
|
+
lastModified: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "lastModified must be an ISO date string (YYYY-MM-DD)")
|
|
1310
|
+
});
|
|
1311
|
+
var DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA = {
|
|
1312
|
+
branding: { version: 1, lastModified: "2026-05-10" },
|
|
1313
|
+
identity: { version: 1, lastModified: "2026-05-10" },
|
|
1314
|
+
customers: { version: 1, lastModified: "2026-05-10" },
|
|
1315
|
+
offerings: { version: 1, lastModified: "2026-05-10" },
|
|
1316
|
+
roles: { version: 1, lastModified: "2026-05-10" },
|
|
1317
|
+
goals: { version: 1, lastModified: "2026-05-10" },
|
|
1318
|
+
systems: { version: 1, lastModified: "2026-05-10" },
|
|
1319
|
+
resources: { version: 1, lastModified: "2026-05-10" },
|
|
1320
|
+
actions: { version: 1, lastModified: "2026-05-10" },
|
|
1321
|
+
entities: { version: 1, lastModified: "2026-05-10" },
|
|
1322
|
+
policies: { version: 1, lastModified: "2026-05-10" },
|
|
1323
|
+
knowledge: { version: 1, lastModified: "2026-05-10" }
|
|
1324
|
+
};
|
|
1325
|
+
var OrganizationModelDomainMetadataByDomainSchema = z.object({
|
|
1326
|
+
branding: OrganizationModelDomainMetadataSchema,
|
|
1327
|
+
identity: OrganizationModelDomainMetadataSchema,
|
|
1328
|
+
customers: OrganizationModelDomainMetadataSchema,
|
|
1329
|
+
offerings: OrganizationModelDomainMetadataSchema,
|
|
1330
|
+
roles: OrganizationModelDomainMetadataSchema,
|
|
1331
|
+
goals: OrganizationModelDomainMetadataSchema,
|
|
1332
|
+
systems: OrganizationModelDomainMetadataSchema,
|
|
1333
|
+
resources: OrganizationModelDomainMetadataSchema,
|
|
1334
|
+
actions: OrganizationModelDomainMetadataSchema,
|
|
1335
|
+
entities: OrganizationModelDomainMetadataSchema,
|
|
1336
|
+
policies: OrganizationModelDomainMetadataSchema,
|
|
1337
|
+
knowledge: OrganizationModelDomainMetadataSchema
|
|
1338
|
+
}).partial().default(DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA).transform((metadata) => ({ ...DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA, ...metadata }));
|
|
1240
1339
|
var OrganizationModelSchemaBase = z.object({
|
|
1241
1340
|
version: z.literal(1).default(1),
|
|
1242
|
-
|
|
1341
|
+
domainMetadata: OrganizationModelDomainMetadataByDomainSchema,
|
|
1243
1342
|
branding: OrganizationModelBrandingSchema,
|
|
1244
|
-
navigation: OrganizationModelNavigationSchema
|
|
1245
|
-
sales: OrganizationModelSalesSchema,
|
|
1246
|
-
prospecting: OrganizationModelProspectingSchema,
|
|
1247
|
-
projects: OrganizationModelProjectsSchema,
|
|
1343
|
+
navigation: OrganizationModelNavigationSchema,
|
|
1248
1344
|
identity: IdentityDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_IDENTITY),
|
|
1249
1345
|
customers: CustomersDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_CUSTOMERS),
|
|
1250
1346
|
offerings: OfferingsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_OFFERINGS),
|
|
1251
1347
|
roles: RolesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ROLES),
|
|
1252
1348
|
goals: GoalsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_GOALS),
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1349
|
+
systems: SystemsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_SYSTEMS),
|
|
1350
|
+
resources: ResourcesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_RESOURCES),
|
|
1351
|
+
actions: ActionsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ACTIONS),
|
|
1352
|
+
entities: EntitiesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ENTITIES),
|
|
1353
|
+
policies: PoliciesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_POLICIES),
|
|
1354
|
+
// D3: flat Record<id, OrgKnowledgeNode> — no wrapper object
|
|
1355
|
+
knowledge: KnowledgeDomainSchema.default({})
|
|
1256
1356
|
});
|
|
1257
1357
|
function addIssue(ctx, path, message) {
|
|
1258
1358
|
ctx.addIssue({
|
|
@@ -1261,167 +1361,547 @@ function addIssue(ctx, path, message) {
|
|
|
1261
1361
|
message
|
|
1262
1362
|
});
|
|
1263
1363
|
}
|
|
1264
|
-
function
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
if (itemsById.has(item.id)) {
|
|
1268
|
-
addIssue(ctx, [...collectionPath, index, "id"], `${label} id "${item.id}" must be unique`);
|
|
1269
|
-
return;
|
|
1270
|
-
}
|
|
1271
|
-
itemsById.set(item.id, item);
|
|
1272
|
-
});
|
|
1273
|
-
return itemsById;
|
|
1274
|
-
}
|
|
1275
|
-
var LEGACY_FEATURE_ALIASES = /* @__PURE__ */ new Map([
|
|
1276
|
-
["crm", "sales.crm"],
|
|
1277
|
-
["lead-gen", "sales.lead-gen"],
|
|
1278
|
-
["submitted-requests", "monitoring.submitted-requests"]
|
|
1279
|
-
]);
|
|
1280
|
-
function hasFeature(featuresById, featureId) {
|
|
1281
|
-
return featuresById.has(featureId) || featuresById.has(LEGACY_FEATURE_ALIASES.get(featureId) ?? "");
|
|
1364
|
+
function isLifecycleEnabled(lifecycle, enabled) {
|
|
1365
|
+
if (enabled === false) return false;
|
|
1366
|
+
return lifecycle !== "deprecated" && lifecycle !== "archived";
|
|
1282
1367
|
}
|
|
1283
|
-
function
|
|
1368
|
+
function defaultSystemPathFor(id) {
|
|
1284
1369
|
return `/${id.replaceAll(".", "/")}`;
|
|
1285
1370
|
}
|
|
1371
|
+
function asRoleHolderArray(heldBy) {
|
|
1372
|
+
return Array.isArray(heldBy) ? heldBy : [heldBy];
|
|
1373
|
+
}
|
|
1374
|
+
function isKnowledgeKindCompatibleWithTarget(knowledgeKind, targetKind) {
|
|
1375
|
+
if (knowledgeKind === "reference") return true;
|
|
1376
|
+
if (knowledgeKind === "playbook") {
|
|
1377
|
+
return ["system", "resource", "stage", "action"].includes(targetKind);
|
|
1378
|
+
}
|
|
1379
|
+
if (knowledgeKind === "strategy") {
|
|
1380
|
+
return ["system", "goal", "offering", "customer-segment"].includes(targetKind);
|
|
1381
|
+
}
|
|
1382
|
+
return false;
|
|
1383
|
+
}
|
|
1286
1384
|
var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ctx) => {
|
|
1287
|
-
|
|
1288
|
-
|
|
1289
|
-
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
if (
|
|
1385
|
+
function collectAllSystems(systems, prefix = "", schemaPath = ["systems"]) {
|
|
1386
|
+
const result = [];
|
|
1387
|
+
for (const [key, system] of Object.entries(systems)) {
|
|
1388
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
1389
|
+
const currentSchemaPath = [...schemaPath, key];
|
|
1390
|
+
result.push({ path, schemaPath: currentSchemaPath, system });
|
|
1391
|
+
if (system.subsystems !== void 0) {
|
|
1392
|
+
result.push(...collectAllSystems(system.subsystems, path, [...currentSchemaPath, "subsystems"]));
|
|
1393
|
+
}
|
|
1394
|
+
}
|
|
1395
|
+
return result;
|
|
1396
|
+
}
|
|
1397
|
+
const allSystems = collectAllSystems(model.systems);
|
|
1398
|
+
const systemsById = /* @__PURE__ */ new Map();
|
|
1399
|
+
for (const { path, system } of allSystems) {
|
|
1400
|
+
systemsById.set(path, system);
|
|
1401
|
+
systemsById.set(system.id, system);
|
|
1402
|
+
}
|
|
1403
|
+
const systemIdsByEffectivePath = /* @__PURE__ */ new Map();
|
|
1404
|
+
allSystems.forEach(({ path, schemaPath, system }) => {
|
|
1405
|
+
if (system.parentSystemId !== void 0 && !systemsById.has(system.parentSystemId)) {
|
|
1406
|
+
addIssue(
|
|
1407
|
+
ctx,
|
|
1408
|
+
[...schemaPath, "parentSystemId"],
|
|
1409
|
+
`System "${system.id}" references unknown parent "${system.parentSystemId}"`
|
|
1410
|
+
);
|
|
1411
|
+
}
|
|
1412
|
+
const hasChildren = Object.keys(system.subsystems ?? {}).length > 0 || allSystems.some((candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes("."));
|
|
1413
|
+
const contributesRoutePath = system.ui?.path !== void 0 || system.path !== void 0 || !hasChildren;
|
|
1414
|
+
if (contributesRoutePath) {
|
|
1415
|
+
const effectivePath = system.ui?.path ?? system.path ?? defaultSystemPathFor(path);
|
|
1416
|
+
const existingSystemId = systemIdsByEffectivePath.get(effectivePath);
|
|
1417
|
+
if (existingSystemId !== void 0) {
|
|
1294
1418
|
addIssue(
|
|
1295
1419
|
ctx,
|
|
1296
|
-
["
|
|
1297
|
-
`
|
|
1420
|
+
[...schemaPath, system.ui?.path !== void 0 ? "ui" : "path"],
|
|
1421
|
+
`System "${path}" effective path "${effectivePath}" duplicates system "${existingSystemId}"`
|
|
1298
1422
|
);
|
|
1423
|
+
} else {
|
|
1424
|
+
systemIdsByEffectivePath.set(effectivePath, path);
|
|
1299
1425
|
}
|
|
1300
1426
|
}
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1427
|
+
if (hasChildren && isLifecycleEnabled(system.lifecycle, system.enabled)) {
|
|
1428
|
+
const hasEnabledDescendant = Object.values(system.subsystems ?? {}).some(
|
|
1429
|
+
(candidate) => isLifecycleEnabled(candidate.lifecycle, candidate.enabled)
|
|
1430
|
+
) || allSystems.some(
|
|
1431
|
+
(candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes(".") && isLifecycleEnabled(candidate.system.lifecycle, candidate.system.enabled)
|
|
1432
|
+
);
|
|
1433
|
+
if (!hasEnabledDescendant) {
|
|
1434
|
+
addIssue(
|
|
1435
|
+
ctx,
|
|
1436
|
+
[...schemaPath, "lifecycle"],
|
|
1437
|
+
`System "${path}" is active but has no active descendants`
|
|
1438
|
+
);
|
|
1439
|
+
}
|
|
1440
|
+
}
|
|
1441
|
+
});
|
|
1442
|
+
allSystems.forEach(({ schemaPath, system }) => {
|
|
1443
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1444
|
+
let currentParentId = system.parentSystemId;
|
|
1445
|
+
while (currentParentId !== void 0) {
|
|
1446
|
+
if (currentParentId === system.id || visited.has(currentParentId)) {
|
|
1447
|
+
addIssue(ctx, [...schemaPath, "parentSystemId"], `System "${system.id}" has a parent cycle`);
|
|
1448
|
+
return;
|
|
1449
|
+
}
|
|
1450
|
+
visited.add(currentParentId);
|
|
1451
|
+
currentParentId = systemsById.get(currentParentId)?.parentSystemId;
|
|
1452
|
+
}
|
|
1453
|
+
});
|
|
1454
|
+
function normalizeRoutePath(path) {
|
|
1455
|
+
return path.length > 1 ? path.replace(/\/+$/, "") : path;
|
|
1456
|
+
}
|
|
1457
|
+
const sidebarNodeIds = /* @__PURE__ */ new Map();
|
|
1458
|
+
const sidebarSurfacePaths = /* @__PURE__ */ new Map();
|
|
1459
|
+
const sidebarSurfaces = [];
|
|
1460
|
+
function collectSidebarNodes(nodes, schemaPath) {
|
|
1461
|
+
Object.entries(nodes).forEach(([nodeId, node]) => {
|
|
1462
|
+
const nodePath = [...schemaPath, nodeId];
|
|
1463
|
+
const existingNodePath = sidebarNodeIds.get(nodeId);
|
|
1464
|
+
if (existingNodePath !== void 0) {
|
|
1465
|
+
addIssue(ctx, nodePath, `Sidebar node id "${nodeId}" duplicates another sidebar node`);
|
|
1466
|
+
} else {
|
|
1467
|
+
sidebarNodeIds.set(nodeId, nodePath);
|
|
1468
|
+
}
|
|
1469
|
+
if (node.type === "group") {
|
|
1470
|
+
collectSidebarNodes(node.children, [...nodePath, "children"]);
|
|
1471
|
+
return;
|
|
1472
|
+
}
|
|
1473
|
+
sidebarSurfaces.push({ id: nodeId, node, path: nodePath });
|
|
1474
|
+
const normalizedPath = normalizeRoutePath(node.path);
|
|
1475
|
+
const existingSurfaceId = sidebarSurfacePaths.get(normalizedPath);
|
|
1476
|
+
if (existingSurfaceId !== void 0) {
|
|
1309
1477
|
addIssue(
|
|
1310
1478
|
ctx,
|
|
1311
|
-
[
|
|
1312
|
-
`
|
|
1479
|
+
[...nodePath, "path"],
|
|
1480
|
+
`Sidebar surface path "${node.path}" duplicates surface "${existingSurfaceId}"`
|
|
1313
1481
|
);
|
|
1314
1482
|
} else {
|
|
1315
|
-
|
|
1483
|
+
sidebarSurfacePaths.set(normalizedPath, nodeId);
|
|
1484
|
+
}
|
|
1485
|
+
node.targets?.systems?.forEach((systemId, systemIndex) => {
|
|
1486
|
+
if (!systemsById.has(systemId)) {
|
|
1487
|
+
addIssue(
|
|
1488
|
+
ctx,
|
|
1489
|
+
[...nodePath, "targets", "systems", systemIndex],
|
|
1490
|
+
`Sidebar surface "${nodeId}" references unknown system "${systemId}"`
|
|
1491
|
+
);
|
|
1492
|
+
}
|
|
1493
|
+
});
|
|
1494
|
+
});
|
|
1495
|
+
}
|
|
1496
|
+
collectSidebarNodes(model.navigation.sidebar.primary, ["navigation", "sidebar", "primary"]);
|
|
1497
|
+
collectSidebarNodes(model.navigation.sidebar.bottom, ["navigation", "sidebar", "bottom"]);
|
|
1498
|
+
const segmentsById = new Map(Object.entries(model.customers));
|
|
1499
|
+
Object.values(model.offerings).forEach((product) => {
|
|
1500
|
+
product.targetSegmentIds.forEach((segmentId, segmentIndex) => {
|
|
1501
|
+
if (!segmentsById.has(segmentId)) {
|
|
1502
|
+
addIssue(
|
|
1503
|
+
ctx,
|
|
1504
|
+
["offerings", product.id, "targetSegmentIds", segmentIndex],
|
|
1505
|
+
`Product "${product.id}" references unknown customer segment "${segmentId}"`
|
|
1506
|
+
);
|
|
1507
|
+
}
|
|
1508
|
+
});
|
|
1509
|
+
if (product.deliveryFeatureId !== void 0 && !systemsById.has(product.deliveryFeatureId)) {
|
|
1510
|
+
addIssue(
|
|
1511
|
+
ctx,
|
|
1512
|
+
["offerings", product.id, "deliveryFeatureId"],
|
|
1513
|
+
`Product "${product.id}" references unknown delivery system "${product.deliveryFeatureId}"`
|
|
1514
|
+
);
|
|
1515
|
+
}
|
|
1516
|
+
});
|
|
1517
|
+
Object.values(model.goals).forEach((objective) => {
|
|
1518
|
+
if (objective.periodEnd <= objective.periodStart) {
|
|
1519
|
+
addIssue(
|
|
1520
|
+
ctx,
|
|
1521
|
+
["goals", objective.id, "periodEnd"],
|
|
1522
|
+
`Goal "${objective.id}" has periodEnd "${objective.periodEnd}" which must be strictly after periodStart "${objective.periodStart}"`
|
|
1523
|
+
);
|
|
1524
|
+
}
|
|
1525
|
+
});
|
|
1526
|
+
const goalsById = new Map(Object.entries(model.goals));
|
|
1527
|
+
const knowledgeById = new Map(Object.entries(model.knowledge));
|
|
1528
|
+
const actionsById = new Map(Object.entries(model.actions));
|
|
1529
|
+
const entitiesById = new Map(Object.entries(model.entities));
|
|
1530
|
+
const policiesById = new Map(Object.entries(model.policies));
|
|
1531
|
+
sidebarSurfaces.forEach(({ id, node, path }) => {
|
|
1532
|
+
node.targets?.entities?.forEach((entityId, entityIndex) => {
|
|
1533
|
+
if (!entitiesById.has(entityId)) {
|
|
1534
|
+
addIssue(
|
|
1535
|
+
ctx,
|
|
1536
|
+
[...path, "targets", "entities", entityIndex],
|
|
1537
|
+
`Sidebar surface "${id}" references unknown entity "${entityId}"`
|
|
1538
|
+
);
|
|
1539
|
+
}
|
|
1540
|
+
});
|
|
1541
|
+
node.targets?.actions?.forEach((actionId, actionIndex) => {
|
|
1542
|
+
if (!actionsById.has(actionId)) {
|
|
1543
|
+
addIssue(
|
|
1544
|
+
ctx,
|
|
1545
|
+
[...path, "targets", "actions", actionIndex],
|
|
1546
|
+
`Sidebar surface "${id}" references unknown action "${actionId}"`
|
|
1547
|
+
);
|
|
1316
1548
|
}
|
|
1549
|
+
});
|
|
1550
|
+
});
|
|
1551
|
+
Object.values(model.entities).forEach((entity) => {
|
|
1552
|
+
if (!systemsById.has(entity.ownedBySystemId)) {
|
|
1553
|
+
addIssue(
|
|
1554
|
+
ctx,
|
|
1555
|
+
["entities", entity.id, "ownedBySystemId"],
|
|
1556
|
+
`Entity "${entity.id}" references unknown ownedBySystemId "${entity.ownedBySystemId}"`
|
|
1557
|
+
);
|
|
1317
1558
|
}
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
(
|
|
1559
|
+
entity.links?.forEach((link, linkIndex) => {
|
|
1560
|
+
if (!entitiesById.has(link.toEntity)) {
|
|
1561
|
+
addIssue(
|
|
1562
|
+
ctx,
|
|
1563
|
+
["entities", entity.id, "links", linkIndex, "toEntity"],
|
|
1564
|
+
`Entity "${entity.id}" links to unknown entity "${link.toEntity}"`
|
|
1565
|
+
);
|
|
1566
|
+
}
|
|
1567
|
+
});
|
|
1568
|
+
});
|
|
1569
|
+
const rolesById = new Map(Object.entries(model.roles));
|
|
1570
|
+
Object.values(model.roles).forEach((role) => {
|
|
1571
|
+
if (role.reportsToId !== void 0 && !rolesById.has(role.reportsToId)) {
|
|
1572
|
+
addIssue(
|
|
1573
|
+
ctx,
|
|
1574
|
+
["roles", role.id, "reportsToId"],
|
|
1575
|
+
`Role "${role.id}" references unknown reportsToId "${role.reportsToId}"`
|
|
1321
1576
|
);
|
|
1322
|
-
|
|
1577
|
+
}
|
|
1578
|
+
});
|
|
1579
|
+
Object.values(model.roles).forEach((role) => {
|
|
1580
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1581
|
+
let currentReportsToId = role.reportsToId;
|
|
1582
|
+
while (currentReportsToId !== void 0) {
|
|
1583
|
+
if (currentReportsToId === role.id || visited.has(currentReportsToId)) {
|
|
1584
|
+
addIssue(ctx, ["roles", role.id, "reportsToId"], `Role "${role.id}" has a reportsToId cycle`);
|
|
1585
|
+
return;
|
|
1586
|
+
}
|
|
1587
|
+
visited.add(currentReportsToId);
|
|
1588
|
+
currentReportsToId = rolesById.get(currentReportsToId)?.reportsToId;
|
|
1589
|
+
}
|
|
1590
|
+
});
|
|
1591
|
+
Object.values(model.roles).forEach((role) => {
|
|
1592
|
+
role.responsibleFor?.forEach((systemId, systemIndex) => {
|
|
1593
|
+
if (!systemsById.has(systemId)) {
|
|
1594
|
+
addIssue(
|
|
1595
|
+
ctx,
|
|
1596
|
+
["roles", role.id, "responsibleFor", systemIndex],
|
|
1597
|
+
`Role "${role.id}" references unknown responsibleFor system "${systemId}"`
|
|
1598
|
+
);
|
|
1599
|
+
}
|
|
1600
|
+
});
|
|
1601
|
+
});
|
|
1602
|
+
allSystems.forEach(({ schemaPath, system }) => {
|
|
1603
|
+
if (system.responsibleRoleId !== void 0 && !rolesById.has(system.responsibleRoleId)) {
|
|
1604
|
+
addIssue(
|
|
1605
|
+
ctx,
|
|
1606
|
+
[...schemaPath, "responsibleRoleId"],
|
|
1607
|
+
`System "${system.id}" references unknown responsibleRoleId "${system.responsibleRoleId}"`
|
|
1608
|
+
);
|
|
1609
|
+
}
|
|
1610
|
+
system.governedByKnowledge?.forEach((nodeId, nodeIndex) => {
|
|
1611
|
+
if (!knowledgeById.has(nodeId)) {
|
|
1612
|
+
addIssue(
|
|
1613
|
+
ctx,
|
|
1614
|
+
[...schemaPath, "governedByKnowledge", nodeIndex],
|
|
1615
|
+
`System "${system.id}" references unknown knowledge node "${nodeId}"`
|
|
1616
|
+
);
|
|
1617
|
+
}
|
|
1618
|
+
});
|
|
1619
|
+
system.drivesGoals?.forEach((goalId, goalIndex) => {
|
|
1620
|
+
if (!goalsById.has(goalId)) {
|
|
1621
|
+
addIssue(
|
|
1622
|
+
ctx,
|
|
1623
|
+
[...schemaPath, "drivesGoals", goalIndex],
|
|
1624
|
+
`System "${system.id}" references unknown goal "${goalId}"`
|
|
1625
|
+
);
|
|
1626
|
+
}
|
|
1627
|
+
});
|
|
1628
|
+
system.actions?.forEach((actionRef, actionIndex) => {
|
|
1629
|
+
if (!actionsById.has(actionRef.actionId)) {
|
|
1630
|
+
addIssue(
|
|
1631
|
+
ctx,
|
|
1632
|
+
[...schemaPath, "actions", actionIndex, "actionId"],
|
|
1633
|
+
`System "${system.id}" references unknown action "${actionRef.actionId}"`
|
|
1634
|
+
);
|
|
1635
|
+
}
|
|
1636
|
+
});
|
|
1637
|
+
system.policies?.forEach((policyId, policyIndex) => {
|
|
1638
|
+
if (!policiesById.has(policyId)) {
|
|
1639
|
+
addIssue(
|
|
1640
|
+
ctx,
|
|
1641
|
+
[...schemaPath, "policies", policyIndex],
|
|
1642
|
+
`System "${system.id}" references unknown policy "${policyId}"`
|
|
1643
|
+
);
|
|
1644
|
+
}
|
|
1645
|
+
});
|
|
1646
|
+
});
|
|
1647
|
+
Object.values(model.actions).forEach((action) => {
|
|
1648
|
+
action.affects?.forEach((entityId, entityIndex) => {
|
|
1649
|
+
if (!entitiesById.has(entityId)) {
|
|
1650
|
+
addIssue(
|
|
1651
|
+
ctx,
|
|
1652
|
+
["actions", action.id, "affects", entityIndex],
|
|
1653
|
+
`Action "${action.id}" affects unknown entity "${entityId}"`
|
|
1654
|
+
);
|
|
1655
|
+
}
|
|
1656
|
+
});
|
|
1657
|
+
});
|
|
1658
|
+
const resourcesById = new Map(Object.entries(model.resources));
|
|
1659
|
+
sidebarSurfaces.forEach(({ id, node, path }) => {
|
|
1660
|
+
node.targets?.resources?.forEach((resourceId, resourceIndex) => {
|
|
1661
|
+
if (!resourcesById.has(resourceId)) {
|
|
1662
|
+
addIssue(
|
|
1663
|
+
ctx,
|
|
1664
|
+
[...path, "targets", "resources", resourceIndex],
|
|
1665
|
+
`Sidebar surface "${id}" references unknown resource "${resourceId}"`
|
|
1666
|
+
);
|
|
1667
|
+
}
|
|
1668
|
+
});
|
|
1669
|
+
});
|
|
1670
|
+
const stageIds = /* @__PURE__ */ new Set();
|
|
1671
|
+
const actionIds = new Set(Object.keys(model.actions));
|
|
1672
|
+
const offeringsById = new Map(Object.entries(model.offerings));
|
|
1673
|
+
Object.values(model.policies).forEach((policy) => {
|
|
1674
|
+
policy.appliesTo.systemIds.forEach((systemId, systemIndex) => {
|
|
1675
|
+
if (!systemsById.has(systemId)) {
|
|
1676
|
+
addIssue(
|
|
1677
|
+
ctx,
|
|
1678
|
+
["policies", policy.id, "appliesTo", "systemIds", systemIndex],
|
|
1679
|
+
`Policy "${policy.id}" applies to unknown system "${systemId}"`
|
|
1680
|
+
);
|
|
1681
|
+
}
|
|
1682
|
+
});
|
|
1683
|
+
policy.appliesTo.actionIds.forEach((actionId, actionIndex) => {
|
|
1684
|
+
if (!actionsById.has(actionId)) {
|
|
1323
1685
|
addIssue(
|
|
1324
1686
|
ctx,
|
|
1325
|
-
["
|
|
1326
|
-
`
|
|
1687
|
+
["policies", policy.id, "appliesTo", "actionIds", actionIndex],
|
|
1688
|
+
`Policy "${policy.id}" applies to unknown action "${actionId}"`
|
|
1327
1689
|
);
|
|
1328
1690
|
}
|
|
1691
|
+
});
|
|
1692
|
+
policy.actions.forEach((action, actionIndex) => {
|
|
1693
|
+
if (action.kind === "invoke-action" && !actionsById.has(action.actionId)) {
|
|
1694
|
+
addIssue(
|
|
1695
|
+
ctx,
|
|
1696
|
+
["policies", policy.id, "actions", actionIndex, "actionId"],
|
|
1697
|
+
`Policy "${policy.id}" invokes unknown action "${action.actionId}"`
|
|
1698
|
+
);
|
|
1699
|
+
}
|
|
1700
|
+
if ((action.kind === "notify-role" || action.kind === "require-approval") && action.roleId !== void 0 && !rolesById.has(action.roleId)) {
|
|
1701
|
+
addIssue(
|
|
1702
|
+
ctx,
|
|
1703
|
+
["policies", policy.id, "actions", actionIndex, "roleId"],
|
|
1704
|
+
`Policy "${policy.id}" references unknown role "${action.roleId}"`
|
|
1705
|
+
);
|
|
1706
|
+
}
|
|
1707
|
+
});
|
|
1708
|
+
if (policy.trigger.kind === "action-invocation" && !actionsById.has(policy.trigger.actionId)) {
|
|
1709
|
+
addIssue(
|
|
1710
|
+
ctx,
|
|
1711
|
+
["policies", policy.id, "trigger", "actionId"],
|
|
1712
|
+
`Policy "${policy.id}" references unknown trigger action "${policy.trigger.actionId}"`
|
|
1713
|
+
);
|
|
1329
1714
|
}
|
|
1330
1715
|
});
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
);
|
|
1716
|
+
function knowledgeTargetExists(kind, id) {
|
|
1717
|
+
if (kind === "system") return systemsById.has(id);
|
|
1718
|
+
if (kind === "resource") return resourcesById.has(id);
|
|
1719
|
+
if (kind === "knowledge") return knowledgeById.has(id);
|
|
1720
|
+
if (kind === "stage") return stageIds.has(id);
|
|
1721
|
+
if (kind === "action") return actionIds.has(id);
|
|
1722
|
+
if (kind === "role") return rolesById.has(id);
|
|
1723
|
+
if (kind === "goal") return goalsById.has(id);
|
|
1724
|
+
if (kind === "customer-segment") return segmentsById.has(id);
|
|
1725
|
+
if (kind === "offering") return offeringsById.has(id);
|
|
1726
|
+
return false;
|
|
1338
1727
|
}
|
|
1339
|
-
model.
|
|
1340
|
-
|
|
1341
|
-
if (!
|
|
1728
|
+
Object.entries(model.knowledge).forEach(([nodeId, node]) => {
|
|
1729
|
+
node.links.forEach((link, linkIndex) => {
|
|
1730
|
+
if (!knowledgeTargetExists(link.target.kind, link.target.id)) {
|
|
1731
|
+
addIssue(
|
|
1732
|
+
ctx,
|
|
1733
|
+
["knowledge", nodeId, "links", linkIndex, "target"],
|
|
1734
|
+
`Knowledge node "${node.id}" references unknown ${link.target.kind} target "${link.target.id}"`
|
|
1735
|
+
);
|
|
1736
|
+
}
|
|
1737
|
+
if (!isKnowledgeKindCompatibleWithTarget(node.kind, link.target.kind)) {
|
|
1342
1738
|
addIssue(
|
|
1343
1739
|
ctx,
|
|
1344
|
-
["
|
|
1345
|
-
`
|
|
1740
|
+
["knowledge", nodeId, "links", linkIndex, "target", "kind"],
|
|
1741
|
+
`Knowledge node "${node.id}" kind "${node.kind}" cannot govern ${link.target.kind} targets`
|
|
1346
1742
|
);
|
|
1347
1743
|
}
|
|
1348
1744
|
});
|
|
1349
1745
|
});
|
|
1350
|
-
model.
|
|
1351
|
-
if (
|
|
1746
|
+
Object.values(model.resources).forEach((resource) => {
|
|
1747
|
+
if (!systemsById.has(resource.systemPath)) {
|
|
1352
1748
|
addIssue(
|
|
1353
1749
|
ctx,
|
|
1354
|
-
["
|
|
1355
|
-
`
|
|
1750
|
+
["resources", resource.id, "systemPath"],
|
|
1751
|
+
`Resource "${resource.id}" references unknown system path "${resource.systemPath}"`
|
|
1356
1752
|
);
|
|
1357
1753
|
}
|
|
1358
|
-
|
|
1359
|
-
|
|
1754
|
+
if (resource.ownerRoleId !== void 0 && !rolesById.has(resource.ownerRoleId)) {
|
|
1755
|
+
addIssue(
|
|
1756
|
+
ctx,
|
|
1757
|
+
["resources", resource.id, "ownerRoleId"],
|
|
1758
|
+
`Resource "${resource.id}" references unknown ownerRoleId "${resource.ownerRoleId}"`
|
|
1759
|
+
);
|
|
1760
|
+
}
|
|
1761
|
+
if (resource.kind === "agent" && resource.actsAsRoleId !== void 0 && !rolesById.has(resource.actsAsRoleId)) {
|
|
1762
|
+
addIssue(
|
|
1763
|
+
ctx,
|
|
1764
|
+
["resources", resource.id, "actsAsRoleId"],
|
|
1765
|
+
`Agent resource "${resource.id}" references unknown actsAsRoleId "${resource.actsAsRoleId}"`
|
|
1766
|
+
);
|
|
1767
|
+
}
|
|
1768
|
+
});
|
|
1769
|
+
Object.values(model.roles).forEach((role) => {
|
|
1770
|
+
if (role.heldBy === void 0) return;
|
|
1771
|
+
asRoleHolderArray(role.heldBy).forEach((holder, holderIndex) => {
|
|
1772
|
+
if (holder.kind !== "agent") return;
|
|
1773
|
+
const resource = resourcesById.get(holder.agentId);
|
|
1774
|
+
if (resource === void 0) {
|
|
1360
1775
|
addIssue(
|
|
1361
1776
|
ctx,
|
|
1362
|
-
["
|
|
1363
|
-
`
|
|
1777
|
+
["roles", role.id, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
|
|
1778
|
+
`Role "${role.id}" references unknown agent holder resource "${holder.agentId}"`
|
|
1779
|
+
);
|
|
1780
|
+
return;
|
|
1781
|
+
}
|
|
1782
|
+
if (resource.kind !== "agent") {
|
|
1783
|
+
addIssue(
|
|
1784
|
+
ctx,
|
|
1785
|
+
["roles", role.id, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
|
|
1786
|
+
`Role "${role.id}" agent holder "${holder.agentId}" must reference an agent resource`
|
|
1364
1787
|
);
|
|
1365
1788
|
}
|
|
1366
1789
|
});
|
|
1367
1790
|
});
|
|
1368
|
-
|
|
1369
|
-
|
|
1370
|
-
|
|
1371
|
-
|
|
1791
|
+
Object.entries(model.knowledge).forEach(([nodeId, node]) => {
|
|
1792
|
+
node.ownerIds.forEach((roleId, ownerIndex) => {
|
|
1793
|
+
if (!rolesById.has(roleId)) {
|
|
1794
|
+
addIssue(
|
|
1795
|
+
ctx,
|
|
1796
|
+
["knowledge", nodeId, "ownerIds", ownerIndex],
|
|
1797
|
+
`Knowledge node "${node.id}" references unknown owner role "${roleId}"`
|
|
1798
|
+
);
|
|
1799
|
+
}
|
|
1800
|
+
});
|
|
1801
|
+
});
|
|
1802
|
+
function validateSystemContent(system, systemPath) {
|
|
1803
|
+
const content = system.content;
|
|
1804
|
+
if (content === void 0 || Object.keys(content).length === 0) {
|
|
1805
|
+
if (system.subsystems !== void 0) {
|
|
1806
|
+
Object.entries(system.subsystems).forEach(([childKey, child]) => {
|
|
1807
|
+
validateSystemContent(child, [...systemPath, "subsystems", childKey]);
|
|
1808
|
+
});
|
|
1809
|
+
}
|
|
1810
|
+
return;
|
|
1811
|
+
}
|
|
1812
|
+
Object.entries(content).forEach(([localId, node]) => {
|
|
1813
|
+
if (node.parentContentId !== void 0 && !(node.parentContentId in content)) {
|
|
1372
1814
|
addIssue(
|
|
1373
1815
|
ctx,
|
|
1374
|
-
[
|
|
1375
|
-
`
|
|
1816
|
+
[...systemPath, "content", localId, "parentContentId"],
|
|
1817
|
+
`Content node "${localId}" parentContentId "${node.parentContentId}" does not resolve within the same system`
|
|
1376
1818
|
);
|
|
1377
1819
|
}
|
|
1378
1820
|
});
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
|
|
1383
|
-
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
}
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1403
|
-
|
|
1821
|
+
Object.entries(content).forEach(([localId, node]) => {
|
|
1822
|
+
const visited = /* @__PURE__ */ new Set();
|
|
1823
|
+
let currentId = node.parentContentId;
|
|
1824
|
+
while (currentId !== void 0) {
|
|
1825
|
+
if (currentId === localId || visited.has(currentId)) {
|
|
1826
|
+
addIssue(
|
|
1827
|
+
ctx,
|
|
1828
|
+
[...systemPath, "content", localId, "parentContentId"],
|
|
1829
|
+
`Content node "${localId}" has a parentContentId cycle`
|
|
1830
|
+
);
|
|
1831
|
+
break;
|
|
1832
|
+
}
|
|
1833
|
+
visited.add(currentId);
|
|
1834
|
+
currentId = content[currentId]?.parentContentId;
|
|
1835
|
+
}
|
|
1836
|
+
});
|
|
1837
|
+
Object.entries(content).forEach(([localId, node]) => {
|
|
1838
|
+
const childDef = lookupContentType(node.kind, node.type);
|
|
1839
|
+
if (childDef !== void 0 && node.data !== void 0) {
|
|
1840
|
+
const result = childDef.payloadSchema.safeParse(node.data);
|
|
1841
|
+
if (!result.success) {
|
|
1842
|
+
addIssue(
|
|
1843
|
+
ctx,
|
|
1844
|
+
[...systemPath, "content", localId, "data"],
|
|
1845
|
+
`Content node "${localId}" (${node.kind}:${node.type}) data failed payload validation: ${result.error.message}`
|
|
1846
|
+
);
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
if (node.parentContentId !== void 0 && childDef !== void 0) {
|
|
1850
|
+
const parentNode = content[node.parentContentId];
|
|
1851
|
+
if (parentNode !== void 0) {
|
|
1852
|
+
const parentDef = lookupContentType(parentNode.kind, parentNode.type);
|
|
1853
|
+
if (parentDef !== void 0 && childDef.kind !== parentDef.kind) {
|
|
1854
|
+
addIssue(
|
|
1855
|
+
ctx,
|
|
1856
|
+
[...systemPath, "content", localId, "parentContentId"],
|
|
1857
|
+
`Content node "${localId}" kind "${childDef.kind}" cannot parent under "${node.parentContentId}" kind "${parentDef.kind}": parentContentId must be same-meta-kind (per L19)`
|
|
1858
|
+
);
|
|
1859
|
+
}
|
|
1860
|
+
}
|
|
1861
|
+
}
|
|
1862
|
+
});
|
|
1863
|
+
if (system.subsystems !== void 0) {
|
|
1864
|
+
Object.entries(system.subsystems).forEach(([childKey, child]) => {
|
|
1865
|
+
validateSystemContent(child, [...systemPath, "subsystems", childKey]);
|
|
1866
|
+
});
|
|
1404
1867
|
}
|
|
1868
|
+
}
|
|
1869
|
+
Object.entries(model.systems).forEach(([systemKey, system]) => {
|
|
1870
|
+
validateSystemContent(system, ["systems", systemKey]);
|
|
1405
1871
|
});
|
|
1406
1872
|
});
|
|
1407
1873
|
var OrganizationGraphNodeKindSchema = z.enum([
|
|
1408
1874
|
"organization",
|
|
1409
|
-
"
|
|
1410
|
-
"
|
|
1875
|
+
"system",
|
|
1876
|
+
"role",
|
|
1877
|
+
"action",
|
|
1411
1878
|
"entity",
|
|
1412
|
-
"
|
|
1879
|
+
"event",
|
|
1880
|
+
"policy",
|
|
1413
1881
|
"stage",
|
|
1414
1882
|
"resource",
|
|
1415
|
-
"knowledge"
|
|
1883
|
+
"knowledge",
|
|
1884
|
+
"customer-segment",
|
|
1885
|
+
"offering",
|
|
1886
|
+
"goal",
|
|
1887
|
+
"surface",
|
|
1888
|
+
"navigation-group",
|
|
1889
|
+
// Phase 3 preview — Phase 4 populates via graph projection of system.content entries.
|
|
1890
|
+
"content-node"
|
|
1416
1891
|
]);
|
|
1417
1892
|
var OrganizationGraphEdgeKindSchema = z.enum([
|
|
1418
1893
|
"contains",
|
|
1419
1894
|
"references",
|
|
1420
|
-
"exposes",
|
|
1421
1895
|
"maps_to",
|
|
1422
|
-
"operates-on",
|
|
1423
1896
|
"uses",
|
|
1424
|
-
"governs"
|
|
1897
|
+
"governs",
|
|
1898
|
+
"links",
|
|
1899
|
+
"affects",
|
|
1900
|
+
"emits",
|
|
1901
|
+
"originates_from",
|
|
1902
|
+
"triggers",
|
|
1903
|
+
"applies_to",
|
|
1904
|
+
"effects"
|
|
1425
1905
|
]);
|
|
1426
1906
|
var OrganizationGraphNodeSchema = z.object({
|
|
1427
1907
|
id: z.string().trim().min(1).max(200),
|
|
@@ -1431,8 +1911,7 @@ var OrganizationGraphNodeSchema = z.object({
|
|
|
1431
1911
|
description: DescriptionSchema.optional(),
|
|
1432
1912
|
icon: IconNameSchema.optional(),
|
|
1433
1913
|
enabled: z.boolean().optional(),
|
|
1434
|
-
|
|
1435
|
-
resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]).optional()
|
|
1914
|
+
resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint", "script"]).optional()
|
|
1436
1915
|
});
|
|
1437
1916
|
var OrganizationGraphEdgeSchema = z.object({
|
|
1438
1917
|
id: z.string().trim().min(1).max(250),
|
|
@@ -1459,328 +1938,1173 @@ var LinkSchema = z.object({
|
|
|
1459
1938
|
kind: OrganizationGraphEdgeKindSchema
|
|
1460
1939
|
});
|
|
1461
1940
|
|
|
1941
|
+
// src/organization-model/contracts.ts
|
|
1942
|
+
var KNOWLEDGE_FEATURE_ID = "knowledge";
|
|
1943
|
+
var KNOWLEDGE_SYSTEM_ID = "knowledge";
|
|
1944
|
+
var PROJECTS_SYSTEM_ID = "projects";
|
|
1945
|
+
var PROJECTS_FEATURE_ID = PROJECTS_SYSTEM_ID;
|
|
1946
|
+
var PROJECTS_INDEX_SURFACE_ID = "projects.index";
|
|
1947
|
+
var PROJECTS_VIEW_ACTION_ID = "delivery.projects.view";
|
|
1948
|
+
var SALES_FEATURE_ID = "crm";
|
|
1949
|
+
var PROSPECTING_FEATURE_ID = "lead-gen";
|
|
1950
|
+
var MONITORING_FEATURE_ID = "monitoring";
|
|
1951
|
+
var SETTINGS_FEATURE_ID = "settings";
|
|
1952
|
+
var SEO_FEATURE_ID = "seo";
|
|
1953
|
+
var SALES_SYSTEM_ID = "sales.crm";
|
|
1954
|
+
var PROSPECTING_SYSTEM_ID = "sales.lead-gen";
|
|
1955
|
+
var OPERATIONS_SYSTEM_ID = "operations";
|
|
1956
|
+
var OPERATIONS_FEATURE_ID = OPERATIONS_SYSTEM_ID;
|
|
1957
|
+
var MONITORING_SYSTEM_ID = "monitoring";
|
|
1958
|
+
var SETTINGS_SYSTEM_ID = "settings";
|
|
1959
|
+
var SEO_SYSTEM_ID = "seo";
|
|
1960
|
+
var SALES_PIPELINE_SURFACE_ID = "crm.pipeline";
|
|
1961
|
+
var PROSPECTING_LISTS_SURFACE_ID = "lead-gen.lists";
|
|
1962
|
+
var OPERATIONS_COMMAND_VIEW_SURFACE_ID = "knowledge.command-view";
|
|
1963
|
+
var SETTINGS_ROLES_SURFACE_ID = "settings.roles";
|
|
1964
|
+
|
|
1462
1965
|
// src/organization-model/defaults.ts
|
|
1463
|
-
var DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE = {
|
|
1464
|
-
|
|
1966
|
+
var DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE = {};
|
|
1967
|
+
var DEFAULT_ORGANIZATION_MODEL_ENTITIES2 = DEFAULT_ORGANIZATION_MODEL_ENTITIES;
|
|
1968
|
+
var DEFAULT_ORGANIZATION_MODEL_NAVIGATION2 = {
|
|
1969
|
+
sidebar: {
|
|
1970
|
+
primary: {
|
|
1971
|
+
dashboard: {
|
|
1972
|
+
type: "surface",
|
|
1973
|
+
label: "Dashboard",
|
|
1974
|
+
path: "/",
|
|
1975
|
+
surfaceType: "dashboard",
|
|
1976
|
+
icon: "feature.dashboard",
|
|
1977
|
+
order: 10,
|
|
1978
|
+
targets: { systems: ["dashboard"] }
|
|
1979
|
+
},
|
|
1980
|
+
business: {
|
|
1981
|
+
type: "group",
|
|
1982
|
+
label: "Business",
|
|
1983
|
+
icon: "feature.business",
|
|
1984
|
+
order: 20,
|
|
1985
|
+
children: {
|
|
1986
|
+
sales: {
|
|
1987
|
+
type: "surface",
|
|
1988
|
+
label: "Sales",
|
|
1989
|
+
path: "/sales",
|
|
1990
|
+
surfaceType: "page",
|
|
1991
|
+
icon: "feature.sales",
|
|
1992
|
+
order: 10,
|
|
1993
|
+
targets: { systems: ["sales"] }
|
|
1994
|
+
},
|
|
1995
|
+
clients: {
|
|
1996
|
+
type: "surface",
|
|
1997
|
+
label: "Clients",
|
|
1998
|
+
path: "/clients",
|
|
1999
|
+
surfaceType: "list",
|
|
2000
|
+
icon: "feature.projects",
|
|
2001
|
+
order: 20,
|
|
2002
|
+
targets: { systems: ["clients"] }
|
|
2003
|
+
},
|
|
2004
|
+
projects: {
|
|
2005
|
+
type: "surface",
|
|
2006
|
+
label: "Projects",
|
|
2007
|
+
path: "/projects",
|
|
2008
|
+
surfaceType: "page",
|
|
2009
|
+
icon: "feature.projects",
|
|
2010
|
+
order: 30,
|
|
2011
|
+
targets: { systems: ["projects"] }
|
|
2012
|
+
}
|
|
2013
|
+
}
|
|
2014
|
+
},
|
|
2015
|
+
operations: {
|
|
2016
|
+
type: "group",
|
|
2017
|
+
label: "Operations",
|
|
2018
|
+
icon: "feature.operations",
|
|
2019
|
+
order: 30,
|
|
2020
|
+
children: {
|
|
2021
|
+
"operations-overview": {
|
|
2022
|
+
type: "surface",
|
|
2023
|
+
label: "Overview",
|
|
2024
|
+
path: "/operations",
|
|
2025
|
+
surfaceType: "page",
|
|
2026
|
+
order: 10,
|
|
2027
|
+
targets: { systems: ["operations.overview"] }
|
|
2028
|
+
},
|
|
2029
|
+
"operations-systems": {
|
|
2030
|
+
type: "surface",
|
|
2031
|
+
label: "Systems",
|
|
2032
|
+
path: "/operations/systems",
|
|
2033
|
+
surfaceType: "page",
|
|
2034
|
+
order: 20,
|
|
2035
|
+
targets: { systems: ["operations"] }
|
|
2036
|
+
},
|
|
2037
|
+
"operations-resources": {
|
|
2038
|
+
type: "surface",
|
|
2039
|
+
label: "Resources",
|
|
2040
|
+
path: "/operations/resources",
|
|
2041
|
+
surfaceType: "list",
|
|
2042
|
+
order: 30,
|
|
2043
|
+
targets: { systems: ["operations.resources"] }
|
|
2044
|
+
},
|
|
2045
|
+
"operations-command-queue": {
|
|
2046
|
+
type: "surface",
|
|
2047
|
+
label: "Command Queue",
|
|
2048
|
+
path: "/operations/command-queue",
|
|
2049
|
+
surfaceType: "list",
|
|
2050
|
+
order: 40,
|
|
2051
|
+
targets: { systems: ["operations.command-queue"] }
|
|
2052
|
+
},
|
|
2053
|
+
"operations-task-scheduler": {
|
|
2054
|
+
type: "surface",
|
|
2055
|
+
label: "Task Scheduler",
|
|
2056
|
+
path: "/operations/task-scheduler",
|
|
2057
|
+
surfaceType: "list",
|
|
2058
|
+
order: 50,
|
|
2059
|
+
targets: { systems: ["operations.task-scheduler"] }
|
|
2060
|
+
}
|
|
2061
|
+
}
|
|
2062
|
+
},
|
|
2063
|
+
monitoring: {
|
|
2064
|
+
type: "group",
|
|
2065
|
+
label: "Monitoring",
|
|
2066
|
+
icon: "feature.monitoring",
|
|
2067
|
+
order: 40,
|
|
2068
|
+
children: {
|
|
2069
|
+
"monitoring-overview": {
|
|
2070
|
+
type: "surface",
|
|
2071
|
+
label: "Overview",
|
|
2072
|
+
path: "/monitoring",
|
|
2073
|
+
surfaceType: "page",
|
|
2074
|
+
order: 10,
|
|
2075
|
+
targets: { systems: ["monitoring"] }
|
|
2076
|
+
},
|
|
2077
|
+
"monitoring-calendar": {
|
|
2078
|
+
type: "surface",
|
|
2079
|
+
label: "Calendar",
|
|
2080
|
+
path: "/monitoring/calendar",
|
|
2081
|
+
surfaceType: "page",
|
|
2082
|
+
order: 20,
|
|
2083
|
+
targets: { systems: ["monitoring.calendar"] }
|
|
2084
|
+
},
|
|
2085
|
+
"monitoring-activity-log": {
|
|
2086
|
+
type: "surface",
|
|
2087
|
+
label: "Activity Log",
|
|
2088
|
+
path: "/monitoring/activity-log",
|
|
2089
|
+
surfaceType: "list",
|
|
2090
|
+
order: 30,
|
|
2091
|
+
targets: { systems: ["monitoring.activity-log"] }
|
|
2092
|
+
},
|
|
2093
|
+
"monitoring-execution-logs": {
|
|
2094
|
+
type: "surface",
|
|
2095
|
+
label: "Execution Logs",
|
|
2096
|
+
path: "/monitoring/execution-logs",
|
|
2097
|
+
surfaceType: "list",
|
|
2098
|
+
order: 40,
|
|
2099
|
+
targets: { systems: ["monitoring.execution-logs"] }
|
|
2100
|
+
},
|
|
2101
|
+
"monitoring-execution-health": {
|
|
2102
|
+
type: "surface",
|
|
2103
|
+
label: "Execution Health",
|
|
2104
|
+
path: "/monitoring/execution-health",
|
|
2105
|
+
surfaceType: "dashboard",
|
|
2106
|
+
order: 50,
|
|
2107
|
+
targets: { systems: ["monitoring.execution-health"] }
|
|
2108
|
+
},
|
|
2109
|
+
"monitoring-notifications": {
|
|
2110
|
+
type: "surface",
|
|
2111
|
+
label: "Notifications",
|
|
2112
|
+
path: "/monitoring/notifications",
|
|
2113
|
+
surfaceType: "list",
|
|
2114
|
+
order: 60,
|
|
2115
|
+
targets: { systems: ["monitoring.notifications"] }
|
|
2116
|
+
},
|
|
2117
|
+
"monitoring-requests": {
|
|
2118
|
+
type: "surface",
|
|
2119
|
+
label: "Requests",
|
|
2120
|
+
path: "/monitoring/requests",
|
|
2121
|
+
surfaceType: "list",
|
|
2122
|
+
order: 70,
|
|
2123
|
+
targets: { systems: ["monitoring.submitted-requests"] }
|
|
2124
|
+
}
|
|
2125
|
+
}
|
|
2126
|
+
},
|
|
2127
|
+
knowledge: {
|
|
2128
|
+
type: "group",
|
|
2129
|
+
label: "Knowledge",
|
|
2130
|
+
icon: "feature.knowledge",
|
|
2131
|
+
order: 50,
|
|
2132
|
+
children: {
|
|
2133
|
+
"knowledge-base": {
|
|
2134
|
+
type: "surface",
|
|
2135
|
+
label: "Knowledge Base",
|
|
2136
|
+
path: "/knowledge",
|
|
2137
|
+
surfaceType: "page",
|
|
2138
|
+
order: 10,
|
|
2139
|
+
targets: { systems: ["knowledge.base"] }
|
|
2140
|
+
},
|
|
2141
|
+
"knowledge-command-view": {
|
|
2142
|
+
type: "surface",
|
|
2143
|
+
label: "Command View",
|
|
2144
|
+
path: "/knowledge/command-view",
|
|
2145
|
+
surfaceType: "graph",
|
|
2146
|
+
order: 20,
|
|
2147
|
+
targets: { systems: ["knowledge.command-view"] },
|
|
2148
|
+
devOnly: true
|
|
2149
|
+
}
|
|
2150
|
+
}
|
|
2151
|
+
}
|
|
2152
|
+
},
|
|
2153
|
+
bottom: {
|
|
2154
|
+
settings: {
|
|
2155
|
+
type: "group",
|
|
2156
|
+
label: "Settings",
|
|
2157
|
+
icon: "feature.settings",
|
|
2158
|
+
order: 10,
|
|
2159
|
+
children: {
|
|
2160
|
+
"settings-account": {
|
|
2161
|
+
type: "surface",
|
|
2162
|
+
label: "Account",
|
|
2163
|
+
path: "/settings/account",
|
|
2164
|
+
surfaceType: "settings",
|
|
2165
|
+
order: 10,
|
|
2166
|
+
targets: { systems: ["settings.account"] }
|
|
2167
|
+
},
|
|
2168
|
+
"settings-appearance": {
|
|
2169
|
+
type: "surface",
|
|
2170
|
+
label: "Appearance",
|
|
2171
|
+
path: "/settings/appearance",
|
|
2172
|
+
surfaceType: "settings",
|
|
2173
|
+
order: 20,
|
|
2174
|
+
targets: { systems: ["settings.appearance"] }
|
|
2175
|
+
},
|
|
2176
|
+
"settings-roles": {
|
|
2177
|
+
type: "surface",
|
|
2178
|
+
label: "My Roles",
|
|
2179
|
+
path: "/settings/roles",
|
|
2180
|
+
surfaceType: "settings",
|
|
2181
|
+
order: 30,
|
|
2182
|
+
targets: { systems: ["settings.roles"] }
|
|
2183
|
+
},
|
|
2184
|
+
"settings-organization": {
|
|
2185
|
+
type: "surface",
|
|
2186
|
+
label: "Organization",
|
|
2187
|
+
path: "/settings/organization",
|
|
2188
|
+
surfaceType: "settings",
|
|
2189
|
+
order: 40,
|
|
2190
|
+
targets: { systems: ["settings.organization"] }
|
|
2191
|
+
},
|
|
2192
|
+
"settings-credentials": {
|
|
2193
|
+
type: "surface",
|
|
2194
|
+
label: "Credentials",
|
|
2195
|
+
path: "/settings/credentials",
|
|
2196
|
+
surfaceType: "settings",
|
|
2197
|
+
order: 50,
|
|
2198
|
+
targets: { systems: ["settings.credentials"] }
|
|
2199
|
+
},
|
|
2200
|
+
"settings-api-keys": {
|
|
2201
|
+
type: "surface",
|
|
2202
|
+
label: "API Keys",
|
|
2203
|
+
path: "/settings/api-keys",
|
|
2204
|
+
surfaceType: "settings",
|
|
2205
|
+
order: 60,
|
|
2206
|
+
targets: { systems: ["settings.api-keys"] }
|
|
2207
|
+
},
|
|
2208
|
+
"settings-webhooks": {
|
|
2209
|
+
type: "surface",
|
|
2210
|
+
label: "Webhooks",
|
|
2211
|
+
path: "/settings/webhooks",
|
|
2212
|
+
surfaceType: "settings",
|
|
2213
|
+
order: 70,
|
|
2214
|
+
targets: { systems: ["settings.webhooks"] }
|
|
2215
|
+
},
|
|
2216
|
+
"settings-deployments": {
|
|
2217
|
+
type: "surface",
|
|
2218
|
+
label: "Deployments",
|
|
2219
|
+
path: "/settings/deployments",
|
|
2220
|
+
surfaceType: "settings",
|
|
2221
|
+
order: 80,
|
|
2222
|
+
targets: { systems: ["settings.deployments"] }
|
|
2223
|
+
}
|
|
2224
|
+
}
|
|
2225
|
+
},
|
|
2226
|
+
admin: {
|
|
2227
|
+
type: "group",
|
|
2228
|
+
label: "Admin",
|
|
2229
|
+
icon: "feature.admin",
|
|
2230
|
+
order: 20,
|
|
2231
|
+
children: {
|
|
2232
|
+
"admin-dashboard": {
|
|
2233
|
+
type: "surface",
|
|
2234
|
+
label: "Dashboard",
|
|
2235
|
+
path: "/admin/dashboard",
|
|
2236
|
+
surfaceType: "dashboard",
|
|
2237
|
+
order: 10,
|
|
2238
|
+
targets: { systems: ["admin"] },
|
|
2239
|
+
requiresAdmin: true
|
|
2240
|
+
},
|
|
2241
|
+
"admin-system-health": {
|
|
2242
|
+
type: "surface",
|
|
2243
|
+
label: "System Health",
|
|
2244
|
+
path: "/admin/system-health",
|
|
2245
|
+
surfaceType: "dashboard",
|
|
2246
|
+
order: 20,
|
|
2247
|
+
targets: { systems: ["admin.system-health"] },
|
|
2248
|
+
requiresAdmin: true
|
|
2249
|
+
},
|
|
2250
|
+
"admin-organizations": {
|
|
2251
|
+
type: "surface",
|
|
2252
|
+
label: "Organizations",
|
|
2253
|
+
path: "/admin/organizations",
|
|
2254
|
+
surfaceType: "list",
|
|
2255
|
+
order: 30,
|
|
2256
|
+
targets: { systems: ["admin.organizations"] },
|
|
2257
|
+
requiresAdmin: true
|
|
2258
|
+
},
|
|
2259
|
+
"admin-users": {
|
|
2260
|
+
type: "surface",
|
|
2261
|
+
label: "Users",
|
|
2262
|
+
path: "/admin/users",
|
|
2263
|
+
surfaceType: "list",
|
|
2264
|
+
order: 40,
|
|
2265
|
+
targets: { systems: ["admin.users"] },
|
|
2266
|
+
requiresAdmin: true
|
|
2267
|
+
},
|
|
2268
|
+
"admin-design-showcase": {
|
|
2269
|
+
type: "surface",
|
|
2270
|
+
label: "Design Showcase",
|
|
2271
|
+
path: "/admin/design-showcase",
|
|
2272
|
+
surfaceType: "page",
|
|
2273
|
+
order: 50,
|
|
2274
|
+
targets: { systems: ["admin.design-showcase"] },
|
|
2275
|
+
requiresAdmin: true
|
|
2276
|
+
},
|
|
2277
|
+
"admin-debug": {
|
|
2278
|
+
type: "surface",
|
|
2279
|
+
label: "Debug",
|
|
2280
|
+
path: "/admin/debug",
|
|
2281
|
+
surfaceType: "page",
|
|
2282
|
+
order: 60,
|
|
2283
|
+
targets: { systems: ["admin.debug"] },
|
|
2284
|
+
requiresAdmin: true
|
|
2285
|
+
}
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
1465
2290
|
};
|
|
1466
2291
|
var DEFAULT_ORGANIZATION_MODEL = {
|
|
1467
2292
|
version: 1,
|
|
1468
|
-
|
|
1469
|
-
|
|
2293
|
+
domainMetadata: DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA,
|
|
2294
|
+
branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
|
|
2295
|
+
navigation: DEFAULT_ORGANIZATION_MODEL_NAVIGATION2,
|
|
2296
|
+
identity: DEFAULT_ORGANIZATION_MODEL_IDENTITY,
|
|
2297
|
+
customers: DEFAULT_ORGANIZATION_MODEL_CUSTOMERS,
|
|
2298
|
+
offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
|
|
2299
|
+
roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
|
|
2300
|
+
goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
|
|
2301
|
+
systems: {
|
|
2302
|
+
dashboard: {
|
|
1470
2303
|
id: "dashboard",
|
|
2304
|
+
order: 10,
|
|
1471
2305
|
label: "Dashboard",
|
|
1472
2306
|
enabled: true,
|
|
2307
|
+
lifecycle: "active",
|
|
1473
2308
|
path: "/",
|
|
1474
|
-
icon: "feature.dashboard"
|
|
1475
|
-
uiPosition: "sidebar-primary"
|
|
1476
|
-
},
|
|
1477
|
-
{
|
|
1478
|
-
id: "identity",
|
|
1479
|
-
label: "Identity",
|
|
1480
|
-
description: "Company identity, positioning, and market context",
|
|
1481
|
-
enabled: true,
|
|
1482
|
-
color: "indigo"
|
|
2309
|
+
icon: "feature.dashboard"
|
|
1483
2310
|
},
|
|
1484
|
-
{
|
|
2311
|
+
platform: {
|
|
1485
2312
|
id: "platform",
|
|
2313
|
+
order: 30,
|
|
1486
2314
|
label: "Platform",
|
|
1487
2315
|
description: "Elevasis platform architecture, capabilities, and implementation patterns",
|
|
1488
2316
|
enabled: true,
|
|
2317
|
+
lifecycle: "active",
|
|
1489
2318
|
color: "cyan",
|
|
1490
2319
|
icon: "feature.platform"
|
|
1491
2320
|
},
|
|
1492
|
-
{
|
|
2321
|
+
finance: {
|
|
1493
2322
|
id: "finance",
|
|
2323
|
+
order: 40,
|
|
1494
2324
|
label: "Finance",
|
|
1495
2325
|
description: "Finance operations, accounting, billing, reconciliation, and tax prep",
|
|
1496
2326
|
enabled: true,
|
|
2327
|
+
lifecycle: "active",
|
|
1497
2328
|
color: "green",
|
|
1498
2329
|
icon: "feature.finance"
|
|
1499
2330
|
},
|
|
1500
|
-
{
|
|
2331
|
+
sales: {
|
|
1501
2332
|
id: "sales",
|
|
2333
|
+
order: 60,
|
|
1502
2334
|
label: "Sales",
|
|
1503
2335
|
description: "Revenue workflows and customer acquisition",
|
|
1504
2336
|
enabled: true,
|
|
2337
|
+
lifecycle: "active",
|
|
1505
2338
|
color: "blue",
|
|
1506
2339
|
icon: "feature.sales",
|
|
1507
|
-
|
|
2340
|
+
path: "/sales"
|
|
1508
2341
|
},
|
|
1509
|
-
{
|
|
2342
|
+
"sales.crm": {
|
|
1510
2343
|
id: "sales.crm",
|
|
2344
|
+
order: 70,
|
|
1511
2345
|
label: "CRM",
|
|
1512
2346
|
description: "Relationship pipeline and deal management",
|
|
1513
2347
|
enabled: true,
|
|
2348
|
+
lifecycle: "active",
|
|
1514
2349
|
color: "blue",
|
|
1515
2350
|
icon: "feature.crm",
|
|
1516
2351
|
path: "/crm"
|
|
1517
2352
|
},
|
|
1518
|
-
{
|
|
2353
|
+
"sales.lead-gen": {
|
|
1519
2354
|
id: "sales.lead-gen",
|
|
2355
|
+
order: 80,
|
|
1520
2356
|
label: "Lead Gen",
|
|
1521
2357
|
description: "Prospecting, qualification, and outreach preparation",
|
|
1522
2358
|
enabled: true,
|
|
2359
|
+
lifecycle: "active",
|
|
2360
|
+
actions: Object.values(DEFAULT_ORGANIZATION_MODEL_ACTIONS).map((action) => ({
|
|
2361
|
+
actionId: action.id,
|
|
2362
|
+
intent: "exposes"
|
|
2363
|
+
})),
|
|
1523
2364
|
color: "cyan",
|
|
1524
2365
|
icon: "feature.lead-gen",
|
|
1525
2366
|
path: "/lead-gen"
|
|
1526
2367
|
},
|
|
1527
|
-
{
|
|
2368
|
+
projects: {
|
|
1528
2369
|
id: "projects",
|
|
2370
|
+
order: 90,
|
|
1529
2371
|
label: "Projects",
|
|
1530
2372
|
description: "Projects, milestones, and client work execution",
|
|
1531
2373
|
enabled: true,
|
|
2374
|
+
lifecycle: "active",
|
|
2375
|
+
color: "orange",
|
|
2376
|
+
icon: "feature.projects",
|
|
2377
|
+
path: "/projects"
|
|
2378
|
+
},
|
|
2379
|
+
clients: {
|
|
2380
|
+
id: "clients",
|
|
2381
|
+
order: 100,
|
|
2382
|
+
label: "Clients",
|
|
2383
|
+
description: "Client relationships, accounts, and business context",
|
|
2384
|
+
enabled: true,
|
|
2385
|
+
lifecycle: "active",
|
|
1532
2386
|
color: "orange",
|
|
1533
2387
|
icon: "feature.projects",
|
|
1534
|
-
path: "/
|
|
1535
|
-
uiPosition: "sidebar-primary"
|
|
2388
|
+
path: "/clients"
|
|
1536
2389
|
},
|
|
1537
|
-
{
|
|
2390
|
+
operations: {
|
|
1538
2391
|
id: "operations",
|
|
2392
|
+
order: 110,
|
|
1539
2393
|
label: "Operations",
|
|
1540
2394
|
description: "Operational resources, topology, and orchestration visibility",
|
|
1541
2395
|
enabled: true,
|
|
2396
|
+
lifecycle: "active",
|
|
1542
2397
|
color: "violet",
|
|
1543
|
-
icon: "feature.operations"
|
|
1544
|
-
uiPosition: "sidebar-primary"
|
|
2398
|
+
icon: "feature.operations"
|
|
1545
2399
|
},
|
|
1546
|
-
{
|
|
2400
|
+
"knowledge.command-view": {
|
|
1547
2401
|
id: "knowledge.command-view",
|
|
2402
|
+
order: 120,
|
|
1548
2403
|
label: "Command View",
|
|
1549
2404
|
enabled: true,
|
|
2405
|
+
lifecycle: "active",
|
|
1550
2406
|
path: "/knowledge/command-view",
|
|
1551
2407
|
devOnly: true
|
|
1552
2408
|
},
|
|
1553
|
-
{
|
|
2409
|
+
"operations.overview": {
|
|
1554
2410
|
id: "operations.overview",
|
|
2411
|
+
order: 130,
|
|
1555
2412
|
label: "Overview",
|
|
1556
2413
|
enabled: true,
|
|
2414
|
+
lifecycle: "active",
|
|
1557
2415
|
path: "/operations"
|
|
1558
2416
|
},
|
|
1559
|
-
{
|
|
2417
|
+
"operations.resources": {
|
|
1560
2418
|
id: "operations.resources",
|
|
2419
|
+
order: 140,
|
|
1561
2420
|
label: "Resources",
|
|
1562
2421
|
enabled: true,
|
|
2422
|
+
lifecycle: "active",
|
|
1563
2423
|
path: "/operations/resources"
|
|
1564
2424
|
},
|
|
1565
|
-
{
|
|
2425
|
+
"operations.command-queue": {
|
|
1566
2426
|
id: "operations.command-queue",
|
|
2427
|
+
order: 150,
|
|
1567
2428
|
label: "Command Queue",
|
|
1568
2429
|
enabled: true,
|
|
2430
|
+
lifecycle: "active",
|
|
1569
2431
|
path: "/operations/command-queue"
|
|
1570
2432
|
},
|
|
1571
|
-
{
|
|
2433
|
+
"operations.sessions": {
|
|
1572
2434
|
id: "operations.sessions",
|
|
2435
|
+
order: 160,
|
|
1573
2436
|
label: "Sessions",
|
|
1574
2437
|
enabled: false,
|
|
2438
|
+
lifecycle: "deprecated",
|
|
1575
2439
|
path: "/operations/sessions"
|
|
1576
2440
|
},
|
|
1577
|
-
{
|
|
2441
|
+
"operations.task-scheduler": {
|
|
1578
2442
|
id: "operations.task-scheduler",
|
|
2443
|
+
order: 170,
|
|
1579
2444
|
label: "Task Scheduler",
|
|
1580
2445
|
enabled: true,
|
|
2446
|
+
lifecycle: "active",
|
|
1581
2447
|
path: "/operations/task-scheduler"
|
|
1582
2448
|
},
|
|
1583
|
-
{
|
|
2449
|
+
monitoring: {
|
|
1584
2450
|
id: "monitoring",
|
|
2451
|
+
order: 180,
|
|
1585
2452
|
label: "Monitoring",
|
|
1586
2453
|
enabled: true,
|
|
1587
|
-
|
|
2454
|
+
lifecycle: "active"
|
|
1588
2455
|
},
|
|
1589
|
-
{
|
|
2456
|
+
"monitoring.calendar": {
|
|
1590
2457
|
id: "monitoring.calendar",
|
|
2458
|
+
order: 190,
|
|
1591
2459
|
label: "Calendar",
|
|
1592
2460
|
description: "Google Calendar events and agenda views",
|
|
1593
2461
|
enabled: true,
|
|
2462
|
+
lifecycle: "active",
|
|
1594
2463
|
path: "/monitoring/calendar",
|
|
1595
2464
|
icon: "feature.calendar"
|
|
1596
2465
|
},
|
|
1597
|
-
{
|
|
2466
|
+
"monitoring.activity-log": {
|
|
1598
2467
|
id: "monitoring.activity-log",
|
|
2468
|
+
order: 200,
|
|
1599
2469
|
label: "Activity Log",
|
|
1600
2470
|
enabled: true,
|
|
2471
|
+
lifecycle: "active",
|
|
1601
2472
|
path: "/monitoring/activity-log"
|
|
1602
2473
|
},
|
|
1603
|
-
{
|
|
2474
|
+
"monitoring.execution-logs": {
|
|
1604
2475
|
id: "monitoring.execution-logs",
|
|
2476
|
+
order: 210,
|
|
1605
2477
|
label: "Execution Logs",
|
|
1606
2478
|
enabled: true,
|
|
2479
|
+
lifecycle: "active",
|
|
1607
2480
|
path: "/monitoring/execution-logs"
|
|
1608
2481
|
},
|
|
1609
|
-
{
|
|
2482
|
+
"monitoring.execution-health": {
|
|
1610
2483
|
id: "monitoring.execution-health",
|
|
2484
|
+
order: 220,
|
|
1611
2485
|
label: "Execution Health",
|
|
1612
2486
|
enabled: true,
|
|
2487
|
+
lifecycle: "active",
|
|
1613
2488
|
path: "/monitoring/execution-health"
|
|
1614
2489
|
},
|
|
1615
|
-
{
|
|
2490
|
+
"monitoring.cost-analytics": {
|
|
1616
2491
|
id: "monitoring.cost-analytics",
|
|
2492
|
+
order: 230,
|
|
1617
2493
|
label: "Cost Analytics",
|
|
1618
2494
|
enabled: false,
|
|
2495
|
+
lifecycle: "deprecated",
|
|
1619
2496
|
path: "/monitoring/cost-analytics"
|
|
1620
2497
|
},
|
|
1621
|
-
{
|
|
2498
|
+
"monitoring.notifications": {
|
|
1622
2499
|
id: "monitoring.notifications",
|
|
2500
|
+
order: 240,
|
|
1623
2501
|
label: "Notifications",
|
|
1624
2502
|
enabled: true,
|
|
2503
|
+
lifecycle: "active",
|
|
1625
2504
|
path: "/monitoring/notifications"
|
|
1626
2505
|
},
|
|
1627
|
-
{
|
|
2506
|
+
"monitoring.submitted-requests": {
|
|
1628
2507
|
id: "monitoring.submitted-requests",
|
|
2508
|
+
order: 250,
|
|
1629
2509
|
label: "Submitted Requests",
|
|
1630
2510
|
enabled: true,
|
|
2511
|
+
lifecycle: "active",
|
|
1631
2512
|
path: "/monitoring/requests"
|
|
1632
2513
|
},
|
|
1633
|
-
{
|
|
2514
|
+
settings: {
|
|
1634
2515
|
id: "settings",
|
|
2516
|
+
order: 260,
|
|
1635
2517
|
label: "Settings",
|
|
1636
2518
|
enabled: true,
|
|
1637
|
-
|
|
1638
|
-
|
|
2519
|
+
lifecycle: "active",
|
|
2520
|
+
icon: "feature.settings"
|
|
1639
2521
|
},
|
|
1640
|
-
{
|
|
2522
|
+
"settings.account": {
|
|
1641
2523
|
id: "settings.account",
|
|
2524
|
+
order: 270,
|
|
1642
2525
|
label: "Account",
|
|
1643
2526
|
enabled: true,
|
|
2527
|
+
lifecycle: "active",
|
|
1644
2528
|
path: "/settings/account"
|
|
1645
2529
|
},
|
|
1646
|
-
{
|
|
2530
|
+
"settings.appearance": {
|
|
1647
2531
|
id: "settings.appearance",
|
|
2532
|
+
order: 280,
|
|
1648
2533
|
label: "Appearance",
|
|
1649
2534
|
enabled: true,
|
|
2535
|
+
lifecycle: "active",
|
|
1650
2536
|
path: "/settings/appearance"
|
|
1651
2537
|
},
|
|
1652
|
-
{
|
|
2538
|
+
"settings.roles": {
|
|
1653
2539
|
id: "settings.roles",
|
|
2540
|
+
order: 290,
|
|
1654
2541
|
label: "My Roles",
|
|
1655
2542
|
enabled: true,
|
|
2543
|
+
lifecycle: "active",
|
|
1656
2544
|
path: "/settings/roles"
|
|
1657
2545
|
},
|
|
1658
|
-
{
|
|
2546
|
+
"settings.organization": {
|
|
1659
2547
|
id: "settings.organization",
|
|
2548
|
+
order: 300,
|
|
1660
2549
|
label: "Organization",
|
|
1661
2550
|
enabled: true,
|
|
2551
|
+
lifecycle: "active",
|
|
1662
2552
|
path: "/settings/organization"
|
|
1663
2553
|
},
|
|
1664
|
-
{
|
|
2554
|
+
"settings.credentials": {
|
|
1665
2555
|
id: "settings.credentials",
|
|
2556
|
+
order: 310,
|
|
1666
2557
|
label: "Credentials",
|
|
1667
2558
|
enabled: true,
|
|
2559
|
+
lifecycle: "active",
|
|
1668
2560
|
path: "/settings/credentials"
|
|
1669
2561
|
},
|
|
1670
|
-
{
|
|
2562
|
+
"settings.api-keys": {
|
|
1671
2563
|
id: "settings.api-keys",
|
|
2564
|
+
order: 320,
|
|
1672
2565
|
label: "API Keys",
|
|
1673
2566
|
enabled: true,
|
|
2567
|
+
lifecycle: "active",
|
|
1674
2568
|
path: "/settings/api-keys"
|
|
1675
2569
|
},
|
|
1676
|
-
{
|
|
2570
|
+
"settings.webhooks": {
|
|
1677
2571
|
id: "settings.webhooks",
|
|
2572
|
+
order: 330,
|
|
1678
2573
|
label: "Webhooks",
|
|
1679
2574
|
enabled: true,
|
|
2575
|
+
lifecycle: "active",
|
|
1680
2576
|
path: "/settings/webhooks"
|
|
1681
2577
|
},
|
|
1682
|
-
{
|
|
2578
|
+
"settings.deployments": {
|
|
1683
2579
|
id: "settings.deployments",
|
|
2580
|
+
order: 340,
|
|
1684
2581
|
label: "Deployments",
|
|
1685
2582
|
enabled: true,
|
|
2583
|
+
lifecycle: "active",
|
|
1686
2584
|
path: "/settings/deployments"
|
|
1687
2585
|
},
|
|
1688
|
-
{
|
|
2586
|
+
admin: {
|
|
1689
2587
|
id: "admin",
|
|
2588
|
+
order: 350,
|
|
1690
2589
|
label: "Admin",
|
|
1691
2590
|
enabled: true,
|
|
2591
|
+
lifecycle: "active",
|
|
1692
2592
|
path: "/admin",
|
|
1693
2593
|
icon: "feature.admin",
|
|
1694
|
-
uiPosition: "sidebar-bottom",
|
|
1695
2594
|
requiresAdmin: true
|
|
1696
2595
|
},
|
|
1697
|
-
{
|
|
2596
|
+
"admin.system-health": {
|
|
1698
2597
|
id: "admin.system-health",
|
|
2598
|
+
order: 360,
|
|
1699
2599
|
label: "System Health",
|
|
1700
2600
|
enabled: true,
|
|
2601
|
+
lifecycle: "active",
|
|
1701
2602
|
path: "/admin/system-health"
|
|
1702
2603
|
},
|
|
1703
|
-
{
|
|
2604
|
+
"admin.organizations": {
|
|
1704
2605
|
id: "admin.organizations",
|
|
2606
|
+
order: 370,
|
|
1705
2607
|
label: "Organizations",
|
|
1706
2608
|
enabled: true,
|
|
2609
|
+
lifecycle: "active",
|
|
1707
2610
|
path: "/admin/organizations"
|
|
1708
2611
|
},
|
|
1709
|
-
{
|
|
2612
|
+
"admin.users": {
|
|
1710
2613
|
id: "admin.users",
|
|
2614
|
+
order: 380,
|
|
1711
2615
|
label: "Users",
|
|
1712
2616
|
enabled: true,
|
|
2617
|
+
lifecycle: "active",
|
|
1713
2618
|
path: "/admin/users"
|
|
1714
2619
|
},
|
|
1715
|
-
{
|
|
2620
|
+
"admin.design-showcase": {
|
|
1716
2621
|
id: "admin.design-showcase",
|
|
2622
|
+
order: 390,
|
|
1717
2623
|
label: "Design Showcase",
|
|
1718
2624
|
enabled: true,
|
|
2625
|
+
lifecycle: "active",
|
|
1719
2626
|
path: "/admin/design-showcase"
|
|
1720
2627
|
},
|
|
1721
|
-
{
|
|
2628
|
+
"admin.debug": {
|
|
1722
2629
|
id: "admin.debug",
|
|
2630
|
+
order: 400,
|
|
1723
2631
|
label: "Debug",
|
|
1724
2632
|
enabled: true,
|
|
2633
|
+
lifecycle: "active",
|
|
1725
2634
|
path: "/admin/debug"
|
|
1726
2635
|
},
|
|
1727
|
-
{
|
|
2636
|
+
archive: {
|
|
1728
2637
|
id: "archive",
|
|
2638
|
+
order: 410,
|
|
1729
2639
|
label: "Archive",
|
|
1730
2640
|
enabled: true,
|
|
2641
|
+
lifecycle: "active",
|
|
1731
2642
|
path: "/archive",
|
|
1732
2643
|
icon: "feature.archive",
|
|
1733
|
-
uiPosition: "sidebar-bottom",
|
|
1734
2644
|
devOnly: true
|
|
1735
2645
|
},
|
|
1736
|
-
{
|
|
2646
|
+
"archive.agent-chat": {
|
|
1737
2647
|
id: "archive.agent-chat",
|
|
2648
|
+
order: 420,
|
|
1738
2649
|
label: "Agent Chat",
|
|
1739
2650
|
enabled: true,
|
|
2651
|
+
lifecycle: "active",
|
|
1740
2652
|
path: "/archive/agent-chat"
|
|
1741
2653
|
},
|
|
1742
|
-
{
|
|
2654
|
+
"archive.execution-runner": {
|
|
1743
2655
|
id: "archive.execution-runner",
|
|
2656
|
+
order: 430,
|
|
1744
2657
|
label: "Execution Runner",
|
|
1745
2658
|
enabled: true,
|
|
2659
|
+
lifecycle: "active",
|
|
1746
2660
|
path: "/archive/execution-runner"
|
|
1747
2661
|
},
|
|
1748
|
-
{
|
|
2662
|
+
seo: {
|
|
1749
2663
|
id: "seo",
|
|
2664
|
+
order: 440,
|
|
1750
2665
|
label: "SEO",
|
|
1751
2666
|
enabled: false,
|
|
2667
|
+
lifecycle: "deprecated",
|
|
1752
2668
|
path: "/seo"
|
|
1753
2669
|
},
|
|
1754
|
-
{
|
|
2670
|
+
knowledge: {
|
|
1755
2671
|
id: "knowledge",
|
|
2672
|
+
order: 450,
|
|
1756
2673
|
label: "Knowledge",
|
|
1757
2674
|
description: "Operational knowledge, playbooks, and strategy docs",
|
|
1758
2675
|
enabled: true,
|
|
2676
|
+
lifecycle: "active",
|
|
1759
2677
|
color: "teal",
|
|
1760
|
-
icon: "feature.knowledge"
|
|
1761
|
-
uiPosition: "sidebar-primary"
|
|
2678
|
+
icon: "feature.knowledge"
|
|
1762
2679
|
},
|
|
1763
|
-
{
|
|
2680
|
+
"knowledge.base": {
|
|
1764
2681
|
id: "knowledge.base",
|
|
2682
|
+
order: 460,
|
|
1765
2683
|
label: "Knowledge Base",
|
|
1766
2684
|
enabled: true,
|
|
2685
|
+
lifecycle: "active",
|
|
1767
2686
|
path: "/knowledge"
|
|
1768
2687
|
}
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
identity: DEFAULT_ORGANIZATION_MODEL_IDENTITY,
|
|
1776
|
-
customers: DEFAULT_ORGANIZATION_MODEL_CUSTOMERS,
|
|
1777
|
-
offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
|
|
1778
|
-
roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
|
|
1779
|
-
goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
|
|
1780
|
-
statuses: DEFAULT_ORGANIZATION_MODEL_STATUSES,
|
|
1781
|
-
operations: DEFAULT_ORGANIZATION_MODEL_OPERATIONS,
|
|
2688
|
+
},
|
|
2689
|
+
resources: DEFAULT_ORGANIZATION_MODEL_RESOURCES,
|
|
2690
|
+
actions: DEFAULT_ORGANIZATION_MODEL_ACTIONS,
|
|
2691
|
+
entities: DEFAULT_ORGANIZATION_MODEL_ENTITIES2,
|
|
2692
|
+
policies: DEFAULT_ORGANIZATION_MODEL_POLICIES,
|
|
2693
|
+
// Phase 4 (D1): statuses top-level field removed; status data lives in system.content.
|
|
1782
2694
|
knowledge: DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE
|
|
1783
2695
|
};
|
|
2696
|
+
var StatusSemanticClassSchema = z.enum([
|
|
2697
|
+
"delivery.task",
|
|
2698
|
+
"delivery.project",
|
|
2699
|
+
"delivery.milestone",
|
|
2700
|
+
"queue",
|
|
2701
|
+
"execution",
|
|
2702
|
+
"schedule",
|
|
2703
|
+
"schedule.run",
|
|
2704
|
+
"request"
|
|
2705
|
+
]);
|
|
2706
|
+
var StatusEntrySchema = z.object({
|
|
2707
|
+
id: z.string().trim().min(1).max(100),
|
|
2708
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
2709
|
+
order: z.number(),
|
|
2710
|
+
label: z.string().trim().min(1).max(120),
|
|
2711
|
+
semanticClass: StatusSemanticClassSchema,
|
|
2712
|
+
category: z.string().trim().min(1).max(80).optional()
|
|
2713
|
+
});
|
|
2714
|
+
var StatusesDomainSchema = z.record(z.string(), StatusEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
2715
|
+
message: "Each status entry id must match its map key"
|
|
2716
|
+
}).default({});
|
|
2717
|
+
var DEFAULT_ORGANIZATION_MODEL_STATUSES = {
|
|
2718
|
+
// --- delivery.task (TaskStatus — 9 values) ---
|
|
2719
|
+
"delivery.task.planned": {
|
|
2720
|
+
id: "delivery.task.planned",
|
|
2721
|
+
order: 10,
|
|
2722
|
+
label: "Planned",
|
|
2723
|
+
semanticClass: "delivery.task",
|
|
2724
|
+
category: "delivery"
|
|
2725
|
+
},
|
|
2726
|
+
"delivery.task.in_progress": {
|
|
2727
|
+
id: "delivery.task.in_progress",
|
|
2728
|
+
order: 20,
|
|
2729
|
+
label: "In Progress",
|
|
2730
|
+
semanticClass: "delivery.task",
|
|
2731
|
+
category: "delivery"
|
|
2732
|
+
},
|
|
2733
|
+
"delivery.task.blocked": {
|
|
2734
|
+
id: "delivery.task.blocked",
|
|
2735
|
+
order: 30,
|
|
2736
|
+
label: "Blocked",
|
|
2737
|
+
semanticClass: "delivery.task",
|
|
2738
|
+
category: "delivery"
|
|
2739
|
+
},
|
|
2740
|
+
"delivery.task.submitted": {
|
|
2741
|
+
id: "delivery.task.submitted",
|
|
2742
|
+
order: 40,
|
|
2743
|
+
label: "Submitted",
|
|
2744
|
+
semanticClass: "delivery.task",
|
|
2745
|
+
category: "delivery"
|
|
2746
|
+
},
|
|
2747
|
+
"delivery.task.approved": {
|
|
2748
|
+
id: "delivery.task.approved",
|
|
2749
|
+
order: 50,
|
|
2750
|
+
label: "Approved",
|
|
2751
|
+
semanticClass: "delivery.task",
|
|
2752
|
+
category: "delivery"
|
|
2753
|
+
},
|
|
2754
|
+
"delivery.task.revision_requested": {
|
|
2755
|
+
id: "delivery.task.revision_requested",
|
|
2756
|
+
order: 60,
|
|
2757
|
+
label: "Revision Requested",
|
|
2758
|
+
semanticClass: "delivery.task",
|
|
2759
|
+
category: "delivery"
|
|
2760
|
+
},
|
|
2761
|
+
"delivery.task.rejected": {
|
|
2762
|
+
id: "delivery.task.rejected",
|
|
2763
|
+
order: 70,
|
|
2764
|
+
label: "Rejected",
|
|
2765
|
+
semanticClass: "delivery.task",
|
|
2766
|
+
category: "delivery"
|
|
2767
|
+
},
|
|
2768
|
+
"delivery.task.cancelled": {
|
|
2769
|
+
id: "delivery.task.cancelled",
|
|
2770
|
+
order: 80,
|
|
2771
|
+
label: "Cancelled",
|
|
2772
|
+
semanticClass: "delivery.task",
|
|
2773
|
+
category: "delivery"
|
|
2774
|
+
},
|
|
2775
|
+
"delivery.task.completed": {
|
|
2776
|
+
id: "delivery.task.completed",
|
|
2777
|
+
order: 90,
|
|
2778
|
+
label: "Completed",
|
|
2779
|
+
semanticClass: "delivery.task",
|
|
2780
|
+
category: "delivery"
|
|
2781
|
+
},
|
|
2782
|
+
// --- delivery.project (ProjectStatus — 6 values) ---
|
|
2783
|
+
"delivery.project.active": {
|
|
2784
|
+
id: "delivery.project.active",
|
|
2785
|
+
order: 100,
|
|
2786
|
+
label: "Active",
|
|
2787
|
+
semanticClass: "delivery.project",
|
|
2788
|
+
category: "delivery"
|
|
2789
|
+
},
|
|
2790
|
+
"delivery.project.on_track": {
|
|
2791
|
+
id: "delivery.project.on_track",
|
|
2792
|
+
order: 110,
|
|
2793
|
+
label: "On Track",
|
|
2794
|
+
semanticClass: "delivery.project",
|
|
2795
|
+
category: "delivery"
|
|
2796
|
+
},
|
|
2797
|
+
"delivery.project.at_risk": {
|
|
2798
|
+
id: "delivery.project.at_risk",
|
|
2799
|
+
order: 120,
|
|
2800
|
+
label: "At Risk",
|
|
2801
|
+
semanticClass: "delivery.project",
|
|
2802
|
+
category: "delivery"
|
|
2803
|
+
},
|
|
2804
|
+
"delivery.project.blocked": {
|
|
2805
|
+
id: "delivery.project.blocked",
|
|
2806
|
+
order: 130,
|
|
2807
|
+
label: "Blocked",
|
|
2808
|
+
semanticClass: "delivery.project",
|
|
2809
|
+
category: "delivery"
|
|
2810
|
+
},
|
|
2811
|
+
"delivery.project.paused": {
|
|
2812
|
+
id: "delivery.project.paused",
|
|
2813
|
+
order: 140,
|
|
2814
|
+
label: "Paused",
|
|
2815
|
+
semanticClass: "delivery.project",
|
|
2816
|
+
category: "delivery"
|
|
2817
|
+
},
|
|
2818
|
+
"delivery.project.completed": {
|
|
2819
|
+
id: "delivery.project.completed",
|
|
2820
|
+
order: 150,
|
|
2821
|
+
label: "Completed",
|
|
2822
|
+
semanticClass: "delivery.project",
|
|
2823
|
+
category: "delivery"
|
|
2824
|
+
},
|
|
2825
|
+
// --- delivery.milestone (MilestoneStatus — 5 values) ---
|
|
2826
|
+
"delivery.milestone.upcoming": {
|
|
2827
|
+
id: "delivery.milestone.upcoming",
|
|
2828
|
+
order: 160,
|
|
2829
|
+
label: "Upcoming",
|
|
2830
|
+
semanticClass: "delivery.milestone",
|
|
2831
|
+
category: "delivery"
|
|
2832
|
+
},
|
|
2833
|
+
"delivery.milestone.in_progress": {
|
|
2834
|
+
id: "delivery.milestone.in_progress",
|
|
2835
|
+
order: 170,
|
|
2836
|
+
label: "In Progress",
|
|
2837
|
+
semanticClass: "delivery.milestone",
|
|
2838
|
+
category: "delivery"
|
|
2839
|
+
},
|
|
2840
|
+
"delivery.milestone.blocked": {
|
|
2841
|
+
id: "delivery.milestone.blocked",
|
|
2842
|
+
order: 180,
|
|
2843
|
+
label: "Blocked",
|
|
2844
|
+
semanticClass: "delivery.milestone",
|
|
2845
|
+
category: "delivery"
|
|
2846
|
+
},
|
|
2847
|
+
"delivery.milestone.overdue": {
|
|
2848
|
+
id: "delivery.milestone.overdue",
|
|
2849
|
+
order: 190,
|
|
2850
|
+
label: "Overdue",
|
|
2851
|
+
semanticClass: "delivery.milestone",
|
|
2852
|
+
category: "delivery"
|
|
2853
|
+
},
|
|
2854
|
+
"delivery.milestone.completed": {
|
|
2855
|
+
id: "delivery.milestone.completed",
|
|
2856
|
+
order: 200,
|
|
2857
|
+
label: "Completed",
|
|
2858
|
+
semanticClass: "delivery.milestone",
|
|
2859
|
+
category: "delivery"
|
|
2860
|
+
},
|
|
2861
|
+
// --- queue (QueueTaskStatus — 5 values, maps hitl/command-queue tasks) ---
|
|
2862
|
+
"queue.pending": { id: "queue.pending", order: 210, label: "Pending", semanticClass: "queue", category: "queue" },
|
|
2863
|
+
"queue.processing": {
|
|
2864
|
+
id: "queue.processing",
|
|
2865
|
+
order: 220,
|
|
2866
|
+
label: "Processing",
|
|
2867
|
+
semanticClass: "queue",
|
|
2868
|
+
category: "queue"
|
|
2869
|
+
},
|
|
2870
|
+
"queue.completed": {
|
|
2871
|
+
id: "queue.completed",
|
|
2872
|
+
order: 230,
|
|
2873
|
+
label: "Completed",
|
|
2874
|
+
semanticClass: "queue",
|
|
2875
|
+
category: "queue"
|
|
2876
|
+
},
|
|
2877
|
+
"queue.failed": { id: "queue.failed", order: 240, label: "Failed", semanticClass: "queue", category: "queue" },
|
|
2878
|
+
"queue.expired": { id: "queue.expired", order: 250, label: "Expired", semanticClass: "queue", category: "queue" },
|
|
2879
|
+
// --- execution (ExecutionStatus — 5 values) ---
|
|
2880
|
+
"execution.pending": {
|
|
2881
|
+
id: "execution.pending",
|
|
2882
|
+
order: 260,
|
|
2883
|
+
label: "Pending",
|
|
2884
|
+
semanticClass: "execution",
|
|
2885
|
+
category: "execution"
|
|
2886
|
+
},
|
|
2887
|
+
"execution.running": {
|
|
2888
|
+
id: "execution.running",
|
|
2889
|
+
order: 270,
|
|
2890
|
+
label: "Running",
|
|
2891
|
+
semanticClass: "execution",
|
|
2892
|
+
category: "execution"
|
|
2893
|
+
},
|
|
2894
|
+
"execution.completed": {
|
|
2895
|
+
id: "execution.completed",
|
|
2896
|
+
order: 280,
|
|
2897
|
+
label: "Completed",
|
|
2898
|
+
semanticClass: "execution",
|
|
2899
|
+
category: "execution"
|
|
2900
|
+
},
|
|
2901
|
+
"execution.failed": {
|
|
2902
|
+
id: "execution.failed",
|
|
2903
|
+
order: 290,
|
|
2904
|
+
label: "Failed",
|
|
2905
|
+
semanticClass: "execution",
|
|
2906
|
+
category: "execution"
|
|
2907
|
+
},
|
|
2908
|
+
"execution.warning": {
|
|
2909
|
+
id: "execution.warning",
|
|
2910
|
+
order: 300,
|
|
2911
|
+
label: "Warning",
|
|
2912
|
+
semanticClass: "execution",
|
|
2913
|
+
category: "execution"
|
|
2914
|
+
},
|
|
2915
|
+
// --- schedule (schedule status — 4 values) ---
|
|
2916
|
+
"schedule.active": {
|
|
2917
|
+
id: "schedule.active",
|
|
2918
|
+
order: 310,
|
|
2919
|
+
label: "Active",
|
|
2920
|
+
semanticClass: "schedule",
|
|
2921
|
+
category: "schedule"
|
|
2922
|
+
},
|
|
2923
|
+
"schedule.paused": {
|
|
2924
|
+
id: "schedule.paused",
|
|
2925
|
+
order: 320,
|
|
2926
|
+
label: "Paused",
|
|
2927
|
+
semanticClass: "schedule",
|
|
2928
|
+
category: "schedule"
|
|
2929
|
+
},
|
|
2930
|
+
"schedule.completed": {
|
|
2931
|
+
id: "schedule.completed",
|
|
2932
|
+
order: 330,
|
|
2933
|
+
label: "Completed",
|
|
2934
|
+
semanticClass: "schedule",
|
|
2935
|
+
category: "schedule"
|
|
2936
|
+
},
|
|
2937
|
+
"schedule.cancelled": {
|
|
2938
|
+
id: "schedule.cancelled",
|
|
2939
|
+
order: 340,
|
|
2940
|
+
label: "Cancelled",
|
|
2941
|
+
semanticClass: "schedule",
|
|
2942
|
+
category: "schedule"
|
|
2943
|
+
},
|
|
2944
|
+
// --- schedule.run (schedule run status — 4 values) ---
|
|
2945
|
+
"schedule.run.running": {
|
|
2946
|
+
id: "schedule.run.running",
|
|
2947
|
+
order: 350,
|
|
2948
|
+
label: "Running",
|
|
2949
|
+
semanticClass: "schedule.run",
|
|
2950
|
+
category: "schedule"
|
|
2951
|
+
},
|
|
2952
|
+
"schedule.run.completed": {
|
|
2953
|
+
id: "schedule.run.completed",
|
|
2954
|
+
order: 360,
|
|
2955
|
+
label: "Completed",
|
|
2956
|
+
semanticClass: "schedule.run",
|
|
2957
|
+
category: "schedule"
|
|
2958
|
+
},
|
|
2959
|
+
"schedule.run.failed": {
|
|
2960
|
+
id: "schedule.run.failed",
|
|
2961
|
+
order: 370,
|
|
2962
|
+
label: "Failed",
|
|
2963
|
+
semanticClass: "schedule.run",
|
|
2964
|
+
category: "schedule"
|
|
2965
|
+
},
|
|
2966
|
+
"schedule.run.cancelled": {
|
|
2967
|
+
id: "schedule.run.cancelled",
|
|
2968
|
+
order: 380,
|
|
2969
|
+
label: "Cancelled",
|
|
2970
|
+
semanticClass: "schedule.run",
|
|
2971
|
+
category: "schedule"
|
|
2972
|
+
},
|
|
2973
|
+
// --- request (RequestStatus — 4 values, maps reported_requests) ---
|
|
2974
|
+
"request.open": { id: "request.open", order: 390, label: "Open", semanticClass: "request", category: "request" },
|
|
2975
|
+
"request.investigating": {
|
|
2976
|
+
id: "request.investigating",
|
|
2977
|
+
order: 400,
|
|
2978
|
+
label: "Investigating",
|
|
2979
|
+
semanticClass: "request",
|
|
2980
|
+
category: "request"
|
|
2981
|
+
},
|
|
2982
|
+
"request.resolved": {
|
|
2983
|
+
id: "request.resolved",
|
|
2984
|
+
order: 410,
|
|
2985
|
+
label: "Resolved",
|
|
2986
|
+
semanticClass: "request",
|
|
2987
|
+
category: "request"
|
|
2988
|
+
},
|
|
2989
|
+
"request.wont_fix": {
|
|
2990
|
+
id: "request.wont_fix",
|
|
2991
|
+
order: 420,
|
|
2992
|
+
label: "Won't Fix",
|
|
2993
|
+
semanticClass: "request",
|
|
2994
|
+
category: "request"
|
|
2995
|
+
}
|
|
2996
|
+
};
|
|
2997
|
+
|
|
2998
|
+
// src/organization-model/catalogs/lead-gen.ts
|
|
2999
|
+
var LEAD_GEN_STAGE_CATALOG = {
|
|
3000
|
+
// Prospecting - company population
|
|
3001
|
+
scraped: {
|
|
3002
|
+
key: "scraped",
|
|
3003
|
+
label: "Scraped",
|
|
3004
|
+
description: "Company was scraped from a source directory (Apify actor run).",
|
|
3005
|
+
order: 1,
|
|
3006
|
+
entity: "company"
|
|
3007
|
+
},
|
|
3008
|
+
populated: {
|
|
3009
|
+
key: "populated",
|
|
3010
|
+
label: "Companies found",
|
|
3011
|
+
description: "Companies have been found and added to the lead-gen list.",
|
|
3012
|
+
order: 2,
|
|
3013
|
+
entity: "company"
|
|
3014
|
+
},
|
|
3015
|
+
crawled: {
|
|
3016
|
+
key: "crawled",
|
|
3017
|
+
label: "Websites crawled",
|
|
3018
|
+
description: "Company websites have been crawled (e.g. via Apify) and raw page content stored for downstream LLM analysis.",
|
|
3019
|
+
order: 2.5,
|
|
3020
|
+
entity: "company"
|
|
3021
|
+
},
|
|
3022
|
+
extracted: {
|
|
3023
|
+
key: "extracted",
|
|
3024
|
+
label: "Websites analyzed",
|
|
3025
|
+
description: "Company websites have been analyzed for business signals.",
|
|
3026
|
+
order: 3,
|
|
3027
|
+
entity: "company"
|
|
3028
|
+
},
|
|
3029
|
+
enriched: {
|
|
3030
|
+
key: "enriched",
|
|
3031
|
+
label: "Enriched",
|
|
3032
|
+
description: "Company or contact enriched with third-party data (e.g. Tomba, Anymailfinder).",
|
|
3033
|
+
order: 4,
|
|
3034
|
+
entity: "company"
|
|
3035
|
+
},
|
|
3036
|
+
"decision-makers-enriched": {
|
|
3037
|
+
key: "decision-makers-enriched",
|
|
3038
|
+
label: "Decision-makers found",
|
|
3039
|
+
description: "Decision-maker contacts discovered and attached to a qualified company.",
|
|
3040
|
+
order: 6,
|
|
3041
|
+
entity: "company",
|
|
3042
|
+
recordEntity: "contact",
|
|
3043
|
+
recordStageKey: "discovered"
|
|
3044
|
+
},
|
|
3045
|
+
// Prospecting - contact discovery
|
|
3046
|
+
discovered: {
|
|
3047
|
+
key: "discovered",
|
|
3048
|
+
label: "Decision-makers found",
|
|
3049
|
+
description: "Decision-maker contact details have been found.",
|
|
3050
|
+
order: 5,
|
|
3051
|
+
entity: "contact"
|
|
3052
|
+
},
|
|
3053
|
+
verified: {
|
|
3054
|
+
key: "verified",
|
|
3055
|
+
label: "Emails verified",
|
|
3056
|
+
description: "Contact email addresses have been checked for deliverability.",
|
|
3057
|
+
order: 7,
|
|
3058
|
+
entity: "contact"
|
|
3059
|
+
},
|
|
3060
|
+
// Qualification
|
|
3061
|
+
qualified: {
|
|
3062
|
+
key: "qualified",
|
|
3063
|
+
label: "Companies qualified",
|
|
3064
|
+
description: "Companies have been scored against the qualification criteria.",
|
|
3065
|
+
order: 8,
|
|
3066
|
+
entity: "company"
|
|
3067
|
+
},
|
|
3068
|
+
// Outreach
|
|
3069
|
+
personalized: {
|
|
3070
|
+
key: "personalized",
|
|
3071
|
+
label: "Personalized",
|
|
3072
|
+
description: "Outreach message personalized for the contact (Instantly personalization workflow).",
|
|
3073
|
+
order: 9,
|
|
3074
|
+
entity: "contact"
|
|
3075
|
+
},
|
|
3076
|
+
uploaded: {
|
|
3077
|
+
key: "uploaded",
|
|
3078
|
+
label: "Reviewed and exported",
|
|
3079
|
+
description: "Approved records have been reviewed and exported for handoff.",
|
|
3080
|
+
order: 10,
|
|
3081
|
+
entity: "company",
|
|
3082
|
+
additionalEntities: ["contact"]
|
|
3083
|
+
},
|
|
3084
|
+
interested: {
|
|
3085
|
+
key: "interested",
|
|
3086
|
+
label: "Interested",
|
|
3087
|
+
description: "Contact replied with a positive signal (Instantly reply-handler transition).",
|
|
3088
|
+
order: 11,
|
|
3089
|
+
entity: "contact"
|
|
3090
|
+
}
|
|
3091
|
+
};
|
|
3092
|
+
|
|
3093
|
+
// src/organization-model/helpers.ts
|
|
3094
|
+
function listAllSystems(model) {
|
|
3095
|
+
const results = [];
|
|
3096
|
+
function walk(map, prefix) {
|
|
3097
|
+
for (const [localId, system] of Object.entries(map)) {
|
|
3098
|
+
const fullPath = prefix ? `${prefix}.${localId}` : localId;
|
|
3099
|
+
results.push({ path: fullPath, system });
|
|
3100
|
+
if (system.subsystems) {
|
|
3101
|
+
walk(system.subsystems, fullPath);
|
|
3102
|
+
}
|
|
3103
|
+
}
|
|
3104
|
+
}
|
|
3105
|
+
walk(model.systems, "");
|
|
3106
|
+
return results;
|
|
3107
|
+
}
|
|
1784
3108
|
|
|
1785
3109
|
// src/organization-model/resolve.ts
|
|
1786
3110
|
function isPlainObject(value) {
|
|
@@ -1809,43 +3133,119 @@ function defineOrganizationModel(model) {
|
|
|
1809
3133
|
}
|
|
1810
3134
|
function resolveOrganizationModel(override, organizationId) {
|
|
1811
3135
|
const merged = deepMerge(DEFAULT_ORGANIZATION_MODEL, override);
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
3136
|
+
return OrganizationModelSchema.parse(merged);
|
|
3137
|
+
}
|
|
3138
|
+
function resolveOrganizationModelWithResources(override, organizationId) {
|
|
3139
|
+
const model = resolveOrganizationModel(override);
|
|
3140
|
+
const byPath = /* @__PURE__ */ new Map();
|
|
3141
|
+
for (const resource of Object.values(model.resources ?? {})) {
|
|
3142
|
+
const existing = byPath.get(resource.systemPath);
|
|
3143
|
+
if (existing) {
|
|
3144
|
+
existing.push(resource);
|
|
3145
|
+
} else {
|
|
3146
|
+
byPath.set(resource.systemPath, [resource]);
|
|
3147
|
+
}
|
|
1818
3148
|
}
|
|
1819
|
-
|
|
3149
|
+
const enrichedSystems = {};
|
|
3150
|
+
for (const { path, system } of listAllSystems(model)) {
|
|
3151
|
+
const resources = byPath.get(path) ?? byPath.get(system.id);
|
|
3152
|
+
enrichedSystems[path] = resources !== void 0 ? { ...system, id: path, resources } : { ...system, id: path };
|
|
3153
|
+
}
|
|
3154
|
+
return { ...model, systems: enrichedSystems };
|
|
3155
|
+
}
|
|
3156
|
+
|
|
3157
|
+
// src/organization-model/surface-projection.ts
|
|
3158
|
+
function collectSystemsById(model) {
|
|
3159
|
+
const systemsById = /* @__PURE__ */ new Map();
|
|
3160
|
+
for (const { path, system } of listAllSystems(model)) {
|
|
3161
|
+
systemsById.set(path, system);
|
|
3162
|
+
systemsById.set(system.id, system);
|
|
3163
|
+
}
|
|
3164
|
+
return systemsById;
|
|
3165
|
+
}
|
|
3166
|
+
function getSystemWithAncestors(systemsById, systemId) {
|
|
3167
|
+
const systems = [];
|
|
3168
|
+
let current = systemsById.get(systemId);
|
|
3169
|
+
while (current !== void 0) {
|
|
3170
|
+
systems.unshift(current);
|
|
3171
|
+
current = current.parentSystemId ? systemsById.get(current.parentSystemId) : void 0;
|
|
3172
|
+
}
|
|
3173
|
+
return systems;
|
|
3174
|
+
}
|
|
3175
|
+
function hasInheritedFlag(systemsById, systemIds, flag) {
|
|
3176
|
+
return systemIds.some(
|
|
3177
|
+
(systemId) => getSystemWithAncestors(systemsById, systemId).some((system) => system[flag] === true)
|
|
3178
|
+
);
|
|
3179
|
+
}
|
|
3180
|
+
function isLifecycleEnabled2(system) {
|
|
3181
|
+
if (system.enabled === false) return false;
|
|
3182
|
+
return system.lifecycle !== "deprecated" && system.lifecycle !== "archived";
|
|
3183
|
+
}
|
|
3184
|
+
function isLifecycleDevOnly(system) {
|
|
3185
|
+
return system.devOnly === true || system.lifecycle === "beta";
|
|
3186
|
+
}
|
|
3187
|
+
function isSystemEnabled(systemsById, systemId) {
|
|
3188
|
+
const systemLineage = getSystemWithAncestors(systemsById, systemId);
|
|
3189
|
+
return systemLineage.length > 0 && systemLineage.every(isLifecycleEnabled2);
|
|
3190
|
+
}
|
|
3191
|
+
function unique(values) {
|
|
3192
|
+
return [...new Set(values)];
|
|
3193
|
+
}
|
|
3194
|
+
function collectSidebarSurfaces(nodes, schemaPath, surfaces = []) {
|
|
3195
|
+
getSortedSidebarEntries(nodes).forEach(([id, node]) => {
|
|
3196
|
+
const nodePath = [...schemaPath, id];
|
|
3197
|
+
if (node.type === "group") {
|
|
3198
|
+
collectSidebarSurfaces(node.children, [...nodePath, "children"], surfaces);
|
|
3199
|
+
return;
|
|
3200
|
+
}
|
|
3201
|
+
surfaces.push({ id, surface: node, path: nodePath });
|
|
3202
|
+
});
|
|
3203
|
+
return surfaces;
|
|
3204
|
+
}
|
|
3205
|
+
function getSidebarSurfaces(model) {
|
|
3206
|
+
return [
|
|
3207
|
+
...collectSidebarSurfaces(model.navigation.sidebar.primary, ["navigation", "sidebar", "primary"]),
|
|
3208
|
+
...collectSidebarSurfaces(model.navigation.sidebar.bottom, ["navigation", "sidebar", "bottom"])
|
|
3209
|
+
];
|
|
3210
|
+
}
|
|
3211
|
+
function projectOrganizationSurfaces(model) {
|
|
3212
|
+
const systemsById = collectSystemsById(model);
|
|
3213
|
+
return getSidebarSurfaces(model).map(({ id, surface }) => {
|
|
3214
|
+
const targets = surface.targets ?? {};
|
|
3215
|
+
const systemIds = unique((targets.systems ?? []).filter((systemId) => systemsById.has(systemId)));
|
|
3216
|
+
const enabled = systemIds.every((candidate) => isSystemEnabled(systemsById, candidate));
|
|
3217
|
+
const devOnly = surface.devOnly === true || hasInheritedFlag(systemsById, systemIds, "devOnly") || systemIds.some((candidate) => getSystemWithAncestors(systemsById, candidate).some(isLifecycleDevOnly));
|
|
3218
|
+
const requiresAdmin = hasInheritedFlag(systemsById, systemIds, "requiresAdmin");
|
|
3219
|
+
return {
|
|
3220
|
+
id,
|
|
3221
|
+
label: surface.label,
|
|
3222
|
+
path: surface.path,
|
|
3223
|
+
surfaceType: surface.surfaceType,
|
|
3224
|
+
...surface.description !== void 0 ? { description: surface.description } : {},
|
|
3225
|
+
...surface.icon !== void 0 ? { icon: surface.icon } : {},
|
|
3226
|
+
...surface.order !== void 0 ? { order: surface.order } : {},
|
|
3227
|
+
systemIds,
|
|
3228
|
+
entityIds: [...targets.entities ?? []],
|
|
3229
|
+
resourceIds: [...targets.resources ?? []],
|
|
3230
|
+
actionIds: [...targets.actions ?? []],
|
|
3231
|
+
enabled,
|
|
3232
|
+
...devOnly ? { devOnly } : {},
|
|
3233
|
+
...surface.requiresAdmin === true || requiresAdmin ? { requiresAdmin: true } : {}
|
|
3234
|
+
};
|
|
3235
|
+
});
|
|
1820
3236
|
}
|
|
1821
3237
|
|
|
1822
3238
|
// src/organization-model/foundation.ts
|
|
1823
3239
|
function createFoundationOrganizationModel(override) {
|
|
1824
3240
|
const canonical = resolveOrganizationModel(override);
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
}
|
|
1830
|
-
return feature;
|
|
1831
|
-
}
|
|
1832
|
-
const operationsFeature = requireCoreFeature("operations");
|
|
1833
|
-
const projectsFeature = requireCoreFeature("projects");
|
|
1834
|
-
const leadGenFeature = requireCoreFeature("sales.lead-gen");
|
|
1835
|
-
const crmFeature = requireCoreFeature("sales.crm");
|
|
1836
|
-
const navigationSurfaces = [
|
|
1837
|
-
{ ...operationsFeature, id: "operations", path: "/operations", icon: "feature.operations", surfaceType: "dashboard" },
|
|
1838
|
-
{ ...projectsFeature, icon: "feature.projects", surfaceType: "list" },
|
|
1839
|
-
{ ...leadGenFeature, id: "lead-gen", icon: "feature.lead-gen", surfaceType: "list" },
|
|
1840
|
-
{ ...crmFeature, id: "crm", icon: "feature.crm", surfaceType: "graph" },
|
|
1841
|
-
{ ...requireCoreFeature("settings.account"), id: "settings", icon: "feature.settings", surfaceType: "settings" }
|
|
1842
|
-
];
|
|
1843
|
-
const homeLabel = "Dashboard";
|
|
1844
|
-
const quickAccessSurfaceIds = ["operations", "projects", "lead-gen", "crm"];
|
|
3241
|
+
const navigationSurfaces = projectOrganizationSurfaces(canonical);
|
|
3242
|
+
const defaultSurface = navigationSurfaces.find((surface) => surface.path === "/") ?? navigationSurfaces[0];
|
|
3243
|
+
const homeLabel = defaultSurface?.label ?? "Dashboard";
|
|
3244
|
+
const quickAccessSurfaceIds = navigationSurfaces.filter((surface) => surface.id !== defaultSurface?.id && surface.surfaceType !== "settings").slice(0, 4).map((surface) => surface.id);
|
|
1845
3245
|
const model = {
|
|
1846
3246
|
...canonical,
|
|
1847
3247
|
navigation: {
|
|
1848
|
-
defaultSurfaceId: "
|
|
3248
|
+
defaultSurfaceId: defaultSurface?.id ?? "",
|
|
1849
3249
|
homeLabel,
|
|
1850
3250
|
quickAccessSurfaceIds: [...quickAccessSurfaceIds],
|
|
1851
3251
|
surfaces: navigationSurfaces
|
|
@@ -1863,4 +3263,4 @@ function createFoundationOrganizationModel(override) {
|
|
|
1863
3263
|
};
|
|
1864
3264
|
}
|
|
1865
3265
|
|
|
1866
|
-
export { CustomerSegmentSchema, CustomersDomainSchema, DEFAULT_ORGANIZATION_MODEL, DEFAULT_ORGANIZATION_MODEL_CUSTOMERS, DEFAULT_ORGANIZATION_MODEL_GOALS, DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
|
|
3266
|
+
export { ActionIdSchema, ActionInvocationKindSchema, ActionInvocationSchema, ActionRefSchema, ActionSchema, ActionScopeSchema, ActionsDomainSchema, AgentKindSchema, AgentResourceEntrySchema, AgentRoleHolderSchema, ApiEndpointInvocationSchema, CustomerSegmentSchema, CustomersDomainSchema, DEFAULT_ORGANIZATION_MODEL, DEFAULT_ORGANIZATION_MODEL_ACTIONS, DEFAULT_ORGANIZATION_MODEL_CUSTOMERS, DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA, DEFAULT_ORGANIZATION_MODEL_ENTITIES, DEFAULT_ORGANIZATION_MODEL_GOALS, DEFAULT_ORGANIZATION_MODEL_NAVIGATION, DEFAULT_ORGANIZATION_MODEL_OFFERINGS, DEFAULT_ORGANIZATION_MODEL_POLICIES, DEFAULT_ORGANIZATION_MODEL_RESOURCES, DEFAULT_ORGANIZATION_MODEL_ROLES, DEFAULT_ORGANIZATION_MODEL_STATUSES, DEFAULT_ORGANIZATION_MODEL_SYSTEMS, EntitiesDomainSchema, EntityIdSchema, EntityLinkKindSchema, EntityLinkSchema, EntitySchema, EventDescriptorSchema, EventEmissionDescriptorSchema, EventIdSchema, FirmographicsSchema, GoalsDomainSchema, HumanRoleHolderSchema, IconNameSchema, IntegrationResourceEntrySchema, KNOWLEDGE_FEATURE_ID, KNOWLEDGE_SYSTEM_ID, KeyResultSchema, KnowledgeDomainSchema, KnowledgeLinkSchema, KnowledgeTargetKindSchema, KnowledgeTargetRefSchema, LEAD_GEN_ACTION_ENTRIES, LEAD_GEN_STAGE_CATALOG, LinkSchema, MONITORING_FEATURE_ID, MONITORING_SYSTEM_ID, McpToolInvocationSchema, NavigationGroupSchema, NodeIdPathSchema, NodeIdStringSchema, OPERATIONS_COMMAND_VIEW_SURFACE_ID, OPERATIONS_FEATURE_ID, OPERATIONS_SYSTEM_ID, ORGANIZATION_MODEL_ICON_TOKENS, ObjectiveSchema, OfferingsDomainSchema, OrgKnowledgeKindSchema, OrgKnowledgeNodeSchema, OrganizationModelBuiltinIconTokenSchema, OrganizationModelDomainKeySchema, OrganizationModelDomainMetadataByDomainSchema, OrganizationModelDomainMetadataSchema, OrganizationModelIconTokenSchema, OrganizationModelNavigationSchema, OrganizationModelSchema, PROJECTS_FEATURE_ID, PROJECTS_INDEX_SURFACE_ID, PROJECTS_SYSTEM_ID, PROJECTS_VIEW_ACTION_ID, PROSPECTING_FEATURE_ID, PROSPECTING_LISTS_SURFACE_ID, PROSPECTING_SYSTEM_ID, PoliciesDomainSchema, PolicyApplicabilitySchema, PolicyEffectSchema, PolicyIdSchema, PolicyPredicateSchema, PolicySchema, PolicyTriggerSchema, PricingModelSchema, ProductSchema, ResourceEntrySchema, ResourceGovernanceStatusSchema, ResourceIdSchema, ResourceKindSchema, ResourcesDomainSchema, RoleHolderSchema, RoleHoldersSchema, RoleIdSchema, RoleSchema, RolesDomainSchema, SALES_FEATURE_ID, SALES_PIPELINE_SURFACE_ID, SALES_SYSTEM_ID, SEO_FEATURE_ID, SEO_SYSTEM_ID, SETTINGS_FEATURE_ID, SETTINGS_ROLES_SURFACE_ID, SETTINGS_SYSTEM_ID, ScriptExecutionInvocationSchema, ScriptResourceEntrySchema, ScriptResourceLanguageSchema, ScriptResourceSourceSchema, SidebarNavigationSchema, SidebarNodeSchema, SidebarSectionSchema, SidebarSurfaceTargetsSchema, SlashCommandInvocationSchema, StatusEntrySchema, StatusSemanticClassSchema, StatusesDomainSchema, SurfaceDefinitionSchema, SurfaceTypeSchema, SystemEntrySchema, SystemIdSchema, SystemKindSchema, SystemLifecycleSchema, SystemPathSchema, SystemStatusSchema, SystemUiSchema, SystemsDomainSchema, TeamRoleHolderSchema, TechStackEntrySchema, UiPositionSchema, WorkflowResourceEntrySchema, createFoundationOrganizationModel, defineOrganizationModel, defineResource, defineResources, findOrganizationActionById, getSortedSidebarEntries, resolveOrganizationModel, resolveOrganizationModelWithResources };
|