@elevasis/core 0.20.0 → 0.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.
Files changed (77) hide show
  1. package/dist/index.d.ts +524 -6
  2. package/dist/index.js +417 -42
  3. package/dist/knowledge/index.d.ts +151 -1
  4. package/dist/organization-model/index.d.ts +524 -6
  5. package/dist/organization-model/index.js +417 -42
  6. package/dist/test-utils/index.d.ts +270 -1
  7. package/dist/test-utils/index.js +407 -41
  8. package/package.json +5 -5
  9. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +501 -303
  10. package/src/auth/multi-tenancy/permissions.ts +20 -8
  11. package/src/business/README.md +2 -2
  12. package/src/business/acquisition/api-schemas.test.ts +198 -0
  13. package/src/business/acquisition/api-schemas.ts +250 -9
  14. package/src/business/acquisition/build-templates.test.ts +28 -0
  15. package/src/business/acquisition/build-templates.ts +20 -8
  16. package/src/business/acquisition/index.ts +12 -0
  17. package/src/business/acquisition/types.ts +6 -1
  18. package/src/business/clients/api-schemas.test.ts +115 -0
  19. package/src/business/clients/api-schemas.ts +158 -0
  20. package/src/business/clients/index.ts +1 -0
  21. package/src/business/deals/api-schemas.ts +8 -0
  22. package/src/business/index.ts +5 -2
  23. package/src/business/projects/types.ts +19 -0
  24. package/src/execution/engine/__tests__/fixtures/test-agents.ts +10 -8
  25. package/src/execution/engine/agent/core/__tests__/agent.test.ts +16 -12
  26. package/src/execution/engine/agent/core/__tests__/error-passthrough.test.ts +4 -3
  27. package/src/execution/engine/agent/core/types.ts +25 -15
  28. package/src/execution/engine/agent/index.ts +6 -4
  29. package/src/execution/engine/agent/reasoning/__tests__/request-builder.test.ts +24 -18
  30. package/src/execution/engine/index.ts +3 -0
  31. package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.test.ts +55 -0
  32. package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.ts +107 -41
  33. package/src/execution/engine/tools/integration/server/adapters/apollo/apollo-adapter.test.ts +48 -0
  34. package/src/execution/engine/tools/integration/server/adapters/apollo/apollo-adapter.ts +99 -0
  35. package/src/execution/engine/tools/integration/server/adapters/apollo/index.ts +1 -0
  36. package/src/execution/engine/tools/integration/server/adapters/clickup/clickup-adapter.test.ts +18 -0
  37. package/src/execution/engine/tools/integration/server/adapters/clickup/clickup-adapter.ts +194 -0
  38. package/src/execution/engine/tools/integration/server/adapters/clickup/index.ts +7 -0
  39. package/src/execution/engine/workflow/types.ts +7 -0
  40. package/src/integrations/credentials/api-schemas.ts +21 -2
  41. package/src/integrations/credentials/schemas.ts +200 -164
  42. package/src/organization-model/README.md +10 -3
  43. package/src/organization-model/__tests__/defaults.test.ts +6 -0
  44. package/src/organization-model/__tests__/domains/resources.test.ts +188 -0
  45. package/src/organization-model/__tests__/domains/roles.test.ts +402 -347
  46. package/src/organization-model/__tests__/domains/systems.test.ts +193 -0
  47. package/src/organization-model/__tests__/knowledge.test.ts +39 -0
  48. package/src/organization-model/__tests__/prospecting-ssot.test.ts +7 -4
  49. package/src/organization-model/__tests__/resolve.test.ts +1 -1
  50. package/src/organization-model/defaults.ts +24 -3
  51. package/src/organization-model/domains/knowledge.ts +3 -2
  52. package/src/organization-model/domains/prospecting.ts +182 -25
  53. package/src/organization-model/domains/resources.ts +88 -0
  54. package/src/organization-model/domains/roles.ts +93 -55
  55. package/src/organization-model/domains/sales.ts +24 -3
  56. package/src/organization-model/domains/systems.ts +46 -0
  57. package/src/organization-model/icons.ts +1 -0
  58. package/src/organization-model/index.ts +2 -0
  59. package/src/organization-model/organization-model.mdx +33 -14
  60. package/src/organization-model/published.ts +52 -1
  61. package/src/organization-model/schema.ts +121 -0
  62. package/src/organization-model/types.ts +46 -1
  63. package/src/platform/api/types.ts +38 -35
  64. package/src/platform/constants/versions.ts +1 -1
  65. package/src/platform/registry/__tests__/resource-registry.test.ts +2051 -2005
  66. package/src/platform/registry/__tests__/validation.test.ts +1343 -1086
  67. package/src/platform/registry/index.ts +14 -0
  68. package/src/platform/registry/resource-registry.ts +40 -2
  69. package/src/platform/registry/serialization.ts +241 -202
  70. package/src/platform/registry/serialized-types.ts +1 -0
  71. package/src/platform/registry/types.ts +411 -361
  72. package/src/platform/registry/validation.ts +743 -513
  73. package/src/projects/api-schemas.ts +290 -267
  74. package/src/reference/_generated/contracts.md +501 -303
  75. package/src/reference/glossary.md +8 -3
  76. package/src/server.ts +2 -0
  77. package/src/supabase/database.types.ts +121 -0
@@ -19434,6 +19434,7 @@ var ORGANIZATION_MODEL_ICON_TOKENS = [
19434
19434
  "knowledge.reference",
19435
19435
  "feature.dashboard",
19436
19436
  "feature.calendar",
19437
+ "feature.business",
19437
19438
  "feature.sales",
19438
19439
  "feature.crm",
19439
19440
  "feature.finance",
@@ -19654,6 +19655,13 @@ var LEAD_GEN_STAGE_CATALOG = {
19654
19655
  order: 2,
19655
19656
  entity: "company"
19656
19657
  },
19658
+ crawled: {
19659
+ key: "crawled",
19660
+ label: "Websites crawled",
19661
+ description: "Company websites have been crawled (e.g. via Apify) and raw page content stored for downstream LLM analysis.",
19662
+ order: 2.5,
19663
+ entity: "company"
19664
+ },
19657
19665
  extracted: {
19658
19666
  key: "extracted",
19659
19667
  label: "Websites analyzed",
@@ -19673,7 +19681,9 @@ var LEAD_GEN_STAGE_CATALOG = {
19673
19681
  label: "Decision-makers found",
19674
19682
  description: "Decision-maker contacts discovered and attached to a qualified company.",
19675
19683
  order: 6,
19676
- entity: "company"
19684
+ entity: "company",
19685
+ recordEntity: "contact",
19686
+ recordStageKey: "discovered"
19677
19687
  },
19678
19688
  // Prospecting — contact discovery
19679
19689
  discovered: {
@@ -19711,7 +19721,8 @@ var LEAD_GEN_STAGE_CATALOG = {
19711
19721
  label: "Reviewed and exported",
19712
19722
  description: "Approved records have been reviewed and exported for handoff.",
19713
19723
  order: 10,
19714
- entity: "contact"
19724
+ entity: "company",
19725
+ additionalEntities: ["contact"]
19715
19726
  },
19716
19727
  interested: {
19717
19728
  key: "interested",
@@ -19781,18 +19792,47 @@ var FeatureSchema = z.object({
19781
19792
  });
19782
19793
  var ProspectingLifecycleStageSchema = DisplayMetadataSchema.extend({
19783
19794
  id: ModelIdSchema,
19784
- order: z.number().int().min(0)
19795
+ order: z.number().min(0)
19796
+ });
19797
+ var RecordColumnConfigSchema = z.object({
19798
+ key: ModelIdSchema,
19799
+ label: z.string().trim().min(1).max(120),
19800
+ path: z.string().trim().min(1).max(500),
19801
+ width: z.union([z.number().positive(), z.string().trim().min(1).max(100)]).optional(),
19802
+ renderType: z.enum(["text", "badge", "datetime", "count", "json"]).optional(),
19803
+ badgeColor: z.string().trim().min(1).max(40).optional()
19804
+ });
19805
+ var RecordColumnsConfigSchema = z.object({
19806
+ company: z.array(RecordColumnConfigSchema).optional(),
19807
+ contact: z.array(RecordColumnConfigSchema).optional()
19808
+ }).refine((columns) => Boolean(columns.company?.length || columns.contact?.length), {
19809
+ message: "recordColumns must include at least one entity column set"
19810
+ });
19811
+ var CredentialRequirementSchema = z.object({
19812
+ key: ModelIdSchema,
19813
+ provider: ModelIdSchema,
19814
+ credentialType: z.enum(["api-key", "api-key-secret", "oauth", "webhook-secret"]),
19815
+ label: z.string().trim().min(1).max(120),
19816
+ required: z.boolean(),
19817
+ selectionMode: z.enum(["single", "multiple"]).optional(),
19818
+ inputPath: z.string().trim().min(1).max(500),
19819
+ verifyOnRun: z.boolean().optional()
19785
19820
  });
19786
19821
  var ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
19787
19822
  id: ModelIdSchema,
19788
19823
  primaryEntity: z.enum(["company", "contact"]),
19789
19824
  outputs: z.array(z.enum(["company", "contact", "export"])).min(1),
19790
19825
  stageKey: ModelIdSchema,
19826
+ recordEntity: z.enum(["company", "contact"]).optional(),
19827
+ recordsStageKey: ModelIdSchema.optional(),
19828
+ recordSourceStageKey: ModelIdSchema.optional(),
19791
19829
  dependsOn: z.array(ModelIdSchema).optional(),
19792
19830
  dependencyMode: z.literal("per-record-eligibility"),
19793
19831
  capabilityKey: ModelIdSchema,
19794
19832
  defaultBatchSize: z.number().int().positive(),
19795
- maxBatchSize: z.number().int().positive()
19833
+ maxBatchSize: z.number().int().positive(),
19834
+ recordColumns: RecordColumnsConfigSchema.optional(),
19835
+ credentialRequirements: z.array(CredentialRequirementSchema).optional()
19796
19836
  }).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
19797
19837
  message: "defaultBatchSize must be less than or equal to maxBatchSize",
19798
19838
  path: ["defaultBatchSize"]
@@ -19801,6 +19841,62 @@ var ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
19801
19841
  id: ModelIdSchema,
19802
19842
  steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
19803
19843
  });
19844
+ var DTC_RECORD_COLUMNS = {
19845
+ populated: {
19846
+ company: [
19847
+ { key: "name", label: "Company", path: "company.name" },
19848
+ { key: "domain", label: "Domain", path: "company.domain" },
19849
+ { key: "employee-count", label: "Employees", path: "company.numEmployees", renderType: "count" },
19850
+ { key: "apollo-industry", label: "Apollo industry", path: "company.category" },
19851
+ { key: "location", label: "Location", path: "company.locationState" }
19852
+ ]
19853
+ },
19854
+ crawled: {
19855
+ company: [
19856
+ { key: "name", label: "Company", path: "company.name" },
19857
+ { key: "domain", label: "Domain", path: "company.domain" },
19858
+ { key: "page-count", label: "Pages", path: "company.enrichmentData.websiteCrawl.pageCount", renderType: "count" },
19859
+ { key: "crawl-status", label: "Crawl status", path: "processingState.crawled.status", renderType: "badge" }
19860
+ ]
19861
+ },
19862
+ extracted: {
19863
+ company: [
19864
+ { key: "name", label: "Company", path: "company.name" },
19865
+ { key: "domain", label: "Domain", path: "company.domain" },
19866
+ { key: "description", label: "Description", path: "company.enrichmentData.websiteCrawl.companyDescription" },
19867
+ { key: "services", label: "Services", path: "company.enrichmentData.websiteCrawl.services", renderType: "json" },
19868
+ { key: "automation-gaps", label: "Automation gaps", path: "company.enrichmentData.websiteCrawl.automationGaps", renderType: "json" },
19869
+ { key: "contact-count", label: "Contacts", path: "company.enrichmentData.websiteCrawl.emailCount", renderType: "count" }
19870
+ ]
19871
+ },
19872
+ qualified: {
19873
+ company: [
19874
+ { key: "name", label: "Company", path: "company.name" },
19875
+ { key: "domain", label: "Domain", path: "company.domain" },
19876
+ { key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
19877
+ { key: "signals", label: "Signals", path: "company.qualificationSignals", renderType: "json" },
19878
+ { key: "disqualified-reason", label: "Disqualified reason", path: "processingState.qualified.data.disqualifiedReason" }
19879
+ ]
19880
+ },
19881
+ decisionMakers: {
19882
+ contact: [
19883
+ { key: "name", label: "Name", path: "contact.name" },
19884
+ { key: "title", label: "Title", path: "contact.title" },
19885
+ { key: "email", label: "Email", path: "contact.email" },
19886
+ { key: "linkedin", label: "LinkedIn", path: "contact.linkedinUrl" },
19887
+ { key: "priority-score", label: "Priority", path: "contact.enrichmentData.apollo.priorityScore", renderType: "badge" }
19888
+ ]
19889
+ },
19890
+ uploaded: {
19891
+ company: [
19892
+ { key: "name", label: "Company", path: "company.name" },
19893
+ { key: "domain", label: "Domain", path: "company.domain" },
19894
+ { key: "contacts", label: "Contacts", path: "company.enrichmentData.approvedLeadListExport.contacts", renderType: "json" },
19895
+ { key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
19896
+ { key: "approval", label: "Approval", path: "company.enrichmentData.approvedLeadListExport.approvalStatus", renderType: "badge" }
19897
+ ]
19898
+ }
19899
+ };
19804
19900
  z.object({
19805
19901
  id: ModelIdSchema,
19806
19902
  label: z.string(),
@@ -19904,7 +20000,45 @@ var PROSPECTING_STEPS = {
19904
20000
  dependencyMode: "per-record-eligibility",
19905
20001
  capabilityKey: "lead-gen.company.apollo-import",
19906
20002
  defaultBatchSize: 250,
19907
- maxBatchSize: 1e3
20003
+ maxBatchSize: 1e3,
20004
+ recordColumns: DTC_RECORD_COLUMNS.populated,
20005
+ credentialRequirements: [
20006
+ {
20007
+ key: "apollo",
20008
+ provider: "apollo",
20009
+ credentialType: "api-key-secret",
20010
+ label: "Apollo API key",
20011
+ required: true,
20012
+ selectionMode: "single",
20013
+ inputPath: "credential"
20014
+ }
20015
+ ]
20016
+ },
20017
+ apifyCrawl: {
20018
+ id: "apify-crawl",
20019
+ label: "Websites crawled",
20020
+ description: "Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis. Overwrites the synthetic seed Apollo Import wrote with real page content.",
20021
+ primaryEntity: "company",
20022
+ outputs: ["company"],
20023
+ stageKey: "crawled",
20024
+ dependsOn: ["import-apollo-search"],
20025
+ dependencyMode: "per-record-eligibility",
20026
+ capabilityKey: "lead-gen.company.apify-crawl",
20027
+ defaultBatchSize: 50,
20028
+ maxBatchSize: 100,
20029
+ recordColumns: DTC_RECORD_COLUMNS.crawled,
20030
+ credentialRequirements: [
20031
+ {
20032
+ key: "apify",
20033
+ provider: "apify",
20034
+ credentialType: "api-key-secret",
20035
+ label: "Apify API token",
20036
+ required: true,
20037
+ selectionMode: "single",
20038
+ inputPath: "credential",
20039
+ verifyOnRun: true
20040
+ }
20041
+ ]
19908
20042
  },
19909
20043
  analyzeWebsites: {
19910
20044
  id: "analyze-websites",
@@ -19913,11 +20047,12 @@ var PROSPECTING_STEPS = {
19913
20047
  primaryEntity: "company",
19914
20048
  outputs: ["company"],
19915
20049
  stageKey: "extracted",
19916
- dependsOn: ["import-apollo-search"],
20050
+ dependsOn: ["apify-crawl"],
19917
20051
  dependencyMode: "per-record-eligibility",
19918
20052
  capabilityKey: "lead-gen.company.website-extract",
19919
20053
  defaultBatchSize: 50,
19920
- maxBatchSize: 100
20054
+ maxBatchSize: 100,
20055
+ recordColumns: DTC_RECORD_COLUMNS.extracted
19921
20056
  },
19922
20057
  scoreDtcFit: {
19923
20058
  id: "score-dtc-fit",
@@ -19930,7 +20065,8 @@ var PROSPECTING_STEPS = {
19930
20065
  dependencyMode: "per-record-eligibility",
19931
20066
  capabilityKey: "lead-gen.company.dtc-subscription-qualify",
19932
20067
  defaultBatchSize: 100,
19933
- maxBatchSize: 250
20068
+ maxBatchSize: 250,
20069
+ recordColumns: DTC_RECORD_COLUMNS.qualified
19934
20070
  },
19935
20071
  enrichDecisionMakers: {
19936
20072
  id: "enrich-decision-makers",
@@ -19939,37 +20075,52 @@ var PROSPECTING_STEPS = {
19939
20075
  primaryEntity: "company",
19940
20076
  outputs: ["contact"],
19941
20077
  stageKey: "decision-makers-enriched",
20078
+ recordEntity: "contact",
19942
20079
  dependsOn: ["score-dtc-fit"],
19943
20080
  dependencyMode: "per-record-eligibility",
19944
20081
  capabilityKey: "lead-gen.contact.apollo-decision-maker-enrich",
19945
20082
  defaultBatchSize: 100,
19946
- maxBatchSize: 250
19947
- },
19948
- verifyEmails: {
19949
- id: "verify-emails",
19950
- label: "Emails verified",
19951
- description: "Verify deliverability before the QC and handoff step.",
19952
- primaryEntity: "contact",
19953
- outputs: ["contact"],
19954
- stageKey: "verified",
19955
- dependsOn: ["enrich-decision-makers"],
19956
- dependencyMode: "per-record-eligibility",
19957
- capabilityKey: "lead-gen.contact.verify-email",
19958
- defaultBatchSize: 250,
19959
- maxBatchSize: 500
20083
+ maxBatchSize: 250,
20084
+ recordColumns: DTC_RECORD_COLUMNS.decisionMakers,
20085
+ credentialRequirements: [
20086
+ {
20087
+ key: "apollo",
20088
+ provider: "apollo",
20089
+ credentialType: "api-key-secret",
20090
+ label: "Apollo API key",
20091
+ required: true,
20092
+ selectionMode: "single",
20093
+ inputPath: "credential"
20094
+ }
20095
+ ]
19960
20096
  },
19961
20097
  reviewAndExport: {
19962
20098
  id: "review-and-export",
19963
20099
  label: "Reviewed and exported",
19964
- description: "Operator QC approves or rejects leads, then approved records are exported as a lead list.",
20100
+ description: "Operator QC approves or rejects qualified companies, then approved records are exported as a lead list with unverified emails.",
19965
20101
  primaryEntity: "company",
19966
20102
  outputs: ["export"],
19967
20103
  stageKey: "uploaded",
19968
- dependsOn: ["verify-emails"],
20104
+ recordsStageKey: "uploaded",
20105
+ recordSourceStageKey: "qualified",
20106
+ dependsOn: ["enrich-decision-makers"],
19969
20107
  dependencyMode: "per-record-eligibility",
19970
20108
  capabilityKey: "lead-gen.export.list",
19971
20109
  defaultBatchSize: 100,
19972
- maxBatchSize: 250
20110
+ maxBatchSize: 250,
20111
+ recordColumns: DTC_RECORD_COLUMNS.uploaded,
20112
+ credentialRequirements: [
20113
+ {
20114
+ key: "clickup",
20115
+ provider: "clickup",
20116
+ credentialType: "api-key-secret",
20117
+ label: "ClickUp API token",
20118
+ required: true,
20119
+ selectionMode: "single",
20120
+ inputPath: "clickupCredential",
20121
+ verifyOnRun: true
20122
+ }
20123
+ ]
19973
20124
  }
19974
20125
  }
19975
20126
  };
@@ -19991,7 +20142,7 @@ function toProspectingLifecycleStage(stage) {
19991
20142
  };
19992
20143
  }
19993
20144
  function leadGenStagesForEntity(entity) {
19994
- return Object.values(LEAD_GEN_STAGE_CATALOG).filter((stage) => stage.entity === entity).sort((a3, b2) => a3.order - b2.order).map(toProspectingLifecycleStage);
20145
+ return Object.values(LEAD_GEN_STAGE_CATALOG).filter((stage) => stage.entity === entity || stage.additionalEntities?.includes(entity)).sort((a3, b2) => a3.order - b2.order).map(toProspectingLifecycleStage);
19995
20146
  }
19996
20147
  var DEFAULT_ORGANIZATION_MODEL_PROSPECTING = {
19997
20148
  listEntityId: "leadgen.list",
@@ -20021,10 +20172,10 @@ var DEFAULT_ORGANIZATION_MODEL_PROSPECTING = {
20021
20172
  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.",
20022
20173
  steps: [
20023
20174
  PROSPECTING_STEPS.dtcApolloClickup.importApolloSearch,
20175
+ PROSPECTING_STEPS.dtcApolloClickup.apifyCrawl,
20024
20176
  PROSPECTING_STEPS.dtcApolloClickup.analyzeWebsites,
20025
20177
  PROSPECTING_STEPS.dtcApolloClickup.scoreDtcFit,
20026
20178
  PROSPECTING_STEPS.dtcApolloClickup.enrichDecisionMakers,
20027
- PROSPECTING_STEPS.dtcApolloClickup.verifyEmails,
20028
20179
  PROSPECTING_STEPS.dtcApolloClickup.reviewAndExport
20029
20180
  ]
20030
20181
  }
@@ -20216,13 +20367,104 @@ var OfferingsDomainSchema = z.object({
20216
20367
  var DEFAULT_ORGANIZATION_MODEL_OFFERINGS = {
20217
20368
  products: []
20218
20369
  };
20370
+ var SystemKindSchema = z.enum(["product", "operational", "platform", "diagnostic"]);
20371
+ var SystemStatusSchema = z.enum(["active", "deprecated", "archived"]);
20372
+ var SystemIdSchema = ModelIdSchema;
20373
+ var SystemEntrySchema = z.object({
20374
+ /** Stable tenant-defined system id (e.g. "sys.lead-gen"). */
20375
+ id: SystemIdSchema,
20376
+ /** Human-readable system title shown in governance and operations UI. */
20377
+ title: LabelSchema,
20378
+ /** One-paragraph purpose statement for the bounded context. */
20379
+ description: DescriptionSchema,
20380
+ /** Closed system shape enum; catalog values remain tenant-defined. */
20381
+ kind: SystemKindSchema,
20382
+ /** Optional role responsible for this system. */
20383
+ responsibleRoleId: ModelIdSchema.optional(),
20384
+ /** Optional knowledge nodes that govern this system. */
20385
+ governedByKnowledge: ReferenceIdsSchema,
20386
+ /** Optional goals this system contributes to. */
20387
+ drivesGoals: ReferenceIdsSchema,
20388
+ status: SystemStatusSchema
20389
+ });
20390
+ var SystemsDomainSchema = z.object({
20391
+ systems: z.array(SystemEntrySchema).default([])
20392
+ });
20393
+ var DEFAULT_ORGANIZATION_MODEL_SYSTEMS = {
20394
+ systems: []
20395
+ };
20396
+
20397
+ // src/organization-model/domains/resources.ts
20398
+ z.enum(["workflow", "agent", "integration"]);
20399
+ var ResourceGovernanceStatusSchema = z.enum(["active", "deprecated", "archived"]);
20400
+ var AgentKindSchema = z.enum(["orchestrator", "specialist", "utility", "system"]);
20401
+ 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");
20402
+ var ResourceEntryBaseSchema = z.object({
20403
+ /** Canonical resource id; runtime resourceId derives from this value. */
20404
+ id: ResourceIdSchema,
20405
+ /** Required single System membership. */
20406
+ systemId: SystemIdSchema,
20407
+ /** Optional role responsible for maintaining this resource. */
20408
+ ownerRoleId: ModelIdSchema.optional(),
20409
+ status: ResourceGovernanceStatusSchema
20410
+ });
20411
+ var WorkflowResourceEntrySchema = ResourceEntryBaseSchema.extend({
20412
+ kind: z.literal("workflow"),
20413
+ /** Mirrors WorkflowConfig.capabilityKey when the runtime workflow has one. */
20414
+ capabilityKey: z.string().trim().min(1).max(255).optional()
20415
+ });
20416
+ var AgentResourceEntrySchema = ResourceEntryBaseSchema.extend({
20417
+ kind: z.literal("agent"),
20418
+ /** Mirrors code-side AgentConfig.kind. */
20419
+ agentKind: AgentKindSchema,
20420
+ /** Role this agent embodies, if any. */
20421
+ actsAsRoleId: ModelIdSchema.optional(),
20422
+ /** Mirrors AgentConfig.sessionCapable. */
20423
+ sessionCapable: z.boolean()
20424
+ });
20425
+ var IntegrationResourceEntrySchema = ResourceEntryBaseSchema.extend({
20426
+ kind: z.literal("integration"),
20427
+ provider: z.string().trim().min(1).max(100)
20428
+ });
20429
+ var ResourceEntrySchema = z.discriminatedUnion("kind", [
20430
+ WorkflowResourceEntrySchema,
20431
+ AgentResourceEntrySchema,
20432
+ IntegrationResourceEntrySchema
20433
+ ]);
20434
+ var ResourcesDomainSchema = z.object({
20435
+ entries: z.array(ResourceEntrySchema).default([])
20436
+ });
20437
+ var DEFAULT_ORGANIZATION_MODEL_RESOURCES = {
20438
+ entries: []
20439
+ };
20440
+
20441
+ // src/organization-model/domains/roles.ts
20442
+ var RoleIdSchema = ModelIdSchema;
20443
+ var HumanRoleHolderSchema = z.object({
20444
+ kind: z.literal("human"),
20445
+ userId: z.string().trim().min(1).max(200)
20446
+ });
20447
+ var AgentRoleHolderSchema = z.object({
20448
+ kind: z.literal("agent"),
20449
+ agentId: ResourceIdSchema
20450
+ });
20451
+ var TeamRoleHolderSchema = z.object({
20452
+ kind: z.literal("team"),
20453
+ memberIds: z.array(z.string().trim().min(1).max(200)).min(1)
20454
+ });
20455
+ var RoleHolderSchema = z.discriminatedUnion("kind", [
20456
+ HumanRoleHolderSchema,
20457
+ AgentRoleHolderSchema,
20458
+ TeamRoleHolderSchema
20459
+ ]);
20460
+ var RoleHoldersSchema = z.union([RoleHolderSchema, z.array(RoleHolderSchema).min(1)]);
20219
20461
  var RoleSchema = z.object({
20220
20462
  /** Stable unique identifier for the role (e.g. "role-ceo", "role-head-of-sales"). */
20221
- id: z.string().trim().min(1).max(100),
20463
+ id: RoleIdSchema,
20222
20464
  /** Human-readable title shown to agents and in UI (e.g. "CEO", "Head of Sales"). */
20223
20465
  title: z.string().trim().min(1).max(200),
20224
20466
  /**
20225
- * List of responsibilities this role owns plain-language descriptions of
20467
+ * List of responsibilities this role owns - plain-language descriptions of
20226
20468
  * what the person in this role is accountable for delivering.
20227
20469
  * Defaults to empty array so minimal role definitions stay concise.
20228
20470
  */
@@ -20230,16 +20472,18 @@ var RoleSchema = z.object({
20230
20472
  /**
20231
20473
  * Optional: ID of another role this role reports to.
20232
20474
  * When present, must reference another `roles[].id` in the same organization.
20233
- * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
20234
- * Absence indicates a top-level role (no reporting line).
20235
20475
  */
20236
- reportsToId: z.string().trim().min(1).max(100).optional(),
20476
+ reportsToId: RoleIdSchema.optional(),
20237
20477
  /**
20238
- * Optional: name or email of the person currently holding this role.
20239
- * Free-form string supports "Alice Johnson", "alice@example.com", or
20240
- * any human-readable identifier. Not validated against any user registry.
20478
+ * Optional: human, agent, or team holder currently filling this role.
20479
+ * Agent holders reference OM Resource IDs and are validated at the model level.
20241
20480
  */
20242
- heldBy: z.string().trim().max(200).optional()
20481
+ heldBy: RoleHoldersSchema.optional(),
20482
+ /**
20483
+ * Optional Systems this role is accountable for.
20484
+ * Cross-reference enforced in `OrganizationModelSchema.superRefine()`.
20485
+ */
20486
+ responsibleFor: z.array(SystemIdSchema).optional()
20243
20487
  });
20244
20488
  var RolesDomainSchema = z.object({
20245
20489
  roles: z.array(RoleSchema).default([])
@@ -20474,8 +20718,8 @@ var OrgKnowledgeNodeSchema = z.object({
20474
20718
  skills: z.array(KnowledgeSkillBindingSchema).optional(),
20475
20719
  /** Domain key used to derive fast graph->skill registries. */
20476
20720
  domain: KnowledgeDomainBindingSchema.optional(),
20477
- /** Identifiers of the roles or members who own this knowledge node. */
20478
- ownerIds: z.array(ModelIdSchema).default([]),
20721
+ /** Role identifiers that own this knowledge node. */
20722
+ ownerIds: z.array(RoleIdSchema).default([]),
20479
20723
  /** ISO date string (YYYY-MM-DD or full ISO 8601) of last meaningful update. */
20480
20724
  updatedAt: z.string().trim().min(1).max(50)
20481
20725
  });
@@ -20497,6 +20741,8 @@ var OrganizationModelSchemaBase = z.object({
20497
20741
  offerings: OfferingsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_OFFERINGS),
20498
20742
  roles: RolesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_ROLES),
20499
20743
  goals: GoalsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_GOALS),
20744
+ systems: SystemsDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_SYSTEMS),
20745
+ resources: ResourcesDomainSchema.default(DEFAULT_ORGANIZATION_MODEL_RESOURCES),
20500
20746
  statuses: StatusesDomainSchema.default({ entries: [] }),
20501
20747
  operations: OperationsDomainSchema.default({ entries: [] }),
20502
20748
  knowledge: KnowledgeDomainSchema.default({ nodes: [] })
@@ -20530,6 +20776,9 @@ function hasFeature(featuresById, featureId) {
20530
20776
  function defaultFeaturePathFor(id) {
20531
20777
  return `/${id.replaceAll(".", "/")}`;
20532
20778
  }
20779
+ function asRoleHolderArray(heldBy) {
20780
+ return Array.isArray(heldBy) ? heldBy : [heldBy];
20781
+ }
20533
20782
  var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ctx) => {
20534
20783
  const featuresById = collectIds(model.features, ctx, ["features"], "Feature");
20535
20784
  const featureIdsByEffectivePath = /* @__PURE__ */ new Map();
@@ -20640,6 +20889,8 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
20640
20889
  );
20641
20890
  }
20642
20891
  });
20892
+ const goalsById = new Map(model.goals.objectives.map((objective) => [objective.id, objective]));
20893
+ const knowledgeById = new Map(model.knowledge.nodes.map((node) => [node.id, node]));
20643
20894
  const rolesById = new Map(model.roles.roles.map((role) => [role.id, role]));
20644
20895
  model.roles.roles.forEach((role, roleIndex) => {
20645
20896
  if (role.reportsToId !== void 0 && !rolesById.has(role.reportsToId)) {
@@ -20650,6 +20901,102 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
20650
20901
  );
20651
20902
  }
20652
20903
  });
20904
+ const systemsById = collectIds(model.systems.systems, ctx, ["systems", "systems"], "System");
20905
+ model.roles.roles.forEach((role, roleIndex) => {
20906
+ role.responsibleFor?.forEach((systemId, systemIndex) => {
20907
+ if (!systemsById.has(systemId)) {
20908
+ addIssue(
20909
+ ctx,
20910
+ ["roles", "roles", roleIndex, "responsibleFor", systemIndex],
20911
+ `Role "${role.id}" references unknown responsibleFor system "${systemId}"`
20912
+ );
20913
+ }
20914
+ });
20915
+ });
20916
+ model.systems.systems.forEach((system, systemIndex) => {
20917
+ if (system.responsibleRoleId !== void 0 && !rolesById.has(system.responsibleRoleId)) {
20918
+ addIssue(
20919
+ ctx,
20920
+ ["systems", "systems", systemIndex, "responsibleRoleId"],
20921
+ `System "${system.id}" references unknown responsibleRoleId "${system.responsibleRoleId}"`
20922
+ );
20923
+ }
20924
+ system.governedByKnowledge.forEach((nodeId, nodeIndex) => {
20925
+ if (!knowledgeById.has(nodeId)) {
20926
+ addIssue(
20927
+ ctx,
20928
+ ["systems", "systems", systemIndex, "governedByKnowledge", nodeIndex],
20929
+ `System "${system.id}" references unknown knowledge node "${nodeId}"`
20930
+ );
20931
+ }
20932
+ });
20933
+ system.drivesGoals.forEach((goalId, goalIndex) => {
20934
+ if (!goalsById.has(goalId)) {
20935
+ addIssue(
20936
+ ctx,
20937
+ ["systems", "systems", systemIndex, "drivesGoals", goalIndex],
20938
+ `System "${system.id}" references unknown goal "${goalId}"`
20939
+ );
20940
+ }
20941
+ });
20942
+ });
20943
+ const resourcesById = collectIds(model.resources.entries, ctx, ["resources", "entries"], "Resource");
20944
+ model.resources.entries.forEach((resource, resourceIndex) => {
20945
+ if (!systemsById.has(resource.systemId)) {
20946
+ addIssue(
20947
+ ctx,
20948
+ ["resources", "entries", resourceIndex, "systemId"],
20949
+ `Resource "${resource.id}" references unknown systemId "${resource.systemId}"`
20950
+ );
20951
+ }
20952
+ if (resource.ownerRoleId !== void 0 && !rolesById.has(resource.ownerRoleId)) {
20953
+ addIssue(
20954
+ ctx,
20955
+ ["resources", "entries", resourceIndex, "ownerRoleId"],
20956
+ `Resource "${resource.id}" references unknown ownerRoleId "${resource.ownerRoleId}"`
20957
+ );
20958
+ }
20959
+ if (resource.kind === "agent" && resource.actsAsRoleId !== void 0 && !rolesById.has(resource.actsAsRoleId)) {
20960
+ addIssue(
20961
+ ctx,
20962
+ ["resources", "entries", resourceIndex, "actsAsRoleId"],
20963
+ `Agent resource "${resource.id}" references unknown actsAsRoleId "${resource.actsAsRoleId}"`
20964
+ );
20965
+ }
20966
+ });
20967
+ model.roles.roles.forEach((role, roleIndex) => {
20968
+ if (role.heldBy === void 0) return;
20969
+ asRoleHolderArray(role.heldBy).forEach((holder, holderIndex) => {
20970
+ if (holder.kind !== "agent") return;
20971
+ const resource = resourcesById.get(holder.agentId);
20972
+ if (resource === void 0) {
20973
+ addIssue(
20974
+ ctx,
20975
+ ["roles", "roles", roleIndex, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
20976
+ `Role "${role.id}" references unknown agent holder resource "${holder.agentId}"`
20977
+ );
20978
+ return;
20979
+ }
20980
+ if (resource.kind !== "agent") {
20981
+ addIssue(
20982
+ ctx,
20983
+ ["roles", "roles", roleIndex, "heldBy", Array.isArray(role.heldBy) ? holderIndex : "agentId"],
20984
+ `Role "${role.id}" agent holder "${holder.agentId}" must reference an agent resource`
20985
+ );
20986
+ }
20987
+ });
20988
+ });
20989
+ model.knowledge.nodes.forEach((node, nodeIndex) => {
20990
+ node.ownerIds.forEach((roleId, ownerIndex) => {
20991
+ if (!rolesById.has(roleId)) {
20992
+ addIssue(
20993
+ ctx,
20994
+ ["knowledge", "nodes", nodeIndex, "ownerIds", ownerIndex],
20995
+ `Knowledge node "${node.id}" references unknown owner role "${roleId}"`
20996
+ );
20997
+ }
20998
+ });
20999
+ });
20653
21000
  });
20654
21001
 
20655
21002
  // src/organization-model/defaults.ts
@@ -20690,6 +21037,15 @@ var DEFAULT_ORGANIZATION_MODEL = {
20690
21037
  color: "green",
20691
21038
  icon: "feature.finance"
20692
21039
  },
21040
+ {
21041
+ id: "business",
21042
+ label: "Business",
21043
+ description: "Revenue, client relationships, and project delivery",
21044
+ enabled: true,
21045
+ color: "blue",
21046
+ icon: "feature.business",
21047
+ uiPosition: "sidebar-primary"
21048
+ },
20693
21049
  {
20694
21050
  id: "sales",
20695
21051
  label: "Sales",
@@ -20697,7 +21053,7 @@ var DEFAULT_ORGANIZATION_MODEL = {
20697
21053
  enabled: true,
20698
21054
  color: "blue",
20699
21055
  icon: "feature.sales",
20700
- uiPosition: "sidebar-primary"
21056
+ path: "/sales"
20701
21057
  },
20702
21058
  {
20703
21059
  id: "sales.crm",
@@ -20724,8 +21080,16 @@ var DEFAULT_ORGANIZATION_MODEL = {
20724
21080
  enabled: true,
20725
21081
  color: "orange",
20726
21082
  icon: "feature.projects",
20727
- path: "/projects",
20728
- uiPosition: "sidebar-primary"
21083
+ path: "/projects"
21084
+ },
21085
+ {
21086
+ id: "clients",
21087
+ label: "Clients",
21088
+ description: "Client relationships, accounts, and business context",
21089
+ enabled: true,
21090
+ color: "orange",
21091
+ icon: "feature.projects",
21092
+ path: "/business/clients"
20729
21093
  },
20730
21094
  {
20731
21095
  id: "operations",
@@ -20970,6 +21334,8 @@ var DEFAULT_ORGANIZATION_MODEL = {
20970
21334
  offerings: DEFAULT_ORGANIZATION_MODEL_OFFERINGS,
20971
21335
  roles: DEFAULT_ORGANIZATION_MODEL_ROLES,
20972
21336
  goals: DEFAULT_ORGANIZATION_MODEL_GOALS,
21337
+ systems: DEFAULT_ORGANIZATION_MODEL_SYSTEMS,
21338
+ resources: DEFAULT_ORGANIZATION_MODEL_RESOURCES,
20973
21339
  statuses: DEFAULT_ORGANIZATION_MODEL_STATUSES,
20974
21340
  operations: DEFAULT_ORGANIZATION_MODEL_OPERATIONS,
20975
21341
  knowledge: DEFAULT_ORGANIZATION_MODEL_KNOWLEDGE
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elevasis/core",
3
- "version": "0.20.0",
3
+ "version": "0.22.0",
4
4
  "license": "MIT",
5
5
  "description": "Minimal shared constants across Elevasis monorepo",
6
6
  "sideEffects": false,
@@ -9,8 +9,6 @@
9
9
  "dist"
10
10
  ],
11
11
  "type": "module",
12
- "main": "./dist/index.js",
13
- "types": "./dist/index.d.ts",
14
12
  "exports": {
15
13
  ".": {
16
14
  "types": "./dist/index.d.ts",
@@ -41,8 +39,8 @@
41
39
  "rollup-plugin-dts": "^6.3.0",
42
40
  "tsup": "^8.0.0",
43
41
  "typescript": "5.9.2",
44
- "@repo/typescript-config": "0.0.0",
45
- "@repo/eslint-config": "0.0.0"
42
+ "@repo/eslint-config": "0.0.0",
43
+ "@repo/typescript-config": "0.0.0"
46
44
  },
47
45
  "dependencies": {
48
46
  "@anthropic-ai/sdk": "^0.62.0",
@@ -65,6 +63,8 @@
65
63
  "stripe": "^20.2.0",
66
64
  "zod": "^4.1.0"
67
65
  },
66
+ "main": "./dist/index.js",
67
+ "types": "./dist/index.d.ts",
68
68
  "scripts": {
69
69
  "build": "tsc --noEmit",
70
70
  "build:publish": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json && pnpm exec tsup && pnpm exec rollup -c rollup.dts.config.mjs && node -e \"require('fs').rmSync('dist/_dts',{recursive:true,force:true})\"",