@elevasis/sdk 1.20.2 → 1.22.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/cli.cjs +4220 -1583
- package/dist/index.d.ts +1035 -481
- package/dist/index.js +7381 -4187
- package/dist/node/index.d.ts +1 -3
- package/dist/node/index.js +40 -49
- package/dist/test-utils/index.d.ts +699 -123
- package/dist/test-utils/index.js +3826 -630
- package/dist/worker/index.js +3616 -442
- package/package.json +3 -3
- package/reference/_navigation.md +9 -7
- package/reference/_reference-manifest.json +1 -1
- package/reference/claude-config/hooks/post-edit-validate.mjs +98 -98
- package/reference/claude-config/hooks/scaffold-registry-reminder.mjs +188 -188
- package/reference/claude-config/hooks/tool-failure-recovery.mjs +73 -73
- package/reference/claude-config/registries/graph-skills.json +4 -4
- package/reference/claude-config/registries/knowledge-flags.json +0 -2
- package/reference/claude-config/rules/active-change-index.md +80 -80
- package/reference/claude-config/rules/agent-start-here.md +277 -273
- package/reference/claude-config/rules/deployment.md +57 -57
- package/reference/claude-config/rules/error-handling.md +56 -56
- package/reference/claude-config/rules/execution.md +40 -40
- package/reference/claude-config/rules/frontend.md +4 -4
- package/reference/claude-config/rules/observability.md +31 -31
- package/reference/claude-config/rules/operations.md +29 -17
- package/reference/claude-config/rules/organization-model.md +108 -40
- package/reference/claude-config/rules/organization-os.md +115 -113
- package/reference/claude-config/rules/package-taxonomy.md +33 -33
- package/reference/claude-config/rules/platform.md +42 -42
- package/reference/claude-config/rules/shared-types.md +49 -46
- package/reference/claude-config/rules/task-tracking.md +47 -47
- package/reference/claude-config/rules/ui.md +200 -200
- package/reference/claude-config/rules/vibe.md +235 -231
- package/reference/claude-config/scripts/statusline-command.js +18 -18
- package/reference/claude-config/settings.json +34 -34
- package/reference/claude-config/skills/deploy/{SKILL.md → skill.md} +156 -156
- package/reference/claude-config/skills/dsp/SKILL.md +66 -66
- package/reference/claude-config/skills/elevasis/SKILL.md +235 -235
- package/reference/claude-config/skills/explore/SKILL.md +6 -6
- package/reference/claude-config/skills/git-sync/SKILL.md +126 -126
- package/reference/claude-config/skills/knowledge/SKILL.md +330 -271
- package/reference/claude-config/skills/knowledge/operations/codify-level-a.md +100 -100
- package/reference/claude-config/skills/knowledge/operations/codify-level-b.md +159 -158
- package/reference/claude-config/skills/knowledge/operations/customers.md +109 -109
- package/reference/claude-config/skills/knowledge/operations/features.md +76 -113
- package/reference/claude-config/skills/knowledge/operations/goals.md +118 -118
- package/reference/claude-config/skills/knowledge/operations/identity.md +93 -93
- package/reference/claude-config/skills/knowledge/operations/labels.md +94 -89
- package/reference/claude-config/skills/knowledge/operations/offerings.md +109 -109
- package/reference/claude-config/skills/knowledge/operations/roles.md +99 -99
- package/reference/claude-config/skills/knowledge/operations/techStack.md +30 -30
- package/reference/claude-config/skills/project/SKILL.md +1088 -1088
- package/reference/claude-config/skills/run-ui/SKILL.md +73 -73
- package/reference/claude-config/skills/save/SKILL.md +3 -3
- package/reference/claude-config/skills/setup/SKILL.md +275 -275
- package/reference/claude-config/skills/status/SKILL.md +59 -59
- package/reference/claude-config/skills/submit-request/SKILL.md +180 -180
- package/reference/claude-config/skills/sync/SKILL.md +47 -47
- package/reference/claude-config/skills/tutorial/SKILL.md +259 -259
- package/reference/claude-config/skills/tutorial/progress-template.md +74 -74
- package/reference/claude-config/skills/tutorial/technical.md +1303 -1306
- package/reference/claude-config/skills/tutorial/vibe-coder.md +890 -890
- package/reference/claude-config/sync-notes/2026-04-22-git-sync-and-sync-notes.md +27 -27
- package/reference/claude-config/sync-notes/2026-04-22-lead-gen-deliverability-removal.md +30 -30
- package/reference/claude-config/sync-notes/2026-04-24-test-utils-and-template-tests.md +73 -73
- package/reference/claude-config/sync-notes/2026-04-24-ui-consolidation-and-sdk-cli-train.md +86 -86
- package/reference/claude-config/sync-notes/2026-04-25-auth-role-system-and-settings-roles.md +55 -55
- package/reference/claude-config/sync-notes/2026-04-27-crm-hitl-action-layer-cutover.md +97 -97
- package/reference/claude-config/sync-notes/2026-04-27-lead-gen-substrate-train.md +112 -112
- package/reference/claude-config/sync-notes/2026-04-29-crm-state-and-lead-gen-processing-status.md +93 -93
- package/reference/claude-config/sync-notes/2026-05-02-crm-ownership-next-action.md +58 -58
- package/reference/claude-config/sync-notes/2026-05-02-template-hardcode-workos-config.md +56 -56
- package/reference/claude-config/sync-notes/2026-05-04-elevasis-workspace.md +71 -71
- package/reference/claude-config/sync-notes/2026-05-04-knowledge-bundle.md +83 -83
- package/reference/claude-config/sync-notes/2026-05-04-template-skills-run-ui-and-tutorial.md +59 -59
- package/reference/claude-config/sync-notes/2026-05-05-list-builder.md +42 -42
- package/reference/claude-config/sync-notes/2026-05-06-crm-spine.md +60 -60
- package/reference/claude-config/sync-notes/2026-05-06-sdk-changes-release-train.md +37 -37
- package/reference/claude-config/sync-notes/2026-05-07-sdk-changes-release-train.md +34 -34
- package/reference/claude-config/sync-notes/2026-05-08-resource-governance-scaffold-guidance.md +38 -38
- package/reference/claude-config/sync-notes/2026-05-09-clients-domain.md +32 -32
- package/reference/claude-config/sync-notes/2026-05-09-command-system.md +33 -33
- package/reference/claude-config/sync-notes/2026-05-09-resource-governance-and-misc.md +69 -69
- package/reference/claude-config/sync-notes/2026-05-12-sdk-ready-release-train.md +30 -0
- package/reference/claude-config/sync-notes/2026-05-14-organization-model-ontology-refactor.md +42 -0
- package/reference/claude-config/sync-notes/README.md +43 -43
- package/reference/cli.mdx +808 -668
- package/reference/concepts.mdx +146 -146
- package/reference/deployment/api.mdx +297 -297
- package/reference/deployment/command-center.mdx +209 -209
- package/reference/deployment/index.mdx +195 -195
- package/reference/deployment/provided-features.mdx +107 -93
- package/reference/deployment/ui-execution.mdx +250 -250
- package/reference/examples/organization-model.ts +147 -84
- package/reference/framework/agent.mdx +156 -156
- package/reference/framework/index.mdx +195 -195
- package/reference/framework/interaction-guidance.mdx +182 -182
- package/reference/framework/memory.mdx +326 -326
- package/reference/framework/project-structure.mdx +282 -282
- package/reference/framework/tutorial-system.mdx +135 -135
- package/reference/getting-started.mdx +142 -142
- package/reference/index.mdx +106 -106
- package/reference/packages/core/src/README.md +14 -14
- package/reference/packages/core/src/business/README.md +2 -2
- package/reference/packages/core/src/knowledge/README.md +33 -32
- package/reference/packages/core/src/organization-model/README.md +149 -109
- package/reference/packages/core/src/test-utils/README.md +37 -37
- package/reference/packages/ui/src/api/README.md +18 -18
- package/reference/packages/ui/src/app/README.md +24 -24
- package/reference/packages/ui/src/auth/README.md +18 -18
- package/reference/packages/ui/src/components/README.md +24 -24
- package/reference/packages/ui/src/execution/README.md +16 -16
- package/reference/packages/ui/src/features/README.md +28 -28
- package/reference/packages/ui/src/graph/README.md +16 -16
- package/reference/packages/ui/src/hooks/README.md +23 -23
- package/reference/packages/ui/src/initialization/README.md +19 -19
- package/reference/packages/ui/src/knowledge/README.md +31 -31
- package/reference/packages/ui/src/organization/README.md +18 -18
- package/reference/packages/ui/src/profile/README.md +19 -19
- package/reference/packages/ui/src/provider/README.md +32 -32
- package/reference/packages/ui/src/router/README.md +18 -18
- package/reference/packages/ui/src/sse/README.md +13 -13
- package/reference/packages/ui/src/test-utils/README.md +7 -7
- package/reference/packages/ui/src/theme/README.md +23 -23
- package/reference/packages/ui/src/theme/presets/README.md +19 -19
- package/reference/packages/ui/src/types/README.md +16 -16
- package/reference/packages/ui/src/utils/README.md +18 -18
- package/reference/packages/ui/src/zustand/README.md +18 -18
- package/reference/platform-tools/adapters-integration.mdx +301 -301
- package/reference/platform-tools/adapters-platform.mdx +553 -553
- package/reference/platform-tools/index.mdx +217 -217
- package/reference/platform-tools/type-safety.mdx +82 -82
- package/reference/resources/index.mdx +349 -349
- package/reference/resources/patterns.mdx +449 -449
- package/reference/resources/types.mdx +116 -116
- package/reference/roadmap.mdx +165 -165
- package/reference/runtime.mdx +173 -173
- package/reference/scaffold/core/organization-graph.mdx +110 -89
- package/reference/scaffold/core/organization-model.mdx +226 -171
- package/reference/scaffold/index.mdx +67 -67
- package/reference/scaffold/operations/propagation-pipeline.md +77 -77
- package/reference/scaffold/operations/scaffold-maintenance.md +10 -10
- package/reference/scaffold/operations/workflow-recipes.md +138 -138
- package/reference/scaffold/recipes/add-a-feature.md +310 -88
- package/reference/scaffold/recipes/add-a-resource.md +137 -117
- package/reference/scaffold/recipes/customize-crm-actions.md +439 -439
- package/reference/scaffold/recipes/customize-knowledge-browser.md +384 -0
- package/reference/scaffold/recipes/customize-organization-model.md +281 -118
- package/reference/scaffold/recipes/extend-a-base-entity.md +8 -8
- package/reference/scaffold/recipes/extend-crm.md +40 -39
- package/reference/scaffold/recipes/extend-lead-gen.md +400 -401
- package/reference/scaffold/recipes/gate-by-feature-or-admin.md +118 -114
- package/reference/scaffold/recipes/index.md +47 -46
- package/reference/scaffold/recipes/query-the-knowledge-graph.md +227 -0
- package/reference/scaffold/reference/contracts.md +2389 -2121
- package/reference/scaffold/reference/feature-registry.md +9 -20
- package/reference/scaffold/reference/glossary.md +76 -76
- package/reference/scaffold/ui/composition-extensibility.mdx +233 -233
- package/reference/scaffold/ui/customization.md +243 -243
- package/reference/scaffold/ui/feature-flags-and-gating.md +46 -46
- package/reference/scaffold/ui/feature-shell.mdx +72 -72
- package/reference/scaffold/ui/recipes.md +221 -213
- package/reference/spine/spine-primer.md +96 -96
- package/reference/templates/index.mdx +47 -47
- package/reference/troubleshooting.mdx +223 -223
package/dist/worker/index.js
CHANGED
|
@@ -4604,73 +4604,78 @@ Fix the errors and generate a valid output.
|
|
|
4604
4604
|
}
|
|
4605
4605
|
};
|
|
4606
4606
|
var ORGANIZATION_MODEL_ICON_TOKENS = [
|
|
4607
|
-
|
|
4608
|
-
"
|
|
4609
|
-
"
|
|
4610
|
-
"
|
|
4611
|
-
"
|
|
4612
|
-
"
|
|
4613
|
-
"
|
|
4614
|
-
"
|
|
4615
|
-
"
|
|
4616
|
-
"
|
|
4617
|
-
"
|
|
4618
|
-
"
|
|
4619
|
-
"
|
|
4620
|
-
"
|
|
4621
|
-
"
|
|
4622
|
-
"
|
|
4623
|
-
"
|
|
4624
|
-
|
|
4625
|
-
"
|
|
4626
|
-
"
|
|
4627
|
-
"
|
|
4628
|
-
|
|
4629
|
-
"
|
|
4630
|
-
"
|
|
4631
|
-
"
|
|
4632
|
-
"
|
|
4633
|
-
"
|
|
4634
|
-
"
|
|
4635
|
-
|
|
4636
|
-
"
|
|
4637
|
-
"
|
|
4638
|
-
"
|
|
4639
|
-
|
|
4640
|
-
"
|
|
4641
|
-
"
|
|
4642
|
-
"
|
|
4643
|
-
"
|
|
4644
|
-
"
|
|
4645
|
-
"
|
|
4646
|
-
|
|
4647
|
-
"
|
|
4648
|
-
"
|
|
4649
|
-
"
|
|
4650
|
-
"
|
|
4651
|
-
"
|
|
4652
|
-
"
|
|
4653
|
-
"
|
|
4654
|
-
"
|
|
4655
|
-
"
|
|
4656
|
-
"
|
|
4657
|
-
"
|
|
4658
|
-
|
|
4659
|
-
"
|
|
4660
|
-
"
|
|
4661
|
-
"
|
|
4662
|
-
"
|
|
4663
|
-
"
|
|
4664
|
-
|
|
4665
|
-
"
|
|
4666
|
-
"
|
|
4667
|
-
"
|
|
4668
|
-
"
|
|
4669
|
-
"
|
|
4670
|
-
"
|
|
4671
|
-
"
|
|
4607
|
+
// Navigation / app areas
|
|
4608
|
+
"dashboard",
|
|
4609
|
+
"calendar",
|
|
4610
|
+
"sales",
|
|
4611
|
+
"crm",
|
|
4612
|
+
"lead-gen",
|
|
4613
|
+
"projects",
|
|
4614
|
+
"operations",
|
|
4615
|
+
"monitoring",
|
|
4616
|
+
"knowledge",
|
|
4617
|
+
"settings",
|
|
4618
|
+
"admin",
|
|
4619
|
+
"archive",
|
|
4620
|
+
"business",
|
|
4621
|
+
"finance",
|
|
4622
|
+
"platform",
|
|
4623
|
+
"seo",
|
|
4624
|
+
// Knowledge kinds
|
|
4625
|
+
"playbook",
|
|
4626
|
+
"strategy",
|
|
4627
|
+
"reference",
|
|
4628
|
+
// Resource kinds
|
|
4629
|
+
"agent",
|
|
4630
|
+
"workflow",
|
|
4631
|
+
"integration",
|
|
4632
|
+
"database",
|
|
4633
|
+
"user",
|
|
4634
|
+
"team",
|
|
4635
|
+
// Integration specifics
|
|
4636
|
+
"gmail",
|
|
4637
|
+
"google-sheets",
|
|
4638
|
+
"attio",
|
|
4639
|
+
// Surface / UI views
|
|
4640
|
+
"overview",
|
|
4641
|
+
"command-view",
|
|
4642
|
+
"command-queue",
|
|
4643
|
+
"pipeline",
|
|
4644
|
+
"lists",
|
|
4645
|
+
"resources",
|
|
4646
|
+
// Actions
|
|
4647
|
+
"approve",
|
|
4648
|
+
"reject",
|
|
4649
|
+
"retry",
|
|
4650
|
+
"edit",
|
|
4651
|
+
"view",
|
|
4652
|
+
"launch",
|
|
4653
|
+
"message",
|
|
4654
|
+
"escalate",
|
|
4655
|
+
"promote",
|
|
4656
|
+
"submit",
|
|
4657
|
+
"email",
|
|
4658
|
+
// Status
|
|
4659
|
+
"success",
|
|
4660
|
+
"error",
|
|
4661
|
+
"warning",
|
|
4662
|
+
"info",
|
|
4663
|
+
"pending",
|
|
4664
|
+
// OM / UI group icons
|
|
4665
|
+
"bolt",
|
|
4666
|
+
"building",
|
|
4667
|
+
"briefcase",
|
|
4668
|
+
"apps",
|
|
4669
|
+
"graph",
|
|
4670
|
+
"shield",
|
|
4671
|
+
"users",
|
|
4672
|
+
"chart-bar",
|
|
4673
|
+
"search"
|
|
4672
4674
|
];
|
|
4673
|
-
var CustomIconTokenSchema = z.string().trim().max(80).regex(
|
|
4675
|
+
var CustomIconTokenSchema = z.string().trim().max(80).regex(
|
|
4676
|
+
/^custom\.[a-z0-9]+(?:[-._][a-z0-9]+)*$/,
|
|
4677
|
+
'Custom icon tokens must start with "custom." followed by lowercase alphanumeric segments'
|
|
4678
|
+
);
|
|
4674
4679
|
var OrganizationModelBuiltinIconTokenSchema = z.enum(ORGANIZATION_MODEL_ICON_TOKENS);
|
|
4675
4680
|
var OrganizationModelIconTokenSchema = z.union([
|
|
4676
4681
|
OrganizationModelBuiltinIconTokenSchema,
|
|
@@ -4683,7 +4688,7 @@ var LabelSchema = z.string().trim().min(1).max(120);
|
|
|
4683
4688
|
var DescriptionSchema = z.string().trim().min(1).max(2e3);
|
|
4684
4689
|
var ColorTokenSchema = z.string().trim().min(1).max(50);
|
|
4685
4690
|
var IconNameSchema = OrganizationModelIconTokenSchema;
|
|
4686
|
-
z.string().trim().startsWith("/").max(300);
|
|
4691
|
+
var PathSchema = z.string().trim().startsWith("/").max(300);
|
|
4687
4692
|
var ReferenceIdsSchema = z.array(ModelIdSchema).default([]);
|
|
4688
4693
|
var DisplayMetadataSchema = z.object({
|
|
4689
4694
|
label: LabelSchema,
|
|
@@ -4714,380 +4719,556 @@ DisplayMetadataSchema.extend({
|
|
|
4714
4719
|
id: ModelIdSchema,
|
|
4715
4720
|
resourceId: z.string().trim().min(1).max(255),
|
|
4716
4721
|
resourceType: z.enum(["workflow", "agent", "trigger", "integration", "external", "human_checkpoint"]),
|
|
4717
|
-
|
|
4722
|
+
systemIds: ReferenceIdsSchema,
|
|
4718
4723
|
entityIds: ReferenceIdsSchema,
|
|
4719
4724
|
surfaceIds: ReferenceIdsSchema,
|
|
4720
|
-
|
|
4725
|
+
actionIds: ReferenceIdsSchema,
|
|
4721
4726
|
/** Optional tech-stack metadata for external-SaaS integrations. */
|
|
4722
4727
|
techStack: TechStackEntrySchema.optional()
|
|
4723
4728
|
});
|
|
4724
4729
|
|
|
4725
|
-
// ../core/src/organization-model/domains/
|
|
4726
|
-
var
|
|
4727
|
-
var
|
|
4728
|
-
|
|
4729
|
-
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4730
|
+
// ../core/src/organization-model/domains/entities.ts
|
|
4731
|
+
var EntityIdSchema = ModelIdSchema;
|
|
4732
|
+
var EntityLinkKindSchema = z.enum(["belongs-to", "has-many", "has-one", "many-to-many"]).meta({ label: "Link kind" });
|
|
4733
|
+
var EntityLinkSchema = z.object({
|
|
4734
|
+
toEntity: EntityIdSchema.meta({ ref: "entity" }),
|
|
4735
|
+
kind: EntityLinkKindSchema,
|
|
4736
|
+
via: z.string().trim().min(1).max(255).optional(),
|
|
4737
|
+
label: LabelSchema.optional()
|
|
4733
4738
|
});
|
|
4734
|
-
var
|
|
4735
|
-
id:
|
|
4736
|
-
|
|
4739
|
+
var EntitySchema = z.object({
|
|
4740
|
+
id: EntityIdSchema,
|
|
4741
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
4742
|
+
order: z.number(),
|
|
4743
|
+
label: LabelSchema,
|
|
4737
4744
|
description: DescriptionSchema.optional(),
|
|
4738
|
-
|
|
4739
|
-
|
|
4740
|
-
|
|
4741
|
-
|
|
4742
|
-
|
|
4743
|
-
defaultPipelineId: ModelIdSchema,
|
|
4744
|
-
pipelines: z.array(SalesPipelineSchema).min(1)
|
|
4745
|
+
ownedBySystemId: ModelIdSchema.meta({ ref: "system" }),
|
|
4746
|
+
table: z.string().trim().min(1).max(255).optional(),
|
|
4747
|
+
rowSchema: ModelIdSchema.optional(),
|
|
4748
|
+
stateCatalogId: ModelIdSchema.optional(),
|
|
4749
|
+
links: z.array(EntityLinkSchema).optional()
|
|
4745
4750
|
});
|
|
4746
|
-
var
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
stateKey: "discovery_booking_cancelled",
|
|
4760
|
-
label: "Discovery Booking Cancelled"
|
|
4761
|
-
};
|
|
4762
|
-
var CRM_REPLY_SENT_STATE = {
|
|
4763
|
-
stateKey: "reply_sent",
|
|
4764
|
-
label: "Reply Sent"
|
|
4765
|
-
};
|
|
4766
|
-
var CRM_FOLLOWUP_1_SENT_STATE = {
|
|
4767
|
-
stateKey: "followup_1_sent",
|
|
4768
|
-
label: "Follow-up 1 Sent"
|
|
4769
|
-
};
|
|
4770
|
-
var CRM_FOLLOWUP_2_SENT_STATE = {
|
|
4771
|
-
stateKey: "followup_2_sent",
|
|
4772
|
-
label: "Follow-up 2 Sent"
|
|
4773
|
-
};
|
|
4774
|
-
var CRM_FOLLOWUP_3_SENT_STATE = {
|
|
4775
|
-
stateKey: "followup_3_sent",
|
|
4776
|
-
label: "Follow-up 3 Sent"
|
|
4777
|
-
};
|
|
4778
|
-
var CRM_PIPELINE_DEFINITION = {
|
|
4779
|
-
pipelineKey: "crm",
|
|
4780
|
-
stages: [
|
|
4781
|
-
{
|
|
4782
|
-
stageKey: "interested",
|
|
4783
|
-
label: "Interested",
|
|
4784
|
-
color: "blue",
|
|
4785
|
-
states: [
|
|
4786
|
-
CRM_DISCOVERY_REPLIED_STATE,
|
|
4787
|
-
CRM_DISCOVERY_LINK_SENT_STATE,
|
|
4788
|
-
CRM_DISCOVERY_NUDGING_STATE,
|
|
4789
|
-
CRM_DISCOVERY_BOOKING_CANCELLED_STATE,
|
|
4790
|
-
CRM_REPLY_SENT_STATE,
|
|
4791
|
-
CRM_FOLLOWUP_1_SENT_STATE,
|
|
4792
|
-
CRM_FOLLOWUP_2_SENT_STATE,
|
|
4793
|
-
CRM_FOLLOWUP_3_SENT_STATE
|
|
4794
|
-
]
|
|
4795
|
-
},
|
|
4796
|
-
{ stageKey: "proposal", label: "Proposal", color: "yellow", states: [] },
|
|
4797
|
-
{ stageKey: "closing", label: "Closing", color: "orange", states: [] },
|
|
4798
|
-
{ stageKey: "closed_won", label: "Closed Won", color: "green", states: [] },
|
|
4799
|
-
{ stageKey: "closed_lost", label: "Closed Lost", color: "red", states: [] },
|
|
4800
|
-
{ stageKey: "nurturing", label: "Nurturing", color: "grape", states: [] }
|
|
4801
|
-
]
|
|
4802
|
-
};
|
|
4803
|
-
var LEAD_GEN_STAGE_CATALOG = {
|
|
4804
|
-
// Prospecting — company population
|
|
4805
|
-
scraped: {
|
|
4806
|
-
key: "scraped",
|
|
4807
|
-
label: "Scraped",
|
|
4808
|
-
description: "Company was scraped from a source directory (Apify actor run).",
|
|
4809
|
-
order: 1,
|
|
4810
|
-
entity: "company"
|
|
4811
|
-
},
|
|
4812
|
-
populated: {
|
|
4813
|
-
key: "populated",
|
|
4814
|
-
label: "Companies found",
|
|
4815
|
-
description: "Companies have been found and added to the lead-gen list.",
|
|
4816
|
-
order: 2,
|
|
4817
|
-
entity: "company"
|
|
4818
|
-
},
|
|
4819
|
-
crawled: {
|
|
4820
|
-
key: "crawled",
|
|
4821
|
-
label: "Websites crawled",
|
|
4822
|
-
description: "Company websites have been crawled (e.g. via Apify) and raw page content stored for downstream LLM analysis.",
|
|
4823
|
-
order: 2.5,
|
|
4824
|
-
entity: "company"
|
|
4825
|
-
},
|
|
4826
|
-
extracted: {
|
|
4827
|
-
key: "extracted",
|
|
4828
|
-
label: "Websites analyzed",
|
|
4829
|
-
description: "Company websites have been analyzed for business signals.",
|
|
4830
|
-
order: 3,
|
|
4831
|
-
entity: "company"
|
|
4832
|
-
},
|
|
4833
|
-
enriched: {
|
|
4834
|
-
key: "enriched",
|
|
4835
|
-
label: "Enriched",
|
|
4836
|
-
description: "Company or contact enriched with third-party data (e.g. Tomba, Anymailfinder).",
|
|
4837
|
-
order: 4,
|
|
4838
|
-
entity: "company"
|
|
4751
|
+
var EntitiesDomainSchema = z.record(z.string(), EntitySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
4752
|
+
message: "Each entity entry id must match its map key"
|
|
4753
|
+
}).default({});
|
|
4754
|
+
var ENTITY_ENTRY_INPUTS = [
|
|
4755
|
+
{
|
|
4756
|
+
id: "crm.deal",
|
|
4757
|
+
order: 10,
|
|
4758
|
+
label: "Deal",
|
|
4759
|
+
description: "A CRM opportunity or sales pipeline record.",
|
|
4760
|
+
ownedBySystemId: "sales.crm",
|
|
4761
|
+
table: "crm_deals",
|
|
4762
|
+
stateCatalogId: "crm.pipeline",
|
|
4763
|
+
links: [{ toEntity: "crm.contact", kind: "has-many", via: "deal_contacts", label: "contacts" }]
|
|
4839
4764
|
},
|
|
4840
|
-
|
|
4841
|
-
|
|
4842
|
-
|
|
4843
|
-
|
|
4844
|
-
|
|
4845
|
-
|
|
4846
|
-
|
|
4847
|
-
recordStageKey: "discovered"
|
|
4765
|
+
{
|
|
4766
|
+
id: "crm.contact",
|
|
4767
|
+
order: 20,
|
|
4768
|
+
label: "CRM Contact",
|
|
4769
|
+
description: "A person associated with a CRM relationship or deal.",
|
|
4770
|
+
ownedBySystemId: "sales.crm",
|
|
4771
|
+
table: "crm_contacts"
|
|
4848
4772
|
},
|
|
4849
|
-
|
|
4850
|
-
|
|
4851
|
-
|
|
4852
|
-
label: "
|
|
4853
|
-
description: "
|
|
4854
|
-
|
|
4855
|
-
|
|
4773
|
+
{
|
|
4774
|
+
id: "leadgen.list",
|
|
4775
|
+
order: 30,
|
|
4776
|
+
label: "Lead List",
|
|
4777
|
+
description: "A prospecting list that groups companies and contacts for acquisition workflows.",
|
|
4778
|
+
ownedBySystemId: "sales.lead-gen",
|
|
4779
|
+
table: "acq_lists",
|
|
4780
|
+
links: [
|
|
4781
|
+
{ toEntity: "leadgen.company", kind: "has-many", via: "acq_list_companies", label: "companies" },
|
|
4782
|
+
{ toEntity: "leadgen.contact", kind: "has-many", via: "acq_list_members", label: "contacts" }
|
|
4783
|
+
]
|
|
4856
4784
|
},
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
4860
|
-
|
|
4861
|
-
|
|
4862
|
-
|
|
4785
|
+
{
|
|
4786
|
+
id: "leadgen.company",
|
|
4787
|
+
order: 40,
|
|
4788
|
+
label: "Lead Company",
|
|
4789
|
+
description: "A company record sourced, enriched, and qualified during prospecting.",
|
|
4790
|
+
ownedBySystemId: "sales.lead-gen",
|
|
4791
|
+
table: "acq_list_companies",
|
|
4792
|
+
stateCatalogId: "lead-gen.company",
|
|
4793
|
+
links: [
|
|
4794
|
+
{ toEntity: "leadgen.list", kind: "belongs-to", via: "list_id", label: "list" },
|
|
4795
|
+
{ toEntity: "leadgen.contact", kind: "has-many", via: "company_id", label: "contacts" }
|
|
4796
|
+
]
|
|
4863
4797
|
},
|
|
4864
|
-
|
|
4865
|
-
|
|
4866
|
-
|
|
4867
|
-
label: "
|
|
4868
|
-
description: "
|
|
4869
|
-
|
|
4870
|
-
|
|
4798
|
+
{
|
|
4799
|
+
id: "leadgen.contact",
|
|
4800
|
+
order: 50,
|
|
4801
|
+
label: "Lead Contact",
|
|
4802
|
+
description: "A prospect contact discovered or enriched during lead generation.",
|
|
4803
|
+
ownedBySystemId: "sales.lead-gen",
|
|
4804
|
+
table: "acq_list_members",
|
|
4805
|
+
stateCatalogId: "lead-gen.contact",
|
|
4806
|
+
links: [
|
|
4807
|
+
{ toEntity: "leadgen.list", kind: "belongs-to", via: "list_id", label: "list" },
|
|
4808
|
+
{ toEntity: "leadgen.company", kind: "belongs-to", via: "company_id", label: "company" }
|
|
4809
|
+
]
|
|
4871
4810
|
},
|
|
4872
|
-
|
|
4873
|
-
|
|
4874
|
-
|
|
4875
|
-
label: "
|
|
4876
|
-
description: "
|
|
4877
|
-
|
|
4878
|
-
|
|
4811
|
+
{
|
|
4812
|
+
id: "delivery.project",
|
|
4813
|
+
order: 60,
|
|
4814
|
+
label: "Project",
|
|
4815
|
+
description: "A client delivery project.",
|
|
4816
|
+
ownedBySystemId: "projects",
|
|
4817
|
+
table: "projects",
|
|
4818
|
+
links: [
|
|
4819
|
+
{ toEntity: "delivery.milestone", kind: "has-many", via: "project_id", label: "milestones" },
|
|
4820
|
+
{ toEntity: "delivery.task", kind: "has-many", via: "project_id", label: "tasks" }
|
|
4821
|
+
]
|
|
4879
4822
|
},
|
|
4880
|
-
|
|
4881
|
-
|
|
4882
|
-
|
|
4883
|
-
|
|
4884
|
-
|
|
4885
|
-
|
|
4886
|
-
|
|
4823
|
+
{
|
|
4824
|
+
id: "delivery.milestone",
|
|
4825
|
+
order: 70,
|
|
4826
|
+
label: "Milestone",
|
|
4827
|
+
description: "A delivery checkpoint within a project.",
|
|
4828
|
+
ownedBySystemId: "projects",
|
|
4829
|
+
table: "project_milestones",
|
|
4830
|
+
links: [
|
|
4831
|
+
{ toEntity: "delivery.project", kind: "belongs-to", via: "project_id", label: "project" },
|
|
4832
|
+
{ toEntity: "delivery.task", kind: "has-many", via: "milestone_id", label: "tasks" }
|
|
4833
|
+
]
|
|
4887
4834
|
},
|
|
4888
|
-
|
|
4889
|
-
|
|
4890
|
-
|
|
4891
|
-
|
|
4892
|
-
|
|
4893
|
-
|
|
4835
|
+
{
|
|
4836
|
+
id: "delivery.task",
|
|
4837
|
+
order: 80,
|
|
4838
|
+
label: "Task",
|
|
4839
|
+
description: "A delivery task that can move through the task status catalog.",
|
|
4840
|
+
ownedBySystemId: "projects",
|
|
4841
|
+
table: "project_tasks",
|
|
4842
|
+
stateCatalogId: "delivery.task",
|
|
4843
|
+
links: [
|
|
4844
|
+
{ toEntity: "delivery.project", kind: "belongs-to", via: "project_id", label: "project" },
|
|
4845
|
+
{ toEntity: "delivery.milestone", kind: "belongs-to", via: "milestone_id", label: "milestone" }
|
|
4846
|
+
]
|
|
4894
4847
|
}
|
|
4895
|
-
|
|
4848
|
+
];
|
|
4849
|
+
var DEFAULT_ORGANIZATION_MODEL_ENTITIES = Object.fromEntries(
|
|
4850
|
+
ENTITY_ENTRY_INPUTS.map((entity) => {
|
|
4851
|
+
const parsed = EntitySchema.parse(entity);
|
|
4852
|
+
return [parsed.id, parsed];
|
|
4853
|
+
})
|
|
4854
|
+
);
|
|
4896
4855
|
|
|
4897
|
-
// ../core/src/organization-model/domains/
|
|
4898
|
-
var
|
|
4899
|
-
|
|
4900
|
-
|
|
4856
|
+
// ../core/src/organization-model/domains/actions.ts
|
|
4857
|
+
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");
|
|
4858
|
+
z.enum(["slash-command", "mcp-tool", "api-endpoint", "script-execution"]).meta({ label: "Invocation kind" });
|
|
4859
|
+
var ActionIdSchema = ModelIdSchema;
|
|
4860
|
+
var ActionScopeSchema = z.union([
|
|
4861
|
+
z.literal("global"),
|
|
4862
|
+
z.object({
|
|
4863
|
+
domain: ModelIdSchema
|
|
4864
|
+
})
|
|
4865
|
+
]);
|
|
4866
|
+
var ActionRefSchema = z.object({
|
|
4867
|
+
actionId: ActionIdSchema.meta({ ref: "action" }),
|
|
4868
|
+
intent: z.enum(["exposes", "consumes"]).meta({ label: "Intent" })
|
|
4901
4869
|
});
|
|
4902
|
-
var
|
|
4903
|
-
|
|
4904
|
-
|
|
4905
|
-
|
|
4906
|
-
width: z.union([z.number().positive(), z.string().trim().min(1).max(100)]).optional(),
|
|
4907
|
-
renderType: z.enum(["text", "badge", "datetime", "count", "json"]).optional(),
|
|
4908
|
-
badgeColor: z.string().trim().min(1).max(40).optional()
|
|
4870
|
+
var SlashCommandInvocationSchema = z.object({
|
|
4871
|
+
kind: z.literal("slash-command"),
|
|
4872
|
+
command: z.string().trim().min(1).max(200).regex(/^\/[^\s].*$/, "Slash commands must start with /"),
|
|
4873
|
+
toolFactory: ModelIdSchema.optional()
|
|
4909
4874
|
});
|
|
4910
|
-
var
|
|
4911
|
-
|
|
4912
|
-
|
|
4913
|
-
|
|
4914
|
-
message: "recordColumns must include at least one entity column set"
|
|
4875
|
+
var McpToolInvocationSchema = z.object({
|
|
4876
|
+
kind: z.literal("mcp-tool"),
|
|
4877
|
+
server: ModelIdSchema,
|
|
4878
|
+
name: ModelIdSchema
|
|
4915
4879
|
});
|
|
4916
|
-
var
|
|
4917
|
-
|
|
4918
|
-
|
|
4919
|
-
|
|
4920
|
-
|
|
4921
|
-
|
|
4922
|
-
selectionMode: z.enum(["single", "multiple"]).optional(),
|
|
4923
|
-
inputPath: z.string().trim().min(1).max(500),
|
|
4924
|
-
verifyOnRun: z.boolean().optional()
|
|
4880
|
+
var ApiEndpointInvocationSchema = z.object({
|
|
4881
|
+
kind: z.literal("api-endpoint"),
|
|
4882
|
+
method: z.enum(["GET", "POST", "PATCH", "DELETE"]).meta({ label: "HTTP method" }),
|
|
4883
|
+
path: z.string().trim().startsWith("/").max(500),
|
|
4884
|
+
requestSchema: ModelIdSchema.optional(),
|
|
4885
|
+
responseSchema: ModelIdSchema.optional()
|
|
4925
4886
|
});
|
|
4926
|
-
var
|
|
4927
|
-
|
|
4928
|
-
|
|
4929
|
-
outputs: z.array(z.enum(["company", "contact", "export"])).min(1),
|
|
4930
|
-
stageKey: ModelIdSchema,
|
|
4931
|
-
recordEntity: z.enum(["company", "contact"]).optional(),
|
|
4932
|
-
recordsStageKey: ModelIdSchema.optional(),
|
|
4933
|
-
recordSourceStageKey: ModelIdSchema.optional(),
|
|
4934
|
-
dependsOn: z.array(ModelIdSchema).optional(),
|
|
4935
|
-
dependencyMode: z.literal("per-record-eligibility"),
|
|
4936
|
-
capabilityKey: ModelIdSchema,
|
|
4937
|
-
defaultBatchSize: z.number().int().positive(),
|
|
4938
|
-
maxBatchSize: z.number().int().positive(),
|
|
4939
|
-
recordColumns: RecordColumnsConfigSchema.optional(),
|
|
4940
|
-
credentialRequirements: z.array(CredentialRequirementSchema).optional()
|
|
4941
|
-
}).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
|
|
4942
|
-
message: "defaultBatchSize must be less than or equal to maxBatchSize",
|
|
4943
|
-
path: ["defaultBatchSize"]
|
|
4887
|
+
var ScriptExecutionInvocationSchema = z.object({
|
|
4888
|
+
kind: z.literal("script-execution"),
|
|
4889
|
+
resourceId: ActionResourceIdSchema
|
|
4944
4890
|
});
|
|
4945
|
-
var
|
|
4946
|
-
|
|
4947
|
-
|
|
4891
|
+
var ActionInvocationSchema = z.discriminatedUnion("kind", [
|
|
4892
|
+
SlashCommandInvocationSchema,
|
|
4893
|
+
McpToolInvocationSchema,
|
|
4894
|
+
ApiEndpointInvocationSchema,
|
|
4895
|
+
ScriptExecutionInvocationSchema
|
|
4896
|
+
]);
|
|
4897
|
+
var ActionSchema = z.object({
|
|
4898
|
+
id: ActionIdSchema,
|
|
4899
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
4900
|
+
order: z.number(),
|
|
4901
|
+
label: LabelSchema,
|
|
4902
|
+
description: DescriptionSchema.optional(),
|
|
4903
|
+
scope: ActionScopeSchema.default("global"),
|
|
4904
|
+
resourceId: ActionResourceIdSchema.optional(),
|
|
4905
|
+
affects: z.array(EntityIdSchema.meta({ ref: "entity" })).optional(),
|
|
4906
|
+
invocations: z.array(ActionInvocationSchema).default([]),
|
|
4907
|
+
knowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
|
|
4908
|
+
lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
|
|
4948
4909
|
});
|
|
4949
|
-
var
|
|
4950
|
-
|
|
4951
|
-
|
|
4952
|
-
|
|
4953
|
-
|
|
4954
|
-
|
|
4955
|
-
|
|
4956
|
-
|
|
4957
|
-
|
|
4958
|
-
|
|
4959
|
-
|
|
4960
|
-
|
|
4961
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
4962
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
4963
|
-
{ key: "page-count", label: "Pages", path: "company.enrichmentData.websiteCrawl.pageCount", renderType: "count" },
|
|
4964
|
-
{ key: "crawl-status", label: "Crawl status", path: "processingState.crawled.status", renderType: "badge" }
|
|
4965
|
-
]
|
|
4910
|
+
var ActionsDomainSchema = z.record(z.string(), ActionSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
4911
|
+
message: "Each action entry id must match its map key"
|
|
4912
|
+
}).default({});
|
|
4913
|
+
var LEAD_GEN_ACTION_ENTRY_INPUTS = [
|
|
4914
|
+
{
|
|
4915
|
+
id: "lead-gen.company.source",
|
|
4916
|
+
order: 10,
|
|
4917
|
+
label: "Source companies",
|
|
4918
|
+
description: "Import source companies from a list provider.",
|
|
4919
|
+
scope: { domain: "sales" },
|
|
4920
|
+
resourceId: "lgn-import-workflow",
|
|
4921
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/source" }]
|
|
4966
4922
|
},
|
|
4967
|
-
|
|
4968
|
-
|
|
4969
|
-
|
|
4970
|
-
|
|
4971
|
-
|
|
4972
|
-
|
|
4973
|
-
|
|
4974
|
-
|
|
4975
|
-
]
|
|
4976
|
-
},
|
|
4977
|
-
qualified: {
|
|
4978
|
-
company: [
|
|
4979
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
4980
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
4981
|
-
{ key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
|
|
4982
|
-
{ key: "signals", label: "Signals", path: "company.qualificationSignals", renderType: "json" },
|
|
4983
|
-
{ key: "disqualified-reason", label: "Disqualified reason", path: "processingState.qualified.data.disqualifiedReason" }
|
|
4984
|
-
]
|
|
4985
|
-
},
|
|
4986
|
-
decisionMakers: {
|
|
4987
|
-
contact: [
|
|
4988
|
-
{ key: "name", label: "Name", path: "contact.name" },
|
|
4989
|
-
{ key: "title", label: "Title", path: "contact.title" },
|
|
4990
|
-
{ key: "email", label: "Email", path: "contact.email" },
|
|
4991
|
-
{ key: "linkedin", label: "LinkedIn", path: "contact.linkedinUrl" },
|
|
4992
|
-
{ key: "priority-score", label: "Priority", path: "contact.enrichmentData.apollo.priorityScore", renderType: "badge" }
|
|
4993
|
-
]
|
|
4994
|
-
},
|
|
4995
|
-
uploaded: {
|
|
4996
|
-
company: [
|
|
4997
|
-
{ key: "name", label: "Company", path: "company.name" },
|
|
4998
|
-
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
4999
|
-
{ key: "contacts", label: "Contacts", path: "company.enrichmentData.approvedLeadListExport.contacts", renderType: "json" },
|
|
5000
|
-
{ key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
|
|
5001
|
-
{ key: "approval", label: "Approval", path: "company.enrichmentData.approvedLeadListExport.approvalStatus", renderType: "badge" }
|
|
5002
|
-
]
|
|
5003
|
-
}
|
|
5004
|
-
};
|
|
5005
|
-
z.object({
|
|
5006
|
-
id: ModelIdSchema,
|
|
5007
|
-
label: z.string(),
|
|
5008
|
-
description: z.string(),
|
|
5009
|
-
resourceId: ModelIdSchema
|
|
5010
|
-
});
|
|
5011
|
-
var CAPABILITY_REGISTRY = [
|
|
5012
|
-
{
|
|
5013
|
-
id: "lead-gen.company.source",
|
|
5014
|
-
label: "Source companies",
|
|
5015
|
-
description: "Import source companies from a list provider.",
|
|
5016
|
-
resourceId: "lgn-import-workflow"
|
|
5017
|
-
},
|
|
5018
|
-
{
|
|
5019
|
-
id: "lead-gen.company.apollo-import",
|
|
5020
|
-
label: "Import from Apollo",
|
|
5021
|
-
description: "Pull companies and seed contact data from an Apollo search or list.",
|
|
5022
|
-
resourceId: "lgn-01c-apollo-import-workflow"
|
|
4923
|
+
{
|
|
4924
|
+
id: "lead-gen.company.apollo-import",
|
|
4925
|
+
order: 20,
|
|
4926
|
+
label: "Import from Apollo",
|
|
4927
|
+
description: "Pull companies and seed contact data from an Apollo search or list.",
|
|
4928
|
+
scope: { domain: "sales" },
|
|
4929
|
+
resourceId: "lgn-01c-apollo-import-workflow",
|
|
4930
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/apollo-import" }]
|
|
5023
4931
|
},
|
|
5024
4932
|
{
|
|
5025
4933
|
id: "lead-gen.contact.discover",
|
|
4934
|
+
order: 30,
|
|
5026
4935
|
label: "Discover contact emails",
|
|
5027
4936
|
description: "Find email addresses for contacts at qualified companies.",
|
|
5028
|
-
|
|
4937
|
+
scope: { domain: "sales" },
|
|
4938
|
+
resourceId: "lgn-04-email-discovery-workflow",
|
|
4939
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/discover" }]
|
|
5029
4940
|
},
|
|
5030
4941
|
{
|
|
5031
4942
|
id: "lead-gen.contact.verify-email",
|
|
4943
|
+
order: 40,
|
|
5032
4944
|
label: "Verify emails",
|
|
5033
4945
|
description: "Check email deliverability before outreach.",
|
|
5034
|
-
|
|
4946
|
+
scope: { domain: "sales" },
|
|
4947
|
+
resourceId: "lgn-05-email-verification-workflow",
|
|
4948
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/verify-email" }]
|
|
5035
4949
|
},
|
|
5036
4950
|
{
|
|
5037
4951
|
id: "lead-gen.company.apify-crawl",
|
|
4952
|
+
order: 50,
|
|
5038
4953
|
label: "Crawl websites",
|
|
5039
4954
|
description: "Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis.",
|
|
5040
|
-
|
|
4955
|
+
scope: { domain: "sales" },
|
|
4956
|
+
resourceId: "lgn-02a-apify-website-crawl-workflow",
|
|
4957
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/apify-crawl" }]
|
|
5041
4958
|
},
|
|
5042
4959
|
{
|
|
5043
4960
|
id: "lead-gen.company.website-extract",
|
|
4961
|
+
order: 60,
|
|
5044
4962
|
label: "Extract website signals",
|
|
5045
4963
|
description: "Scrape and analyze company websites for qualification signals.",
|
|
5046
|
-
|
|
4964
|
+
scope: { domain: "sales" },
|
|
4965
|
+
resourceId: "lgn-02-website-extract-workflow",
|
|
4966
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/website-extract" }]
|
|
5047
4967
|
},
|
|
5048
4968
|
{
|
|
5049
4969
|
id: "lead-gen.company.qualify",
|
|
4970
|
+
order: 70,
|
|
5050
4971
|
label: "Qualify companies",
|
|
5051
4972
|
description: "Score and filter companies against the ICP rubric.",
|
|
5052
|
-
|
|
4973
|
+
scope: { domain: "sales" },
|
|
4974
|
+
resourceId: "lgn-03-company-qualification-workflow",
|
|
4975
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/qualify" }]
|
|
5053
4976
|
},
|
|
5054
4977
|
{
|
|
5055
4978
|
id: "lead-gen.company.dtc-subscription-qualify",
|
|
4979
|
+
order: 80,
|
|
5056
4980
|
label: "Qualify DTC subscription fit",
|
|
5057
4981
|
description: "Classify subscription potential and consumable-product fit for DTC brands.",
|
|
5058
|
-
|
|
4982
|
+
scope: { domain: "sales" },
|
|
4983
|
+
resourceId: "lgn-03b-dtc-subscription-score-workflow",
|
|
4984
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/dtc-subscription-qualify" }]
|
|
5059
4985
|
},
|
|
5060
4986
|
{
|
|
5061
4987
|
id: "lead-gen.contact.apollo-decision-maker-enrich",
|
|
4988
|
+
order: 90,
|
|
5062
4989
|
label: "Enrich decision-makers",
|
|
5063
4990
|
description: "Find and enrich qualified contacts at qualified companies via Apollo.",
|
|
5064
|
-
|
|
4991
|
+
scope: { domain: "sales" },
|
|
4992
|
+
resourceId: "lgn-04b-apollo-decision-maker-enrich-workflow",
|
|
4993
|
+
invocations: [
|
|
4994
|
+
{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/apollo-decision-maker-enrich" }
|
|
4995
|
+
]
|
|
5065
4996
|
},
|
|
5066
4997
|
{
|
|
5067
4998
|
id: "lead-gen.contact.personalize",
|
|
4999
|
+
order: 100,
|
|
5068
5000
|
label: "Personalize outreach",
|
|
5069
5001
|
description: "Generate personalized opening lines for each contact.",
|
|
5070
|
-
|
|
5002
|
+
scope: { domain: "sales" },
|
|
5003
|
+
resourceId: "ist-personalization-workflow",
|
|
5004
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/contacts/personalize" }]
|
|
5071
5005
|
},
|
|
5072
5006
|
{
|
|
5073
5007
|
id: "lead-gen.review.outreach-ready",
|
|
5008
|
+
order: 110,
|
|
5074
5009
|
label: "Upload to outreach",
|
|
5075
5010
|
description: "Upload approved contacts to the outreach sequence after QC review.",
|
|
5076
|
-
|
|
5011
|
+
scope: { domain: "sales" },
|
|
5012
|
+
resourceId: "ist-upload-contacts-workflow",
|
|
5013
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/review/outreach-ready" }]
|
|
5077
5014
|
},
|
|
5078
5015
|
{
|
|
5079
5016
|
id: "lead-gen.export.list",
|
|
5017
|
+
order: 120,
|
|
5080
5018
|
label: "Export lead list",
|
|
5081
5019
|
description: "Export approved leads as a downloadable lead list.",
|
|
5082
|
-
|
|
5020
|
+
scope: { domain: "sales" },
|
|
5021
|
+
resourceId: "lgn-06-export-list-workflow",
|
|
5022
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/export/list" }]
|
|
5083
5023
|
},
|
|
5084
5024
|
{
|
|
5085
5025
|
id: "lead-gen.company.cleanup",
|
|
5026
|
+
order: 130,
|
|
5086
5027
|
label: "Clean up companies",
|
|
5087
5028
|
description: "Remove disqualified or duplicate companies from the list.",
|
|
5088
|
-
|
|
5029
|
+
scope: { domain: "sales" },
|
|
5030
|
+
resourceId: "lgn-company-cleanup-workflow",
|
|
5031
|
+
invocations: [{ kind: "api-endpoint", method: "POST", path: "/api/prospecting/companies/cleanup" }]
|
|
5032
|
+
}
|
|
5033
|
+
];
|
|
5034
|
+
var LEAD_GEN_ACTION_ENTRIES = Object.fromEntries(
|
|
5035
|
+
LEAD_GEN_ACTION_ENTRY_INPUTS.map((action) => {
|
|
5036
|
+
const parsed = ActionSchema.parse(action);
|
|
5037
|
+
return [parsed.id, parsed];
|
|
5038
|
+
})
|
|
5039
|
+
);
|
|
5040
|
+
var CRM_ACTION_ENTRY_INPUTS = [
|
|
5041
|
+
{
|
|
5042
|
+
id: "send_reply",
|
|
5043
|
+
order: 210,
|
|
5044
|
+
label: "Send Reply",
|
|
5045
|
+
description: "Send a contextual reply for an active CRM deal.",
|
|
5046
|
+
scope: { domain: "sales" },
|
|
5047
|
+
resourceId: "crm-send-reply-workflow",
|
|
5048
|
+
affects: ["crm.deal"]
|
|
5049
|
+
},
|
|
5050
|
+
{
|
|
5051
|
+
id: "send_link",
|
|
5052
|
+
order: 220,
|
|
5053
|
+
label: "Send Booking Link",
|
|
5054
|
+
description: "Send a booking link to move a deal toward a scheduled call.",
|
|
5055
|
+
scope: { domain: "sales" },
|
|
5056
|
+
resourceId: "crm-send-booking-link-workflow",
|
|
5057
|
+
affects: ["crm.deal"]
|
|
5058
|
+
},
|
|
5059
|
+
{
|
|
5060
|
+
id: "send_nudge",
|
|
5061
|
+
order: 230,
|
|
5062
|
+
label: "Send Nudge",
|
|
5063
|
+
description: "Send a follow-up nudge for a stalled CRM deal.",
|
|
5064
|
+
scope: { domain: "sales" },
|
|
5065
|
+
resourceId: "crm-send-nudge-workflow",
|
|
5066
|
+
affects: ["crm.deal"]
|
|
5067
|
+
},
|
|
5068
|
+
{
|
|
5069
|
+
id: "rebook",
|
|
5070
|
+
order: 240,
|
|
5071
|
+
label: "Rebook",
|
|
5072
|
+
description: "Rebook a missed or rescheduled CRM appointment.",
|
|
5073
|
+
scope: { domain: "sales" },
|
|
5074
|
+
resourceId: "crm-rebook-workflow",
|
|
5075
|
+
affects: ["crm.deal"]
|
|
5076
|
+
},
|
|
5077
|
+
{
|
|
5078
|
+
id: "move_to_proposal",
|
|
5079
|
+
order: 250,
|
|
5080
|
+
label: "Move to Proposal",
|
|
5081
|
+
description: "Advance a qualified CRM deal into the proposal stage.",
|
|
5082
|
+
scope: { domain: "sales" },
|
|
5083
|
+
resourceId: "move_to_proposal-workflow",
|
|
5084
|
+
affects: ["crm.deal"]
|
|
5085
|
+
},
|
|
5086
|
+
{
|
|
5087
|
+
id: "move_to_closing",
|
|
5088
|
+
order: 260,
|
|
5089
|
+
label: "Move to Closing",
|
|
5090
|
+
description: "Advance a proposal-stage CRM deal into closing.",
|
|
5091
|
+
scope: { domain: "sales" },
|
|
5092
|
+
resourceId: "move_to_closing-workflow",
|
|
5093
|
+
affects: ["crm.deal"]
|
|
5094
|
+
},
|
|
5095
|
+
{
|
|
5096
|
+
id: "move_to_closed_won",
|
|
5097
|
+
order: 270,
|
|
5098
|
+
label: "Close Won",
|
|
5099
|
+
description: "Mark a CRM deal as closed won.",
|
|
5100
|
+
scope: { domain: "sales" },
|
|
5101
|
+
resourceId: "move_to_closed_won-workflow",
|
|
5102
|
+
affects: ["crm.deal"]
|
|
5103
|
+
},
|
|
5104
|
+
{
|
|
5105
|
+
id: "move_to_closed_lost",
|
|
5106
|
+
order: 280,
|
|
5107
|
+
label: "Close Lost",
|
|
5108
|
+
description: "Mark a CRM deal as closed lost.",
|
|
5109
|
+
scope: { domain: "sales" },
|
|
5110
|
+
resourceId: "move_to_closed_lost-workflow",
|
|
5111
|
+
affects: ["crm.deal"]
|
|
5112
|
+
},
|
|
5113
|
+
{
|
|
5114
|
+
id: "move_to_nurturing",
|
|
5115
|
+
order: 290,
|
|
5116
|
+
label: "Move to Nurturing",
|
|
5117
|
+
description: "Move a CRM deal into nurturing for future follow-up.",
|
|
5118
|
+
scope: { domain: "sales" },
|
|
5119
|
+
resourceId: "move_to_nurturing-workflow",
|
|
5120
|
+
affects: ["crm.deal"]
|
|
5089
5121
|
}
|
|
5090
5122
|
];
|
|
5123
|
+
var CRM_ACTION_ENTRIES = Object.fromEntries(
|
|
5124
|
+
CRM_ACTION_ENTRY_INPUTS.map((action) => {
|
|
5125
|
+
const parsed = ActionSchema.parse(action);
|
|
5126
|
+
return [parsed.id, parsed];
|
|
5127
|
+
})
|
|
5128
|
+
);
|
|
5129
|
+
var DEFAULT_ORGANIZATION_MODEL_ACTIONS = {
|
|
5130
|
+
...LEAD_GEN_ACTION_ENTRIES,
|
|
5131
|
+
...CRM_ACTION_ENTRIES
|
|
5132
|
+
};
|
|
5133
|
+
|
|
5134
|
+
// ../core/src/organization-model/domains/prospecting.ts
|
|
5135
|
+
DisplayMetadataSchema.extend({
|
|
5136
|
+
id: ModelIdSchema,
|
|
5137
|
+
order: z.number().min(0)
|
|
5138
|
+
});
|
|
5139
|
+
var RecordColumnConfigSchema = z.object({
|
|
5140
|
+
key: ModelIdSchema,
|
|
5141
|
+
label: z.string().trim().min(1).max(120),
|
|
5142
|
+
path: z.string().trim().min(1).max(500),
|
|
5143
|
+
width: z.union([z.number().positive(), z.string().trim().min(1).max(100)]).optional(),
|
|
5144
|
+
renderType: z.enum(["text", "badge", "datetime", "count", "json"]).optional(),
|
|
5145
|
+
badgeColor: z.string().trim().min(1).max(40).optional()
|
|
5146
|
+
});
|
|
5147
|
+
var RecordColumnsConfigSchema = z.object({
|
|
5148
|
+
company: z.array(RecordColumnConfigSchema).optional(),
|
|
5149
|
+
contact: z.array(RecordColumnConfigSchema).optional()
|
|
5150
|
+
}).refine((columns) => Boolean(columns.company?.length || columns.contact?.length), {
|
|
5151
|
+
message: "recordColumns must include at least one entity column set"
|
|
5152
|
+
});
|
|
5153
|
+
var CredentialRequirementSchema = z.object({
|
|
5154
|
+
key: ModelIdSchema,
|
|
5155
|
+
provider: ModelIdSchema,
|
|
5156
|
+
credentialType: z.enum(["api-key", "api-key-secret", "oauth", "webhook-secret"]),
|
|
5157
|
+
label: z.string().trim().min(1).max(120),
|
|
5158
|
+
required: z.boolean(),
|
|
5159
|
+
selectionMode: z.enum(["single", "multiple"]).optional(),
|
|
5160
|
+
inputPath: z.string().trim().min(1).max(500),
|
|
5161
|
+
verifyOnRun: z.boolean().optional()
|
|
5162
|
+
});
|
|
5163
|
+
var ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
|
|
5164
|
+
id: ModelIdSchema,
|
|
5165
|
+
primaryEntity: z.enum(["company", "contact"]),
|
|
5166
|
+
outputs: z.array(z.enum(["company", "contact", "export"])).min(1),
|
|
5167
|
+
stageKey: ModelIdSchema,
|
|
5168
|
+
recordEntity: z.enum(["company", "contact"]).optional(),
|
|
5169
|
+
recordsStageKey: ModelIdSchema.optional(),
|
|
5170
|
+
recordSourceStageKey: ModelIdSchema.optional(),
|
|
5171
|
+
dependsOn: z.array(ModelIdSchema).optional(),
|
|
5172
|
+
dependencyMode: z.literal("per-record-eligibility"),
|
|
5173
|
+
actionKey: ModelIdSchema,
|
|
5174
|
+
defaultBatchSize: z.number().int().positive(),
|
|
5175
|
+
maxBatchSize: z.number().int().positive(),
|
|
5176
|
+
recordColumns: RecordColumnsConfigSchema.optional(),
|
|
5177
|
+
credentialRequirements: z.array(CredentialRequirementSchema).optional()
|
|
5178
|
+
}).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
|
|
5179
|
+
message: "defaultBatchSize must be less than or equal to maxBatchSize",
|
|
5180
|
+
path: ["defaultBatchSize"]
|
|
5181
|
+
});
|
|
5182
|
+
DisplayMetadataSchema.extend({
|
|
5183
|
+
id: ModelIdSchema,
|
|
5184
|
+
steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
|
|
5185
|
+
});
|
|
5186
|
+
var DTC_RECORD_COLUMNS = {
|
|
5187
|
+
populated: {
|
|
5188
|
+
company: [
|
|
5189
|
+
{ key: "name", label: "Company", path: "company.name" },
|
|
5190
|
+
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
5191
|
+
{ key: "employee-count", label: "Employees", path: "company.numEmployees", renderType: "count" },
|
|
5192
|
+
{ key: "apollo-industry", label: "Apollo industry", path: "company.category" },
|
|
5193
|
+
{ key: "location", label: "Location", path: "company.locationState" }
|
|
5194
|
+
]
|
|
5195
|
+
},
|
|
5196
|
+
crawled: {
|
|
5197
|
+
company: [
|
|
5198
|
+
{ key: "name", label: "Company", path: "company.name" },
|
|
5199
|
+
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
5200
|
+
{ key: "page-count", label: "Pages", path: "company.enrichmentData.websiteCrawl.pageCount", renderType: "count" },
|
|
5201
|
+
{ key: "crawl-status", label: "Crawl status", path: "processingState.crawled.status", renderType: "badge" }
|
|
5202
|
+
]
|
|
5203
|
+
},
|
|
5204
|
+
extracted: {
|
|
5205
|
+
company: [
|
|
5206
|
+
{ key: "name", label: "Company", path: "company.name" },
|
|
5207
|
+
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
5208
|
+
{ key: "description", label: "Description", path: "company.enrichmentData.websiteCrawl.companyDescription" },
|
|
5209
|
+
{ key: "services", label: "Services", path: "company.enrichmentData.websiteCrawl.services", renderType: "json" },
|
|
5210
|
+
{
|
|
5211
|
+
key: "automation-gaps",
|
|
5212
|
+
label: "Automation gaps",
|
|
5213
|
+
path: "company.enrichmentData.websiteCrawl.automationGaps",
|
|
5214
|
+
renderType: "json"
|
|
5215
|
+
},
|
|
5216
|
+
{
|
|
5217
|
+
key: "contact-count",
|
|
5218
|
+
label: "Contacts",
|
|
5219
|
+
path: "company.enrichmentData.websiteCrawl.emailCount",
|
|
5220
|
+
renderType: "count"
|
|
5221
|
+
}
|
|
5222
|
+
]
|
|
5223
|
+
},
|
|
5224
|
+
qualified: {
|
|
5225
|
+
company: [
|
|
5226
|
+
{ key: "name", label: "Company", path: "company.name" },
|
|
5227
|
+
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
5228
|
+
{ key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
|
|
5229
|
+
{ key: "signals", label: "Signals", path: "company.qualificationSignals", renderType: "json" },
|
|
5230
|
+
{
|
|
5231
|
+
key: "disqualified-reason",
|
|
5232
|
+
label: "Disqualified reason",
|
|
5233
|
+
path: "processingState.qualified.data.disqualifiedReason"
|
|
5234
|
+
}
|
|
5235
|
+
]
|
|
5236
|
+
},
|
|
5237
|
+
decisionMakers: {
|
|
5238
|
+
contact: [
|
|
5239
|
+
{ key: "name", label: "Name", path: "contact.name" },
|
|
5240
|
+
{ key: "title", label: "Title", path: "contact.title" },
|
|
5241
|
+
{ key: "email", label: "Email", path: "contact.email" },
|
|
5242
|
+
{ key: "linkedin", label: "LinkedIn", path: "contact.linkedinUrl" },
|
|
5243
|
+
{
|
|
5244
|
+
key: "priority-score",
|
|
5245
|
+
label: "Priority",
|
|
5246
|
+
path: "contact.enrichmentData.apollo.priorityScore",
|
|
5247
|
+
renderType: "badge"
|
|
5248
|
+
}
|
|
5249
|
+
]
|
|
5250
|
+
},
|
|
5251
|
+
uploaded: {
|
|
5252
|
+
company: [
|
|
5253
|
+
{ key: "name", label: "Company", path: "company.name" },
|
|
5254
|
+
{ key: "domain", label: "Domain", path: "company.domain" },
|
|
5255
|
+
{
|
|
5256
|
+
key: "contacts",
|
|
5257
|
+
label: "Contacts",
|
|
5258
|
+
path: "company.enrichmentData.approvedLeadListExport.contacts",
|
|
5259
|
+
renderType: "json"
|
|
5260
|
+
},
|
|
5261
|
+
{ key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
|
|
5262
|
+
{
|
|
5263
|
+
key: "approval",
|
|
5264
|
+
label: "Approval",
|
|
5265
|
+
path: "company.enrichmentData.approvedLeadListExport.approvalStatus",
|
|
5266
|
+
renderType: "badge"
|
|
5267
|
+
}
|
|
5268
|
+
]
|
|
5269
|
+
}
|
|
5270
|
+
};
|
|
5271
|
+
Object.values(LEAD_GEN_ACTION_ENTRIES);
|
|
5091
5272
|
var PROSPECTING_STEPS = {
|
|
5092
5273
|
localServices: {
|
|
5093
5274
|
sourceCompanies: {
|
|
@@ -5097,7 +5278,7 @@ var PROSPECTING_STEPS = {
|
|
|
5097
5278
|
outputs: ["company"],
|
|
5098
5279
|
stageKey: "populated",
|
|
5099
5280
|
dependencyMode: "per-record-eligibility",
|
|
5100
|
-
|
|
5281
|
+
actionKey: "lead-gen.company.source",
|
|
5101
5282
|
defaultBatchSize: 100,
|
|
5102
5283
|
maxBatchSize: 250
|
|
5103
5284
|
},
|
|
@@ -5109,7 +5290,7 @@ var PROSPECTING_STEPS = {
|
|
|
5109
5290
|
stageKey: "extracted",
|
|
5110
5291
|
dependsOn: ["source-companies"],
|
|
5111
5292
|
dependencyMode: "per-record-eligibility",
|
|
5112
|
-
|
|
5293
|
+
actionKey: "lead-gen.company.website-extract",
|
|
5113
5294
|
defaultBatchSize: 50,
|
|
5114
5295
|
maxBatchSize: 100
|
|
5115
5296
|
},
|
|
@@ -5121,7 +5302,7 @@ var PROSPECTING_STEPS = {
|
|
|
5121
5302
|
stageKey: "qualified",
|
|
5122
5303
|
dependsOn: ["analyze-websites"],
|
|
5123
5304
|
dependencyMode: "per-record-eligibility",
|
|
5124
|
-
|
|
5305
|
+
actionKey: "lead-gen.company.qualify",
|
|
5125
5306
|
defaultBatchSize: 100,
|
|
5126
5307
|
maxBatchSize: 250
|
|
5127
5308
|
},
|
|
@@ -5133,7 +5314,7 @@ var PROSPECTING_STEPS = {
|
|
|
5133
5314
|
stageKey: "discovered",
|
|
5134
5315
|
dependsOn: ["qualify-companies"],
|
|
5135
5316
|
dependencyMode: "per-record-eligibility",
|
|
5136
|
-
|
|
5317
|
+
actionKey: "lead-gen.contact.discover",
|
|
5137
5318
|
defaultBatchSize: 50,
|
|
5138
5319
|
maxBatchSize: 100
|
|
5139
5320
|
},
|
|
@@ -5145,7 +5326,7 @@ var PROSPECTING_STEPS = {
|
|
|
5145
5326
|
stageKey: "verified",
|
|
5146
5327
|
dependsOn: ["find-contacts"],
|
|
5147
5328
|
dependencyMode: "per-record-eligibility",
|
|
5148
|
-
|
|
5329
|
+
actionKey: "lead-gen.contact.verify-email",
|
|
5149
5330
|
defaultBatchSize: 100,
|
|
5150
5331
|
maxBatchSize: 500
|
|
5151
5332
|
},
|
|
@@ -5157,7 +5338,7 @@ var PROSPECTING_STEPS = {
|
|
|
5157
5338
|
stageKey: "personalized",
|
|
5158
5339
|
dependsOn: ["verify-emails"],
|
|
5159
5340
|
dependencyMode: "per-record-eligibility",
|
|
5160
|
-
|
|
5341
|
+
actionKey: "lead-gen.contact.personalize",
|
|
5161
5342
|
defaultBatchSize: 25,
|
|
5162
5343
|
maxBatchSize: 100
|
|
5163
5344
|
},
|
|
@@ -5169,7 +5350,7 @@ var PROSPECTING_STEPS = {
|
|
|
5169
5350
|
stageKey: "uploaded",
|
|
5170
5351
|
dependsOn: ["personalize"],
|
|
5171
5352
|
dependencyMode: "per-record-eligibility",
|
|
5172
|
-
|
|
5353
|
+
actionKey: "lead-gen.review.outreach-ready",
|
|
5173
5354
|
defaultBatchSize: 25,
|
|
5174
5355
|
maxBatchSize: 100
|
|
5175
5356
|
}
|
|
@@ -5183,7 +5364,7 @@ var PROSPECTING_STEPS = {
|
|
|
5183
5364
|
outputs: ["company", "contact"],
|
|
5184
5365
|
stageKey: "populated",
|
|
5185
5366
|
dependencyMode: "per-record-eligibility",
|
|
5186
|
-
|
|
5367
|
+
actionKey: "lead-gen.company.apollo-import",
|
|
5187
5368
|
defaultBatchSize: 250,
|
|
5188
5369
|
maxBatchSize: 1e3,
|
|
5189
5370
|
recordColumns: DTC_RECORD_COLUMNS.populated,
|
|
@@ -5208,7 +5389,7 @@ var PROSPECTING_STEPS = {
|
|
|
5208
5389
|
stageKey: "crawled",
|
|
5209
5390
|
dependsOn: ["import-apollo-search"],
|
|
5210
5391
|
dependencyMode: "per-record-eligibility",
|
|
5211
|
-
|
|
5392
|
+
actionKey: "lead-gen.company.apify-crawl",
|
|
5212
5393
|
defaultBatchSize: 50,
|
|
5213
5394
|
maxBatchSize: 100,
|
|
5214
5395
|
recordColumns: DTC_RECORD_COLUMNS.crawled,
|
|
@@ -5234,7 +5415,7 @@ var PROSPECTING_STEPS = {
|
|
|
5234
5415
|
stageKey: "extracted",
|
|
5235
5416
|
dependsOn: ["apify-crawl"],
|
|
5236
5417
|
dependencyMode: "per-record-eligibility",
|
|
5237
|
-
|
|
5418
|
+
actionKey: "lead-gen.company.website-extract",
|
|
5238
5419
|
defaultBatchSize: 50,
|
|
5239
5420
|
maxBatchSize: 100,
|
|
5240
5421
|
recordColumns: DTC_RECORD_COLUMNS.extracted
|
|
@@ -5248,7 +5429,7 @@ var PROSPECTING_STEPS = {
|
|
|
5248
5429
|
stageKey: "qualified",
|
|
5249
5430
|
dependsOn: ["analyze-websites"],
|
|
5250
5431
|
dependencyMode: "per-record-eligibility",
|
|
5251
|
-
|
|
5432
|
+
actionKey: "lead-gen.company.dtc-subscription-qualify",
|
|
5252
5433
|
defaultBatchSize: 100,
|
|
5253
5434
|
maxBatchSize: 250,
|
|
5254
5435
|
recordColumns: DTC_RECORD_COLUMNS.qualified
|
|
@@ -5263,7 +5444,7 @@ var PROSPECTING_STEPS = {
|
|
|
5263
5444
|
recordEntity: "contact",
|
|
5264
5445
|
dependsOn: ["score-dtc-fit"],
|
|
5265
5446
|
dependencyMode: "per-record-eligibility",
|
|
5266
|
-
|
|
5447
|
+
actionKey: "lead-gen.contact.apollo-decision-maker-enrich",
|
|
5267
5448
|
defaultBatchSize: 100,
|
|
5268
5449
|
maxBatchSize: 250,
|
|
5269
5450
|
recordColumns: DTC_RECORD_COLUMNS.decisionMakers,
|
|
@@ -5290,7 +5471,7 @@ var PROSPECTING_STEPS = {
|
|
|
5290
5471
|
recordSourceStageKey: "qualified",
|
|
5291
5472
|
dependsOn: ["enrich-decision-makers"],
|
|
5292
5473
|
dependencyMode: "per-record-eligibility",
|
|
5293
|
-
|
|
5474
|
+
actionKey: "lead-gen.export.list",
|
|
5294
5475
|
defaultBatchSize: 100,
|
|
5295
5476
|
maxBatchSize: 250,
|
|
5296
5477
|
recordColumns: DTC_RECORD_COLUMNS.uploaded,
|
|
@@ -5309,80 +5490,3075 @@ var PROSPECTING_STEPS = {
|
|
|
5309
5490
|
}
|
|
5310
5491
|
}
|
|
5311
5492
|
};
|
|
5312
|
-
z.object({
|
|
5313
|
-
listEntityId: ModelIdSchema,
|
|
5314
|
-
companyEntityId: ModelIdSchema,
|
|
5315
|
-
contactEntityId: ModelIdSchema,
|
|
5316
|
-
description: DescriptionSchema.optional(),
|
|
5317
|
-
companyStages: z.array(ProspectingLifecycleStageSchema).min(1),
|
|
5318
|
-
contactStages: z.array(ProspectingLifecycleStageSchema).min(1),
|
|
5319
|
-
defaultBuildTemplateId: ModelIdSchema,
|
|
5320
|
-
buildTemplates: z.array(ProspectingBuildTemplateSchema).min(1)
|
|
5321
|
-
});
|
|
5322
|
-
function toProspectingLifecycleStage(stage) {
|
|
5323
|
-
return {
|
|
5324
|
-
id: stage.key,
|
|
5325
|
-
label: stage.label,
|
|
5326
|
-
order: stage.order
|
|
5327
|
-
};
|
|
5328
|
-
}
|
|
5329
|
-
function leadGenStagesForEntity(entity) {
|
|
5330
|
-
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);
|
|
5331
|
-
}
|
|
5332
|
-
var DEFAULT_ORGANIZATION_MODEL_PROSPECTING = {
|
|
5333
|
-
companyStages: leadGenStagesForEntity("company"),
|
|
5334
|
-
contactStages: leadGenStagesForEntity("contact"),
|
|
5335
|
-
buildTemplates: [
|
|
5336
|
-
{
|
|
5337
|
-
id: "local-services",
|
|
5338
|
-
label: "Local Services Prospecting",
|
|
5339
|
-
description: "Curated local-services list build using company sourcing, website analysis, qualification, contact discovery, verification, personalization, and review.",
|
|
5340
|
-
steps: [
|
|
5341
|
-
PROSPECTING_STEPS.localServices.sourceCompanies,
|
|
5342
|
-
PROSPECTING_STEPS.localServices.analyzeWebsites,
|
|
5343
|
-
PROSPECTING_STEPS.localServices.qualifyCompanies,
|
|
5344
|
-
PROSPECTING_STEPS.localServices.findContacts,
|
|
5345
|
-
PROSPECTING_STEPS.localServices.verifyEmails,
|
|
5346
|
-
PROSPECTING_STEPS.localServices.personalize,
|
|
5347
|
-
PROSPECTING_STEPS.localServices.review
|
|
5348
|
-
]
|
|
5349
|
-
},
|
|
5350
|
-
{
|
|
5351
|
-
id: "dtc-subscription-apollo-clickup",
|
|
5352
|
-
label: "DTC Subscription Apollo Export",
|
|
5353
|
-
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.",
|
|
5354
|
-
steps: [
|
|
5355
|
-
PROSPECTING_STEPS.dtcApolloClickup.importApolloSearch,
|
|
5356
|
-
PROSPECTING_STEPS.dtcApolloClickup.apifyCrawl,
|
|
5357
|
-
PROSPECTING_STEPS.dtcApolloClickup.analyzeWebsites,
|
|
5358
|
-
PROSPECTING_STEPS.dtcApolloClickup.scoreDtcFit,
|
|
5359
|
-
PROSPECTING_STEPS.dtcApolloClickup.enrichDecisionMakers,
|
|
5360
|
-
PROSPECTING_STEPS.dtcApolloClickup.reviewAndExport
|
|
5361
|
-
]
|
|
5362
|
-
}
|
|
5363
|
-
]
|
|
5364
|
-
};
|
|
5365
5493
|
|
|
5366
5494
|
// ../core/src/business/acquisition/build-templates.ts
|
|
5367
|
-
var
|
|
5368
|
-
|
|
5369
|
-
id,
|
|
5370
|
-
label,
|
|
5371
|
-
description
|
|
5372
|
-
|
|
5373
|
-
|
|
5495
|
+
var BUILD_TEMPLATE_CATALOG = [
|
|
5496
|
+
{
|
|
5497
|
+
id: "local-services",
|
|
5498
|
+
label: "Local Services",
|
|
5499
|
+
description: "Source, analyze, qualify, and personalize local service businesses for outreach.",
|
|
5500
|
+
steps: Object.values(PROSPECTING_STEPS.localServices)
|
|
5501
|
+
},
|
|
5502
|
+
{
|
|
5503
|
+
id: "dtc-subscription-apollo-clickup",
|
|
5504
|
+
label: "DTC Subscription (Apollo + ClickUp)",
|
|
5505
|
+
description: "Import DTC brand leads from Apollo, crawl their websites, score fit, enrich contacts, and export via ClickUp.",
|
|
5506
|
+
steps: Object.values(PROSPECTING_STEPS.dtcApolloClickup)
|
|
5507
|
+
}
|
|
5508
|
+
];
|
|
5509
|
+
var PROSPECTING_BUILD_TEMPLATE_OPTIONS = BUILD_TEMPLATE_CATALOG.map(({ id, label, description }) => ({
|
|
5510
|
+
id,
|
|
5511
|
+
label,
|
|
5512
|
+
description
|
|
5513
|
+
}));
|
|
5374
5514
|
function isProspectingBuildTemplateId(value) {
|
|
5375
5515
|
return PROSPECTING_BUILD_TEMPLATE_OPTIONS.some((template) => template.id === value);
|
|
5376
5516
|
}
|
|
5517
|
+
|
|
5518
|
+
// ../core/src/organization-model/catalogs/lead-gen.ts
|
|
5519
|
+
var LEAD_GEN_STAGE_CATALOG = {
|
|
5520
|
+
// Prospecting - company population
|
|
5521
|
+
scraped: {
|
|
5522
|
+
key: "scraped",
|
|
5523
|
+
label: "Scraped",
|
|
5524
|
+
description: "Company was scraped from a source directory (Apify actor run).",
|
|
5525
|
+
order: 1,
|
|
5526
|
+
entity: "company"
|
|
5527
|
+
},
|
|
5528
|
+
populated: {
|
|
5529
|
+
key: "populated",
|
|
5530
|
+
label: "Companies found",
|
|
5531
|
+
description: "Companies have been found and added to the lead-gen list.",
|
|
5532
|
+
order: 2,
|
|
5533
|
+
entity: "company"
|
|
5534
|
+
},
|
|
5535
|
+
crawled: {
|
|
5536
|
+
key: "crawled",
|
|
5537
|
+
label: "Websites crawled",
|
|
5538
|
+
description: "Company websites have been crawled (e.g. via Apify) and raw page content stored for downstream LLM analysis.",
|
|
5539
|
+
order: 2.5,
|
|
5540
|
+
entity: "company"
|
|
5541
|
+
},
|
|
5542
|
+
extracted: {
|
|
5543
|
+
key: "extracted",
|
|
5544
|
+
label: "Websites analyzed",
|
|
5545
|
+
description: "Company websites have been analyzed for business signals.",
|
|
5546
|
+
order: 3,
|
|
5547
|
+
entity: "company"
|
|
5548
|
+
},
|
|
5549
|
+
enriched: {
|
|
5550
|
+
key: "enriched",
|
|
5551
|
+
label: "Enriched",
|
|
5552
|
+
description: "Company or contact enriched with third-party data (e.g. Tomba, Anymailfinder).",
|
|
5553
|
+
order: 4,
|
|
5554
|
+
entity: "company"
|
|
5555
|
+
},
|
|
5556
|
+
"decision-makers-enriched": {
|
|
5557
|
+
key: "decision-makers-enriched",
|
|
5558
|
+
label: "Decision-makers found",
|
|
5559
|
+
description: "Decision-maker contacts discovered and attached to a qualified company.",
|
|
5560
|
+
order: 6,
|
|
5561
|
+
entity: "company",
|
|
5562
|
+
recordEntity: "contact",
|
|
5563
|
+
recordStageKey: "discovered"
|
|
5564
|
+
},
|
|
5565
|
+
// Prospecting - contact discovery
|
|
5566
|
+
discovered: {
|
|
5567
|
+
key: "discovered",
|
|
5568
|
+
label: "Decision-makers found",
|
|
5569
|
+
description: "Decision-maker contact details have been found.",
|
|
5570
|
+
order: 5,
|
|
5571
|
+
entity: "contact"
|
|
5572
|
+
},
|
|
5573
|
+
verified: {
|
|
5574
|
+
key: "verified",
|
|
5575
|
+
label: "Emails verified",
|
|
5576
|
+
description: "Contact email addresses have been checked for deliverability.",
|
|
5577
|
+
order: 7,
|
|
5578
|
+
entity: "contact"
|
|
5579
|
+
},
|
|
5580
|
+
// Qualification
|
|
5581
|
+
qualified: {
|
|
5582
|
+
key: "qualified",
|
|
5583
|
+
label: "Companies qualified",
|
|
5584
|
+
description: "Companies have been scored against the qualification criteria.",
|
|
5585
|
+
order: 8,
|
|
5586
|
+
entity: "company"
|
|
5587
|
+
},
|
|
5588
|
+
// Outreach
|
|
5589
|
+
personalized: {
|
|
5590
|
+
key: "personalized",
|
|
5591
|
+
label: "Personalized",
|
|
5592
|
+
description: "Outreach message personalized for the contact (Instantly personalization workflow).",
|
|
5593
|
+
order: 9,
|
|
5594
|
+
entity: "contact"
|
|
5595
|
+
},
|
|
5596
|
+
uploaded: {
|
|
5597
|
+
key: "uploaded",
|
|
5598
|
+
label: "Reviewed and exported",
|
|
5599
|
+
description: "Approved records have been reviewed and exported for handoff.",
|
|
5600
|
+
order: 10,
|
|
5601
|
+
entity: "company",
|
|
5602
|
+
additionalEntities: ["contact"]
|
|
5603
|
+
},
|
|
5604
|
+
interested: {
|
|
5605
|
+
key: "interested",
|
|
5606
|
+
label: "Interested",
|
|
5607
|
+
description: "Contact replied with a positive signal (Instantly reply-handler transition).",
|
|
5608
|
+
order: 11,
|
|
5609
|
+
entity: "contact"
|
|
5610
|
+
}
|
|
5611
|
+
};
|
|
5612
|
+
|
|
5613
|
+
// ../core/src/organization-model/domains/sales.ts
|
|
5614
|
+
var SalesStageSemanticClassSchema = z.enum(["open", "active", "nurturing", "closed_won", "closed_lost"]);
|
|
5615
|
+
var SalesStageSchema = DisplayMetadataSchema.extend({
|
|
5616
|
+
id: ModelIdSchema,
|
|
5617
|
+
order: z.number().int().min(0),
|
|
5618
|
+
semanticClass: SalesStageSemanticClassSchema,
|
|
5619
|
+
surfaceIds: ReferenceIdsSchema,
|
|
5620
|
+
resourceIds: ReferenceIdsSchema
|
|
5621
|
+
});
|
|
5622
|
+
z.object({
|
|
5623
|
+
id: ModelIdSchema,
|
|
5624
|
+
label: z.string().trim().min(1).max(120),
|
|
5625
|
+
description: DescriptionSchema.optional(),
|
|
5626
|
+
entityId: ModelIdSchema,
|
|
5627
|
+
stages: z.array(SalesStageSchema).min(1)
|
|
5628
|
+
});
|
|
5629
|
+
var CRM_DISCOVERY_REPLIED_STATE = {
|
|
5630
|
+
stateKey: "discovery_replied",
|
|
5631
|
+
label: "Discovery Replied"
|
|
5632
|
+
};
|
|
5633
|
+
var CRM_DISCOVERY_LINK_SENT_STATE = {
|
|
5634
|
+
stateKey: "discovery_link_sent",
|
|
5635
|
+
label: "Discovery Link Sent"
|
|
5636
|
+
};
|
|
5637
|
+
var CRM_DISCOVERY_NUDGING_STATE = {
|
|
5638
|
+
stateKey: "discovery_nudging",
|
|
5639
|
+
label: "Discovery Nudging"
|
|
5640
|
+
};
|
|
5641
|
+
var CRM_DISCOVERY_BOOKING_CANCELLED_STATE = {
|
|
5642
|
+
stateKey: "discovery_booking_cancelled",
|
|
5643
|
+
label: "Discovery Booking Cancelled"
|
|
5644
|
+
};
|
|
5645
|
+
var CRM_REPLY_SENT_STATE = {
|
|
5646
|
+
stateKey: "reply_sent",
|
|
5647
|
+
label: "Reply Sent"
|
|
5648
|
+
};
|
|
5649
|
+
var CRM_FOLLOWUP_1_SENT_STATE = {
|
|
5650
|
+
stateKey: "followup_1_sent",
|
|
5651
|
+
label: "Follow-up 1 Sent"
|
|
5652
|
+
};
|
|
5653
|
+
var CRM_FOLLOWUP_2_SENT_STATE = {
|
|
5654
|
+
stateKey: "followup_2_sent",
|
|
5655
|
+
label: "Follow-up 2 Sent"
|
|
5656
|
+
};
|
|
5657
|
+
var CRM_FOLLOWUP_3_SENT_STATE = {
|
|
5658
|
+
stateKey: "followup_3_sent",
|
|
5659
|
+
label: "Follow-up 3 Sent"
|
|
5660
|
+
};
|
|
5661
|
+
var CRM_PIPELINE_DEFINITION = {
|
|
5662
|
+
pipelineKey: "crm",
|
|
5663
|
+
label: "CRM",
|
|
5664
|
+
entityKey: "crm.deal",
|
|
5665
|
+
stages: [
|
|
5666
|
+
{
|
|
5667
|
+
stageKey: "interested",
|
|
5668
|
+
label: "Interested",
|
|
5669
|
+
color: "blue",
|
|
5670
|
+
states: [
|
|
5671
|
+
CRM_DISCOVERY_REPLIED_STATE,
|
|
5672
|
+
CRM_DISCOVERY_LINK_SENT_STATE,
|
|
5673
|
+
CRM_DISCOVERY_NUDGING_STATE,
|
|
5674
|
+
CRM_DISCOVERY_BOOKING_CANCELLED_STATE,
|
|
5675
|
+
CRM_REPLY_SENT_STATE,
|
|
5676
|
+
CRM_FOLLOWUP_1_SENT_STATE,
|
|
5677
|
+
CRM_FOLLOWUP_2_SENT_STATE,
|
|
5678
|
+
CRM_FOLLOWUP_3_SENT_STATE
|
|
5679
|
+
]
|
|
5680
|
+
},
|
|
5681
|
+
{ stageKey: "proposal", label: "Proposal", color: "yellow", states: [] },
|
|
5682
|
+
{ stageKey: "closing", label: "Closing", color: "orange", states: [] },
|
|
5683
|
+
{ stageKey: "closed_won", label: "Closed Won", color: "green", states: [] },
|
|
5684
|
+
{ stageKey: "closed_lost", label: "Closed Lost", color: "red", states: [] },
|
|
5685
|
+
{ stageKey: "nurturing", label: "Nurturing", color: "grape", states: [] }
|
|
5686
|
+
]
|
|
5687
|
+
};
|
|
5688
|
+
var OrganizationModelBrandingSchema = z.object({
|
|
5689
|
+
organizationName: LabelSchema,
|
|
5690
|
+
productName: LabelSchema,
|
|
5691
|
+
shortName: z.string().trim().min(1).max(40),
|
|
5692
|
+
description: DescriptionSchema.optional(),
|
|
5693
|
+
logos: z.object({
|
|
5694
|
+
light: z.string().trim().min(1).max(2048).optional(),
|
|
5695
|
+
dark: z.string().trim().min(1).max(2048).optional()
|
|
5696
|
+
}).default({})
|
|
5697
|
+
});
|
|
5698
|
+
var DEFAULT_ORGANIZATION_MODEL_BRANDING = {
|
|
5699
|
+
organizationName: "Default Organization",
|
|
5700
|
+
productName: "Elevasis",
|
|
5701
|
+
shortName: "Elevasis",
|
|
5702
|
+
logos: {}
|
|
5703
|
+
};
|
|
5704
|
+
var BusinessHoursDaySchema = z.object({
|
|
5705
|
+
open: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format"),
|
|
5706
|
+
close: z.string().trim().regex(/^\d{2}:\d{2}$/, "Expected HH:MM format")
|
|
5707
|
+
});
|
|
5708
|
+
var BusinessHoursSchema = z.object({
|
|
5709
|
+
monday: BusinessHoursDaySchema.optional(),
|
|
5710
|
+
tuesday: BusinessHoursDaySchema.optional(),
|
|
5711
|
+
wednesday: BusinessHoursDaySchema.optional(),
|
|
5712
|
+
thursday: BusinessHoursDaySchema.optional(),
|
|
5713
|
+
friday: BusinessHoursDaySchema.optional(),
|
|
5714
|
+
saturday: BusinessHoursDaySchema.optional(),
|
|
5715
|
+
sunday: BusinessHoursDaySchema.optional()
|
|
5716
|
+
}).default({});
|
|
5717
|
+
var IdentityDomainSchema = z.object({
|
|
5718
|
+
/** Why the organization exists — one or two plain-language sentences. */
|
|
5719
|
+
mission: z.string().trim().max(1e3).default(""),
|
|
5720
|
+
/** Long-term direction the organization is moving toward. */
|
|
5721
|
+
vision: z.string().trim().max(1e3).default(""),
|
|
5722
|
+
/** Legal registered name of the entity. */
|
|
5723
|
+
legalName: z.string().trim().max(200).default(""),
|
|
5724
|
+
/**
|
|
5725
|
+
* Type of legal entity (e.g. "LLC", "Corporation", "Sole Proprietor",
|
|
5726
|
+
* "Non-profit"). Free-form string so it covers any jurisdiction.
|
|
5727
|
+
*/
|
|
5728
|
+
entityType: z.string().trim().max(100).default(""),
|
|
5729
|
+
/**
|
|
5730
|
+
* Primary jurisdiction of registration or operation
|
|
5731
|
+
* (e.g. "United States – Delaware", "Canada – Ontario").
|
|
5732
|
+
*/
|
|
5733
|
+
jurisdiction: z.string().trim().max(200).default(""),
|
|
5734
|
+
/**
|
|
5735
|
+
* Industry category — broad classification (e.g. "Marketing Agency",
|
|
5736
|
+
* "Software / SaaS", "Professional Services").
|
|
5737
|
+
*/
|
|
5738
|
+
industryCategory: z.string().trim().max(200).default(""),
|
|
5739
|
+
/**
|
|
5740
|
+
* Geographic focus — where the organization primarily operates or serves
|
|
5741
|
+
* (e.g. "North America", "Global", "Southeast Asia").
|
|
5742
|
+
*/
|
|
5743
|
+
geographicFocus: z.string().trim().max(200).default(""),
|
|
5744
|
+
/**
|
|
5745
|
+
* IANA timezone identifier for the organization's primary operating timezone
|
|
5746
|
+
* (e.g. "America/Los_Angeles", "Europe/London", "UTC").
|
|
5747
|
+
*/
|
|
5748
|
+
timeZone: z.string().trim().max(100).default("UTC"),
|
|
5749
|
+
/** Typical operating hours per day of week. Empty object means not configured. */
|
|
5750
|
+
businessHours: BusinessHoursSchema,
|
|
5751
|
+
/**
|
|
5752
|
+
* Long-form markdown capturing client context, problem narrative, and domain
|
|
5753
|
+
* background. Populated by /setup; surfaced to agents as organizational context.
|
|
5754
|
+
* Optional — many projects have no external client.
|
|
5755
|
+
*/
|
|
5756
|
+
clientBrief: z.string().trim().default("")
|
|
5757
|
+
});
|
|
5758
|
+
var DEFAULT_ORGANIZATION_MODEL_IDENTITY = {
|
|
5759
|
+
mission: "",
|
|
5760
|
+
vision: "",
|
|
5761
|
+
legalName: "",
|
|
5762
|
+
entityType: "",
|
|
5763
|
+
jurisdiction: "",
|
|
5764
|
+
industryCategory: "",
|
|
5765
|
+
geographicFocus: "",
|
|
5766
|
+
timeZone: "UTC",
|
|
5767
|
+
businessHours: {},
|
|
5768
|
+
clientBrief: ""
|
|
5769
|
+
};
|
|
5770
|
+
var FirmographicsSchema = z.object({
|
|
5771
|
+
/** Industry vertical (e.g. "Marketing Agency", "Legal", "Real Estate"). */
|
|
5772
|
+
industry: z.string().trim().max(200).optional(),
|
|
5773
|
+
/**
|
|
5774
|
+
* Company headcount band (e.g. "1–10", "11–50", "51–200", "200+").
|
|
5775
|
+
* Free-form string to accommodate any band notation.
|
|
5776
|
+
*/
|
|
5777
|
+
companySize: z.string().trim().max(100).optional(),
|
|
5778
|
+
/**
|
|
5779
|
+
* Primary geographic region the segment operates in or is targeted from
|
|
5780
|
+
* (e.g. "North America", "Europe", "Global").
|
|
5781
|
+
*/
|
|
5782
|
+
region: z.string().trim().max(200).optional()
|
|
5783
|
+
});
|
|
5784
|
+
var CustomerSegmentSchema = z.object({
|
|
5785
|
+
/** Stable unique identifier for the segment (e.g. "segment-smb-agencies"). */
|
|
5786
|
+
id: z.string().trim().min(1).max(100),
|
|
5787
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
5788
|
+
order: z.number(),
|
|
5789
|
+
/** Human-readable name shown to agents and in UI (e.g. "SMB Marketing Agencies"). */
|
|
5790
|
+
name: z.string().trim().max(200).default(""),
|
|
5791
|
+
/** One or two sentences describing who this segment is. */
|
|
5792
|
+
description: z.string().trim().max(2e3).default(""),
|
|
5793
|
+
/**
|
|
5794
|
+
* The primary job(s) this segment is trying to get done — the goal they hire
|
|
5795
|
+
* a product/service to accomplish. Plain-language narrative or bullet list.
|
|
5796
|
+
*/
|
|
5797
|
+
jobsToBeDone: z.string().trim().max(2e3).default(""),
|
|
5798
|
+
/**
|
|
5799
|
+
* Pains — frustrations, obstacles, and risks the segment experiences
|
|
5800
|
+
* when trying to accomplish their jobs-to-be-done.
|
|
5801
|
+
*/
|
|
5802
|
+
pains: z.array(z.string().trim().max(500)).default([]),
|
|
5803
|
+
/**
|
|
5804
|
+
* Gains — outcomes and benefits the segment desires; positive motivators
|
|
5805
|
+
* beyond merely resolving pains.
|
|
5806
|
+
*/
|
|
5807
|
+
gains: z.array(z.string().trim().max(500)).default([]),
|
|
5808
|
+
/** Firmographic profile for targeting and filtering. */
|
|
5809
|
+
firmographics: FirmographicsSchema.default({}),
|
|
5810
|
+
/**
|
|
5811
|
+
* Value proposition — one or two sentences stating why this organization's
|
|
5812
|
+
* offering is uniquely suited for this segment's needs.
|
|
5813
|
+
*/
|
|
5814
|
+
valueProp: z.string().trim().max(2e3).default("")
|
|
5815
|
+
});
|
|
5816
|
+
var CustomersDomainSchema = z.record(z.string(), CustomerSegmentSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
5817
|
+
message: "Each segment entry id must match its map key"
|
|
5818
|
+
}).default({});
|
|
5819
|
+
var DEFAULT_ORGANIZATION_MODEL_CUSTOMERS = {};
|
|
5820
|
+
var PricingModelSchema = z.enum(["one-time", "subscription", "usage-based", "custom"]).meta({ label: "Pricing model", color: "green" });
|
|
5821
|
+
var ProductSchema = z.object({
|
|
5822
|
+
/** Stable unique identifier for the product (e.g. "product-starter-plan"). */
|
|
5823
|
+
id: z.string().trim().min(1).max(100),
|
|
5824
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
5825
|
+
order: z.number(),
|
|
5826
|
+
/** Human-readable name shown to agents and in UI (e.g. "Starter Plan"). */
|
|
5827
|
+
name: z.string().trim().max(200).default(""),
|
|
5828
|
+
/** One or two sentences describing what this product/service delivers. */
|
|
5829
|
+
description: z.string().trim().max(2e3).default(""),
|
|
5830
|
+
/**
|
|
5831
|
+
* How this product is priced:
|
|
5832
|
+
* - "one-time" — single purchase (setup fee, project fee)
|
|
5833
|
+
* - "subscription" — recurring (monthly/annual SaaS, retainer)
|
|
5834
|
+
* - "usage-based" — metered by consumption (API calls, seats)
|
|
5835
|
+
* - "custom" — negotiated or bespoke pricing
|
|
5836
|
+
*/
|
|
5837
|
+
pricingModel: PricingModelSchema.default("custom"),
|
|
5838
|
+
/** Base price amount (≥ 0). Currency unit defined by `currency`. */
|
|
5839
|
+
price: z.number().min(0).default(0),
|
|
5840
|
+
/**
|
|
5841
|
+
* ISO 4217 currency code (e.g. "USD", "EUR", "GBP").
|
|
5842
|
+
* Free-form string to accommodate any currency; defaults to "USD".
|
|
5843
|
+
*/
|
|
5844
|
+
currency: z.string().trim().max(10).default("USD"),
|
|
5845
|
+
/**
|
|
5846
|
+
* IDs of customer segments this product targets.
|
|
5847
|
+
* Each id must reference a declared `customers.segments[].id`.
|
|
5848
|
+
* Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
|
|
5849
|
+
*/
|
|
5850
|
+
targetSegmentIds: z.array(z.string().trim().min(1)).default([]),
|
|
5851
|
+
/**
|
|
5852
|
+
* Optional: ID of the platform system responsible for delivering this product.
|
|
5853
|
+
* When present, must reference a declared `systems.systems[].id`.
|
|
5854
|
+
* Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
|
|
5855
|
+
*/
|
|
5856
|
+
deliveryFeatureId: z.string().trim().min(1).optional()
|
|
5857
|
+
});
|
|
5858
|
+
var OfferingsDomainSchema = z.record(z.string(), ProductSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
5859
|
+
message: "Each product entry id must match its map key"
|
|
5860
|
+
}).default({});
|
|
5861
|
+
var DEFAULT_ORGANIZATION_MODEL_OFFERINGS = {};
|
|
5862
|
+
var ContentNodeBaseSchema = z.object({
|
|
5863
|
+
/** Human-readable label for the content node. */
|
|
5864
|
+
label: z.string().trim().min(1).max(120).meta({ label: "Label" }),
|
|
5865
|
+
/** Optional one-paragraph description. */
|
|
5866
|
+
description: z.string().trim().min(1).max(2e3).optional().meta({ label: "Description" }),
|
|
5867
|
+
/** Optional display order within the system content map. */
|
|
5868
|
+
order: z.number().int().optional().meta({ label: "Order" }),
|
|
5869
|
+
/**
|
|
5870
|
+
* Local NodeId of the parent content node within the SAME system.
|
|
5871
|
+
* Per B4/L9: MUST resolve to a sibling in the same `system.content` map.
|
|
5872
|
+
* Per L19: parent and child MUST share the same `kind` (meta-category).
|
|
5873
|
+
*/
|
|
5874
|
+
parentContentId: z.string().trim().min(1).max(200).optional().meta({ label: "Parent content id" })
|
|
5875
|
+
});
|
|
5876
|
+
var ContentNodeSchema = ContentNodeBaseSchema.extend({
|
|
5877
|
+
/** Meta-category (e.g. 'schema', 'config', 'knowledge', tenant-defined). */
|
|
5878
|
+
kind: z.string().trim().min(1).max(100).meta({ label: "Kind" }),
|
|
5879
|
+
/** Specific family within the meta-category (e.g. 'pipeline', 'kv'). */
|
|
5880
|
+
type: z.string().trim().min(1).max(100).meta({ label: "Type" }),
|
|
5881
|
+
/** Payload data; validated against registered payloadSchema when (kind, type) is known. */
|
|
5882
|
+
data: z.record(z.string(), z.unknown()).optional().meta({ label: "Data" })
|
|
5883
|
+
});
|
|
5884
|
+
z.object({
|
|
5885
|
+
/** Meta-category (tenant-defined or registry-shipped). */
|
|
5886
|
+
kind: z.string().trim().min(1).max(100).meta({ label: "Kind" }),
|
|
5887
|
+
/** Specific family within the meta-category. */
|
|
5888
|
+
type: z.string().trim().min(1).max(100).meta({ label: "Type" }),
|
|
5889
|
+
/** Human-readable label shown in the KB tree and describe views. */
|
|
5890
|
+
label: z.string().trim().min(1).max(120).meta({ label: "Label" }),
|
|
5891
|
+
/** Optional description. */
|
|
5892
|
+
description: z.string().trim().min(1).max(2e3).optional().meta({ label: "Description" }),
|
|
5893
|
+
/**
|
|
5894
|
+
* Which KB tree group this extension renders in.
|
|
5895
|
+
* Per L6: 'business-model' places it alongside Customers / Offerings / Goals.
|
|
5896
|
+
*/
|
|
5897
|
+
treeGroup: z.union([z.enum(["profile", "business-model", "systems", "graph", "governance-wiring"]), z.string().min(1).max(100)]).meta({ label: "Tree group" }),
|
|
5898
|
+
/** Untyped payload; shape governed by the registered payloadSchema when available. */
|
|
5899
|
+
data: z.record(z.string(), z.unknown()).optional().meta({ label: "Data" })
|
|
5900
|
+
});
|
|
5901
|
+
var OntologyKindSchema = z.enum([
|
|
5902
|
+
"object",
|
|
5903
|
+
"link",
|
|
5904
|
+
"action",
|
|
5905
|
+
"catalog",
|
|
5906
|
+
"event",
|
|
5907
|
+
"interface",
|
|
5908
|
+
"value-type",
|
|
5909
|
+
"property",
|
|
5910
|
+
"group",
|
|
5911
|
+
"surface"
|
|
5912
|
+
]);
|
|
5913
|
+
var SYSTEM_PATH_PATTERN = "[a-z0-9][a-z0-9-]*(?:\\.[a-z0-9][a-z0-9-]*)*";
|
|
5914
|
+
var LOCAL_ID_PATTERN = "[a-z0-9][a-z0-9._-]*";
|
|
5915
|
+
var ONTOLOGY_ID_PATTERN = `^(global|${SYSTEM_PATH_PATTERN}):(${OntologyKindSchema.options.join("|")})\\/(${LOCAL_ID_PATTERN})$`;
|
|
5916
|
+
var ONTOLOGY_ID_REGEX = new RegExp(ONTOLOGY_ID_PATTERN);
|
|
5917
|
+
var OntologyIdSchema = z.string().trim().min(1).max(300).regex(
|
|
5918
|
+
ONTOLOGY_ID_REGEX,
|
|
5919
|
+
"Ontology IDs must use <system-path>:<kind>/<local-id> or global:<kind>/<local-id>"
|
|
5920
|
+
);
|
|
5921
|
+
function parseOntologyId(id) {
|
|
5922
|
+
const normalized = OntologyIdSchema.parse(id);
|
|
5923
|
+
const match = ONTOLOGY_ID_REGEX.exec(normalized);
|
|
5924
|
+
if (match === null) {
|
|
5925
|
+
throw new Error(`Invalid ontology ID "${id}"`);
|
|
5926
|
+
}
|
|
5927
|
+
return {
|
|
5928
|
+
id: normalized,
|
|
5929
|
+
scope: match[1],
|
|
5930
|
+
kind: match[2],
|
|
5931
|
+
localId: match[3],
|
|
5932
|
+
isGlobal: match[1] === "global"
|
|
5933
|
+
};
|
|
5934
|
+
}
|
|
5935
|
+
function formatOntologyId(input) {
|
|
5936
|
+
return OntologyIdSchema.parse(`${input.scope}:${input.kind}/${input.localId}`);
|
|
5937
|
+
}
|
|
5938
|
+
var OntologyReferenceListSchema = z.array(OntologyIdSchema).default([]).optional();
|
|
5939
|
+
var OntologyRecordBaseSchema = z.object({
|
|
5940
|
+
id: OntologyIdSchema,
|
|
5941
|
+
label: z.string().trim().min(1).max(160).optional(),
|
|
5942
|
+
description: z.string().trim().min(1).max(2e3).optional(),
|
|
5943
|
+
ownerSystemId: z.string().trim().min(1).max(200).optional(),
|
|
5944
|
+
aliases: z.array(OntologyIdSchema).optional()
|
|
5945
|
+
}).passthrough();
|
|
5946
|
+
var OntologyObjectTypeSchema = OntologyRecordBaseSchema.extend({
|
|
5947
|
+
properties: z.record(z.string().trim().min(1).max(200), z.unknown()).optional(),
|
|
5948
|
+
storage: z.record(z.string(), z.unknown()).optional()
|
|
5949
|
+
});
|
|
5950
|
+
var OntologyLinkTypeSchema = OntologyRecordBaseSchema.extend({
|
|
5951
|
+
from: OntologyIdSchema,
|
|
5952
|
+
to: OntologyIdSchema,
|
|
5953
|
+
cardinality: z.string().trim().min(1).max(80).optional(),
|
|
5954
|
+
via: z.string().trim().min(1).max(255).optional()
|
|
5955
|
+
});
|
|
5956
|
+
var OntologyActionTypeSchema = OntologyRecordBaseSchema.extend({
|
|
5957
|
+
actsOn: OntologyReferenceListSchema,
|
|
5958
|
+
input: z.record(z.string().trim().min(1).max(200), z.unknown()).optional(),
|
|
5959
|
+
effects: z.array(z.record(z.string(), z.unknown())).optional()
|
|
5960
|
+
});
|
|
5961
|
+
var OntologyCatalogTypeSchema = OntologyRecordBaseSchema.extend({
|
|
5962
|
+
kind: z.string().trim().min(1).max(120).optional(),
|
|
5963
|
+
appliesTo: OntologyIdSchema.optional(),
|
|
5964
|
+
entries: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
|
|
5965
|
+
});
|
|
5966
|
+
var OntologyEventTypeSchema = OntologyRecordBaseSchema.extend({
|
|
5967
|
+
payload: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
|
|
5968
|
+
});
|
|
5969
|
+
var OntologyInterfaceTypeSchema = OntologyRecordBaseSchema.extend({
|
|
5970
|
+
properties: z.record(z.string().trim().min(1).max(200), z.unknown()).optional()
|
|
5971
|
+
});
|
|
5972
|
+
var OntologyValueTypeSchema = OntologyRecordBaseSchema.extend({
|
|
5973
|
+
primitive: z.string().trim().min(1).max(120).optional()
|
|
5974
|
+
});
|
|
5975
|
+
var OntologySharedPropertySchema = OntologyRecordBaseSchema.extend({
|
|
5976
|
+
valueType: OntologyIdSchema.optional(),
|
|
5977
|
+
searchable: z.boolean().optional(),
|
|
5978
|
+
pii: z.boolean().optional()
|
|
5979
|
+
});
|
|
5980
|
+
var OntologyGroupSchema = OntologyRecordBaseSchema.extend({
|
|
5981
|
+
members: OntologyReferenceListSchema
|
|
5982
|
+
});
|
|
5983
|
+
var OntologySurfaceTypeSchema = OntologyRecordBaseSchema.extend({
|
|
5984
|
+
route: z.string().trim().min(1).max(500).optional()
|
|
5985
|
+
});
|
|
5986
|
+
var OntologyScopeSchema = z.object({
|
|
5987
|
+
objectTypes: z.record(OntologyIdSchema, OntologyObjectTypeSchema).default({}).optional(),
|
|
5988
|
+
linkTypes: z.record(OntologyIdSchema, OntologyLinkTypeSchema).default({}).optional(),
|
|
5989
|
+
actionTypes: z.record(OntologyIdSchema, OntologyActionTypeSchema).default({}).optional(),
|
|
5990
|
+
catalogTypes: z.record(OntologyIdSchema, OntologyCatalogTypeSchema).default({}).optional(),
|
|
5991
|
+
eventTypes: z.record(OntologyIdSchema, OntologyEventTypeSchema).default({}).optional(),
|
|
5992
|
+
interfaceTypes: z.record(OntologyIdSchema, OntologyInterfaceTypeSchema).default({}).optional(),
|
|
5993
|
+
valueTypes: z.record(OntologyIdSchema, OntologyValueTypeSchema).default({}).optional(),
|
|
5994
|
+
sharedProperties: z.record(OntologyIdSchema, OntologySharedPropertySchema).default({}).optional(),
|
|
5995
|
+
groups: z.record(OntologyIdSchema, OntologyGroupSchema).default({}).optional(),
|
|
5996
|
+
surfaces: z.record(OntologyIdSchema, OntologySurfaceTypeSchema).default({}).optional()
|
|
5997
|
+
}).default({});
|
|
5998
|
+
var DEFAULT_ONTOLOGY_SCOPE = {
|
|
5999
|
+
valueTypes: {
|
|
6000
|
+
"global:value-type/uuid": {
|
|
6001
|
+
id: "global:value-type/uuid",
|
|
6002
|
+
label: "UUID",
|
|
6003
|
+
primitive: "string"
|
|
6004
|
+
},
|
|
6005
|
+
"global:value-type/text": {
|
|
6006
|
+
id: "global:value-type/text",
|
|
6007
|
+
label: "Text",
|
|
6008
|
+
primitive: "string"
|
|
6009
|
+
},
|
|
6010
|
+
"global:value-type/url": {
|
|
6011
|
+
id: "global:value-type/url",
|
|
6012
|
+
label: "URL",
|
|
6013
|
+
primitive: "string"
|
|
6014
|
+
},
|
|
6015
|
+
"global:value-type/email": {
|
|
6016
|
+
id: "global:value-type/email",
|
|
6017
|
+
label: "Email",
|
|
6018
|
+
primitive: "string"
|
|
6019
|
+
}
|
|
6020
|
+
}
|
|
6021
|
+
};
|
|
6022
|
+
var SCOPE_KIND = {
|
|
6023
|
+
objectTypes: "object",
|
|
6024
|
+
linkTypes: "link",
|
|
6025
|
+
actionTypes: "action",
|
|
6026
|
+
catalogTypes: "catalog",
|
|
6027
|
+
eventTypes: "event",
|
|
6028
|
+
interfaceTypes: "interface",
|
|
6029
|
+
valueTypes: "value-type",
|
|
6030
|
+
sharedProperties: "property",
|
|
6031
|
+
groups: "group",
|
|
6032
|
+
surfaces: "surface"
|
|
6033
|
+
};
|
|
6034
|
+
var SCOPE_KEYS = Object.keys(SCOPE_KIND);
|
|
6035
|
+
function listResolvedOntologyRecords(index) {
|
|
6036
|
+
return SCOPE_KEYS.flatMap((scopeKey) => {
|
|
6037
|
+
const kind = SCOPE_KIND[scopeKey];
|
|
6038
|
+
return Object.entries(index[scopeKey]).sort(([leftId], [rightId]) => leftId.localeCompare(rightId)).map(([id, record]) => ({
|
|
6039
|
+
id,
|
|
6040
|
+
kind,
|
|
6041
|
+
record
|
|
6042
|
+
}));
|
|
6043
|
+
});
|
|
6044
|
+
}
|
|
6045
|
+
function originFromContext(context) {
|
|
6046
|
+
return {
|
|
6047
|
+
kind: context.kind,
|
|
6048
|
+
source: context.source,
|
|
6049
|
+
path: context.path,
|
|
6050
|
+
...context.systemPath !== void 0 ? { systemPath: context.systemPath } : {},
|
|
6051
|
+
...context.legacyId !== void 0 ? { legacyId: context.legacyId } : {}
|
|
6052
|
+
};
|
|
6053
|
+
}
|
|
6054
|
+
function createEmptyIndex() {
|
|
6055
|
+
return {
|
|
6056
|
+
objectTypes: {},
|
|
6057
|
+
linkTypes: {},
|
|
6058
|
+
actionTypes: {},
|
|
6059
|
+
catalogTypes: {},
|
|
6060
|
+
eventTypes: {},
|
|
6061
|
+
interfaceTypes: {},
|
|
6062
|
+
valueTypes: {},
|
|
6063
|
+
sharedProperties: {},
|
|
6064
|
+
groups: {},
|
|
6065
|
+
surfaces: {}
|
|
6066
|
+
};
|
|
6067
|
+
}
|
|
6068
|
+
function sortResolvedOntologyIndex(index) {
|
|
6069
|
+
const sorted = createEmptyIndex();
|
|
6070
|
+
for (const scopeKey of SCOPE_KEYS) {
|
|
6071
|
+
const target = sorted[scopeKey];
|
|
6072
|
+
for (const [id, record] of Object.entries(index[scopeKey]).sort(
|
|
6073
|
+
([leftId], [rightId]) => leftId.localeCompare(rightId)
|
|
6074
|
+
)) {
|
|
6075
|
+
target[id] = record;
|
|
6076
|
+
}
|
|
6077
|
+
}
|
|
6078
|
+
return sorted;
|
|
6079
|
+
}
|
|
6080
|
+
function childSystemsOf(system) {
|
|
6081
|
+
return system.systems ?? system.subsystems ?? {};
|
|
6082
|
+
}
|
|
6083
|
+
function addRecord(index, diagnostics, sourcesById, scopeKey, record, context) {
|
|
6084
|
+
let parsed;
|
|
6085
|
+
try {
|
|
6086
|
+
parsed = parseOntologyId(record.id);
|
|
6087
|
+
} catch {
|
|
6088
|
+
diagnostics.push({
|
|
6089
|
+
code: "invalid_ontology_id",
|
|
6090
|
+
message: `Invalid ontology ID "${record.id}" from ${context.source} at ${context.path.join(".")}`,
|
|
6091
|
+
id: record.id,
|
|
6092
|
+
path: context.path,
|
|
6093
|
+
source: context.source,
|
|
6094
|
+
origin: originFromContext(context)
|
|
6095
|
+
});
|
|
6096
|
+
return;
|
|
6097
|
+
}
|
|
6098
|
+
const expectedKind = SCOPE_KIND[scopeKey];
|
|
6099
|
+
if (parsed.kind !== expectedKind) {
|
|
6100
|
+
diagnostics.push({
|
|
6101
|
+
code: "ontology_kind_mismatch",
|
|
6102
|
+
message: `Ontology ID "${record.id}" has kind "${parsed.kind}" but was authored in ${scopeKey} (${expectedKind}) at ${context.path.join(".")}`,
|
|
6103
|
+
id: record.id,
|
|
6104
|
+
path: context.path,
|
|
6105
|
+
source: context.source,
|
|
6106
|
+
origin: originFromContext(context)
|
|
6107
|
+
});
|
|
6108
|
+
return;
|
|
6109
|
+
}
|
|
6110
|
+
const existing = sourcesById.get(parsed.id);
|
|
6111
|
+
if (existing !== void 0) {
|
|
6112
|
+
diagnostics.push({
|
|
6113
|
+
code: "duplicate_ontology_id",
|
|
6114
|
+
message: `Duplicate ontology ID "${parsed.id}" from ${context.source} at ${context.path.join(".")} conflicts with ${existing.source} at ${existing.path.join(".")}`,
|
|
6115
|
+
id: parsed.id,
|
|
6116
|
+
path: context.path,
|
|
6117
|
+
source: context.source,
|
|
6118
|
+
origin: originFromContext(context),
|
|
6119
|
+
existingSource: existing.source,
|
|
6120
|
+
existingOrigin: originFromContext(existing)
|
|
6121
|
+
});
|
|
6122
|
+
return;
|
|
6123
|
+
}
|
|
6124
|
+
sourcesById.set(parsed.id, context);
|
|
6125
|
+
index[scopeKey][parsed.id] = {
|
|
6126
|
+
...record,
|
|
6127
|
+
origin: originFromContext(context)
|
|
6128
|
+
};
|
|
6129
|
+
}
|
|
6130
|
+
function addScope(index, diagnostics, sourcesById, scope, source, path) {
|
|
6131
|
+
if (scope === void 0) return;
|
|
6132
|
+
for (const scopeKey of SCOPE_KEYS) {
|
|
6133
|
+
const records = scope[scopeKey] ?? {};
|
|
6134
|
+
for (const [key, record] of Object.entries(records)) {
|
|
6135
|
+
addRecord(index, diagnostics, sourcesById, scopeKey, record, {
|
|
6136
|
+
source,
|
|
6137
|
+
path: [...path, scopeKey, key],
|
|
6138
|
+
kind: "authored",
|
|
6139
|
+
systemPath: source.startsWith("system:") ? source.slice("system:".length, -".ontology".length) : void 0
|
|
6140
|
+
});
|
|
6141
|
+
}
|
|
6142
|
+
}
|
|
6143
|
+
}
|
|
6144
|
+
function legacyObjectId(entity) {
|
|
6145
|
+
return formatOntologyId({ scope: entity.ownedBySystemId, kind: "object", localId: entity.id });
|
|
6146
|
+
}
|
|
6147
|
+
function legacyActionOwner(action, entities) {
|
|
6148
|
+
const firstAffectedEntityId = action.affects?.find((entityId) => entities[entityId] !== void 0);
|
|
6149
|
+
if (firstAffectedEntityId !== void 0) {
|
|
6150
|
+
return entities[firstAffectedEntityId].ownedBySystemId;
|
|
6151
|
+
}
|
|
6152
|
+
if (typeof action.scope === "object") {
|
|
6153
|
+
return action.scope.domain;
|
|
6154
|
+
}
|
|
6155
|
+
return "global";
|
|
6156
|
+
}
|
|
6157
|
+
function addLegacyEntityProjections(index, diagnostics, sourcesById, entities) {
|
|
6158
|
+
for (const entity of Object.values(entities)) {
|
|
6159
|
+
const objectType = {
|
|
6160
|
+
id: legacyObjectId(entity),
|
|
6161
|
+
label: entity.label,
|
|
6162
|
+
description: entity.description,
|
|
6163
|
+
ownerSystemId: entity.ownedBySystemId,
|
|
6164
|
+
...entity.table !== void 0 ? {
|
|
6165
|
+
storage: {
|
|
6166
|
+
kind: "table",
|
|
6167
|
+
table: entity.table
|
|
6168
|
+
}
|
|
6169
|
+
} : {},
|
|
6170
|
+
legacyEntityId: entity.id,
|
|
6171
|
+
...entity.rowSchema !== void 0 ? { rowSchema: entity.rowSchema } : {},
|
|
6172
|
+
...entity.stateCatalogId !== void 0 ? { stateCatalogId: entity.stateCatalogId } : {}
|
|
6173
|
+
};
|
|
6174
|
+
addRecord(index, diagnostics, sourcesById, "objectTypes", objectType, {
|
|
6175
|
+
source: "legacy.entities",
|
|
6176
|
+
path: ["entities", entity.id],
|
|
6177
|
+
kind: "projected",
|
|
6178
|
+
systemPath: entity.ownedBySystemId,
|
|
6179
|
+
legacyId: entity.id
|
|
6180
|
+
});
|
|
6181
|
+
entity.links?.forEach((link, linkIndex) => {
|
|
6182
|
+
const targetEntity = entities[link.toEntity];
|
|
6183
|
+
if (targetEntity === void 0) return;
|
|
6184
|
+
const linkType = {
|
|
6185
|
+
id: formatOntologyId({
|
|
6186
|
+
scope: entity.ownedBySystemId,
|
|
6187
|
+
kind: "link",
|
|
6188
|
+
localId: `${entity.id}-${link.toEntity}-${linkIndex}`
|
|
6189
|
+
}),
|
|
6190
|
+
label: link.label ?? link.kind,
|
|
6191
|
+
ownerSystemId: entity.ownedBySystemId,
|
|
6192
|
+
from: legacyObjectId(entity),
|
|
6193
|
+
to: legacyObjectId(targetEntity),
|
|
6194
|
+
cardinality: link.kind,
|
|
6195
|
+
...link.via !== void 0 ? { via: link.via } : {},
|
|
6196
|
+
legacyEntityId: entity.id
|
|
6197
|
+
};
|
|
6198
|
+
addRecord(index, diagnostics, sourcesById, "linkTypes", linkType, {
|
|
6199
|
+
source: "legacy.entities.links",
|
|
6200
|
+
path: ["entities", entity.id, "links", linkIndex],
|
|
6201
|
+
kind: "projected",
|
|
6202
|
+
systemPath: entity.ownedBySystemId,
|
|
6203
|
+
legacyId: `${entity.id}.links.${linkIndex}`
|
|
6204
|
+
});
|
|
6205
|
+
});
|
|
6206
|
+
}
|
|
6207
|
+
}
|
|
6208
|
+
function addLegacyActionProjections(index, diagnostics, sourcesById, actions, entities) {
|
|
6209
|
+
for (const action of Object.values(actions)) {
|
|
6210
|
+
const ownerSystemId = legacyActionOwner(action, entities);
|
|
6211
|
+
const actionType = {
|
|
6212
|
+
id: formatOntologyId({ scope: ownerSystemId, kind: "action", localId: action.id }),
|
|
6213
|
+
label: action.label,
|
|
6214
|
+
description: action.description,
|
|
6215
|
+
ownerSystemId,
|
|
6216
|
+
actsOn: action.affects?.map((entityId) => entities[entityId] ? legacyObjectId(entities[entityId]) : void 0).filter((id) => id !== void 0),
|
|
6217
|
+
...action.resourceId !== void 0 ? { resourceId: action.resourceId } : {},
|
|
6218
|
+
...action.invocations !== void 0 ? { invocations: action.invocations } : {},
|
|
6219
|
+
...action.lifecycle !== void 0 ? { lifecycle: action.lifecycle } : {},
|
|
6220
|
+
legacyActionId: action.id
|
|
6221
|
+
};
|
|
6222
|
+
addRecord(index, diagnostics, sourcesById, "actionTypes", actionType, {
|
|
6223
|
+
source: "legacy.actions",
|
|
6224
|
+
path: ["actions", action.id],
|
|
6225
|
+
kind: "projected",
|
|
6226
|
+
systemPath: ownerSystemId,
|
|
6227
|
+
legacyId: action.id
|
|
6228
|
+
});
|
|
6229
|
+
}
|
|
6230
|
+
}
|
|
6231
|
+
function addSystemContentProjections(index, diagnostics, sourcesById, systemPath, system, schemaPath) {
|
|
6232
|
+
const content = system.content ?? {};
|
|
6233
|
+
for (const [localId, node] of Object.entries(content)) {
|
|
6234
|
+
if (node.kind !== "schema") continue;
|
|
6235
|
+
const entries = Object.fromEntries(
|
|
6236
|
+
Object.entries(content).filter(([, candidate]) => candidate.parentContentId === localId).map(([entryId, candidate]) => [
|
|
6237
|
+
entryId,
|
|
6238
|
+
{
|
|
6239
|
+
label: candidate.label ?? entryId,
|
|
6240
|
+
type: candidate.type,
|
|
6241
|
+
...candidate.description !== void 0 ? { description: candidate.description } : {},
|
|
6242
|
+
...candidate.data !== void 0 ? candidate.data : {}
|
|
6243
|
+
}
|
|
6244
|
+
])
|
|
6245
|
+
);
|
|
6246
|
+
const catalogType = {
|
|
6247
|
+
id: formatOntologyId({ scope: systemPath, kind: "catalog", localId }),
|
|
6248
|
+
label: node.label ?? localId,
|
|
6249
|
+
description: node.description,
|
|
6250
|
+
ownerSystemId: systemPath,
|
|
6251
|
+
kind: node.type,
|
|
6252
|
+
...typeof node.data?.["entityId"] === "string" ? { appliesTo: formatOntologyId({ scope: systemPath, kind: "object", localId: node.data["entityId"] }) } : {},
|
|
6253
|
+
...Object.keys(entries).length > 0 ? { entries } : {},
|
|
6254
|
+
...node.data !== void 0 ? { data: node.data } : {},
|
|
6255
|
+
legacyContentId: `${systemPath}:${localId}`
|
|
6256
|
+
};
|
|
6257
|
+
addRecord(index, diagnostics, sourcesById, "catalogTypes", catalogType, {
|
|
6258
|
+
source: "legacy.system.content",
|
|
6259
|
+
path: [...schemaPath, "content", localId],
|
|
6260
|
+
kind: "projected",
|
|
6261
|
+
systemPath,
|
|
6262
|
+
legacyId: `${systemPath}:${localId}`
|
|
6263
|
+
});
|
|
6264
|
+
}
|
|
6265
|
+
}
|
|
6266
|
+
function addSystemScopes(index, diagnostics, sourcesById, systems, prefix, schemaPath) {
|
|
6267
|
+
for (const [key, system] of Object.entries(systems)) {
|
|
6268
|
+
const systemPath = prefix ? `${prefix}.${key}` : key;
|
|
6269
|
+
const currentPath = [...schemaPath, key];
|
|
6270
|
+
addScope(index, diagnostics, sourcesById, system.ontology, `system:${systemPath}.ontology`, [
|
|
6271
|
+
...currentPath,
|
|
6272
|
+
"ontology"
|
|
6273
|
+
]);
|
|
6274
|
+
addSystemContentProjections(index, diagnostics, sourcesById, systemPath, system, currentPath);
|
|
6275
|
+
addSystemScopes(index, diagnostics, sourcesById, childSystemsOf(system), systemPath, [
|
|
6276
|
+
...currentPath,
|
|
6277
|
+
system.systems !== void 0 ? "systems" : "subsystems"
|
|
6278
|
+
]);
|
|
6279
|
+
}
|
|
6280
|
+
}
|
|
6281
|
+
function compileOrganizationOntology(model) {
|
|
6282
|
+
const ontology = createEmptyIndex();
|
|
6283
|
+
const diagnostics = [];
|
|
6284
|
+
const sourcesById = /* @__PURE__ */ new Map();
|
|
6285
|
+
addScope(ontology, diagnostics, sourcesById, model.ontology, "organization.ontology", ["ontology"]);
|
|
6286
|
+
addSystemScopes(ontology, diagnostics, sourcesById, model.systems ?? {}, "", ["systems"]);
|
|
6287
|
+
addLegacyEntityProjections(ontology, diagnostics, sourcesById, model.entities ?? {});
|
|
6288
|
+
addLegacyActionProjections(ontology, diagnostics, sourcesById, model.actions ?? {}, model.entities ?? {});
|
|
6289
|
+
return { ontology: sortResolvedOntologyIndex(ontology), diagnostics };
|
|
6290
|
+
}
|
|
6291
|
+
|
|
6292
|
+
// ../core/src/organization-model/domains/systems.ts
|
|
6293
|
+
var SystemKindSchema = z.enum(["product", "operational", "platform", "diagnostic"]).meta({ label: "System kind", color: "blue" });
|
|
6294
|
+
var SystemLifecycleSchema = z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" });
|
|
6295
|
+
var SystemStatusSchema = z.enum(["active", "deprecated", "archived"]).meta({ label: "Status", color: "teal" });
|
|
6296
|
+
var SystemIdSchema = ModelIdSchema;
|
|
6297
|
+
var SystemPathSchema = z.string().trim().min(1).regex(
|
|
6298
|
+
/^[a-z0-9][a-z0-9-]*(?:\.[a-z0-9][a-z0-9-]*)*$/,
|
|
6299
|
+
'must be a dotted lowercase path (e.g. "sales.lead-gen" or "sales.crm")'
|
|
6300
|
+
);
|
|
6301
|
+
var UiPositionSchema = z.enum(["sidebar-primary", "sidebar-bottom"]).meta({ label: "UI position" });
|
|
6302
|
+
var NodeIdStringSchema = z.string().trim().min(1).max(200).regex(
|
|
6303
|
+
/^[a-z][a-z-]*:([a-z0-9-]+)(\.[a-z0-9-]+)*(:[a-z0-9.-]+)*$/,
|
|
6304
|
+
"Node references must use kind:dotted-path (e.g. system:sales.crm or content-node:sales.crm:pipeline-id)"
|
|
6305
|
+
);
|
|
6306
|
+
var SystemUiSchema = z.object({
|
|
6307
|
+
path: PathSchema,
|
|
6308
|
+
surfaces: ReferenceIdsSchema,
|
|
6309
|
+
icon: IconNameSchema.optional(),
|
|
6310
|
+
order: z.number().int().optional()
|
|
6311
|
+
});
|
|
6312
|
+
var JsonValueSchema = z.lazy(
|
|
6313
|
+
() => z.union([
|
|
6314
|
+
z.string(),
|
|
6315
|
+
z.number(),
|
|
6316
|
+
z.boolean(),
|
|
6317
|
+
z.null(),
|
|
6318
|
+
z.array(JsonValueSchema),
|
|
6319
|
+
z.record(z.string(), JsonValueSchema)
|
|
6320
|
+
])
|
|
6321
|
+
);
|
|
6322
|
+
var SystemConfigSchema = z.record(z.string().trim().min(1).max(200), JsonValueSchema).default({}).optional();
|
|
6323
|
+
var SystemEntrySchema = z.object({
|
|
6324
|
+
/** Stable tenant-defined system id (e.g. "sys.lead-gen" or "sales.crm"). */
|
|
6325
|
+
id: SystemIdSchema,
|
|
6326
|
+
/** Human-readable system label shown in UI, governance, and operations surfaces. */
|
|
6327
|
+
label: LabelSchema.optional(),
|
|
6328
|
+
/** @deprecated Use label. Accepted for pre-consolidation System declarations. */
|
|
6329
|
+
title: LabelSchema.optional(),
|
|
6330
|
+
/** One-paragraph purpose statement for the bounded context. */
|
|
6331
|
+
description: DescriptionSchema.optional(),
|
|
6332
|
+
/** Closed system shape enum; catalog values remain tenant-defined. */
|
|
6333
|
+
kind: SystemKindSchema.optional(),
|
|
6334
|
+
/** Optional self-reference for System hierarchy. */
|
|
6335
|
+
parentSystemId: SystemIdSchema.optional(),
|
|
6336
|
+
/** Optional UI presence. Systems without UI omit this. */
|
|
6337
|
+
ui: SystemUiSchema.optional(),
|
|
6338
|
+
/** Canonical lifecycle state. Replaces Feature.enabled/devOnly and System.status. */
|
|
6339
|
+
lifecycle: SystemLifecycleSchema.optional(),
|
|
6340
|
+
/** Optional role responsible for this system. */
|
|
6341
|
+
responsibleRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
|
|
6342
|
+
/** Optional knowledge nodes that govern this system. */
|
|
6343
|
+
governedByKnowledge: z.array(ModelIdSchema.meta({ ref: "knowledge" })).default([]).optional(),
|
|
6344
|
+
/** Optional actions this system exposes or consumes. */
|
|
6345
|
+
actions: z.array(ActionRefSchema).optional(),
|
|
6346
|
+
/** Optional operational policies that apply to this system. */
|
|
6347
|
+
policies: z.array(ModelIdSchema.meta({ ref: "policy" })).default([]).optional(),
|
|
6348
|
+
/** Optional goals this system contributes to. */
|
|
6349
|
+
drivesGoals: z.array(ModelIdSchema.meta({ ref: "goal" })).default([]).optional(),
|
|
6350
|
+
/** @deprecated Use lifecycle. Accepted for one publish cycle. */
|
|
6351
|
+
status: SystemStatusSchema.optional(),
|
|
6352
|
+
/** @deprecated Use ui.path. Kept for one-cycle Feature compatibility. */
|
|
6353
|
+
path: PathSchema.optional(),
|
|
6354
|
+
/** @deprecated Use ui.icon. Kept for one-cycle Feature compatibility. */
|
|
6355
|
+
icon: IconNameSchema.optional(),
|
|
6356
|
+
/** @deprecated Feature color token, retained for one-cycle compatibility. */
|
|
6357
|
+
color: ColorTokenSchema.optional(),
|
|
6358
|
+
/** @deprecated UI placement hint, retained for one-cycle compatibility. */
|
|
6359
|
+
uiPosition: UiPositionSchema.optional(),
|
|
6360
|
+
/** @deprecated Use lifecycle. */
|
|
6361
|
+
enabled: z.boolean().optional(),
|
|
6362
|
+
/** @deprecated Use lifecycle: "beta". */
|
|
6363
|
+
devOnly: z.boolean().optional(),
|
|
6364
|
+
requiresAdmin: z.boolean().optional(),
|
|
6365
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
6366
|
+
order: z.number(),
|
|
6367
|
+
/**
|
|
6368
|
+
* System-local JSON settings and defaults. Strongly typed OM fields,
|
|
6369
|
+
* secrets, credentials, and runtime state stay outside this bucket.
|
|
6370
|
+
*/
|
|
6371
|
+
config: SystemConfigSchema,
|
|
6372
|
+
/**
|
|
6373
|
+
* System-owned ontology declarations. `systems` is now the canonical child
|
|
6374
|
+
* key; this scope holds the object, action, catalog, link, event, and
|
|
6375
|
+
* shared contract records owned by this system.
|
|
6376
|
+
*/
|
|
6377
|
+
ontology: OntologyScopeSchema.optional(),
|
|
6378
|
+
/**
|
|
6379
|
+
* @deprecated Compatibility-only bridge for old tenant content nodes and
|
|
6380
|
+
* migration readers. New schema/catalog authoring belongs in ontology;
|
|
6381
|
+
* new system-local settings belong in config. Bridge nodes are keyed by
|
|
6382
|
+
* local NodeId and may still project to content-node:* graph IDs.
|
|
6383
|
+
*/
|
|
6384
|
+
content: z.record(z.string().trim().min(1).max(200), ContentNodeSchema).optional(),
|
|
6385
|
+
/**
|
|
6386
|
+
* Recursive child systems, authored via nesting (per L11).
|
|
6387
|
+
* The key is the local system id; the full path is computed by joining
|
|
6388
|
+
* ancestor keys with `.` (e.g. parent key `'sales'` + child key `'crm'` → `'sales.crm'`).
|
|
6389
|
+
* Per Phase 4: `id` and `parentSystemId` fields will be removed in favour of
|
|
6390
|
+
* position-derived paths. Both still exist on this schema for backward compat.
|
|
6391
|
+
*/
|
|
6392
|
+
systems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional(),
|
|
6393
|
+
/** @deprecated Use systems. Accepted as a compatibility alias during the ontology bridge. */
|
|
6394
|
+
subsystems: z.lazy(() => z.record(z.string().trim().min(1).max(100), SystemEntrySchema)).optional()
|
|
6395
|
+
}).refine((system) => system.label !== void 0 || system.title !== void 0, {
|
|
6396
|
+
path: ["label"],
|
|
6397
|
+
message: "System must provide label or title"
|
|
6398
|
+
}).transform((system) => {
|
|
6399
|
+
const normalizedSystem = system.systems !== void 0 && system.subsystems === void 0 ? { ...system, subsystems: system.systems } : system;
|
|
6400
|
+
if (normalizedSystem.status === void 0) return normalizedSystem;
|
|
6401
|
+
console.warn("[organization-model] System.status is deprecated; use System.lifecycle instead.");
|
|
6402
|
+
return normalizedSystem.lifecycle === void 0 ? { ...normalizedSystem, lifecycle: normalizedSystem.status } : normalizedSystem;
|
|
6403
|
+
});
|
|
6404
|
+
var SystemsDomainSchema = z.record(z.string(), SystemEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
6405
|
+
message: "Each system entry id must match its map key"
|
|
6406
|
+
}).default({});
|
|
6407
|
+
var DEFAULT_ORGANIZATION_MODEL_SYSTEMS = {};
|
|
6408
|
+
|
|
6409
|
+
// ../core/src/organization-model/domains/resources.ts
|
|
6410
|
+
z.enum(["workflow", "agent", "integration", "script"]).meta({ label: "Resource kind", color: "orange" });
|
|
6411
|
+
var ResourceGovernanceStatusSchema = z.enum(["active", "deprecated", "archived"]).meta({ label: "Governance status", color: "teal" });
|
|
6412
|
+
var AgentKindSchema = z.enum(["orchestrator", "specialist", "utility", "platform"]).meta({ label: "Agent kind", color: "violet" });
|
|
6413
|
+
var ScriptResourceLanguageSchema = z.enum(["shell", "sql", "typescript", "python"]).meta({ label: "Language" });
|
|
6414
|
+
var CodeReferenceRoleSchema = z.enum(["entrypoint", "handler", "schema", "test", "docs", "config"]).meta({ label: "Code reference role", color: "blue" });
|
|
6415
|
+
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");
|
|
6416
|
+
var EventIdSchema = z.string().trim().min(1).max(300).regex(
|
|
6417
|
+
/^[A-Za-z0-9]+(?:[-._][A-Za-z0-9]+)*:[a-z0-9]+(?:[-._][a-z0-9]+)*$/,
|
|
6418
|
+
"Event IDs must use <owner-id>:<event-key>"
|
|
6419
|
+
);
|
|
6420
|
+
var EventKeySchema = ModelIdSchema;
|
|
6421
|
+
var EventEmissionDescriptorSchema = z.object({
|
|
6422
|
+
eventKey: EventKeySchema,
|
|
6423
|
+
label: z.string().trim().min(1).max(120),
|
|
6424
|
+
payloadSchema: ModelIdSchema.optional(),
|
|
6425
|
+
lifecycle: SystemLifecycleSchema.optional()
|
|
6426
|
+
});
|
|
6427
|
+
EventEmissionDescriptorSchema.extend({
|
|
6428
|
+
id: EventIdSchema,
|
|
6429
|
+
ownerId: z.union([ResourceIdSchema, ModelIdSchema]),
|
|
6430
|
+
ownerKind: z.enum(["resource", "entity"]).meta({ label: "Owner kind" })
|
|
6431
|
+
});
|
|
6432
|
+
var ResourceOntologyBindingSchema = z.object({
|
|
6433
|
+
implements: z.array(OntologyIdSchema).optional(),
|
|
6434
|
+
reads: z.array(OntologyIdSchema).optional(),
|
|
6435
|
+
writes: z.array(OntologyIdSchema).optional(),
|
|
6436
|
+
usesCatalogs: z.array(OntologyIdSchema).optional(),
|
|
6437
|
+
emits: z.array(OntologyIdSchema).optional()
|
|
6438
|
+
});
|
|
6439
|
+
var CodeReferenceSchema = z.object({
|
|
6440
|
+
path: z.string().trim().min(1).max(500).regex(/^[A-Za-z0-9_./$@()[\] -]+$/, "Code reference paths must be repo-relative paths"),
|
|
6441
|
+
role: CodeReferenceRoleSchema,
|
|
6442
|
+
symbol: z.string().trim().min(1).max(200).optional(),
|
|
6443
|
+
description: z.string().trim().min(1).max(300).optional()
|
|
6444
|
+
});
|
|
6445
|
+
var ResourceEntryBaseSchema = z.object({
|
|
6446
|
+
/** Canonical resource id; runtime resourceId derives from this value. */
|
|
6447
|
+
id: ResourceIdSchema,
|
|
6448
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
6449
|
+
order: z.number().default(0),
|
|
6450
|
+
/** Required single System membership — value is a dot-separated system path (e.g. "sales.lead-gen"). */
|
|
6451
|
+
systemPath: SystemPathSchema.meta({ ref: "system" }),
|
|
6452
|
+
/** Optional role responsible for maintaining this resource. */
|
|
6453
|
+
ownerRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
|
|
6454
|
+
status: ResourceGovernanceStatusSchema,
|
|
6455
|
+
/**
|
|
6456
|
+
* Ontology contract bindings for the semantic work this resource performs.
|
|
6457
|
+
* `emits` stays nested here so top-level resource emits descriptors remain
|
|
6458
|
+
* compatible with graph event projection during the bridge.
|
|
6459
|
+
*/
|
|
6460
|
+
ontology: ResourceOntologyBindingSchema.optional(),
|
|
6461
|
+
/** Repo-relative implementation breadcrumbs for agents and operators. */
|
|
6462
|
+
codeRefs: z.array(CodeReferenceSchema).default([])
|
|
6463
|
+
});
|
|
6464
|
+
var WorkflowResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
6465
|
+
kind: z.literal("workflow"),
|
|
6466
|
+
/** Mirrors WorkflowConfig.actionKey when the runtime workflow has one. */
|
|
6467
|
+
actionKey: z.string().trim().min(1).max(255).optional(),
|
|
6468
|
+
emits: z.array(EventEmissionDescriptorSchema).optional()
|
|
6469
|
+
});
|
|
6470
|
+
var AgentResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
6471
|
+
kind: z.literal("agent"),
|
|
6472
|
+
/** Mirrors code-side AgentConfig.kind. */
|
|
6473
|
+
agentKind: AgentKindSchema,
|
|
6474
|
+
/** Role this agent embodies, if any. */
|
|
6475
|
+
actsAsRoleId: ModelIdSchema.meta({ ref: "role" }).optional(),
|
|
6476
|
+
/** Mirrors AgentConfig.sessionCapable. */
|
|
6477
|
+
sessionCapable: z.boolean(),
|
|
6478
|
+
/** Broad/composite callable entry points orchestrated by this agent. */
|
|
6479
|
+
invocations: z.array(ActionInvocationSchema).default([]),
|
|
6480
|
+
emits: z.array(EventEmissionDescriptorSchema).optional()
|
|
6481
|
+
});
|
|
6482
|
+
var IntegrationResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
6483
|
+
kind: z.literal("integration"),
|
|
6484
|
+
provider: z.string().trim().min(1).max(100)
|
|
6485
|
+
});
|
|
6486
|
+
var ScriptResourceSourceSchema = z.union([
|
|
6487
|
+
z.string().trim().min(1).max(5e4),
|
|
6488
|
+
z.object({
|
|
6489
|
+
file: z.string().trim().min(1).max(500)
|
|
6490
|
+
})
|
|
6491
|
+
]);
|
|
6492
|
+
var ScriptResourceEntrySchema = ResourceEntryBaseSchema.extend({
|
|
6493
|
+
kind: z.literal("script"),
|
|
6494
|
+
language: ScriptResourceLanguageSchema,
|
|
6495
|
+
source: ScriptResourceSourceSchema
|
|
6496
|
+
});
|
|
6497
|
+
var ResourceEntrySchema = z.discriminatedUnion("kind", [
|
|
6498
|
+
WorkflowResourceEntrySchema,
|
|
6499
|
+
AgentResourceEntrySchema,
|
|
6500
|
+
IntegrationResourceEntrySchema,
|
|
6501
|
+
ScriptResourceEntrySchema
|
|
6502
|
+
]);
|
|
6503
|
+
var ResourcesDomainSchema = z.record(z.string(), ResourceEntrySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
6504
|
+
message: "Each resource entry id must match its map key"
|
|
6505
|
+
}).default({});
|
|
6506
|
+
var DEFAULT_ORGANIZATION_MODEL_RESOURCES = {};
|
|
6507
|
+
|
|
6508
|
+
// ../core/src/organization-model/domains/roles.ts
|
|
6509
|
+
var RoleIdSchema = ModelIdSchema;
|
|
6510
|
+
var HumanRoleHolderSchema = z.object({
|
|
6511
|
+
kind: z.literal("human"),
|
|
6512
|
+
userId: z.string().trim().min(1).max(200)
|
|
6513
|
+
});
|
|
6514
|
+
var AgentRoleHolderSchema = z.object({
|
|
6515
|
+
kind: z.literal("agent"),
|
|
6516
|
+
agentId: ResourceIdSchema.meta({ ref: "resource" })
|
|
6517
|
+
});
|
|
6518
|
+
var TeamRoleHolderSchema = z.object({
|
|
6519
|
+
kind: z.literal("team"),
|
|
6520
|
+
memberIds: z.array(z.string().trim().min(1).max(200)).min(1)
|
|
6521
|
+
});
|
|
6522
|
+
var RoleHolderSchema = z.discriminatedUnion("kind", [
|
|
6523
|
+
HumanRoleHolderSchema,
|
|
6524
|
+
AgentRoleHolderSchema,
|
|
6525
|
+
TeamRoleHolderSchema
|
|
6526
|
+
]);
|
|
6527
|
+
var RoleHoldersSchema = z.union([RoleHolderSchema, z.array(RoleHolderSchema).min(1)]);
|
|
6528
|
+
var RoleSchema = z.object({
|
|
6529
|
+
/** Stable unique identifier for the role (e.g. "role-ceo", "role-head-of-sales"). */
|
|
6530
|
+
id: RoleIdSchema,
|
|
6531
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
6532
|
+
order: z.number(),
|
|
6533
|
+
/** Human-readable title shown to agents and in UI (e.g. "CEO", "Head of Sales"). */
|
|
6534
|
+
title: z.string().trim().min(1).max(200),
|
|
6535
|
+
/**
|
|
6536
|
+
* List of responsibilities this role owns - plain-language descriptions of
|
|
6537
|
+
* what the person in this role is accountable for delivering.
|
|
6538
|
+
* Defaults to empty array so minimal role definitions stay concise.
|
|
6539
|
+
*/
|
|
6540
|
+
responsibilities: z.array(z.string().trim().max(500)).default([]),
|
|
6541
|
+
/**
|
|
6542
|
+
* Optional: ID of another role this role reports to.
|
|
6543
|
+
* When present, must reference another `roles[].id` in the same organization.
|
|
6544
|
+
*/
|
|
6545
|
+
reportsToId: RoleIdSchema.meta({ ref: "role" }).optional(),
|
|
6546
|
+
/**
|
|
6547
|
+
* Optional: human, agent, or team holder currently filling this role.
|
|
6548
|
+
* Agent holders reference OM Resource IDs and are validated at the model level.
|
|
6549
|
+
*/
|
|
6550
|
+
heldBy: RoleHoldersSchema.optional(),
|
|
6551
|
+
/**
|
|
6552
|
+
* Optional Systems this role is accountable for.
|
|
6553
|
+
* Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
|
|
6554
|
+
*/
|
|
6555
|
+
responsibleFor: z.array(SystemIdSchema.meta({ ref: "system" })).optional()
|
|
6556
|
+
});
|
|
6557
|
+
var RolesDomainSchema = z.record(z.string(), RoleSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
6558
|
+
message: "Each role entry id must match its map key"
|
|
6559
|
+
}).default({});
|
|
6560
|
+
var DEFAULT_ORGANIZATION_MODEL_ROLES = {};
|
|
6561
|
+
var KeyResultSchema = z.object({
|
|
6562
|
+
/** Stable unique identifier for the measurable outcome (e.g. "kr-revenue-q1"). */
|
|
6563
|
+
id: z.string().trim().min(1).max(100),
|
|
6564
|
+
/** Plain-language description of this measurable outcome (e.g. "Increase trial-to-paid conversion"). */
|
|
6565
|
+
description: z.string().trim().min(1).max(500),
|
|
6566
|
+
/**
|
|
6567
|
+
* What is being measured — the metric name (e.g. "monthly revenue", "NPS score",
|
|
6568
|
+
* "trial-to-paid conversion rate"). Free-form string.
|
|
6569
|
+
*/
|
|
6570
|
+
targetMetric: z.string().trim().min(1).max(200),
|
|
6571
|
+
/** Current measured value. Defaults to 0 when not yet tracked. */
|
|
6572
|
+
currentValue: z.number().default(0),
|
|
6573
|
+
/**
|
|
6574
|
+
* Target value to reach for this measurable outcome to be considered achieved.
|
|
6575
|
+
* Optional — omit if the outcome is directional (e.g. "reduce churn") without
|
|
6576
|
+
* a hard numeric target.
|
|
6577
|
+
*/
|
|
6578
|
+
targetValue: z.number().optional()
|
|
6579
|
+
});
|
|
6580
|
+
var ISO_DATE_REGEX = /^\d{4}-\d{2}-\d{2}$/;
|
|
6581
|
+
var ObjectiveSchema = z.object({
|
|
6582
|
+
/** Stable unique identifier for the goal (e.g. "goal-grow-arr-q1-2026"). */
|
|
6583
|
+
id: z.string().trim().min(1).max(100),
|
|
6584
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
6585
|
+
order: z.number(),
|
|
6586
|
+
/** Plain-language description of what the organization wants to achieve. */
|
|
6587
|
+
description: z.string().trim().min(1).max(1e3),
|
|
6588
|
+
/**
|
|
6589
|
+
* Start of the period this goal is active for — ISO 8601 date string (YYYY-MM-DD).
|
|
6590
|
+
* Must be strictly before `periodEnd`.
|
|
6591
|
+
*/
|
|
6592
|
+
periodStart: z.string().regex(ISO_DATE_REGEX, "periodStart must be an ISO date string (YYYY-MM-DD)"),
|
|
6593
|
+
/**
|
|
6594
|
+
* End of the period this goal is active for — ISO 8601 date string (YYYY-MM-DD).
|
|
6595
|
+
* Must be strictly after `periodStart`.
|
|
6596
|
+
* Enforced via `OrganizationModelSchema.superRefine()`.
|
|
6597
|
+
*/
|
|
6598
|
+
periodEnd: z.string().regex(ISO_DATE_REGEX, "periodEnd must be an ISO date string (YYYY-MM-DD)"),
|
|
6599
|
+
/**
|
|
6600
|
+
* List of measurable outcomes that define success for this goal.
|
|
6601
|
+
* Defaults to empty array so goals can be declared before outcomes are defined.
|
|
6602
|
+
*/
|
|
6603
|
+
keyResults: z.array(KeyResultSchema).default([])
|
|
6604
|
+
});
|
|
6605
|
+
var GoalsDomainSchema = z.record(z.string(), ObjectiveSchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
6606
|
+
message: "Each objective entry id must match its map key"
|
|
6607
|
+
}).default({});
|
|
6608
|
+
var DEFAULT_ORGANIZATION_MODEL_GOALS = {};
|
|
6609
|
+
var PolicyIdSchema = ModelIdSchema;
|
|
6610
|
+
var PolicyApplicabilitySchema = z.object({
|
|
6611
|
+
systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
|
|
6612
|
+
actionIds: z.array(ModelIdSchema.meta({ ref: "action" })).default([]),
|
|
6613
|
+
resourceIds: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]),
|
|
6614
|
+
roleIds: z.array(ModelIdSchema.meta({ ref: "role" })).default([])
|
|
6615
|
+
});
|
|
6616
|
+
var PolicyTriggerSchema = z.discriminatedUnion("kind", [
|
|
6617
|
+
z.object({
|
|
6618
|
+
kind: z.literal("event"),
|
|
6619
|
+
eventId: EventIdSchema.meta({ ref: "event" })
|
|
6620
|
+
}),
|
|
6621
|
+
z.object({
|
|
6622
|
+
kind: z.literal("action-invocation"),
|
|
6623
|
+
actionId: ModelIdSchema.meta({ ref: "action" })
|
|
6624
|
+
}),
|
|
6625
|
+
z.object({
|
|
6626
|
+
kind: z.literal("schedule"),
|
|
6627
|
+
cron: z.string().trim().min(1).max(120)
|
|
6628
|
+
}),
|
|
6629
|
+
z.object({
|
|
6630
|
+
kind: z.literal("manual")
|
|
6631
|
+
})
|
|
6632
|
+
]);
|
|
6633
|
+
var PolicyPredicateSchema = z.discriminatedUnion("kind", [
|
|
6634
|
+
z.object({
|
|
6635
|
+
kind: z.literal("always")
|
|
6636
|
+
}),
|
|
6637
|
+
z.object({
|
|
6638
|
+
kind: z.literal("expression"),
|
|
6639
|
+
expression: z.string().trim().min(1).max(2e3)
|
|
6640
|
+
}),
|
|
6641
|
+
z.object({
|
|
6642
|
+
kind: z.literal("threshold"),
|
|
6643
|
+
metric: ModelIdSchema,
|
|
6644
|
+
operator: z.enum(["lt", "lte", "eq", "gte", "gt"]).meta({ label: "Operator" }),
|
|
6645
|
+
value: z.number()
|
|
6646
|
+
})
|
|
6647
|
+
]);
|
|
6648
|
+
var PolicyEffectSchema = z.discriminatedUnion("kind", [
|
|
6649
|
+
z.object({
|
|
6650
|
+
kind: z.literal("require-approval"),
|
|
6651
|
+
roleId: ModelIdSchema.meta({ ref: "role" }).optional()
|
|
6652
|
+
}),
|
|
6653
|
+
z.object({
|
|
6654
|
+
kind: z.literal("invoke-action"),
|
|
6655
|
+
actionId: ModelIdSchema.meta({ ref: "action" })
|
|
6656
|
+
}),
|
|
6657
|
+
z.object({
|
|
6658
|
+
kind: z.literal("notify-role"),
|
|
6659
|
+
roleId: ModelIdSchema.meta({ ref: "role" })
|
|
6660
|
+
}),
|
|
6661
|
+
z.object({
|
|
6662
|
+
kind: z.literal("block")
|
|
6663
|
+
})
|
|
6664
|
+
]);
|
|
6665
|
+
var PolicySchema = z.object({
|
|
6666
|
+
id: PolicyIdSchema,
|
|
6667
|
+
/** Domain-map iteration order. Convention: multiples of 10 (10, 20, 30, ...) to allow easy insertion. */
|
|
6668
|
+
order: z.number(),
|
|
6669
|
+
label: LabelSchema,
|
|
6670
|
+
description: DescriptionSchema.optional(),
|
|
6671
|
+
trigger: PolicyTriggerSchema,
|
|
6672
|
+
predicate: PolicyPredicateSchema.default({ kind: "always" }),
|
|
6673
|
+
actions: z.array(PolicyEffectSchema).min(1),
|
|
6674
|
+
appliesTo: PolicyApplicabilitySchema.default({
|
|
6675
|
+
systemIds: [],
|
|
6676
|
+
actionIds: [],
|
|
6677
|
+
resourceIds: [],
|
|
6678
|
+
roleIds: []
|
|
6679
|
+
}),
|
|
6680
|
+
lifecycle: z.enum(["draft", "beta", "active", "deprecated", "archived"]).meta({ label: "Lifecycle", color: "teal" }).default("active")
|
|
6681
|
+
});
|
|
6682
|
+
var PoliciesDomainSchema = z.record(z.string(), PolicySchema).refine((record) => Object.entries(record).every(([key, entry]) => entry.id === key), {
|
|
6683
|
+
message: "Each policy entry id must match its map key"
|
|
6684
|
+
}).default({});
|
|
6685
|
+
var DEFAULT_ORGANIZATION_MODEL_POLICIES = {};
|
|
6686
|
+
|
|
6687
|
+
// ../core/src/organization-model/content-kinds/registry.ts
|
|
6688
|
+
function defineContentType(def) {
|
|
6689
|
+
return def;
|
|
6690
|
+
}
|
|
6691
|
+
var PipelinePayloadSchema = z.object({
|
|
6692
|
+
/**
|
|
6693
|
+
* Local NodeId of the entity this pipeline applies to (e.g. 'crm.deal').
|
|
6694
|
+
* `.meta({ ref: 'entity' })` enables SchemaDrivenFieldList to render a
|
|
6695
|
+
* clickable graph link to the referenced entity node.
|
|
6696
|
+
*/
|
|
6697
|
+
entityId: z.string().trim().min(1).max(200).meta({ label: "Entity", ref: "entity", hint: "The entity type this pipeline tracks" }),
|
|
6698
|
+
/**
|
|
6699
|
+
* Optional Kanban column color token for UI rendering.
|
|
6700
|
+
*/
|
|
6701
|
+
kanbanColor: z.string().trim().min(1).max(40).optional().meta({ label: "Kanban color", hint: "UI color token" })
|
|
6702
|
+
});
|
|
6703
|
+
var pipelineKind = defineContentType({
|
|
6704
|
+
kind: "schema",
|
|
6705
|
+
type: "pipeline",
|
|
6706
|
+
label: "Pipeline",
|
|
6707
|
+
description: "A named progression pipeline that applies to a specific entity type.",
|
|
6708
|
+
payloadSchema: PipelinePayloadSchema,
|
|
6709
|
+
parentTypes: []
|
|
6710
|
+
});
|
|
6711
|
+
var StagePayloadSchema = z.object({
|
|
6712
|
+
/**
|
|
6713
|
+
* Semantic classification for this stage.
|
|
6714
|
+
* Drives color, icon, and CRM-priority logic in consuming views.
|
|
6715
|
+
* Optional — prospecting stages use data.entityKind instead.
|
|
6716
|
+
* Enum aligned with SalesStageSemanticClassSchema (sales.ts).
|
|
6717
|
+
*/
|
|
6718
|
+
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" })
|
|
6719
|
+
});
|
|
6720
|
+
var stageKind = defineContentType({
|
|
6721
|
+
kind: "schema",
|
|
6722
|
+
type: "stage",
|
|
6723
|
+
label: "Stage",
|
|
6724
|
+
description: "A stage within a pipeline. Must be parented under a schema:pipeline content node.",
|
|
6725
|
+
payloadSchema: StagePayloadSchema,
|
|
6726
|
+
parentTypes: ["schema:pipeline"]
|
|
6727
|
+
});
|
|
6728
|
+
var TemplatePayloadSchema = z.object({
|
|
6729
|
+
/**
|
|
6730
|
+
* Optional description surfaced in the KB describe view and tooling.
|
|
6731
|
+
*/
|
|
6732
|
+
description: z.string().trim().min(1).max(2e3).optional().meta({ label: "Description", hint: "What this template is used for" })
|
|
6733
|
+
});
|
|
6734
|
+
var templateKind = defineContentType({
|
|
6735
|
+
kind: "schema",
|
|
6736
|
+
type: "template",
|
|
6737
|
+
label: "Template",
|
|
6738
|
+
description: "A named build template (e.g. a prospecting pipeline sequence).",
|
|
6739
|
+
payloadSchema: TemplatePayloadSchema,
|
|
6740
|
+
parentTypes: []
|
|
6741
|
+
});
|
|
6742
|
+
var TemplateStepPayloadSchema = z.object({
|
|
6743
|
+
/**
|
|
6744
|
+
* Which entity type this step primarily operates on.
|
|
6745
|
+
*/
|
|
6746
|
+
primaryEntity: z.enum(["company", "contact"]).meta({ label: "Primary entity", hint: "Entity type this step processes", color: "blue" }),
|
|
6747
|
+
/**
|
|
6748
|
+
* Action key identifying the workflow action executed by this step.
|
|
6749
|
+
* `.meta({ ref: 'action' })` enables SchemaDrivenFieldList to render a
|
|
6750
|
+
* clickable graph link.
|
|
6751
|
+
*/
|
|
6752
|
+
actionKey: z.string().trim().min(1).max(200).meta({ label: "Action", ref: "action", hint: "Workflow action executed by this step" }),
|
|
6753
|
+
/**
|
|
6754
|
+
* IDs of sibling step local NodeIds this step depends on.
|
|
6755
|
+
*/
|
|
6756
|
+
dependsOn: z.array(z.string().trim().min(1).max(200)).optional().meta({ label: "Depends on", hint: "Local NodeIds of prerequisite steps" })
|
|
6757
|
+
});
|
|
6758
|
+
var templateStepKind = defineContentType({
|
|
6759
|
+
kind: "schema",
|
|
6760
|
+
type: "template-step",
|
|
6761
|
+
label: "Template Step",
|
|
6762
|
+
description: "A step within a build template. Must be parented under a schema:template content node.",
|
|
6763
|
+
payloadSchema: TemplateStepPayloadSchema,
|
|
6764
|
+
parentTypes: ["schema:template"]
|
|
6765
|
+
});
|
|
6766
|
+
var StatusFlowPayloadSchema = z.object({
|
|
6767
|
+
/**
|
|
6768
|
+
* Which entity scope this status flow governs.
|
|
6769
|
+
*/
|
|
6770
|
+
appliesTo: z.enum(["project", "milestone", "task"]).meta({ label: "Applies to", hint: "Entity scope governed by this status flow", color: "blue" })
|
|
6771
|
+
});
|
|
6772
|
+
var statusFlowKind = defineContentType({
|
|
6773
|
+
kind: "schema",
|
|
6774
|
+
type: "status-flow",
|
|
6775
|
+
label: "Status Flow",
|
|
6776
|
+
description: "A named set of statuses governing a project, milestone, or task entity.",
|
|
6777
|
+
payloadSchema: StatusFlowPayloadSchema,
|
|
6778
|
+
parentTypes: []
|
|
6779
|
+
});
|
|
6780
|
+
var StatusPayloadSchema = z.object({
|
|
6781
|
+
/**
|
|
6782
|
+
* Semantic classification string for this status.
|
|
6783
|
+
* Free-form to allow tenant-defined classifications (e.g. 'active', 'blocked',
|
|
6784
|
+
* 'completed'). Used by UI to apply color and icon fallbacks.
|
|
6785
|
+
* Optional — status nodes may omit this when the label is self-descriptive.
|
|
6786
|
+
*/
|
|
6787
|
+
semanticClass: z.string().trim().min(1).max(100).optional().meta({ label: "Semantic class", hint: "Semantic meaning of this status (e.g. active, blocked, completed)" }),
|
|
6788
|
+
/**
|
|
6789
|
+
* Optional UI color token override for this status.
|
|
6790
|
+
*/
|
|
6791
|
+
color: z.string().trim().min(1).max(40).optional().meta({ label: "Color", hint: "UI color token" })
|
|
6792
|
+
});
|
|
6793
|
+
var statusKind = defineContentType({
|
|
6794
|
+
kind: "schema",
|
|
6795
|
+
type: "status",
|
|
6796
|
+
label: "Status",
|
|
6797
|
+
description: "A single status within a status flow. Must be parented under a schema:status-flow content node.",
|
|
6798
|
+
payloadSchema: StatusPayloadSchema,
|
|
6799
|
+
parentTypes: ["schema:status-flow"]
|
|
6800
|
+
});
|
|
6801
|
+
var ConfigKvPayloadSchema = z.object({
|
|
6802
|
+
/**
|
|
6803
|
+
* Flat key-value entries. Values are JSON primitives.
|
|
6804
|
+
* Keys are short identifiers (e.g. 'maxBatchSize', 'featureEnabled').
|
|
6805
|
+
*/
|
|
6806
|
+
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)" })
|
|
6807
|
+
});
|
|
6808
|
+
var configKvKind = defineContentType({
|
|
6809
|
+
kind: "config",
|
|
6810
|
+
type: "kv",
|
|
6811
|
+
label: "Key-Value Config",
|
|
6812
|
+
description: "A flat key-value configuration store co-located with a system. Values are JSON primitives.",
|
|
6813
|
+
payloadSchema: ConfigKvPayloadSchema,
|
|
6814
|
+
parentTypes: []
|
|
6815
|
+
});
|
|
6816
|
+
|
|
6817
|
+
// ../core/src/organization-model/content-kinds/index.ts
|
|
6818
|
+
var CONTENT_KIND_REGISTRY = {
|
|
6819
|
+
"schema:pipeline": pipelineKind,
|
|
6820
|
+
"schema:stage": stageKind,
|
|
6821
|
+
"schema:template": templateKind,
|
|
6822
|
+
"schema:template-step": templateStepKind,
|
|
6823
|
+
"schema:status-flow": statusFlowKind,
|
|
6824
|
+
"schema:status": statusKind,
|
|
6825
|
+
"config:kv": configKvKind
|
|
6826
|
+
};
|
|
6827
|
+
function lookupContentType(kind, type) {
|
|
6828
|
+
const key = `${kind}:${type}`;
|
|
6829
|
+
return CONTENT_KIND_REGISTRY[key];
|
|
6830
|
+
}
|
|
6831
|
+
var SurfaceTypeSchema = z.enum(["page", "dashboard", "graph", "detail", "list", "settings"]).meta({ label: "Surface type", color: "blue" });
|
|
6832
|
+
z.object({
|
|
6833
|
+
id: ModelIdSchema,
|
|
6834
|
+
label: LabelSchema,
|
|
6835
|
+
path: PathSchema,
|
|
6836
|
+
surfaceType: SurfaceTypeSchema,
|
|
6837
|
+
description: DescriptionSchema.optional(),
|
|
6838
|
+
enabled: z.boolean().default(true),
|
|
6839
|
+
devOnly: z.boolean().optional(),
|
|
6840
|
+
icon: IconNameSchema.optional(),
|
|
6841
|
+
systemIds: z.array(ModelIdSchema.meta({ ref: "system" })).default([]),
|
|
6842
|
+
entityIds: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]),
|
|
6843
|
+
resourceIds: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]),
|
|
6844
|
+
actionIds: z.array(ModelIdSchema.meta({ ref: "action" })).default([]),
|
|
6845
|
+
parentId: ModelIdSchema.meta({ ref: "surface" }).optional()
|
|
6846
|
+
});
|
|
6847
|
+
var SidebarSurfaceTargetsSchema = z.object({
|
|
6848
|
+
systems: z.array(ModelIdSchema.meta({ ref: "system" })).default([]).optional(),
|
|
6849
|
+
entities: z.array(ModelIdSchema.meta({ ref: "entity" })).default([]).optional(),
|
|
6850
|
+
resources: z.array(ModelIdSchema.meta({ ref: "resource" })).default([]).optional(),
|
|
6851
|
+
actions: z.array(ModelIdSchema.meta({ ref: "action" })).default([]).optional()
|
|
6852
|
+
}).default({});
|
|
6853
|
+
var SidebarNodeSchema = z.lazy(
|
|
6854
|
+
() => z.discriminatedUnion("type", [
|
|
6855
|
+
z.object({
|
|
6856
|
+
type: z.literal("group"),
|
|
6857
|
+
label: LabelSchema,
|
|
6858
|
+
description: DescriptionSchema.optional(),
|
|
6859
|
+
icon: IconNameSchema.optional(),
|
|
6860
|
+
order: z.number().int().optional(),
|
|
6861
|
+
children: z.record(z.string(), SidebarNodeSchema).default({})
|
|
6862
|
+
}),
|
|
6863
|
+
z.object({
|
|
6864
|
+
type: z.literal("surface"),
|
|
6865
|
+
label: LabelSchema,
|
|
6866
|
+
path: PathSchema,
|
|
6867
|
+
surfaceType: SurfaceTypeSchema,
|
|
6868
|
+
description: DescriptionSchema.optional(),
|
|
6869
|
+
icon: IconNameSchema.optional(),
|
|
6870
|
+
order: z.number().int().optional(),
|
|
6871
|
+
targets: SidebarSurfaceTargetsSchema.optional(),
|
|
6872
|
+
devOnly: z.boolean().optional(),
|
|
6873
|
+
requiresAdmin: z.boolean().optional()
|
|
6874
|
+
})
|
|
6875
|
+
])
|
|
6876
|
+
);
|
|
6877
|
+
var SidebarSectionSchema = z.record(z.string(), SidebarNodeSchema).default({});
|
|
6878
|
+
var SidebarNavigationSchema = z.object({
|
|
6879
|
+
primary: SidebarSectionSchema,
|
|
6880
|
+
bottom: SidebarSectionSchema
|
|
6881
|
+
}).default({ primary: {}, bottom: {} });
|
|
6882
|
+
var OrganizationModelNavigationSchema = z.object({
|
|
6883
|
+
sidebar: SidebarNavigationSchema
|
|
6884
|
+
}).default({ sidebar: { primary: {}, bottom: {} } });
|
|
6885
|
+
z.object({
|
|
6886
|
+
id: ModelIdSchema,
|
|
6887
|
+
label: LabelSchema,
|
|
6888
|
+
placement: z.string().trim().min(1).max(50),
|
|
6889
|
+
surfaceIds: z.array(ModelIdSchema.meta({ ref: "surface" })).default([])
|
|
6890
|
+
});
|
|
6891
|
+
var KnowledgeTargetKindSchema = z.enum([
|
|
6892
|
+
"system",
|
|
6893
|
+
"resource",
|
|
6894
|
+
"knowledge",
|
|
6895
|
+
"stage",
|
|
6896
|
+
"action",
|
|
6897
|
+
"role",
|
|
6898
|
+
"goal",
|
|
6899
|
+
"customer-segment",
|
|
6900
|
+
"offering",
|
|
6901
|
+
"ontology",
|
|
6902
|
+
// D4: content nodes are a valid knowledge target after compound-domain data moved into system.content
|
|
6903
|
+
"content-node"
|
|
6904
|
+
]).meta({ label: "Target kind" });
|
|
6905
|
+
var KnowledgeTargetRefSchema = z.object({
|
|
6906
|
+
kind: KnowledgeTargetKindSchema,
|
|
6907
|
+
// D4: content-node targets use a qualified id format '<system-path>:<local-content-id>'.
|
|
6908
|
+
// Ontology targets use the canonical '<scope>:<kind>/<local-id>' ontology id format.
|
|
6909
|
+
// Business-logic validation of target existence is done in OrganizationModelSchema.superRefine.
|
|
6910
|
+
id: z.string().trim().min(1).max(300)
|
|
6911
|
+
}).superRefine((target, ctx) => {
|
|
6912
|
+
if (target.kind !== "ontology") return;
|
|
6913
|
+
const result = OntologyIdSchema.safeParse(target.id);
|
|
6914
|
+
if (!result.success) {
|
|
6915
|
+
ctx.addIssue({
|
|
6916
|
+
code: z.ZodIssueCode.custom,
|
|
6917
|
+
path: ["id"],
|
|
6918
|
+
message: "Ontology knowledge targets must use <system-path>:<kind>/<local-id> or global:<kind>/<local-id>"
|
|
6919
|
+
});
|
|
6920
|
+
}
|
|
6921
|
+
});
|
|
6922
|
+
var LegacyKnowledgeLinkSchema = z.object({
|
|
6923
|
+
nodeId: z.union([NodeIdStringSchema, z.templateLiteral(["ontology:", OntologyIdSchema])])
|
|
6924
|
+
});
|
|
6925
|
+
var CanonicalKnowledgeLinkSchema = z.object({
|
|
6926
|
+
target: KnowledgeTargetRefSchema
|
|
6927
|
+
});
|
|
6928
|
+
function nodeIdFromTarget(target) {
|
|
6929
|
+
return `${target.kind}:${target.id}`;
|
|
6930
|
+
}
|
|
6931
|
+
function targetFromNodeId(nodeId) {
|
|
6932
|
+
const [kind, ...idParts] = nodeId.split(":");
|
|
6933
|
+
return {
|
|
6934
|
+
kind: KnowledgeTargetKindSchema.parse(kind),
|
|
6935
|
+
id: idParts.join(":")
|
|
6936
|
+
};
|
|
6937
|
+
}
|
|
6938
|
+
var KnowledgeLinkSchema = z.union([CanonicalKnowledgeLinkSchema, LegacyKnowledgeLinkSchema]).transform((link) => {
|
|
6939
|
+
const target = "target" in link ? link.target : targetFromNodeId(link.nodeId);
|
|
6940
|
+
return {
|
|
6941
|
+
target,
|
|
6942
|
+
nodeId: nodeIdFromTarget(target)
|
|
6943
|
+
};
|
|
6944
|
+
});
|
|
6945
|
+
var OrgKnowledgeKindSchema = z.enum(["playbook", "strategy", "reference"]).meta({ label: "Knowledge kind", color: "grape" });
|
|
6946
|
+
var OrgKnowledgeNodeSchema = z.object({
|
|
6947
|
+
id: ModelIdSchema,
|
|
6948
|
+
kind: OrgKnowledgeKindSchema,
|
|
6949
|
+
title: z.string().trim().min(1).max(200),
|
|
6950
|
+
summary: z.string().trim().min(1).max(1e3),
|
|
6951
|
+
icon: IconNameSchema.optional(),
|
|
6952
|
+
/** Canonical documentation URL when body content is a local summary. */
|
|
6953
|
+
externalUrl: z.string().trim().url().max(500).optional(),
|
|
6954
|
+
/** Optional generated source file path for local MDX-backed knowledge nodes. */
|
|
6955
|
+
sourceFilePath: z.string().trim().min(1).max(500).optional(),
|
|
6956
|
+
/** Raw MDX string. Phase 2 will introduce a structured block format. */
|
|
6957
|
+
body: z.string().trim().min(1),
|
|
6958
|
+
/**
|
|
6959
|
+
* Graph links to other OM nodes this knowledge node governs.
|
|
6960
|
+
* Each link emits a `governs` edge: knowledge-node -> target node.
|
|
6961
|
+
*/
|
|
6962
|
+
links: z.array(KnowledgeLinkSchema).default([]),
|
|
6963
|
+
/** Role identifiers that own this knowledge node. */
|
|
6964
|
+
ownerIds: z.array(RoleIdSchema.meta({ ref: "role" })).default([]),
|
|
6965
|
+
/** ISO date string (YYYY-MM-DD or full ISO 8601) of last meaningful update. */
|
|
6966
|
+
updatedAt: z.string().trim().min(1).max(50)
|
|
6967
|
+
});
|
|
6968
|
+
var KnowledgeDomainSchema = z.record(ModelIdSchema, OrgKnowledgeNodeSchema).default({});
|
|
6969
|
+
|
|
6970
|
+
// ../core/src/organization-model/schema.ts
|
|
6971
|
+
z.enum([
|
|
6972
|
+
"branding",
|
|
6973
|
+
"identity",
|
|
6974
|
+
"customers",
|
|
6975
|
+
"offerings",
|
|
6976
|
+
"roles",
|
|
6977
|
+
"goals",
|
|
6978
|
+
"systems",
|
|
6979
|
+
"ontology",
|
|
6980
|
+
"resources",
|
|
6981
|
+
"actions",
|
|
6982
|
+
"entities",
|
|
6983
|
+
"policies",
|
|
6984
|
+
"knowledge"
|
|
6985
|
+
]);
|
|
6986
|
+
var OrganizationModelDomainMetadataSchema = z.object({
|
|
6987
|
+
version: z.literal(1).default(1),
|
|
6988
|
+
lastModified: z.string().regex(/^\d{4}-\d{2}-\d{2}$/, "lastModified must be an ISO date string (YYYY-MM-DD)")
|
|
6989
|
+
});
|
|
6990
|
+
var DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA = {
|
|
6991
|
+
branding: { version: 1, lastModified: "2026-05-10" },
|
|
6992
|
+
identity: { version: 1, lastModified: "2026-05-10" },
|
|
6993
|
+
customers: { version: 1, lastModified: "2026-05-10" },
|
|
6994
|
+
offerings: { version: 1, lastModified: "2026-05-10" },
|
|
6995
|
+
roles: { version: 1, lastModified: "2026-05-10" },
|
|
6996
|
+
goals: { version: 1, lastModified: "2026-05-10" },
|
|
6997
|
+
systems: { version: 1, lastModified: "2026-05-10" },
|
|
6998
|
+
ontology: { version: 1, lastModified: "2026-05-14" },
|
|
6999
|
+
resources: { version: 1, lastModified: "2026-05-10" },
|
|
7000
|
+
actions: { version: 1, lastModified: "2026-05-10" },
|
|
7001
|
+
entities: { version: 1, lastModified: "2026-05-10" },
|
|
7002
|
+
policies: { version: 1, lastModified: "2026-05-10" },
|
|
7003
|
+
knowledge: { version: 1, lastModified: "2026-05-10" }
|
|
7004
|
+
};
|
|
7005
|
+
var OrganizationModelDomainMetadataByDomainSchema = z.object({
|
|
7006
|
+
branding: OrganizationModelDomainMetadataSchema,
|
|
7007
|
+
identity: OrganizationModelDomainMetadataSchema,
|
|
7008
|
+
customers: OrganizationModelDomainMetadataSchema,
|
|
7009
|
+
offerings: OrganizationModelDomainMetadataSchema,
|
|
7010
|
+
roles: OrganizationModelDomainMetadataSchema,
|
|
7011
|
+
goals: OrganizationModelDomainMetadataSchema,
|
|
7012
|
+
systems: OrganizationModelDomainMetadataSchema,
|
|
7013
|
+
ontology: OrganizationModelDomainMetadataSchema,
|
|
7014
|
+
resources: OrganizationModelDomainMetadataSchema,
|
|
7015
|
+
actions: OrganizationModelDomainMetadataSchema,
|
|
7016
|
+
entities: OrganizationModelDomainMetadataSchema,
|
|
7017
|
+
policies: OrganizationModelDomainMetadataSchema,
|
|
7018
|
+
knowledge: OrganizationModelDomainMetadataSchema
|
|
7019
|
+
}).partial().default(DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA).transform((metadata) => ({ ...DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA, ...metadata }));
|
|
7020
|
+
var OrganizationModelSchemaBase = z.object({
|
|
7021
|
+
version: z.literal(1).default(1),
|
|
7022
|
+
domainMetadata: OrganizationModelDomainMetadataByDomainSchema,
|
|
7023
|
+
branding: OrganizationModelBrandingSchema,
|
|
7024
|
+
navigation: OrganizationModelNavigationSchema,
|
|
7025
|
+
identity: IdentityDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_IDENTITY),
|
|
7026
|
+
customers: CustomersDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_CUSTOMERS),
|
|
7027
|
+
offerings: OfferingsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_OFFERINGS),
|
|
7028
|
+
roles: RolesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ROLES),
|
|
7029
|
+
goals: GoalsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_GOALS),
|
|
7030
|
+
systems: SystemsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_SYSTEMS),
|
|
7031
|
+
ontology: OntologyScopeSchema.default(DEFAULT_ONTOLOGY_SCOPE),
|
|
7032
|
+
resources: ResourcesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_RESOURCES),
|
|
7033
|
+
actions: ActionsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ACTIONS),
|
|
7034
|
+
entities: EntitiesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ENTITIES),
|
|
7035
|
+
policies: PoliciesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_POLICIES),
|
|
7036
|
+
// D3: flat Record<id, OrgKnowledgeNode> — no wrapper object
|
|
7037
|
+
knowledge: KnowledgeDomainSchema.default({})
|
|
7038
|
+
});
|
|
7039
|
+
function addIssue(ctx, path, message) {
|
|
7040
|
+
ctx.addIssue({
|
|
7041
|
+
code: z.ZodIssueCode.custom,
|
|
7042
|
+
path,
|
|
7043
|
+
message
|
|
7044
|
+
});
|
|
7045
|
+
}
|
|
7046
|
+
function isLifecycleEnabled(lifecycle, enabled) {
|
|
7047
|
+
if (enabled === false) return false;
|
|
7048
|
+
return lifecycle !== "deprecated" && lifecycle !== "archived";
|
|
7049
|
+
}
|
|
7050
|
+
function defaultSystemPathFor(id) {
|
|
7051
|
+
return `/${id.replaceAll(".", "/")}`;
|
|
7052
|
+
}
|
|
7053
|
+
function asRoleHolderArray(heldBy) {
|
|
7054
|
+
return Array.isArray(heldBy) ? heldBy : [heldBy];
|
|
7055
|
+
}
|
|
7056
|
+
function isKnowledgeKindCompatibleWithTarget(knowledgeKind, targetKind) {
|
|
7057
|
+
if (knowledgeKind === "reference") return true;
|
|
7058
|
+
if (knowledgeKind === "playbook") {
|
|
7059
|
+
return ["system", "resource", "stage", "action", "ontology"].includes(targetKind);
|
|
7060
|
+
}
|
|
7061
|
+
if (knowledgeKind === "strategy") {
|
|
7062
|
+
return ["system", "goal", "offering", "customer-segment", "ontology"].includes(targetKind);
|
|
7063
|
+
}
|
|
7064
|
+
return false;
|
|
7065
|
+
}
|
|
7066
|
+
function isRecord(value) {
|
|
7067
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
7068
|
+
}
|
|
7069
|
+
OrganizationModelSchemaBase.superRefine((model, ctx) => {
|
|
7070
|
+
function collectAllSystems(systems, prefix = "", schemaPath = ["systems"]) {
|
|
7071
|
+
const result = [];
|
|
7072
|
+
for (const [key, system] of Object.entries(systems)) {
|
|
7073
|
+
const path = prefix ? `${prefix}.${key}` : key;
|
|
7074
|
+
const currentSchemaPath = [...schemaPath, key];
|
|
7075
|
+
result.push({ path, schemaPath: currentSchemaPath, system });
|
|
7076
|
+
const childSystems = system.systems ?? system.subsystems;
|
|
7077
|
+
if (childSystems !== void 0) {
|
|
7078
|
+
result.push(
|
|
7079
|
+
...collectAllSystems(childSystems, path, [...currentSchemaPath, system.systems !== void 0 ? "systems" : "subsystems"])
|
|
7080
|
+
);
|
|
7081
|
+
}
|
|
7082
|
+
}
|
|
7083
|
+
return result;
|
|
7084
|
+
}
|
|
7085
|
+
const allSystems = collectAllSystems(model.systems);
|
|
7086
|
+
const systemsById = /* @__PURE__ */ new Map();
|
|
7087
|
+
for (const { path, system } of allSystems) {
|
|
7088
|
+
systemsById.set(path, system);
|
|
7089
|
+
systemsById.set(system.id, system);
|
|
7090
|
+
}
|
|
7091
|
+
const systemIdsByEffectivePath = /* @__PURE__ */ new Map();
|
|
7092
|
+
allSystems.forEach(({ path, schemaPath, system }) => {
|
|
7093
|
+
if (system.parentSystemId !== void 0 && !systemsById.has(system.parentSystemId)) {
|
|
7094
|
+
addIssue(
|
|
7095
|
+
ctx,
|
|
7096
|
+
[...schemaPath, "parentSystemId"],
|
|
7097
|
+
`System "${system.id}" references unknown parent "${system.parentSystemId}"`
|
|
7098
|
+
);
|
|
7099
|
+
}
|
|
7100
|
+
const hasChildren = Object.keys(system.systems ?? system.subsystems ?? {}).length > 0 || allSystems.some((candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes("."));
|
|
7101
|
+
const contributesRoutePath = system.ui?.path !== void 0 || system.path !== void 0 || !hasChildren;
|
|
7102
|
+
if (contributesRoutePath) {
|
|
7103
|
+
const effectivePath = system.ui?.path ?? system.path ?? defaultSystemPathFor(path);
|
|
7104
|
+
const existingSystemId = systemIdsByEffectivePath.get(effectivePath);
|
|
7105
|
+
if (existingSystemId !== void 0) {
|
|
7106
|
+
addIssue(
|
|
7107
|
+
ctx,
|
|
7108
|
+
[...schemaPath, system.ui?.path !== void 0 ? "ui" : "path"],
|
|
7109
|
+
`System "${path}" effective path "${effectivePath}" duplicates system "${existingSystemId}"`
|
|
7110
|
+
);
|
|
7111
|
+
} else {
|
|
7112
|
+
systemIdsByEffectivePath.set(effectivePath, path);
|
|
7113
|
+
}
|
|
7114
|
+
}
|
|
7115
|
+
if (hasChildren && isLifecycleEnabled(system.lifecycle, system.enabled)) {
|
|
7116
|
+
const hasEnabledDescendant = Object.values(system.systems ?? system.subsystems ?? {}).some(
|
|
7117
|
+
(candidate) => isLifecycleEnabled(candidate.lifecycle, candidate.enabled)
|
|
7118
|
+
) || allSystems.some(
|
|
7119
|
+
(candidate) => candidate.path.startsWith(`${path}.`) && !candidate.path.slice(path.length + 1).includes(".") && isLifecycleEnabled(candidate.system.lifecycle, candidate.system.enabled)
|
|
7120
|
+
);
|
|
7121
|
+
if (!hasEnabledDescendant) {
|
|
7122
|
+
addIssue(
|
|
7123
|
+
ctx,
|
|
7124
|
+
[...schemaPath, "lifecycle"],
|
|
7125
|
+
`System "${path}" is active but has no active descendants`
|
|
7126
|
+
);
|
|
7127
|
+
}
|
|
7128
|
+
}
|
|
7129
|
+
});
|
|
7130
|
+
allSystems.forEach(({ schemaPath, system }) => {
|
|
7131
|
+
const visited = /* @__PURE__ */ new Set();
|
|
7132
|
+
let currentParentId = system.parentSystemId;
|
|
7133
|
+
while (currentParentId !== void 0) {
|
|
7134
|
+
if (currentParentId === system.id || visited.has(currentParentId)) {
|
|
7135
|
+
addIssue(ctx, [...schemaPath, "parentSystemId"], `System "${system.id}" has a parent cycle`);
|
|
7136
|
+
return;
|
|
7137
|
+
}
|
|
7138
|
+
visited.add(currentParentId);
|
|
7139
|
+
currentParentId = systemsById.get(currentParentId)?.parentSystemId;
|
|
7140
|
+
}
|
|
7141
|
+
});
|
|
7142
|
+
function normalizeRoutePath(path) {
|
|
7143
|
+
return path.length > 1 ? path.replace(/\/+$/, "") : path;
|
|
7144
|
+
}
|
|
7145
|
+
const sidebarNodeIds = /* @__PURE__ */ new Map();
|
|
7146
|
+
const sidebarSurfacePaths = /* @__PURE__ */ new Map();
|
|
7147
|
+
const sidebarSurfaces = [];
|
|
7148
|
+
function collectSidebarNodes(nodes, schemaPath) {
|
|
7149
|
+
Object.entries(nodes).forEach(([nodeId, node]) => {
|
|
7150
|
+
const nodePath = [...schemaPath, nodeId];
|
|
7151
|
+
const existingNodePath = sidebarNodeIds.get(nodeId);
|
|
7152
|
+
if (existingNodePath !== void 0) {
|
|
7153
|
+
addIssue(ctx, nodePath, `Sidebar node id "${nodeId}" duplicates another sidebar node`);
|
|
7154
|
+
} else {
|
|
7155
|
+
sidebarNodeIds.set(nodeId, nodePath);
|
|
7156
|
+
}
|
|
7157
|
+
if (node.type === "group") {
|
|
7158
|
+
collectSidebarNodes(node.children, [...nodePath, "children"]);
|
|
7159
|
+
return;
|
|
7160
|
+
}
|
|
7161
|
+
sidebarSurfaces.push({ id: nodeId, node, path: nodePath });
|
|
7162
|
+
const normalizedPath = normalizeRoutePath(node.path);
|
|
7163
|
+
const existingSurfaceId = sidebarSurfacePaths.get(normalizedPath);
|
|
7164
|
+
if (existingSurfaceId !== void 0) {
|
|
7165
|
+
addIssue(
|
|
7166
|
+
ctx,
|
|
7167
|
+
[...nodePath, "path"],
|
|
7168
|
+
`Sidebar surface path "${node.path}" duplicates surface "${existingSurfaceId}"`
|
|
7169
|
+
);
|
|
7170
|
+
} else {
|
|
7171
|
+
sidebarSurfacePaths.set(normalizedPath, nodeId);
|
|
7172
|
+
}
|
|
7173
|
+
node.targets?.systems?.forEach((systemId, systemIndex) => {
|
|
7174
|
+
if (!systemsById.has(systemId)) {
|
|
7175
|
+
addIssue(
|
|
7176
|
+
ctx,
|
|
7177
|
+
[...nodePath, "targets", "systems", systemIndex],
|
|
7178
|
+
`Sidebar surface "${nodeId}" references unknown system "${systemId}"`
|
|
7179
|
+
);
|
|
7180
|
+
}
|
|
7181
|
+
});
|
|
7182
|
+
});
|
|
7183
|
+
}
|
|
7184
|
+
collectSidebarNodes(model.navigation.sidebar.primary, ["navigation", "sidebar", "primary"]);
|
|
7185
|
+
collectSidebarNodes(model.navigation.sidebar.bottom, ["navigation", "sidebar", "bottom"]);
|
|
7186
|
+
const segmentsById = new Map(Object.entries(model.customers));
|
|
7187
|
+
Object.values(model.offerings).forEach((product) => {
|
|
7188
|
+
product.targetSegmentIds.forEach((segmentId, segmentIndex) => {
|
|
7189
|
+
if (!segmentsById.has(segmentId)) {
|
|
7190
|
+
addIssue(
|
|
7191
|
+
ctx,
|
|
7192
|
+
["offerings", product.id, "targetSegmentIds", segmentIndex],
|
|
7193
|
+
`Product "${product.id}" references unknown customer segment "${segmentId}"`
|
|
7194
|
+
);
|
|
7195
|
+
}
|
|
7196
|
+
});
|
|
7197
|
+
if (product.deliveryFeatureId !== void 0 && !systemsById.has(product.deliveryFeatureId)) {
|
|
7198
|
+
addIssue(
|
|
7199
|
+
ctx,
|
|
7200
|
+
["offerings", product.id, "deliveryFeatureId"],
|
|
7201
|
+
`Product "${product.id}" references unknown delivery system "${product.deliveryFeatureId}"`
|
|
7202
|
+
);
|
|
7203
|
+
}
|
|
7204
|
+
});
|
|
7205
|
+
Object.values(model.goals).forEach((objective) => {
|
|
7206
|
+
if (objective.periodEnd <= objective.periodStart) {
|
|
7207
|
+
addIssue(
|
|
7208
|
+
ctx,
|
|
7209
|
+
["goals", objective.id, "periodEnd"],
|
|
7210
|
+
`Goal "${objective.id}" has periodEnd "${objective.periodEnd}" which must be strictly after periodStart "${objective.periodStart}"`
|
|
7211
|
+
);
|
|
7212
|
+
}
|
|
7213
|
+
});
|
|
7214
|
+
const goalsById = new Map(Object.entries(model.goals));
|
|
7215
|
+
const knowledgeById = new Map(Object.entries(model.knowledge));
|
|
7216
|
+
const actionsById = new Map(Object.entries(model.actions));
|
|
7217
|
+
const entitiesById = new Map(Object.entries(model.entities));
|
|
7218
|
+
const policiesById = new Map(Object.entries(model.policies));
|
|
7219
|
+
sidebarSurfaces.forEach(({ id, node, path }) => {
|
|
7220
|
+
node.targets?.entities?.forEach((entityId, entityIndex) => {
|
|
7221
|
+
if (!entitiesById.has(entityId)) {
|
|
7222
|
+
addIssue(
|
|
7223
|
+
ctx,
|
|
7224
|
+
[...path, "targets", "entities", entityIndex],
|
|
7225
|
+
`Sidebar surface "${id}" references unknown entity "${entityId}"`
|
|
7226
|
+
);
|
|
7227
|
+
}
|
|
7228
|
+
});
|
|
7229
|
+
node.targets?.actions?.forEach((actionId, actionIndex) => {
|
|
7230
|
+
if (!actionsById.has(actionId)) {
|
|
7231
|
+
addIssue(
|
|
7232
|
+
ctx,
|
|
7233
|
+
[...path, "targets", "actions", actionIndex],
|
|
7234
|
+
`Sidebar surface "${id}" references unknown action "${actionId}"`
|
|
7235
|
+
);
|
|
7236
|
+
}
|
|
7237
|
+
});
|
|
7238
|
+
});
|
|
7239
|
+
Object.values(model.entities).forEach((entity) => {
|
|
7240
|
+
if (!systemsById.has(entity.ownedBySystemId)) {
|
|
7241
|
+
addIssue(
|
|
7242
|
+
ctx,
|
|
7243
|
+
["entities", entity.id, "ownedBySystemId"],
|
|
7244
|
+
`Entity "${entity.id}" references unknown ownedBySystemId "${entity.ownedBySystemId}"`
|
|
7245
|
+
);
|
|
7246
|
+
}
|
|
7247
|
+
entity.links?.forEach((link, linkIndex) => {
|
|
7248
|
+
if (!entitiesById.has(link.toEntity)) {
|
|
7249
|
+
addIssue(
|
|
7250
|
+
ctx,
|
|
7251
|
+
["entities", entity.id, "links", linkIndex, "toEntity"],
|
|
7252
|
+
`Entity "${entity.id}" links to unknown entity "${link.toEntity}"`
|
|
7253
|
+
);
|
|
7254
|
+
}
|
|
7255
|
+
});
|
|
7256
|
+
});
|
|
7257
|
+
const rolesById = new Map(Object.entries(model.roles));
|
|
7258
|
+
Object.values(model.roles).forEach((role) => {
|
|
7259
|
+
if (role.reportsToId !== void 0 && !rolesById.has(role.reportsToId)) {
|
|
7260
|
+
addIssue(
|
|
7261
|
+
ctx,
|
|
7262
|
+
["roles", role.id, "reportsToId"],
|
|
7263
|
+
`Role "${role.id}" references unknown reportsToId "${role.reportsToId}"`
|
|
7264
|
+
);
|
|
7265
|
+
}
|
|
7266
|
+
});
|
|
7267
|
+
Object.values(model.roles).forEach((role) => {
|
|
7268
|
+
const visited = /* @__PURE__ */ new Set();
|
|
7269
|
+
let currentReportsToId = role.reportsToId;
|
|
7270
|
+
while (currentReportsToId !== void 0) {
|
|
7271
|
+
if (currentReportsToId === role.id || visited.has(currentReportsToId)) {
|
|
7272
|
+
addIssue(ctx, ["roles", role.id, "reportsToId"], `Role "${role.id}" has a reportsToId cycle`);
|
|
7273
|
+
return;
|
|
7274
|
+
}
|
|
7275
|
+
visited.add(currentReportsToId);
|
|
7276
|
+
currentReportsToId = rolesById.get(currentReportsToId)?.reportsToId;
|
|
7277
|
+
}
|
|
7278
|
+
});
|
|
7279
|
+
Object.values(model.roles).forEach((role) => {
|
|
7280
|
+
role.responsibleFor?.forEach((systemId, systemIndex) => {
|
|
7281
|
+
if (!systemsById.has(systemId)) {
|
|
7282
|
+
addIssue(
|
|
7283
|
+
ctx,
|
|
7284
|
+
["roles", role.id, "responsibleFor", systemIndex],
|
|
7285
|
+
`Role "${role.id}" references unknown responsibleFor system "${systemId}"`
|
|
7286
|
+
);
|
|
7287
|
+
}
|
|
7288
|
+
});
|
|
7289
|
+
});
|
|
7290
|
+
allSystems.forEach(({ schemaPath, system }) => {
|
|
7291
|
+
if (system.responsibleRoleId !== void 0 && !rolesById.has(system.responsibleRoleId)) {
|
|
7292
|
+
addIssue(
|
|
7293
|
+
ctx,
|
|
7294
|
+
[...schemaPath, "responsibleRoleId"],
|
|
7295
|
+
`System "${system.id}" references unknown responsibleRoleId "${system.responsibleRoleId}"`
|
|
7296
|
+
);
|
|
7297
|
+
}
|
|
7298
|
+
system.governedByKnowledge?.forEach((nodeId, nodeIndex) => {
|
|
7299
|
+
if (!knowledgeById.has(nodeId)) {
|
|
7300
|
+
addIssue(
|
|
7301
|
+
ctx,
|
|
7302
|
+
[...schemaPath, "governedByKnowledge", nodeIndex],
|
|
7303
|
+
`System "${system.id}" references unknown knowledge node "${nodeId}"`
|
|
7304
|
+
);
|
|
7305
|
+
}
|
|
7306
|
+
});
|
|
7307
|
+
system.drivesGoals?.forEach((goalId, goalIndex) => {
|
|
7308
|
+
if (!goalsById.has(goalId)) {
|
|
7309
|
+
addIssue(
|
|
7310
|
+
ctx,
|
|
7311
|
+
[...schemaPath, "drivesGoals", goalIndex],
|
|
7312
|
+
`System "${system.id}" references unknown goal "${goalId}"`
|
|
7313
|
+
);
|
|
7314
|
+
}
|
|
7315
|
+
});
|
|
7316
|
+
system.actions?.forEach((actionRef, actionIndex) => {
|
|
7317
|
+
if (!actionsById.has(actionRef.actionId)) {
|
|
7318
|
+
addIssue(
|
|
7319
|
+
ctx,
|
|
7320
|
+
[...schemaPath, "actions", actionIndex, "actionId"],
|
|
7321
|
+
`System "${system.id}" references unknown action "${actionRef.actionId}"`
|
|
7322
|
+
);
|
|
7323
|
+
}
|
|
7324
|
+
});
|
|
7325
|
+
system.policies?.forEach((policyId, policyIndex) => {
|
|
7326
|
+
if (!policiesById.has(policyId)) {
|
|
7327
|
+
addIssue(
|
|
7328
|
+
ctx,
|
|
7329
|
+
[...schemaPath, "policies", policyIndex],
|
|
7330
|
+
`System "${system.id}" references unknown policy "${policyId}"`
|
|
7331
|
+
);
|
|
7332
|
+
}
|
|
7333
|
+
});
|
|
7334
|
+
});
|
|
7335
|
+
Object.values(model.actions).forEach((action) => {
|
|
7336
|
+
action.affects?.forEach((entityId, entityIndex) => {
|
|
7337
|
+
if (!entitiesById.has(entityId)) {
|
|
7338
|
+
addIssue(
|
|
7339
|
+
ctx,
|
|
7340
|
+
["actions", action.id, "affects", entityIndex],
|
|
7341
|
+
`Action "${action.id}" affects unknown entity "${entityId}"`
|
|
7342
|
+
);
|
|
7343
|
+
}
|
|
7344
|
+
});
|
|
7345
|
+
});
|
|
7346
|
+
const resourcesById = new Map(Object.entries(model.resources));
|
|
7347
|
+
sidebarSurfaces.forEach(({ id, node, path }) => {
|
|
7348
|
+
node.targets?.resources?.forEach((resourceId, resourceIndex) => {
|
|
7349
|
+
if (!resourcesById.has(resourceId)) {
|
|
7350
|
+
addIssue(
|
|
7351
|
+
ctx,
|
|
7352
|
+
[...path, "targets", "resources", resourceIndex],
|
|
7353
|
+
`Sidebar surface "${id}" references unknown resource "${resourceId}"`
|
|
7354
|
+
);
|
|
7355
|
+
}
|
|
7356
|
+
});
|
|
7357
|
+
});
|
|
7358
|
+
const stageIds = /* @__PURE__ */ new Set();
|
|
7359
|
+
const actionIds = new Set(Object.keys(model.actions));
|
|
7360
|
+
const offeringsById = new Map(Object.entries(model.offerings));
|
|
7361
|
+
const ontologyCompilation = compileOrganizationOntology(model);
|
|
7362
|
+
const ontologyIndexByKind = {
|
|
7363
|
+
object: ontologyCompilation.ontology.objectTypes,
|
|
7364
|
+
link: ontologyCompilation.ontology.linkTypes,
|
|
7365
|
+
action: ontologyCompilation.ontology.actionTypes,
|
|
7366
|
+
catalog: ontologyCompilation.ontology.catalogTypes,
|
|
7367
|
+
event: ontologyCompilation.ontology.eventTypes,
|
|
7368
|
+
interface: ontologyCompilation.ontology.interfaceTypes,
|
|
7369
|
+
"value-type": ontologyCompilation.ontology.valueTypes,
|
|
7370
|
+
property: ontologyCompilation.ontology.sharedProperties,
|
|
7371
|
+
group: ontologyCompilation.ontology.groups,
|
|
7372
|
+
surface: ontologyCompilation.ontology.surfaces
|
|
7373
|
+
};
|
|
7374
|
+
const ontologyIds = new Set(Object.values(ontologyIndexByKind).flatMap((index) => Object.keys(index)));
|
|
7375
|
+
const ontologyReferenceKeyKinds = {
|
|
7376
|
+
valueType: "value-type",
|
|
7377
|
+
catalogType: "catalog",
|
|
7378
|
+
objectType: "object",
|
|
7379
|
+
eventType: "event",
|
|
7380
|
+
actionType: "action",
|
|
7381
|
+
linkType: "link",
|
|
7382
|
+
interfaceType: "interface",
|
|
7383
|
+
propertyType: "property",
|
|
7384
|
+
groupType: "group",
|
|
7385
|
+
surfaceType: "surface",
|
|
7386
|
+
stepCatalog: "catalog"
|
|
7387
|
+
};
|
|
7388
|
+
function validateKnownOntologyReferences(ownerId, value, path, seen = /* @__PURE__ */ new WeakSet()) {
|
|
7389
|
+
if (Array.isArray(value)) {
|
|
7390
|
+
value.forEach((entry, index) => validateKnownOntologyReferences(ownerId, entry, [...path, index], seen));
|
|
7391
|
+
return;
|
|
7392
|
+
}
|
|
7393
|
+
if (!isRecord(value)) return;
|
|
7394
|
+
if (seen.has(value)) return;
|
|
7395
|
+
seen.add(value);
|
|
7396
|
+
Object.entries(value).forEach(([key, entry]) => {
|
|
7397
|
+
const expectedKind = ontologyReferenceKeyKinds[key];
|
|
7398
|
+
if (expectedKind !== void 0) {
|
|
7399
|
+
if (typeof entry !== "string") {
|
|
7400
|
+
addIssue(ctx, [...path, key], `Ontology record "${ownerId}" ${key} must be an ontology ID string`);
|
|
7401
|
+
} else if (ontologyIndexByKind[expectedKind][entry] === void 0) {
|
|
7402
|
+
addIssue(
|
|
7403
|
+
ctx,
|
|
7404
|
+
[...path, key],
|
|
7405
|
+
`Ontology record "${ownerId}" ${key} references unknown ${expectedKind} ontology ID "${entry}"`
|
|
7406
|
+
);
|
|
7407
|
+
}
|
|
7408
|
+
}
|
|
7409
|
+
validateKnownOntologyReferences(ownerId, entry, [...path, key], seen);
|
|
7410
|
+
});
|
|
7411
|
+
}
|
|
7412
|
+
for (const { id, record } of listResolvedOntologyRecords(ontologyCompilation.ontology)) {
|
|
7413
|
+
validateKnownOntologyReferences(id, record, record.origin.path);
|
|
7414
|
+
}
|
|
7415
|
+
Object.values(model.policies).forEach((policy) => {
|
|
7416
|
+
policy.appliesTo.systemIds.forEach((systemId, systemIndex) => {
|
|
7417
|
+
if (!systemsById.has(systemId)) {
|
|
7418
|
+
addIssue(
|
|
7419
|
+
ctx,
|
|
7420
|
+
["policies", policy.id, "appliesTo", "systemIds", systemIndex],
|
|
7421
|
+
`Policy "${policy.id}" applies to unknown system "${systemId}"`
|
|
7422
|
+
);
|
|
7423
|
+
}
|
|
7424
|
+
});
|
|
7425
|
+
policy.appliesTo.actionIds.forEach((actionId, actionIndex) => {
|
|
7426
|
+
if (!actionsById.has(actionId)) {
|
|
7427
|
+
addIssue(
|
|
7428
|
+
ctx,
|
|
7429
|
+
["policies", policy.id, "appliesTo", "actionIds", actionIndex],
|
|
7430
|
+
`Policy "${policy.id}" applies to unknown action "${actionId}"`
|
|
7431
|
+
);
|
|
7432
|
+
}
|
|
7433
|
+
});
|
|
7434
|
+
policy.actions.forEach((action, actionIndex) => {
|
|
7435
|
+
if (action.kind === "invoke-action" && !actionsById.has(action.actionId)) {
|
|
7436
|
+
addIssue(
|
|
7437
|
+
ctx,
|
|
7438
|
+
["policies", policy.id, "actions", actionIndex, "actionId"],
|
|
7439
|
+
`Policy "${policy.id}" invokes unknown action "${action.actionId}"`
|
|
7440
|
+
);
|
|
7441
|
+
}
|
|
7442
|
+
if ((action.kind === "notify-role" || action.kind === "require-approval") && action.roleId !== void 0 && !rolesById.has(action.roleId)) {
|
|
7443
|
+
addIssue(
|
|
7444
|
+
ctx,
|
|
7445
|
+
["policies", policy.id, "actions", actionIndex, "roleId"],
|
|
7446
|
+
`Policy "${policy.id}" references unknown role "${action.roleId}"`
|
|
7447
|
+
);
|
|
7448
|
+
}
|
|
7449
|
+
});
|
|
7450
|
+
if (policy.trigger.kind === "action-invocation" && !actionsById.has(policy.trigger.actionId)) {
|
|
7451
|
+
addIssue(
|
|
7452
|
+
ctx,
|
|
7453
|
+
["policies", policy.id, "trigger", "actionId"],
|
|
7454
|
+
`Policy "${policy.id}" references unknown trigger action "${policy.trigger.actionId}"`
|
|
7455
|
+
);
|
|
7456
|
+
}
|
|
7457
|
+
});
|
|
7458
|
+
function knowledgeTargetExists(kind, id) {
|
|
7459
|
+
if (kind === "system") return systemsById.has(id);
|
|
7460
|
+
if (kind === "resource") return resourcesById.has(id);
|
|
7461
|
+
if (kind === "knowledge") return knowledgeById.has(id);
|
|
7462
|
+
if (kind === "stage") return stageIds.has(id);
|
|
7463
|
+
if (kind === "action") return actionIds.has(id);
|
|
7464
|
+
if (kind === "role") return rolesById.has(id);
|
|
7465
|
+
if (kind === "goal") return goalsById.has(id);
|
|
7466
|
+
if (kind === "customer-segment") return segmentsById.has(id);
|
|
7467
|
+
if (kind === "offering") return offeringsById.has(id);
|
|
7468
|
+
if (kind === "ontology") return ontologyIds.has(id);
|
|
7469
|
+
return false;
|
|
7470
|
+
}
|
|
7471
|
+
Object.entries(model.knowledge).forEach(([nodeId, node]) => {
|
|
7472
|
+
node.links.forEach((link, linkIndex) => {
|
|
7473
|
+
if (!knowledgeTargetExists(link.target.kind, link.target.id)) {
|
|
7474
|
+
addIssue(
|
|
7475
|
+
ctx,
|
|
7476
|
+
["knowledge", nodeId, "links", linkIndex, "target"],
|
|
7477
|
+
`Knowledge node "${node.id}" references unknown ${link.target.kind} target "${link.target.id}"`
|
|
7478
|
+
);
|
|
7479
|
+
}
|
|
7480
|
+
if (!isKnowledgeKindCompatibleWithTarget(node.kind, link.target.kind)) {
|
|
7481
|
+
addIssue(
|
|
7482
|
+
ctx,
|
|
7483
|
+
["knowledge", nodeId, "links", linkIndex, "target", "kind"],
|
|
7484
|
+
`Knowledge node "${node.id}" kind "${node.kind}" cannot govern ${link.target.kind} targets`
|
|
7485
|
+
);
|
|
7486
|
+
}
|
|
7487
|
+
});
|
|
7488
|
+
});
|
|
7489
|
+
Object.values(model.resources).forEach((resource) => {
|
|
7490
|
+
if (!systemsById.has(resource.systemPath)) {
|
|
7491
|
+
addIssue(
|
|
7492
|
+
ctx,
|
|
7493
|
+
["resources", resource.id, "systemPath"],
|
|
7494
|
+
`Resource "${resource.id}" references unknown system path "${resource.systemPath}"`
|
|
7495
|
+
);
|
|
7496
|
+
}
|
|
7497
|
+
if (resource.ownerRoleId !== void 0 && !rolesById.has(resource.ownerRoleId)) {
|
|
7498
|
+
addIssue(
|
|
7499
|
+
ctx,
|
|
7500
|
+
["resources", resource.id, "ownerRoleId"],
|
|
7501
|
+
`Resource "${resource.id}" references unknown ownerRoleId "${resource.ownerRoleId}"`
|
|
7502
|
+
);
|
|
7503
|
+
}
|
|
7504
|
+
if (resource.kind === "agent" && resource.actsAsRoleId !== void 0 && !rolesById.has(resource.actsAsRoleId)) {
|
|
7505
|
+
addIssue(
|
|
7506
|
+
ctx,
|
|
7507
|
+
["resources", resource.id, "actsAsRoleId"],
|
|
7508
|
+
`Agent resource "${resource.id}" references unknown actsAsRoleId "${resource.actsAsRoleId}"`
|
|
7509
|
+
);
|
|
7510
|
+
}
|
|
7511
|
+
});
|
|
7512
|
+
function validateResourceOntologyBinding(resourceId, bindingKey, expectedKind, ids) {
|
|
7513
|
+
ids?.forEach((ontologyId, ontologyIndex) => {
|
|
7514
|
+
if (ontologyIndexByKind[expectedKind][ontologyId] === void 0) {
|
|
7515
|
+
addIssue(
|
|
7516
|
+
ctx,
|
|
7517
|
+
["resources", resourceId, "ontology", bindingKey, ontologyIndex],
|
|
7518
|
+
`Resource "${resourceId}" ontology binding "${bindingKey}" references unknown ${expectedKind} ontology ID "${ontologyId}"`
|
|
7519
|
+
);
|
|
7520
|
+
}
|
|
7521
|
+
});
|
|
7522
|
+
}
|
|
7523
|
+
Object.values(model.resources).forEach((resource) => {
|
|
7524
|
+
const binding = resource.ontology;
|
|
7525
|
+
if (binding === void 0) return;
|
|
7526
|
+
validateResourceOntologyBinding(resource.id, "implements", "action", binding.implements);
|
|
7527
|
+
validateResourceOntologyBinding(resource.id, "reads", "object", binding.reads);
|
|
7528
|
+
validateResourceOntologyBinding(resource.id, "writes", "object", binding.writes);
|
|
7529
|
+
validateResourceOntologyBinding(resource.id, "usesCatalogs", "catalog", binding.usesCatalogs);
|
|
7530
|
+
validateResourceOntologyBinding(resource.id, "emits", "event", binding.emits);
|
|
7531
|
+
});
|
|
7532
|
+
Object.values(model.roles).forEach((role) => {
|
|
7533
|
+
if (role.heldBy === void 0) return;
|
|
7534
|
+
asRoleHolderArray(role.heldBy).forEach((holder, holderIndex) => {
|
|
7535
|
+
if (holder.kind !== "agent") return;
|
|
7536
|
+
const resource = resourcesById.get(holder.agentId);
|
|
7537
|
+
if (resource === void 0) {
|
|
7538
|
+
addIssue(
|
|
7539
|
+
ctx,
|
|
7540
|
+
["roles", role.id, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
|
|
7541
|
+
`Role "${role.id}" references unknown agent holder resource "${holder.agentId}"`
|
|
7542
|
+
);
|
|
7543
|
+
return;
|
|
7544
|
+
}
|
|
7545
|
+
if (resource.kind !== "agent") {
|
|
7546
|
+
addIssue(
|
|
7547
|
+
ctx,
|
|
7548
|
+
["roles", role.id, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
|
|
7549
|
+
`Role "${role.id}" agent holder "${holder.agentId}" must reference an agent resource`
|
|
7550
|
+
);
|
|
7551
|
+
}
|
|
7552
|
+
});
|
|
7553
|
+
});
|
|
7554
|
+
Object.entries(model.knowledge).forEach(([nodeId, node]) => {
|
|
7555
|
+
node.ownerIds.forEach((roleId, ownerIndex) => {
|
|
7556
|
+
if (!rolesById.has(roleId)) {
|
|
7557
|
+
addIssue(
|
|
7558
|
+
ctx,
|
|
7559
|
+
["knowledge", nodeId, "ownerIds", ownerIndex],
|
|
7560
|
+
`Knowledge node "${node.id}" references unknown owner role "${roleId}"`
|
|
7561
|
+
);
|
|
7562
|
+
}
|
|
7563
|
+
});
|
|
7564
|
+
});
|
|
7565
|
+
function validateSystemContent(system, systemPath) {
|
|
7566
|
+
const childSystems = system.systems ?? system.subsystems;
|
|
7567
|
+
const childKey = system.systems !== void 0 ? "systems" : "subsystems";
|
|
7568
|
+
const content = system.content;
|
|
7569
|
+
if (content === void 0 || Object.keys(content).length === 0) {
|
|
7570
|
+
if (childSystems !== void 0) {
|
|
7571
|
+
Object.entries(childSystems).forEach(([childLocalId, child]) => {
|
|
7572
|
+
validateSystemContent(child, [...systemPath, childKey, childLocalId]);
|
|
7573
|
+
});
|
|
7574
|
+
}
|
|
7575
|
+
return;
|
|
7576
|
+
}
|
|
7577
|
+
Object.entries(content).forEach(([localId, node]) => {
|
|
7578
|
+
if (node.parentContentId !== void 0 && !(node.parentContentId in content)) {
|
|
7579
|
+
addIssue(
|
|
7580
|
+
ctx,
|
|
7581
|
+
[...systemPath, "content", localId, "parentContentId"],
|
|
7582
|
+
`Content node "${localId}" parentContentId "${node.parentContentId}" does not resolve within the same system`
|
|
7583
|
+
);
|
|
7584
|
+
}
|
|
7585
|
+
});
|
|
7586
|
+
Object.entries(content).forEach(([localId, node]) => {
|
|
7587
|
+
const visited = /* @__PURE__ */ new Set();
|
|
7588
|
+
let currentId = node.parentContentId;
|
|
7589
|
+
while (currentId !== void 0) {
|
|
7590
|
+
if (currentId === localId || visited.has(currentId)) {
|
|
7591
|
+
addIssue(
|
|
7592
|
+
ctx,
|
|
7593
|
+
[...systemPath, "content", localId, "parentContentId"],
|
|
7594
|
+
`Content node "${localId}" has a parentContentId cycle`
|
|
7595
|
+
);
|
|
7596
|
+
break;
|
|
7597
|
+
}
|
|
7598
|
+
visited.add(currentId);
|
|
7599
|
+
currentId = content[currentId]?.parentContentId;
|
|
7600
|
+
}
|
|
7601
|
+
});
|
|
7602
|
+
Object.entries(content).forEach(([localId, node]) => {
|
|
7603
|
+
const childDef = lookupContentType(node.kind, node.type);
|
|
7604
|
+
if (childDef !== void 0 && node.data !== void 0) {
|
|
7605
|
+
const result = childDef.payloadSchema.safeParse(node.data);
|
|
7606
|
+
if (!result.success) {
|
|
7607
|
+
addIssue(
|
|
7608
|
+
ctx,
|
|
7609
|
+
[...systemPath, "content", localId, "data"],
|
|
7610
|
+
`Content node "${localId}" (${node.kind}:${node.type}) data failed payload validation: ${result.error.message}`
|
|
7611
|
+
);
|
|
7612
|
+
}
|
|
7613
|
+
}
|
|
7614
|
+
if (node.parentContentId !== void 0 && childDef !== void 0) {
|
|
7615
|
+
const parentNode = content[node.parentContentId];
|
|
7616
|
+
if (parentNode !== void 0) {
|
|
7617
|
+
const parentDef = lookupContentType(parentNode.kind, parentNode.type);
|
|
7618
|
+
if (parentDef !== void 0 && childDef.kind !== parentDef.kind) {
|
|
7619
|
+
addIssue(
|
|
7620
|
+
ctx,
|
|
7621
|
+
[...systemPath, "content", localId, "parentContentId"],
|
|
7622
|
+
`Content node "${localId}" kind "${childDef.kind}" cannot parent under "${node.parentContentId}" kind "${parentDef.kind}": parentContentId must be same-meta-kind (per L19)`
|
|
7623
|
+
);
|
|
7624
|
+
}
|
|
7625
|
+
}
|
|
7626
|
+
}
|
|
7627
|
+
});
|
|
7628
|
+
if (childSystems !== void 0) {
|
|
7629
|
+
Object.entries(childSystems).forEach(([childLocalId, child]) => {
|
|
7630
|
+
validateSystemContent(child, [...systemPath, childKey, childLocalId]);
|
|
7631
|
+
});
|
|
7632
|
+
}
|
|
7633
|
+
}
|
|
7634
|
+
Object.entries(model.systems).forEach(([systemKey, system]) => {
|
|
7635
|
+
validateSystemContent(system, ["systems", systemKey]);
|
|
7636
|
+
});
|
|
7637
|
+
for (const diagnostic of ontologyCompilation.diagnostics) {
|
|
7638
|
+
addIssue(ctx, diagnostic.path, diagnostic.message);
|
|
7639
|
+
}
|
|
7640
|
+
});
|
|
7641
|
+
|
|
7642
|
+
// ../core/src/organization-model/defaults.ts
|
|
7643
|
+
var DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE = {};
|
|
7644
|
+
var DEFAULT_ORGANIZATION_MODEL_ENTITIES2 = DEFAULT_ORGANIZATION_MODEL_ENTITIES;
|
|
7645
|
+
var DEFAULT_ORGANIZATION_MODEL_NAVIGATION = {
|
|
7646
|
+
sidebar: {
|
|
7647
|
+
primary: {
|
|
7648
|
+
dashboard: {
|
|
7649
|
+
type: "surface",
|
|
7650
|
+
label: "Dashboard",
|
|
7651
|
+
path: "/",
|
|
7652
|
+
surfaceType: "dashboard",
|
|
7653
|
+
icon: "dashboard",
|
|
7654
|
+
order: 10,
|
|
7655
|
+
targets: { systems: ["dashboard"] }
|
|
7656
|
+
},
|
|
7657
|
+
business: {
|
|
7658
|
+
type: "group",
|
|
7659
|
+
label: "Business",
|
|
7660
|
+
icon: "business",
|
|
7661
|
+
order: 20,
|
|
7662
|
+
children: {
|
|
7663
|
+
sales: {
|
|
7664
|
+
type: "surface",
|
|
7665
|
+
label: "Sales",
|
|
7666
|
+
path: "/sales",
|
|
7667
|
+
surfaceType: "page",
|
|
7668
|
+
icon: "sales",
|
|
7669
|
+
order: 10,
|
|
7670
|
+
targets: { systems: ["sales"] }
|
|
7671
|
+
},
|
|
7672
|
+
clients: {
|
|
7673
|
+
type: "surface",
|
|
7674
|
+
label: "Clients",
|
|
7675
|
+
path: "/clients",
|
|
7676
|
+
surfaceType: "list",
|
|
7677
|
+
icon: "projects",
|
|
7678
|
+
order: 20,
|
|
7679
|
+
targets: { systems: ["clients"] }
|
|
7680
|
+
},
|
|
7681
|
+
projects: {
|
|
7682
|
+
type: "surface",
|
|
7683
|
+
label: "Projects",
|
|
7684
|
+
path: "/projects",
|
|
7685
|
+
surfaceType: "page",
|
|
7686
|
+
icon: "projects",
|
|
7687
|
+
order: 30,
|
|
7688
|
+
targets: { systems: ["projects"] }
|
|
7689
|
+
}
|
|
7690
|
+
}
|
|
7691
|
+
},
|
|
7692
|
+
operations: {
|
|
7693
|
+
type: "group",
|
|
7694
|
+
label: "Operations",
|
|
7695
|
+
icon: "operations",
|
|
7696
|
+
order: 30,
|
|
7697
|
+
children: {
|
|
7698
|
+
"operations-overview": {
|
|
7699
|
+
type: "surface",
|
|
7700
|
+
label: "Overview",
|
|
7701
|
+
path: "/operations",
|
|
7702
|
+
surfaceType: "page",
|
|
7703
|
+
order: 10,
|
|
7704
|
+
targets: { systems: ["operations.overview"] }
|
|
7705
|
+
},
|
|
7706
|
+
"operations-systems": {
|
|
7707
|
+
type: "surface",
|
|
7708
|
+
label: "Systems",
|
|
7709
|
+
path: "/operations/systems",
|
|
7710
|
+
surfaceType: "page",
|
|
7711
|
+
order: 20,
|
|
7712
|
+
targets: { systems: ["operations"] }
|
|
7713
|
+
},
|
|
7714
|
+
"operations-resources": {
|
|
7715
|
+
type: "surface",
|
|
7716
|
+
label: "Resources",
|
|
7717
|
+
path: "/operations/resources",
|
|
7718
|
+
surfaceType: "list",
|
|
7719
|
+
order: 30,
|
|
7720
|
+
targets: { systems: ["operations.resources"] }
|
|
7721
|
+
},
|
|
7722
|
+
"operations-command-queue": {
|
|
7723
|
+
type: "surface",
|
|
7724
|
+
label: "Command Queue",
|
|
7725
|
+
path: "/operations/command-queue",
|
|
7726
|
+
surfaceType: "list",
|
|
7727
|
+
order: 40,
|
|
7728
|
+
targets: { systems: ["operations.command-queue"] }
|
|
7729
|
+
},
|
|
7730
|
+
"operations-task-scheduler": {
|
|
7731
|
+
type: "surface",
|
|
7732
|
+
label: "Task Scheduler",
|
|
7733
|
+
path: "/operations/task-scheduler",
|
|
7734
|
+
surfaceType: "list",
|
|
7735
|
+
order: 50,
|
|
7736
|
+
targets: { systems: ["operations.task-scheduler"] }
|
|
7737
|
+
}
|
|
7738
|
+
}
|
|
7739
|
+
},
|
|
7740
|
+
monitoring: {
|
|
7741
|
+
type: "group",
|
|
7742
|
+
label: "Monitoring",
|
|
7743
|
+
icon: "monitoring",
|
|
7744
|
+
order: 40,
|
|
7745
|
+
children: {
|
|
7746
|
+
"monitoring-overview": {
|
|
7747
|
+
type: "surface",
|
|
7748
|
+
label: "Overview",
|
|
7749
|
+
path: "/monitoring",
|
|
7750
|
+
surfaceType: "page",
|
|
7751
|
+
order: 10,
|
|
7752
|
+
targets: { systems: ["monitoring"] }
|
|
7753
|
+
},
|
|
7754
|
+
"monitoring-calendar": {
|
|
7755
|
+
type: "surface",
|
|
7756
|
+
label: "Calendar",
|
|
7757
|
+
path: "/monitoring/calendar",
|
|
7758
|
+
surfaceType: "page",
|
|
7759
|
+
order: 20,
|
|
7760
|
+
targets: { systems: ["monitoring.calendar"] }
|
|
7761
|
+
},
|
|
7762
|
+
"monitoring-activity-log": {
|
|
7763
|
+
type: "surface",
|
|
7764
|
+
label: "Activity Log",
|
|
7765
|
+
path: "/monitoring/activity-log",
|
|
7766
|
+
surfaceType: "list",
|
|
7767
|
+
order: 30,
|
|
7768
|
+
targets: { systems: ["monitoring.activity-log"] }
|
|
7769
|
+
},
|
|
7770
|
+
"monitoring-execution-logs": {
|
|
7771
|
+
type: "surface",
|
|
7772
|
+
label: "Execution Logs",
|
|
7773
|
+
path: "/monitoring/execution-logs",
|
|
7774
|
+
surfaceType: "list",
|
|
7775
|
+
order: 40,
|
|
7776
|
+
targets: { systems: ["monitoring.execution-logs"] }
|
|
7777
|
+
},
|
|
7778
|
+
"monitoring-execution-health": {
|
|
7779
|
+
type: "surface",
|
|
7780
|
+
label: "Execution Health",
|
|
7781
|
+
path: "/monitoring/execution-health",
|
|
7782
|
+
surfaceType: "dashboard",
|
|
7783
|
+
order: 50,
|
|
7784
|
+
targets: { systems: ["monitoring.execution-health"] }
|
|
7785
|
+
},
|
|
7786
|
+
"monitoring-notifications": {
|
|
7787
|
+
type: "surface",
|
|
7788
|
+
label: "Notifications",
|
|
7789
|
+
path: "/monitoring/notifications",
|
|
7790
|
+
surfaceType: "list",
|
|
7791
|
+
order: 60,
|
|
7792
|
+
targets: { systems: ["monitoring.notifications"] }
|
|
7793
|
+
},
|
|
7794
|
+
"monitoring-requests": {
|
|
7795
|
+
type: "surface",
|
|
7796
|
+
label: "Requests",
|
|
7797
|
+
path: "/monitoring/requests",
|
|
7798
|
+
surfaceType: "list",
|
|
7799
|
+
order: 70,
|
|
7800
|
+
targets: { systems: ["monitoring.submitted-requests"] }
|
|
7801
|
+
}
|
|
7802
|
+
}
|
|
7803
|
+
},
|
|
7804
|
+
knowledge: {
|
|
7805
|
+
type: "surface",
|
|
7806
|
+
label: "Knowledge Base",
|
|
7807
|
+
path: "/knowledge",
|
|
7808
|
+
surfaceType: "page",
|
|
7809
|
+
icon: "knowledge",
|
|
7810
|
+
order: 50
|
|
7811
|
+
}
|
|
7812
|
+
},
|
|
7813
|
+
bottom: {
|
|
7814
|
+
settings: {
|
|
7815
|
+
type: "group",
|
|
7816
|
+
label: "Settings",
|
|
7817
|
+
icon: "settings",
|
|
7818
|
+
order: 10,
|
|
7819
|
+
children: {
|
|
7820
|
+
"settings-account": {
|
|
7821
|
+
type: "surface",
|
|
7822
|
+
label: "Account",
|
|
7823
|
+
path: "/settings/account",
|
|
7824
|
+
surfaceType: "settings",
|
|
7825
|
+
order: 10,
|
|
7826
|
+
targets: { systems: ["settings.account"] }
|
|
7827
|
+
},
|
|
7828
|
+
"settings-appearance": {
|
|
7829
|
+
type: "surface",
|
|
7830
|
+
label: "Appearance",
|
|
7831
|
+
path: "/settings/appearance",
|
|
7832
|
+
surfaceType: "settings",
|
|
7833
|
+
order: 20,
|
|
7834
|
+
targets: { systems: ["settings.appearance"] }
|
|
7835
|
+
},
|
|
7836
|
+
"settings-roles": {
|
|
7837
|
+
type: "surface",
|
|
7838
|
+
label: "My Roles",
|
|
7839
|
+
path: "/settings/roles",
|
|
7840
|
+
surfaceType: "settings",
|
|
7841
|
+
order: 30,
|
|
7842
|
+
targets: { systems: ["settings.roles"] }
|
|
7843
|
+
},
|
|
7844
|
+
"settings-organization": {
|
|
7845
|
+
type: "surface",
|
|
7846
|
+
label: "Organization",
|
|
7847
|
+
path: "/settings/organization",
|
|
7848
|
+
surfaceType: "settings",
|
|
7849
|
+
order: 40,
|
|
7850
|
+
targets: { systems: ["settings.organization"] }
|
|
7851
|
+
},
|
|
7852
|
+
"settings-credentials": {
|
|
7853
|
+
type: "surface",
|
|
7854
|
+
label: "Credentials",
|
|
7855
|
+
path: "/settings/credentials",
|
|
7856
|
+
surfaceType: "settings",
|
|
7857
|
+
order: 50,
|
|
7858
|
+
targets: { systems: ["settings.credentials"] }
|
|
7859
|
+
},
|
|
7860
|
+
"settings-api-keys": {
|
|
7861
|
+
type: "surface",
|
|
7862
|
+
label: "API Keys",
|
|
7863
|
+
path: "/settings/api-keys",
|
|
7864
|
+
surfaceType: "settings",
|
|
7865
|
+
order: 60,
|
|
7866
|
+
targets: { systems: ["settings.api-keys"] }
|
|
7867
|
+
},
|
|
7868
|
+
"settings-webhooks": {
|
|
7869
|
+
type: "surface",
|
|
7870
|
+
label: "Webhooks",
|
|
7871
|
+
path: "/settings/webhooks",
|
|
7872
|
+
surfaceType: "settings",
|
|
7873
|
+
order: 70,
|
|
7874
|
+
targets: { systems: ["settings.webhooks"] }
|
|
7875
|
+
},
|
|
7876
|
+
"settings-deployments": {
|
|
7877
|
+
type: "surface",
|
|
7878
|
+
label: "Deployments",
|
|
7879
|
+
path: "/settings/deployments",
|
|
7880
|
+
surfaceType: "settings",
|
|
7881
|
+
order: 80,
|
|
7882
|
+
targets: { systems: ["settings.deployments"] }
|
|
7883
|
+
}
|
|
7884
|
+
}
|
|
7885
|
+
},
|
|
7886
|
+
admin: {
|
|
7887
|
+
type: "group",
|
|
7888
|
+
label: "Admin",
|
|
7889
|
+
icon: "admin",
|
|
7890
|
+
order: 20,
|
|
7891
|
+
children: {
|
|
7892
|
+
"admin-dashboard": {
|
|
7893
|
+
type: "surface",
|
|
7894
|
+
label: "Dashboard",
|
|
7895
|
+
path: "/admin/dashboard",
|
|
7896
|
+
surfaceType: "dashboard",
|
|
7897
|
+
order: 10,
|
|
7898
|
+
targets: { systems: ["admin"] },
|
|
7899
|
+
requiresAdmin: true
|
|
7900
|
+
},
|
|
7901
|
+
"admin-system-health": {
|
|
7902
|
+
type: "surface",
|
|
7903
|
+
label: "System Health",
|
|
7904
|
+
path: "/admin/system-health",
|
|
7905
|
+
surfaceType: "dashboard",
|
|
7906
|
+
order: 20,
|
|
7907
|
+
targets: { systems: ["admin.system-health"] },
|
|
7908
|
+
requiresAdmin: true
|
|
7909
|
+
},
|
|
7910
|
+
"admin-organizations": {
|
|
7911
|
+
type: "surface",
|
|
7912
|
+
label: "Organizations",
|
|
7913
|
+
path: "/admin/organizations",
|
|
7914
|
+
surfaceType: "list",
|
|
7915
|
+
order: 30,
|
|
7916
|
+
targets: { systems: ["admin.organizations"] },
|
|
7917
|
+
requiresAdmin: true
|
|
7918
|
+
},
|
|
7919
|
+
"admin-users": {
|
|
7920
|
+
type: "surface",
|
|
7921
|
+
label: "Users",
|
|
7922
|
+
path: "/admin/users",
|
|
7923
|
+
surfaceType: "list",
|
|
7924
|
+
order: 40,
|
|
7925
|
+
targets: { systems: ["admin.users"] },
|
|
7926
|
+
requiresAdmin: true
|
|
7927
|
+
},
|
|
7928
|
+
"admin-design-showcase": {
|
|
7929
|
+
type: "surface",
|
|
7930
|
+
label: "Design Showcase",
|
|
7931
|
+
path: "/admin/design-showcase",
|
|
7932
|
+
surfaceType: "page",
|
|
7933
|
+
order: 50,
|
|
7934
|
+
targets: { systems: ["admin.design-showcase"] },
|
|
7935
|
+
requiresAdmin: true
|
|
7936
|
+
},
|
|
7937
|
+
"admin-debug": {
|
|
7938
|
+
type: "surface",
|
|
7939
|
+
label: "Debug",
|
|
7940
|
+
path: "/admin/debug",
|
|
7941
|
+
surfaceType: "page",
|
|
7942
|
+
order: 60,
|
|
7943
|
+
targets: { systems: ["admin.debug"] },
|
|
7944
|
+
requiresAdmin: true
|
|
7945
|
+
}
|
|
7946
|
+
}
|
|
7947
|
+
}
|
|
7948
|
+
}
|
|
7949
|
+
}
|
|
7950
|
+
};
|
|
7951
|
+
var DEFAULT_ORGANIZATION_MODEL = {
|
|
7952
|
+
version: 1,
|
|
7953
|
+
domainMetadata: DEFAULT_ORGANIZATION_MODEL_DOMAIN_METADATA,
|
|
7954
|
+
branding: DEFAULT_ORGANIZATION_MODEL_BRANDING,
|
|
7955
|
+
navigation: DEFAULT_ORGANIZATION_MODEL_NAVIGATION,
|
|
7956
|
+
identity: DEFAULT_ORGANIZATION_MODEL_IDENTITY,
|
|
7957
|
+
customers: DEFAULT_ORGANIZATION_MODEL_CUSTOMERS,
|
|
7958
|
+
offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
|
|
7959
|
+
roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
|
|
7960
|
+
goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
|
|
7961
|
+
systems: {
|
|
7962
|
+
dashboard: {
|
|
7963
|
+
id: "dashboard",
|
|
7964
|
+
order: 10,
|
|
7965
|
+
label: "Dashboard",
|
|
7966
|
+
enabled: true,
|
|
7967
|
+
lifecycle: "active",
|
|
7968
|
+
path: "/",
|
|
7969
|
+
icon: "dashboard"
|
|
7970
|
+
},
|
|
7971
|
+
platform: {
|
|
7972
|
+
id: "platform",
|
|
7973
|
+
order: 30,
|
|
7974
|
+
label: "Platform",
|
|
7975
|
+
description: "Elevasis platform architecture, capabilities, and implementation patterns",
|
|
7976
|
+
enabled: true,
|
|
7977
|
+
lifecycle: "active",
|
|
7978
|
+
color: "cyan",
|
|
7979
|
+
icon: "platform"
|
|
7980
|
+
},
|
|
7981
|
+
finance: {
|
|
7982
|
+
id: "finance",
|
|
7983
|
+
order: 40,
|
|
7984
|
+
label: "Finance",
|
|
7985
|
+
description: "Finance operations, accounting, billing, reconciliation, and tax prep",
|
|
7986
|
+
enabled: true,
|
|
7987
|
+
lifecycle: "active",
|
|
7988
|
+
color: "green",
|
|
7989
|
+
icon: "finance"
|
|
7990
|
+
},
|
|
7991
|
+
sales: {
|
|
7992
|
+
id: "sales",
|
|
7993
|
+
order: 60,
|
|
7994
|
+
label: "Sales",
|
|
7995
|
+
description: "Revenue workflows and customer acquisition",
|
|
7996
|
+
enabled: true,
|
|
7997
|
+
lifecycle: "active",
|
|
7998
|
+
color: "blue",
|
|
7999
|
+
icon: "sales",
|
|
8000
|
+
path: "/sales"
|
|
8001
|
+
},
|
|
8002
|
+
"sales.crm": {
|
|
8003
|
+
id: "sales.crm",
|
|
8004
|
+
order: 70,
|
|
8005
|
+
label: "CRM",
|
|
8006
|
+
description: "Relationship pipeline and deal management",
|
|
8007
|
+
enabled: true,
|
|
8008
|
+
lifecycle: "active",
|
|
8009
|
+
actions: Object.values(CRM_ACTION_ENTRIES).map((action) => ({
|
|
8010
|
+
actionId: action.id,
|
|
8011
|
+
intent: "exposes"
|
|
8012
|
+
})),
|
|
8013
|
+
color: "blue",
|
|
8014
|
+
icon: "crm",
|
|
8015
|
+
path: "/crm"
|
|
8016
|
+
},
|
|
8017
|
+
"sales.lead-gen": {
|
|
8018
|
+
id: "sales.lead-gen",
|
|
8019
|
+
order: 80,
|
|
8020
|
+
label: "Lead Gen",
|
|
8021
|
+
description: "Prospecting, qualification, and outreach preparation",
|
|
8022
|
+
enabled: true,
|
|
8023
|
+
lifecycle: "active",
|
|
8024
|
+
actions: Object.values(LEAD_GEN_ACTION_ENTRIES).map((action) => ({
|
|
8025
|
+
actionId: action.id,
|
|
8026
|
+
intent: "exposes"
|
|
8027
|
+
})),
|
|
8028
|
+
color: "cyan",
|
|
8029
|
+
icon: "lead-gen",
|
|
8030
|
+
path: "/lead-gen"
|
|
8031
|
+
},
|
|
8032
|
+
projects: {
|
|
8033
|
+
id: "projects",
|
|
8034
|
+
order: 90,
|
|
8035
|
+
label: "Projects",
|
|
8036
|
+
description: "Projects, milestones, and client work execution",
|
|
8037
|
+
enabled: true,
|
|
8038
|
+
lifecycle: "active",
|
|
8039
|
+
color: "orange",
|
|
8040
|
+
icon: "projects",
|
|
8041
|
+
path: "/projects"
|
|
8042
|
+
},
|
|
8043
|
+
clients: {
|
|
8044
|
+
id: "clients",
|
|
8045
|
+
order: 100,
|
|
8046
|
+
label: "Clients",
|
|
8047
|
+
description: "Client relationships, accounts, and business context",
|
|
8048
|
+
enabled: true,
|
|
8049
|
+
lifecycle: "active",
|
|
8050
|
+
color: "orange",
|
|
8051
|
+
icon: "projects",
|
|
8052
|
+
path: "/clients"
|
|
8053
|
+
},
|
|
8054
|
+
operations: {
|
|
8055
|
+
id: "operations",
|
|
8056
|
+
order: 110,
|
|
8057
|
+
label: "Operations",
|
|
8058
|
+
description: "Operational resources, topology, and orchestration visibility",
|
|
8059
|
+
enabled: true,
|
|
8060
|
+
lifecycle: "active",
|
|
8061
|
+
color: "violet",
|
|
8062
|
+
icon: "operations"
|
|
8063
|
+
},
|
|
8064
|
+
"knowledge.command-view": {
|
|
8065
|
+
id: "knowledge.command-view",
|
|
8066
|
+
order: 120,
|
|
8067
|
+
label: "Command View",
|
|
8068
|
+
enabled: true,
|
|
8069
|
+
lifecycle: "active",
|
|
8070
|
+
path: "/knowledge/command-view",
|
|
8071
|
+
devOnly: true
|
|
8072
|
+
},
|
|
8073
|
+
"operations.overview": {
|
|
8074
|
+
id: "operations.overview",
|
|
8075
|
+
order: 130,
|
|
8076
|
+
label: "Overview",
|
|
8077
|
+
enabled: true,
|
|
8078
|
+
lifecycle: "active",
|
|
8079
|
+
path: "/operations"
|
|
8080
|
+
},
|
|
8081
|
+
"operations.resources": {
|
|
8082
|
+
id: "operations.resources",
|
|
8083
|
+
order: 140,
|
|
8084
|
+
label: "Resources",
|
|
8085
|
+
enabled: true,
|
|
8086
|
+
lifecycle: "active",
|
|
8087
|
+
path: "/operations/resources"
|
|
8088
|
+
},
|
|
8089
|
+
"operations.command-queue": {
|
|
8090
|
+
id: "operations.command-queue",
|
|
8091
|
+
order: 150,
|
|
8092
|
+
label: "Command Queue",
|
|
8093
|
+
enabled: true,
|
|
8094
|
+
lifecycle: "active",
|
|
8095
|
+
path: "/operations/command-queue"
|
|
8096
|
+
},
|
|
8097
|
+
"operations.sessions": {
|
|
8098
|
+
id: "operations.sessions",
|
|
8099
|
+
order: 160,
|
|
8100
|
+
label: "Sessions",
|
|
8101
|
+
enabled: false,
|
|
8102
|
+
lifecycle: "deprecated",
|
|
8103
|
+
path: "/operations/sessions"
|
|
8104
|
+
},
|
|
8105
|
+
"operations.task-scheduler": {
|
|
8106
|
+
id: "operations.task-scheduler",
|
|
8107
|
+
order: 170,
|
|
8108
|
+
label: "Task Scheduler",
|
|
8109
|
+
enabled: true,
|
|
8110
|
+
lifecycle: "active",
|
|
8111
|
+
path: "/operations/task-scheduler"
|
|
8112
|
+
},
|
|
8113
|
+
monitoring: {
|
|
8114
|
+
id: "monitoring",
|
|
8115
|
+
order: 180,
|
|
8116
|
+
label: "Monitoring",
|
|
8117
|
+
enabled: true,
|
|
8118
|
+
lifecycle: "active"
|
|
8119
|
+
},
|
|
8120
|
+
"monitoring.calendar": {
|
|
8121
|
+
id: "monitoring.calendar",
|
|
8122
|
+
order: 190,
|
|
8123
|
+
label: "Calendar",
|
|
8124
|
+
description: "Google Calendar events and agenda views",
|
|
8125
|
+
enabled: true,
|
|
8126
|
+
lifecycle: "active",
|
|
8127
|
+
path: "/monitoring/calendar",
|
|
8128
|
+
icon: "calendar"
|
|
8129
|
+
},
|
|
8130
|
+
"monitoring.activity-log": {
|
|
8131
|
+
id: "monitoring.activity-log",
|
|
8132
|
+
order: 200,
|
|
8133
|
+
label: "Activity Log",
|
|
8134
|
+
enabled: true,
|
|
8135
|
+
lifecycle: "active",
|
|
8136
|
+
path: "/monitoring/activity-log"
|
|
8137
|
+
},
|
|
8138
|
+
"monitoring.execution-logs": {
|
|
8139
|
+
id: "monitoring.execution-logs",
|
|
8140
|
+
order: 210,
|
|
8141
|
+
label: "Execution Logs",
|
|
8142
|
+
enabled: true,
|
|
8143
|
+
lifecycle: "active",
|
|
8144
|
+
path: "/monitoring/execution-logs"
|
|
8145
|
+
},
|
|
8146
|
+
"monitoring.execution-health": {
|
|
8147
|
+
id: "monitoring.execution-health",
|
|
8148
|
+
order: 220,
|
|
8149
|
+
label: "Execution Health",
|
|
8150
|
+
enabled: true,
|
|
8151
|
+
lifecycle: "active",
|
|
8152
|
+
path: "/monitoring/execution-health"
|
|
8153
|
+
},
|
|
8154
|
+
"monitoring.cost-analytics": {
|
|
8155
|
+
id: "monitoring.cost-analytics",
|
|
8156
|
+
order: 230,
|
|
8157
|
+
label: "Cost Analytics",
|
|
8158
|
+
enabled: false,
|
|
8159
|
+
lifecycle: "deprecated",
|
|
8160
|
+
path: "/monitoring/cost-analytics"
|
|
8161
|
+
},
|
|
8162
|
+
"monitoring.notifications": {
|
|
8163
|
+
id: "monitoring.notifications",
|
|
8164
|
+
order: 240,
|
|
8165
|
+
label: "Notifications",
|
|
8166
|
+
enabled: true,
|
|
8167
|
+
lifecycle: "active",
|
|
8168
|
+
path: "/monitoring/notifications"
|
|
8169
|
+
},
|
|
8170
|
+
"monitoring.submitted-requests": {
|
|
8171
|
+
id: "monitoring.submitted-requests",
|
|
8172
|
+
order: 250,
|
|
8173
|
+
label: "Submitted Requests",
|
|
8174
|
+
enabled: true,
|
|
8175
|
+
lifecycle: "active",
|
|
8176
|
+
path: "/monitoring/requests"
|
|
8177
|
+
},
|
|
8178
|
+
settings: {
|
|
8179
|
+
id: "settings",
|
|
8180
|
+
order: 260,
|
|
8181
|
+
label: "Settings",
|
|
8182
|
+
enabled: true,
|
|
8183
|
+
lifecycle: "active",
|
|
8184
|
+
icon: "settings"
|
|
8185
|
+
},
|
|
8186
|
+
"settings.account": {
|
|
8187
|
+
id: "settings.account",
|
|
8188
|
+
order: 270,
|
|
8189
|
+
label: "Account",
|
|
8190
|
+
enabled: true,
|
|
8191
|
+
lifecycle: "active",
|
|
8192
|
+
path: "/settings/account"
|
|
8193
|
+
},
|
|
8194
|
+
"settings.appearance": {
|
|
8195
|
+
id: "settings.appearance",
|
|
8196
|
+
order: 280,
|
|
8197
|
+
label: "Appearance",
|
|
8198
|
+
enabled: true,
|
|
8199
|
+
lifecycle: "active",
|
|
8200
|
+
path: "/settings/appearance"
|
|
8201
|
+
},
|
|
8202
|
+
"settings.roles": {
|
|
8203
|
+
id: "settings.roles",
|
|
8204
|
+
order: 290,
|
|
8205
|
+
label: "My Roles",
|
|
8206
|
+
enabled: true,
|
|
8207
|
+
lifecycle: "active",
|
|
8208
|
+
path: "/settings/roles"
|
|
8209
|
+
},
|
|
8210
|
+
"settings.organization": {
|
|
8211
|
+
id: "settings.organization",
|
|
8212
|
+
order: 300,
|
|
8213
|
+
label: "Organization",
|
|
8214
|
+
enabled: true,
|
|
8215
|
+
lifecycle: "active",
|
|
8216
|
+
path: "/settings/organization"
|
|
8217
|
+
},
|
|
8218
|
+
"settings.credentials": {
|
|
8219
|
+
id: "settings.credentials",
|
|
8220
|
+
order: 310,
|
|
8221
|
+
label: "Credentials",
|
|
8222
|
+
enabled: true,
|
|
8223
|
+
lifecycle: "active",
|
|
8224
|
+
path: "/settings/credentials"
|
|
8225
|
+
},
|
|
8226
|
+
"settings.api-keys": {
|
|
8227
|
+
id: "settings.api-keys",
|
|
8228
|
+
order: 320,
|
|
8229
|
+
label: "API Keys",
|
|
8230
|
+
enabled: true,
|
|
8231
|
+
lifecycle: "active",
|
|
8232
|
+
path: "/settings/api-keys"
|
|
8233
|
+
},
|
|
8234
|
+
"settings.webhooks": {
|
|
8235
|
+
id: "settings.webhooks",
|
|
8236
|
+
order: 330,
|
|
8237
|
+
label: "Webhooks",
|
|
8238
|
+
enabled: true,
|
|
8239
|
+
lifecycle: "active",
|
|
8240
|
+
path: "/settings/webhooks"
|
|
8241
|
+
},
|
|
8242
|
+
"settings.deployments": {
|
|
8243
|
+
id: "settings.deployments",
|
|
8244
|
+
order: 340,
|
|
8245
|
+
label: "Deployments",
|
|
8246
|
+
enabled: true,
|
|
8247
|
+
lifecycle: "active",
|
|
8248
|
+
path: "/settings/deployments"
|
|
8249
|
+
},
|
|
8250
|
+
admin: {
|
|
8251
|
+
id: "admin",
|
|
8252
|
+
order: 350,
|
|
8253
|
+
label: "Admin",
|
|
8254
|
+
enabled: true,
|
|
8255
|
+
lifecycle: "active",
|
|
8256
|
+
path: "/admin",
|
|
8257
|
+
icon: "admin",
|
|
8258
|
+
requiresAdmin: true
|
|
8259
|
+
},
|
|
8260
|
+
"admin.system-health": {
|
|
8261
|
+
id: "admin.system-health",
|
|
8262
|
+
order: 360,
|
|
8263
|
+
label: "System Health",
|
|
8264
|
+
enabled: true,
|
|
8265
|
+
lifecycle: "active",
|
|
8266
|
+
path: "/admin/system-health"
|
|
8267
|
+
},
|
|
8268
|
+
"admin.organizations": {
|
|
8269
|
+
id: "admin.organizations",
|
|
8270
|
+
order: 370,
|
|
8271
|
+
label: "Organizations",
|
|
8272
|
+
enabled: true,
|
|
8273
|
+
lifecycle: "active",
|
|
8274
|
+
path: "/admin/organizations"
|
|
8275
|
+
},
|
|
8276
|
+
"admin.users": {
|
|
8277
|
+
id: "admin.users",
|
|
8278
|
+
order: 380,
|
|
8279
|
+
label: "Users",
|
|
8280
|
+
enabled: true,
|
|
8281
|
+
lifecycle: "active",
|
|
8282
|
+
path: "/admin/users"
|
|
8283
|
+
},
|
|
8284
|
+
"admin.design-showcase": {
|
|
8285
|
+
id: "admin.design-showcase",
|
|
8286
|
+
order: 390,
|
|
8287
|
+
label: "Design Showcase",
|
|
8288
|
+
enabled: true,
|
|
8289
|
+
lifecycle: "active",
|
|
8290
|
+
path: "/admin/design-showcase"
|
|
8291
|
+
},
|
|
8292
|
+
"admin.debug": {
|
|
8293
|
+
id: "admin.debug",
|
|
8294
|
+
order: 400,
|
|
8295
|
+
label: "Debug",
|
|
8296
|
+
enabled: true,
|
|
8297
|
+
lifecycle: "active",
|
|
8298
|
+
path: "/admin/debug"
|
|
8299
|
+
},
|
|
8300
|
+
archive: {
|
|
8301
|
+
id: "archive",
|
|
8302
|
+
order: 410,
|
|
8303
|
+
label: "Archive",
|
|
8304
|
+
enabled: true,
|
|
8305
|
+
lifecycle: "active",
|
|
8306
|
+
path: "/archive",
|
|
8307
|
+
icon: "archive",
|
|
8308
|
+
devOnly: true
|
|
8309
|
+
},
|
|
8310
|
+
"archive.agent-chat": {
|
|
8311
|
+
id: "archive.agent-chat",
|
|
8312
|
+
order: 420,
|
|
8313
|
+
label: "Agent Chat",
|
|
8314
|
+
enabled: true,
|
|
8315
|
+
lifecycle: "active",
|
|
8316
|
+
path: "/archive/agent-chat"
|
|
8317
|
+
},
|
|
8318
|
+
"archive.execution-runner": {
|
|
8319
|
+
id: "archive.execution-runner",
|
|
8320
|
+
order: 430,
|
|
8321
|
+
label: "Execution Runner",
|
|
8322
|
+
enabled: true,
|
|
8323
|
+
lifecycle: "active",
|
|
8324
|
+
path: "/archive/execution-runner"
|
|
8325
|
+
},
|
|
8326
|
+
seo: {
|
|
8327
|
+
id: "seo",
|
|
8328
|
+
order: 440,
|
|
8329
|
+
label: "SEO",
|
|
8330
|
+
enabled: false,
|
|
8331
|
+
lifecycle: "deprecated",
|
|
8332
|
+
path: "/seo"
|
|
8333
|
+
},
|
|
8334
|
+
knowledge: {
|
|
8335
|
+
id: "knowledge",
|
|
8336
|
+
order: 450,
|
|
8337
|
+
label: "Knowledge",
|
|
8338
|
+
description: "Operational knowledge, playbooks, and strategy docs",
|
|
8339
|
+
enabled: true,
|
|
8340
|
+
lifecycle: "active",
|
|
8341
|
+
color: "teal",
|
|
8342
|
+
icon: "knowledge"
|
|
8343
|
+
},
|
|
8344
|
+
"knowledge.base": {
|
|
8345
|
+
id: "knowledge.base",
|
|
8346
|
+
order: 460,
|
|
8347
|
+
label: "Knowledge Base",
|
|
8348
|
+
enabled: true,
|
|
8349
|
+
lifecycle: "active",
|
|
8350
|
+
path: "/knowledge"
|
|
8351
|
+
}
|
|
8352
|
+
},
|
|
8353
|
+
ontology: DEFAULT_ONTOLOGY_SCOPE,
|
|
8354
|
+
resources: DEFAULT_ORGANIZATION_MODEL_RESOURCES,
|
|
8355
|
+
actions: DEFAULT_ORGANIZATION_MODEL_ACTIONS,
|
|
8356
|
+
entities: DEFAULT_ORGANIZATION_MODEL_ENTITIES2,
|
|
8357
|
+
policies: DEFAULT_ORGANIZATION_MODEL_POLICIES,
|
|
8358
|
+
// Phase 4 (D1): statuses top-level field removed; bridge status mirrors may
|
|
8359
|
+
// still project from System.content, but primary authoring belongs in ontology.
|
|
8360
|
+
knowledge: DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE
|
|
8361
|
+
};
|
|
8362
|
+
|
|
8363
|
+
// ../core/src/business/acquisition/ontology-validation.ts
|
|
8364
|
+
var CRM_PIPELINE_CATALOG_ONTOLOGY_ID = formatOntologyId({
|
|
8365
|
+
scope: "sales.crm",
|
|
8366
|
+
kind: "catalog",
|
|
8367
|
+
localId: "crm.pipeline"
|
|
8368
|
+
});
|
|
8369
|
+
var LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID = formatOntologyId({
|
|
8370
|
+
scope: "sales.lead-gen",
|
|
8371
|
+
kind: "catalog",
|
|
8372
|
+
localId: "lead-gen.stage-catalog"
|
|
8373
|
+
});
|
|
8374
|
+
var CRM_DEAL_OBJECT_ONTOLOGY_ID = formatOntologyId({
|
|
8375
|
+
scope: "sales.crm",
|
|
8376
|
+
kind: "object",
|
|
8377
|
+
localId: "crm.deal"
|
|
8378
|
+
});
|
|
8379
|
+
function createCrmPipelineCatalog() {
|
|
8380
|
+
return {
|
|
8381
|
+
id: CRM_PIPELINE_CATALOG_ONTOLOGY_ID,
|
|
8382
|
+
label: CRM_PIPELINE_DEFINITION.label,
|
|
8383
|
+
ownerSystemId: "sales.crm",
|
|
8384
|
+
kind: "pipeline",
|
|
8385
|
+
appliesTo: CRM_DEAL_OBJECT_ONTOLOGY_ID,
|
|
8386
|
+
entries: Object.fromEntries(
|
|
8387
|
+
CRM_PIPELINE_DEFINITION.stages.map((stage, index) => [
|
|
8388
|
+
stage.stageKey,
|
|
8389
|
+
{
|
|
8390
|
+
key: stage.stageKey,
|
|
8391
|
+
label: stage.label,
|
|
8392
|
+
order: (index + 1) * 10,
|
|
8393
|
+
...stage.color !== void 0 ? { color: stage.color } : {},
|
|
8394
|
+
states: stage.states.map((state) => ({ ...state }))
|
|
8395
|
+
}
|
|
8396
|
+
])
|
|
8397
|
+
),
|
|
8398
|
+
legacyPipelineKey: CRM_PIPELINE_DEFINITION.pipelineKey,
|
|
8399
|
+
legacyEntityKey: CRM_PIPELINE_DEFINITION.entityKey
|
|
8400
|
+
};
|
|
8401
|
+
}
|
|
8402
|
+
function createLeadGenStageCatalog() {
|
|
8403
|
+
return {
|
|
8404
|
+
id: LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID,
|
|
8405
|
+
label: "Lead Gen Processing Stages",
|
|
8406
|
+
ownerSystemId: "sales.lead-gen",
|
|
8407
|
+
kind: "processing-stage-catalog",
|
|
8408
|
+
entries: Object.fromEntries(
|
|
8409
|
+
Object.entries(LEAD_GEN_STAGE_CATALOG).map(([key, entry]) => [
|
|
8410
|
+
key,
|
|
8411
|
+
{
|
|
8412
|
+
...entry
|
|
8413
|
+
}
|
|
8414
|
+
])
|
|
8415
|
+
),
|
|
8416
|
+
legacyCatalogKey: "LEAD_GEN_STAGE_CATALOG"
|
|
8417
|
+
};
|
|
8418
|
+
}
|
|
8419
|
+
function isPlainRecord(value) {
|
|
8420
|
+
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
8421
|
+
}
|
|
8422
|
+
function mergeBridgeCatalogs(model) {
|
|
8423
|
+
const baseCatalogTypes = model.ontology?.catalogTypes ?? {};
|
|
8424
|
+
const bridgeCatalogTypes = {};
|
|
8425
|
+
if (baseCatalogTypes[CRM_PIPELINE_CATALOG_ONTOLOGY_ID] === void 0) {
|
|
8426
|
+
bridgeCatalogTypes[CRM_PIPELINE_CATALOG_ONTOLOGY_ID] = createCrmPipelineCatalog();
|
|
8427
|
+
}
|
|
8428
|
+
if (baseCatalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID] === void 0) {
|
|
8429
|
+
bridgeCatalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID] = createLeadGenStageCatalog();
|
|
8430
|
+
}
|
|
8431
|
+
if (Object.keys(bridgeCatalogTypes).length === 0) return model;
|
|
8432
|
+
return {
|
|
8433
|
+
...model,
|
|
8434
|
+
ontology: {
|
|
8435
|
+
...model.ontology ?? {},
|
|
8436
|
+
catalogTypes: {
|
|
8437
|
+
...baseCatalogTypes,
|
|
8438
|
+
...bridgeCatalogTypes
|
|
8439
|
+
}
|
|
8440
|
+
}
|
|
8441
|
+
};
|
|
8442
|
+
}
|
|
8443
|
+
function compileBusinessOntologyValidationIndex(model = DEFAULT_ORGANIZATION_MODEL) {
|
|
8444
|
+
const compilation = compileOrganizationOntology(mergeBridgeCatalogs(model));
|
|
8445
|
+
if (compilation.diagnostics.length > 0) {
|
|
8446
|
+
const summary = compilation.diagnostics.map((diagnostic) => diagnostic.message).join("; ");
|
|
8447
|
+
throw new Error(`Business ontology validation index failed to compile: ${summary}`);
|
|
8448
|
+
}
|
|
8449
|
+
const crmPipelineCatalog = compilation.ontology.catalogTypes[CRM_PIPELINE_CATALOG_ONTOLOGY_ID];
|
|
8450
|
+
const leadGenStageCatalog = compilation.ontology.catalogTypes[LEAD_GEN_STAGE_CATALOG_ONTOLOGY_ID];
|
|
8451
|
+
if (crmPipelineCatalog === void 0 || leadGenStageCatalog === void 0) {
|
|
8452
|
+
throw new Error("Business ontology validation index is missing CRM or lead-gen catalog bridge records");
|
|
8453
|
+
}
|
|
8454
|
+
return {
|
|
8455
|
+
ontology: compilation.ontology,
|
|
8456
|
+
crmPipelineCatalog,
|
|
8457
|
+
leadGenStageCatalog,
|
|
8458
|
+
actionTypesByLegacyId: indexActionTypesByLegacyId(compilation.ontology.actionTypes)
|
|
8459
|
+
};
|
|
8460
|
+
}
|
|
8461
|
+
function indexActionTypesByLegacyId(actionTypes) {
|
|
8462
|
+
const byLegacyId = {};
|
|
8463
|
+
for (const actionType of Object.values(actionTypes)) {
|
|
8464
|
+
const legacyActionId = actionType["legacyActionId"];
|
|
8465
|
+
if (typeof legacyActionId === "string") {
|
|
8466
|
+
byLegacyId[legacyActionId] = actionType;
|
|
8467
|
+
}
|
|
8468
|
+
}
|
|
8469
|
+
return byLegacyId;
|
|
8470
|
+
}
|
|
8471
|
+
var BUSINESS_ONTOLOGY_VALIDATION_INDEX = compileBusinessOntologyValidationIndex();
|
|
8472
|
+
function getCatalogEntries(catalog) {
|
|
8473
|
+
return isPlainRecord(catalog.entries) ? catalog.entries : {};
|
|
8474
|
+
}
|
|
8475
|
+
function asCrmStageEntry(key, value) {
|
|
8476
|
+
const record = isPlainRecord(value) ? value : {};
|
|
8477
|
+
const label = typeof record.label === "string" ? record.label : key;
|
|
8478
|
+
const order = typeof record.order === "number" ? record.order : 0;
|
|
8479
|
+
const color = typeof record.color === "string" ? record.color : void 0;
|
|
8480
|
+
const rawStates = Array.isArray(record.states) ? record.states : [];
|
|
8481
|
+
const states = rawStates.flatMap((state) => {
|
|
8482
|
+
if (!isPlainRecord(state) || typeof state.stateKey !== "string") return [];
|
|
8483
|
+
return [
|
|
8484
|
+
{
|
|
8485
|
+
stateKey: state.stateKey,
|
|
8486
|
+
label: typeof state.label === "string" ? state.label : state.stateKey
|
|
8487
|
+
}
|
|
8488
|
+
];
|
|
8489
|
+
});
|
|
8490
|
+
return {
|
|
8491
|
+
key,
|
|
8492
|
+
label,
|
|
8493
|
+
order,
|
|
8494
|
+
...color !== void 0 ? { color } : {},
|
|
8495
|
+
states
|
|
8496
|
+
};
|
|
8497
|
+
}
|
|
8498
|
+
function asLeadGenStageEntry(key, value) {
|
|
8499
|
+
const record = isPlainRecord(value) ? value : {};
|
|
8500
|
+
const entity = record.entity === "contact" ? "contact" : "company";
|
|
8501
|
+
const additionalEntities = Array.isArray(record.additionalEntities) ? record.additionalEntities.filter(
|
|
8502
|
+
(item) => item === "company" || item === "contact"
|
|
8503
|
+
) : void 0;
|
|
8504
|
+
const recordEntity = record.recordEntity === "company" || record.recordEntity === "contact" ? record.recordEntity : void 0;
|
|
8505
|
+
const recordStageKey = typeof record.recordStageKey === "string" ? record.recordStageKey : void 0;
|
|
8506
|
+
return {
|
|
8507
|
+
key: typeof record.key === "string" ? record.key : key,
|
|
8508
|
+
label: typeof record.label === "string" ? record.label : key,
|
|
8509
|
+
description: typeof record.description === "string" ? record.description : "",
|
|
8510
|
+
order: typeof record.order === "number" ? record.order : 0,
|
|
8511
|
+
entity,
|
|
8512
|
+
...additionalEntities !== void 0 ? { additionalEntities } : {},
|
|
8513
|
+
...recordEntity !== void 0 ? { recordEntity } : {},
|
|
8514
|
+
...recordStageKey !== void 0 ? { recordStageKey } : {}
|
|
8515
|
+
};
|
|
8516
|
+
}
|
|
8517
|
+
var CRM_STAGE_KEYS_FROM_ONTOLOGY = Object.keys(
|
|
8518
|
+
getCatalogEntries(BUSINESS_ONTOLOGY_VALIDATION_INDEX.crmPipelineCatalog)
|
|
8519
|
+
);
|
|
8520
|
+
var CRM_STATE_KEYS_FROM_ONTOLOGY = Object.values(
|
|
8521
|
+
getCatalogEntries(BUSINESS_ONTOLOGY_VALIDATION_INDEX.crmPipelineCatalog)
|
|
8522
|
+
).flatMap((entry, index) => {
|
|
8523
|
+
const stageKey = CRM_STAGE_KEYS_FROM_ONTOLOGY[index];
|
|
8524
|
+
if (stageKey === void 0) return [];
|
|
8525
|
+
return asCrmStageEntry(stageKey, entry).states.map((state) => state.stateKey);
|
|
8526
|
+
});
|
|
8527
|
+
Object.keys(
|
|
8528
|
+
getCatalogEntries(BUSINESS_ONTOLOGY_VALIDATION_INDEX.leadGenStageCatalog)
|
|
8529
|
+
);
|
|
8530
|
+
function getLeadGenStageCatalogFromOntology() {
|
|
8531
|
+
return Object.fromEntries(
|
|
8532
|
+
Object.entries(getCatalogEntries(BUSINESS_ONTOLOGY_VALIDATION_INDEX.leadGenStageCatalog)).map(([key, value]) => [
|
|
8533
|
+
key,
|
|
8534
|
+
asLeadGenStageEntry(key, value)
|
|
8535
|
+
])
|
|
8536
|
+
);
|
|
8537
|
+
}
|
|
8538
|
+
function getLeadGenStageEntry(stageKey) {
|
|
8539
|
+
return getLeadGenStageCatalogFromOntology()[stageKey];
|
|
8540
|
+
}
|
|
8541
|
+
function isLeadGenStageKey(stageKey) {
|
|
8542
|
+
return getLeadGenStageEntry(stageKey) !== void 0;
|
|
8543
|
+
}
|
|
8544
|
+
function isLeadGenRecordStageValidForEntity(stageKey, entity) {
|
|
8545
|
+
const stage = getLeadGenStageEntry(stageKey);
|
|
8546
|
+
return stage !== void 0 && (stage.entity === entity || stage.additionalEntities?.includes(entity) === true || stage.recordEntity === entity);
|
|
8547
|
+
}
|
|
8548
|
+
function isLeadGenActionKey(actionKey) {
|
|
8549
|
+
return actionKey.startsWith("lead-gen.") && BUSINESS_ONTOLOGY_VALIDATION_INDEX.actionTypesByLegacyId[actionKey] !== void 0;
|
|
8550
|
+
}
|
|
8551
|
+
|
|
8552
|
+
// ../core/src/business/acquisition/api-schemas.ts
|
|
5377
8553
|
var ProcessingStageStatusSchema = z.enum(["success", "no_result", "skipped", "error"]);
|
|
5378
|
-
var LeadGenStageKeySchema = z.string().refine((value) =>
|
|
8554
|
+
var LeadGenStageKeySchema = z.string().refine((value) => isLeadGenStageKey(value), {
|
|
5379
8555
|
message: "processing state key must match LEAD_GEN_STAGE_CATALOG"
|
|
5380
8556
|
});
|
|
5381
|
-
var
|
|
5382
|
-
message: "
|
|
8557
|
+
var LeadGenActionKeySchema = z.string().refine((value) => isLeadGenActionKey(value), {
|
|
8558
|
+
message: "actionKey must match ACTION_REGISTRY"
|
|
5383
8559
|
});
|
|
5384
|
-
var crmStageKeys =
|
|
5385
|
-
var crmStateKeys =
|
|
8560
|
+
var crmStageKeys = CRM_STAGE_KEYS_FROM_ONTOLOGY;
|
|
8561
|
+
var crmStateKeys = CRM_STATE_KEYS_FROM_ONTOLOGY;
|
|
5386
8562
|
var CrmStageKeySchema = z.enum(crmStageKeys);
|
|
5387
8563
|
var CrmStateKeySchema = z.enum(crmStateKeys);
|
|
5388
8564
|
var ProcessingStateEntrySchema = z.object({
|
|
@@ -5637,7 +8813,7 @@ var IcpRubricSchema = z.object({
|
|
|
5637
8813
|
customRules: z.string().optional()
|
|
5638
8814
|
});
|
|
5639
8815
|
var PipelineStageSchema = z.object({
|
|
5640
|
-
key: z.string().refine((value) =>
|
|
8816
|
+
key: z.string().refine((value) => isLeadGenStageKey(value), {
|
|
5641
8817
|
message: "pipeline stage key must match LEAD_GEN_STAGE_CATALOG"
|
|
5642
8818
|
}),
|
|
5643
8819
|
label: z.string().optional(),
|
|
@@ -5659,7 +8835,7 @@ var BuildPlanSnapshotStepSchema = z.object({
|
|
|
5659
8835
|
recordSourceStageKey: LeadGenStageKeySchema.optional(),
|
|
5660
8836
|
dependsOn: z.array(z.string().trim().min(1).max(100)).optional(),
|
|
5661
8837
|
dependencyMode: z.literal("per-record-eligibility"),
|
|
5662
|
-
|
|
8838
|
+
actionKey: LeadGenActionKeySchema,
|
|
5663
8839
|
defaultBatchSize: z.number().int().positive(),
|
|
5664
8840
|
maxBatchSize: z.number().int().positive(),
|
|
5665
8841
|
recordColumns: z.object({
|
|
@@ -6109,9 +9285,7 @@ z.object({
|
|
|
6109
9285
|
offset: z.coerce.number().int().min(0).default(0)
|
|
6110
9286
|
}).strict().superRefine((query, ctx) => {
|
|
6111
9287
|
if (!query.stage) return;
|
|
6112
|
-
|
|
6113
|
-
const validEntity = stage?.entity === query.entity || stage?.additionalEntities?.includes(query.entity) || stage?.recordEntity === query.entity;
|
|
6114
|
-
if (!validEntity) {
|
|
9288
|
+
if (!isLeadGenRecordStageValidForEntity(query.stage, query.entity)) {
|
|
6115
9289
|
ctx.addIssue({
|
|
6116
9290
|
code: z.ZodIssueCode.custom,
|
|
6117
9291
|
message: `stage "${query.stage}" is not valid for ${query.entity} records`,
|