@elevasis/core 0.19.0 → 0.21.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 (40) hide show
  1. package/dist/index.d.ts +108 -0
  2. package/dist/index.js +239 -27
  3. package/dist/knowledge/index.d.ts +55 -1
  4. package/dist/organization-model/index.d.ts +108 -0
  5. package/dist/organization-model/index.js +239 -27
  6. package/dist/test-utils/index.d.ts +54 -0
  7. package/dist/test-utils/index.js +238 -27
  8. package/package.json +1 -1
  9. package/src/_gen/__tests__/__snapshots__/contracts.md.snap +17 -5
  10. package/src/business/acquisition/api-schemas.test.ts +125 -14
  11. package/src/business/acquisition/api-schemas.ts +161 -11
  12. package/src/business/acquisition/build-templates.test.ts +28 -0
  13. package/src/business/acquisition/build-templates.ts +20 -8
  14. package/src/business/acquisition/derive-actions.test.ts +1 -1
  15. package/src/business/acquisition/types.ts +7 -2
  16. package/src/business/deals/api-schemas.ts +2 -2
  17. package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.test.ts +55 -0
  18. package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.ts +107 -41
  19. package/src/execution/engine/tools/integration/server/adapters/apollo/apollo-adapter.test.ts +48 -0
  20. package/src/execution/engine/tools/integration/server/adapters/apollo/apollo-adapter.ts +99 -0
  21. package/src/execution/engine/tools/integration/server/adapters/apollo/index.ts +1 -0
  22. package/src/execution/engine/tools/integration/server/adapters/clickup/clickup-adapter.test.ts +18 -0
  23. package/src/execution/engine/tools/integration/server/adapters/clickup/clickup-adapter.ts +194 -0
  24. package/src/execution/engine/tools/integration/server/adapters/clickup/index.ts +7 -0
  25. package/src/integrations/credentials/api-schemas.ts +21 -2
  26. package/src/integrations/credentials/schemas.ts +200 -164
  27. package/src/organization-model/__tests__/graph.test.ts +108 -2
  28. package/src/organization-model/__tests__/prospecting-ssot.test.ts +12 -12
  29. package/src/organization-model/__tests__/schema.test.ts +122 -0
  30. package/src/organization-model/__tests__/surface-projection.test.ts +174 -0
  31. package/src/organization-model/domains/prospecting.ts +273 -41
  32. package/src/organization-model/domains/sales.ts +32 -8
  33. package/src/organization-model/graph/build.ts +74 -0
  34. package/src/organization-model/graph/schema.ts +1 -0
  35. package/src/organization-model/graph/types.ts +1 -0
  36. package/src/organization-model/schema.ts +63 -0
  37. package/src/organization-model/surface-projection.ts +218 -0
  38. package/src/platform/constants/versions.ts +1 -1
  39. package/src/reference/_generated/contracts.md +17 -5
  40. package/src/server.ts +2 -0
@@ -19654,6 +19654,13 @@ var LEAD_GEN_STAGE_CATALOG = {
19654
19654
  order: 2,
19655
19655
  entity: "company"
19656
19656
  },
19657
+ crawled: {
19658
+ key: "crawled",
19659
+ label: "Websites crawled",
19660
+ description: "Company websites have been crawled (e.g. via Apify) and raw page content stored for downstream LLM analysis.",
19661
+ order: 2.5,
19662
+ entity: "company"
19663
+ },
19657
19664
  extracted: {
19658
19665
  key: "extracted",
19659
19666
  label: "Websites analyzed",
@@ -19673,7 +19680,9 @@ var LEAD_GEN_STAGE_CATALOG = {
19673
19680
  label: "Decision-makers found",
19674
19681
  description: "Decision-maker contacts discovered and attached to a qualified company.",
19675
19682
  order: 6,
19676
- entity: "company"
19683
+ entity: "company",
19684
+ recordEntity: "contact",
19685
+ recordStageKey: "discovered"
19677
19686
  },
19678
19687
  // Prospecting — contact discovery
19679
19688
  discovered: {
@@ -19711,7 +19720,8 @@ var LEAD_GEN_STAGE_CATALOG = {
19711
19720
  label: "Reviewed and exported",
19712
19721
  description: "Approved records have been reviewed and exported for handoff.",
19713
19722
  order: 10,
19714
- entity: "contact"
19723
+ entity: "company",
19724
+ additionalEntities: ["contact"]
19715
19725
  },
19716
19726
  interested: {
19717
19727
  key: "interested",
@@ -19781,18 +19791,47 @@ var FeatureSchema = z.object({
19781
19791
  });
19782
19792
  var ProspectingLifecycleStageSchema = DisplayMetadataSchema.extend({
19783
19793
  id: ModelIdSchema,
19784
- order: z.number().int().min(0)
19794
+ order: z.number().min(0)
19795
+ });
19796
+ var RecordColumnConfigSchema = z.object({
19797
+ key: ModelIdSchema,
19798
+ label: z.string().trim().min(1).max(120),
19799
+ path: z.string().trim().min(1).max(500),
19800
+ width: z.union([z.number().positive(), z.string().trim().min(1).max(100)]).optional(),
19801
+ renderType: z.enum(["text", "badge", "datetime", "count", "json"]).optional(),
19802
+ badgeColor: z.string().trim().min(1).max(40).optional()
19803
+ });
19804
+ var RecordColumnsConfigSchema = z.object({
19805
+ company: z.array(RecordColumnConfigSchema).optional(),
19806
+ contact: z.array(RecordColumnConfigSchema).optional()
19807
+ }).refine((columns) => Boolean(columns.company?.length || columns.contact?.length), {
19808
+ message: "recordColumns must include at least one entity column set"
19809
+ });
19810
+ var CredentialRequirementSchema = z.object({
19811
+ key: ModelIdSchema,
19812
+ provider: ModelIdSchema,
19813
+ credentialType: z.enum(["api-key", "api-key-secret", "oauth", "webhook-secret"]),
19814
+ label: z.string().trim().min(1).max(120),
19815
+ required: z.boolean(),
19816
+ selectionMode: z.enum(["single", "multiple"]).optional(),
19817
+ inputPath: z.string().trim().min(1).max(500),
19818
+ verifyOnRun: z.boolean().optional()
19785
19819
  });
19786
19820
  var ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
19787
19821
  id: ModelIdSchema,
19788
19822
  primaryEntity: z.enum(["company", "contact"]),
19789
19823
  outputs: z.array(z.enum(["company", "contact", "export"])).min(1),
19790
19824
  stageKey: ModelIdSchema,
19825
+ recordEntity: z.enum(["company", "contact"]).optional(),
19826
+ recordsStageKey: ModelIdSchema.optional(),
19827
+ recordSourceStageKey: ModelIdSchema.optional(),
19791
19828
  dependsOn: z.array(ModelIdSchema).optional(),
19792
19829
  dependencyMode: z.literal("per-record-eligibility"),
19793
19830
  capabilityKey: ModelIdSchema,
19794
19831
  defaultBatchSize: z.number().int().positive(),
19795
- maxBatchSize: z.number().int().positive()
19832
+ maxBatchSize: z.number().int().positive(),
19833
+ recordColumns: RecordColumnsConfigSchema.optional(),
19834
+ credentialRequirements: z.array(CredentialRequirementSchema).optional()
19796
19835
  }).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
19797
19836
  message: "defaultBatchSize must be less than or equal to maxBatchSize",
19798
19837
  path: ["defaultBatchSize"]
@@ -19801,6 +19840,68 @@ var ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
19801
19840
  id: ModelIdSchema,
19802
19841
  steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
19803
19842
  });
19843
+ var DTC_RECORD_COLUMNS = {
19844
+ populated: {
19845
+ company: [
19846
+ { key: "name", label: "Company", path: "company.name" },
19847
+ { key: "domain", label: "Domain", path: "company.domain" },
19848
+ { key: "employee-count", label: "Employees", path: "company.numEmployees", renderType: "count" },
19849
+ { key: "apollo-industry", label: "Apollo industry", path: "company.category" },
19850
+ { key: "location", label: "Location", path: "company.locationState" }
19851
+ ]
19852
+ },
19853
+ crawled: {
19854
+ company: [
19855
+ { key: "name", label: "Company", path: "company.name" },
19856
+ { key: "domain", label: "Domain", path: "company.domain" },
19857
+ { key: "page-count", label: "Pages", path: "company.enrichmentData.websiteCrawl.pageCount", renderType: "count" },
19858
+ { key: "crawl-status", label: "Crawl status", path: "processingState.crawled.status", renderType: "badge" }
19859
+ ]
19860
+ },
19861
+ extracted: {
19862
+ company: [
19863
+ { key: "name", label: "Company", path: "company.name" },
19864
+ { key: "domain", label: "Domain", path: "company.domain" },
19865
+ { key: "description", label: "Description", path: "company.enrichmentData.websiteCrawl.companyDescription" },
19866
+ { key: "services", label: "Services", path: "company.enrichmentData.websiteCrawl.services", renderType: "json" },
19867
+ { key: "automation-gaps", label: "Automation gaps", path: "company.enrichmentData.websiteCrawl.automationGaps", renderType: "json" },
19868
+ { key: "contact-count", label: "Contacts", path: "company.enrichmentData.websiteCrawl.emailCount", renderType: "count" }
19869
+ ]
19870
+ },
19871
+ qualified: {
19872
+ company: [
19873
+ { key: "name", label: "Company", path: "company.name" },
19874
+ { key: "domain", label: "Domain", path: "company.domain" },
19875
+ { key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
19876
+ { key: "signals", label: "Signals", path: "company.qualificationSignals", renderType: "json" },
19877
+ { key: "disqualified-reason", label: "Disqualified reason", path: "processingState.qualified.data.disqualifiedReason" }
19878
+ ]
19879
+ },
19880
+ decisionMakers: {
19881
+ contact: [
19882
+ { key: "name", label: "Name", path: "contact.name" },
19883
+ { key: "title", label: "Title", path: "contact.title" },
19884
+ { key: "email", label: "Email", path: "contact.email" },
19885
+ { key: "linkedin", label: "LinkedIn", path: "contact.linkedinUrl" },
19886
+ { key: "priority-score", label: "Priority", path: "contact.enrichmentData.apollo.priorityScore", renderType: "badge" }
19887
+ ]
19888
+ },
19889
+ uploaded: {
19890
+ company: [
19891
+ { key: "name", label: "Company", path: "company.name" },
19892
+ { key: "domain", label: "Domain", path: "company.domain" },
19893
+ { key: "contacts", label: "Contacts", path: "company.enrichmentData.approvedLeadListExport.contacts", renderType: "json" },
19894
+ { key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
19895
+ { key: "approval", label: "Approval", path: "company.enrichmentData.approvedLeadListExport.approvalStatus", renderType: "badge" }
19896
+ ]
19897
+ }
19898
+ };
19899
+ z.object({
19900
+ id: ModelIdSchema,
19901
+ label: z.string(),
19902
+ description: z.string(),
19903
+ resourceId: ModelIdSchema
19904
+ });
19804
19905
  var PROSPECTING_STEPS = {
19805
19906
  localServices: {
19806
19907
  sourceCompanies: {
@@ -19898,7 +19999,45 @@ var PROSPECTING_STEPS = {
19898
19999
  dependencyMode: "per-record-eligibility",
19899
20000
  capabilityKey: "lead-gen.company.apollo-import",
19900
20001
  defaultBatchSize: 250,
19901
- maxBatchSize: 1e3
20002
+ maxBatchSize: 1e3,
20003
+ recordColumns: DTC_RECORD_COLUMNS.populated,
20004
+ credentialRequirements: [
20005
+ {
20006
+ key: "apollo",
20007
+ provider: "apollo",
20008
+ credentialType: "api-key-secret",
20009
+ label: "Apollo API key",
20010
+ required: true,
20011
+ selectionMode: "single",
20012
+ inputPath: "credential"
20013
+ }
20014
+ ]
20015
+ },
20016
+ apifyCrawl: {
20017
+ id: "apify-crawl",
20018
+ label: "Websites crawled",
20019
+ 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.",
20020
+ primaryEntity: "company",
20021
+ outputs: ["company"],
20022
+ stageKey: "crawled",
20023
+ dependsOn: ["import-apollo-search"],
20024
+ dependencyMode: "per-record-eligibility",
20025
+ capabilityKey: "lead-gen.company.apify-crawl",
20026
+ defaultBatchSize: 50,
20027
+ maxBatchSize: 100,
20028
+ recordColumns: DTC_RECORD_COLUMNS.crawled,
20029
+ credentialRequirements: [
20030
+ {
20031
+ key: "apify",
20032
+ provider: "apify",
20033
+ credentialType: "api-key-secret",
20034
+ label: "Apify API token",
20035
+ required: true,
20036
+ selectionMode: "single",
20037
+ inputPath: "credential",
20038
+ verifyOnRun: true
20039
+ }
20040
+ ]
19902
20041
  },
19903
20042
  analyzeWebsites: {
19904
20043
  id: "analyze-websites",
@@ -19907,11 +20046,12 @@ var PROSPECTING_STEPS = {
19907
20046
  primaryEntity: "company",
19908
20047
  outputs: ["company"],
19909
20048
  stageKey: "extracted",
19910
- dependsOn: ["import-apollo-search"],
20049
+ dependsOn: ["apify-crawl"],
19911
20050
  dependencyMode: "per-record-eligibility",
19912
20051
  capabilityKey: "lead-gen.company.website-extract",
19913
20052
  defaultBatchSize: 50,
19914
- maxBatchSize: 100
20053
+ maxBatchSize: 100,
20054
+ recordColumns: DTC_RECORD_COLUMNS.extracted
19915
20055
  },
19916
20056
  scoreDtcFit: {
19917
20057
  id: "score-dtc-fit",
@@ -19924,7 +20064,8 @@ var PROSPECTING_STEPS = {
19924
20064
  dependencyMode: "per-record-eligibility",
19925
20065
  capabilityKey: "lead-gen.company.dtc-subscription-qualify",
19926
20066
  defaultBatchSize: 100,
19927
- maxBatchSize: 250
20067
+ maxBatchSize: 250,
20068
+ recordColumns: DTC_RECORD_COLUMNS.qualified
19928
20069
  },
19929
20070
  enrichDecisionMakers: {
19930
20071
  id: "enrich-decision-makers",
@@ -19933,37 +20074,52 @@ var PROSPECTING_STEPS = {
19933
20074
  primaryEntity: "company",
19934
20075
  outputs: ["contact"],
19935
20076
  stageKey: "decision-makers-enriched",
20077
+ recordEntity: "contact",
19936
20078
  dependsOn: ["score-dtc-fit"],
19937
20079
  dependencyMode: "per-record-eligibility",
19938
20080
  capabilityKey: "lead-gen.contact.apollo-decision-maker-enrich",
19939
20081
  defaultBatchSize: 100,
19940
- maxBatchSize: 250
19941
- },
19942
- verifyEmails: {
19943
- id: "verify-emails",
19944
- label: "Emails verified",
19945
- description: "Verify deliverability before the QC and handoff step.",
19946
- primaryEntity: "contact",
19947
- outputs: ["contact"],
19948
- stageKey: "verified",
19949
- dependsOn: ["enrich-decision-makers"],
19950
- dependencyMode: "per-record-eligibility",
19951
- capabilityKey: "lead-gen.contact.verify-email",
19952
- defaultBatchSize: 250,
19953
- maxBatchSize: 500
20082
+ maxBatchSize: 250,
20083
+ recordColumns: DTC_RECORD_COLUMNS.decisionMakers,
20084
+ credentialRequirements: [
20085
+ {
20086
+ key: "apollo",
20087
+ provider: "apollo",
20088
+ credentialType: "api-key-secret",
20089
+ label: "Apollo API key",
20090
+ required: true,
20091
+ selectionMode: "single",
20092
+ inputPath: "credential"
20093
+ }
20094
+ ]
19954
20095
  },
19955
20096
  reviewAndExport: {
19956
20097
  id: "review-and-export",
19957
20098
  label: "Reviewed and exported",
19958
- description: "Operator QC approves or rejects leads, then approved records are exported as a lead list.",
20099
+ description: "Operator QC approves or rejects qualified companies, then approved records are exported as a lead list with unverified emails.",
19959
20100
  primaryEntity: "company",
19960
20101
  outputs: ["export"],
19961
20102
  stageKey: "uploaded",
19962
- dependsOn: ["verify-emails"],
20103
+ recordsStageKey: "uploaded",
20104
+ recordSourceStageKey: "qualified",
20105
+ dependsOn: ["enrich-decision-makers"],
19963
20106
  dependencyMode: "per-record-eligibility",
19964
20107
  capabilityKey: "lead-gen.export.list",
19965
20108
  defaultBatchSize: 100,
19966
- maxBatchSize: 250
20109
+ maxBatchSize: 250,
20110
+ recordColumns: DTC_RECORD_COLUMNS.uploaded,
20111
+ credentialRequirements: [
20112
+ {
20113
+ key: "clickup",
20114
+ provider: "clickup",
20115
+ credentialType: "api-key-secret",
20116
+ label: "ClickUp API token",
20117
+ required: true,
20118
+ selectionMode: "single",
20119
+ inputPath: "clickupCredential",
20120
+ verifyOnRun: true
20121
+ }
20122
+ ]
19967
20123
  }
19968
20124
  }
19969
20125
  };
@@ -19985,7 +20141,7 @@ function toProspectingLifecycleStage(stage) {
19985
20141
  };
19986
20142
  }
19987
20143
  function leadGenStagesForEntity(entity) {
19988
- return Object.values(LEAD_GEN_STAGE_CATALOG).filter((stage) => stage.entity === entity).sort((a3, b2) => a3.order - b2.order).map(toProspectingLifecycleStage);
20144
+ 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);
19989
20145
  }
19990
20146
  var DEFAULT_ORGANIZATION_MODEL_PROSPECTING = {
19991
20147
  listEntityId: "leadgen.list",
@@ -20015,10 +20171,10 @@ var DEFAULT_ORGANIZATION_MODEL_PROSPECTING = {
20015
20171
  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.",
20016
20172
  steps: [
20017
20173
  PROSPECTING_STEPS.dtcApolloClickup.importApolloSearch,
20174
+ PROSPECTING_STEPS.dtcApolloClickup.apifyCrawl,
20018
20175
  PROSPECTING_STEPS.dtcApolloClickup.analyzeWebsites,
20019
20176
  PROSPECTING_STEPS.dtcApolloClickup.scoreDtcFit,
20020
20177
  PROSPECTING_STEPS.dtcApolloClickup.enrichDecisionMakers,
20021
- PROSPECTING_STEPS.dtcApolloClickup.verifyEmails,
20022
20178
  PROSPECTING_STEPS.dtcApolloClickup.reviewAndExport
20023
20179
  ]
20024
20180
  }
@@ -20521,8 +20677,12 @@ var LEGACY_FEATURE_ALIASES = /* @__PURE__ */ new Map([
20521
20677
  function hasFeature(featuresById, featureId) {
20522
20678
  return featuresById.has(featureId) || featuresById.has(LEGACY_FEATURE_ALIASES.get(featureId) ?? "");
20523
20679
  }
20680
+ function defaultFeaturePathFor(id) {
20681
+ return `/${id.replaceAll(".", "/")}`;
20682
+ }
20524
20683
  var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ctx) => {
20525
20684
  const featuresById = collectIds(model.features, ctx, ["features"], "Feature");
20685
+ const featureIdsByEffectivePath = /* @__PURE__ */ new Map();
20526
20686
  model.features.forEach((feature, featureIndex) => {
20527
20687
  const segments = feature.id.split(".");
20528
20688
  if (segments.length > 1) {
@@ -20538,6 +20698,20 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
20538
20698
  const hasChildren = model.features.some(
20539
20699
  (candidate) => candidate.id.startsWith(`${feature.id}.`) && candidate.id !== feature.id
20540
20700
  );
20701
+ const contributesRoutePath = feature.path !== void 0 || !hasChildren;
20702
+ if (contributesRoutePath) {
20703
+ const effectivePath = feature.path ?? defaultFeaturePathFor(feature.id);
20704
+ const existingFeatureId = featureIdsByEffectivePath.get(effectivePath);
20705
+ if (existingFeatureId !== void 0) {
20706
+ addIssue(
20707
+ ctx,
20708
+ ["features", featureIndex, feature.path === void 0 ? "id" : "path"],
20709
+ `Feature "${feature.id}" effective path "${effectivePath}" duplicates feature "${existingFeatureId}"`
20710
+ );
20711
+ } else {
20712
+ featureIdsByEffectivePath.set(effectivePath, feature.id);
20713
+ }
20714
+ }
20541
20715
  if (hasChildren && feature.enabled) {
20542
20716
  const hasEnabledDescendant = model.features.some(
20543
20717
  (candidate) => candidate.id.startsWith(`${feature.id}.`) && candidate.enabled
@@ -20551,6 +20725,43 @@ var OrganizationModelSchema = OrganizationModelSchemaBase.superRefine((model, ct
20551
20725
  }
20552
20726
  }
20553
20727
  });
20728
+ const surfacesById = collectIds(model.navigation.surfaces, ctx, ["navigation", "surfaces"], "Navigation surface");
20729
+ if (model.navigation.defaultSurfaceId !== void 0 && !surfacesById.has(model.navigation.defaultSurfaceId)) {
20730
+ addIssue(
20731
+ ctx,
20732
+ ["navigation", "defaultSurfaceId"],
20733
+ `Navigation defaultSurfaceId references unknown surface "${model.navigation.defaultSurfaceId}"`
20734
+ );
20735
+ }
20736
+ model.navigation.groups.forEach((group, groupIndex) => {
20737
+ group.surfaceIds.forEach((surfaceId, surfaceIndex) => {
20738
+ if (!surfacesById.has(surfaceId)) {
20739
+ addIssue(
20740
+ ctx,
20741
+ ["navigation", "groups", groupIndex, "surfaceIds", surfaceIndex],
20742
+ `Navigation group "${group.id}" references unknown surface "${surfaceId}"`
20743
+ );
20744
+ }
20745
+ });
20746
+ });
20747
+ model.navigation.surfaces.forEach((surface, surfaceIndex) => {
20748
+ if (surface.featureId !== void 0 && !hasFeature(featuresById, surface.featureId)) {
20749
+ addIssue(
20750
+ ctx,
20751
+ ["navigation", "surfaces", surfaceIndex, "featureId"],
20752
+ `Navigation surface "${surface.id}" references unknown feature "${surface.featureId}"`
20753
+ );
20754
+ }
20755
+ surface.featureIds.forEach((featureId, featureIndex) => {
20756
+ if (!hasFeature(featuresById, featureId)) {
20757
+ addIssue(
20758
+ ctx,
20759
+ ["navigation", "surfaces", surfaceIndex, "featureIds", featureIndex],
20760
+ `Navigation surface "${surface.id}" references unknown feature "${featureId}"`
20761
+ );
20762
+ }
20763
+ });
20764
+ });
20554
20765
  const segmentsById = new Map(model.customers.segments.map((seg) => [seg.id, seg]));
20555
20766
  model.offerings.products.forEach((product, productIndex) => {
20556
20767
  product.targetSegmentIds.forEach((segmentId, segmentIndex) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@elevasis/core",
3
- "version": "0.19.0",
3
+ "version": "0.21.0",
4
4
  "license": "MIT",
5
5
  "description": "Minimal shared constants across Elevasis monorepo",
6
6
  "sideEffects": false,
@@ -1123,7 +1123,7 @@ export const DEFAULT_CRM_PRIORITY_RULE_CONFIG: CrmPriorityRuleConfig = {
1123
1123
  ### `DealStageSchema`
1124
1124
 
1125
1125
  ```typescript
1126
- export const DealStageSchema = z.enum(['interested', 'proposal', 'closing', 'closed_won', 'closed_lost', 'nurturing'])
1126
+ export const DealStageSchema = CrmStageKeySchema
1127
1127
  ```
1128
1128
 
1129
1129
  ### `AcqDealTaskKindSchema`
@@ -1215,7 +1215,7 @@ export const TransitionItemRequestSchema = z
1215
1215
  .object({
1216
1216
  pipelineKey: z.string().min(1),
1217
1217
  stageKey: z.string().min(1),
1218
- stateKey: z.string().nullable().optional(),
1218
+ stateKey: z.string().min(1).nullable().optional(),
1219
1219
  reason: z.string().optional(),
1220
1220
  expectedUpdatedAt: z.string().datetime().optional()
1221
1221
  })
@@ -1409,6 +1409,11 @@ export const DealTaskListResponseSchema = z.array(DealTaskResponseSchema)
1409
1409
 
1410
1410
  ```typescript
1411
1411
  export const DealSchemas = {
1412
+ // Primitives
1413
+ CrmStageKey: CrmStageKeySchema,
1414
+ CrmStateKey: CrmStateKeySchema,
1415
+ DealStage: DealStageSchema,
1416
+
1412
1417
  // Params
1413
1418
  DealIdParams: DealIdParamsSchema,
1414
1419
  DealTaskIdParams: DealTaskIdParamsSchema,
@@ -1421,7 +1426,7 @@ export const DealSchemas = {
1421
1426
  // Request bodies
1422
1427
  CreateDealNoteRequest: CreateDealNoteRequestSchema,
1423
1428
  CreateDealTaskRequest: CreateDealTaskRequestSchema,
1424
- TransitionItemRequest: TransitionItemRequestSchema,
1429
+ TransitionItemRequest: CrmTransitionItemRequestSchema,
1425
1430
  TransitionDealStateRequest: TransitionDealStateRequestSchema,
1426
1431
  ExecuteActionParams: ExecuteActionParamsSchema,
1427
1432
  ExecuteActionRequest: ExecuteActionRequestSchema,
@@ -2544,15 +2549,20 @@ export const AcqSubstrateSchemas = {
2544
2549
 
2545
2550
  // List members
2546
2551
  ListMembersQuery: ListMembersQuerySchema,
2552
+ ListRecordsQuery: ListRecordsQuerySchema,
2547
2553
  MemberIdParams: MemberIdParamsSchema,
2548
2554
  AcqListMemberResponse: AcqListMemberResponseSchema,
2549
2555
  AcqListMembersResponse: AcqListMembersResponseSchema,
2556
+ AcqListCompanyRecordRow: AcqListCompanyRecordRowSchema,
2557
+ AcqListContactRecordRow: AcqListContactRecordRowSchema,
2558
+ ListRecordRow: ListRecordRowSchema,
2559
+ ListRecordsResponse: ListRecordsResponseSchema,
2550
2560
 
2551
2561
  // List companies
2552
2562
  ListCompanyIdParams: ListCompanyIdParamsSchema,
2553
2563
  AcqListCompanyResponse: AcqListCompanyResponseSchema,
2554
2564
 
2555
- // Transition (shared with deals — TransitionItemRequestSchema)
2565
+ // Transition (generic stateful substrate)
2556
2566
  TransitionItemRequest: TransitionItemRequestSchema
2557
2567
  }
2558
2568
  ```
@@ -2620,6 +2630,8 @@ export interface StatefulStageDefinition {
2620
2630
  /** Matches stage_key values written by workflow steps. */
2621
2631
  stageKey: string
2622
2632
  label: string
2633
+ /** UI color token. Consumers may map this to their design system. */
2634
+ color?: string
2623
2635
  states: StatefulStateDefinition[]
2624
2636
  }
2625
2637
  ```
@@ -2702,7 +2714,7 @@ export const ACQ_LIST_COMPANIES_LEAD_GEN_PIPELINE: StatefulPipelineDefinition =
2702
2714
  {
2703
2715
  stageKey: 'outreach',
2704
2716
  label: 'Outreach',
2705
- states: [PENDING_STATE]
2717
+ states: [PENDING_STATE, { stateKey: 'uploaded', label: 'Uploaded' }]
2706
2718
  },
2707
2719
  {
2708
2720
  stageKey: 'prospecting',