@elevasis/sdk 1.19.0 → 1.20.1

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 (58) hide show
  1. package/dist/cli.cjs +1718 -72
  2. package/dist/index.d.ts +661 -7
  3. package/dist/index.js +565 -42
  4. package/dist/node/index.d.ts +2 -0
  5. package/dist/node/index.js +219 -2
  6. package/dist/test-utils/index.d.ts +459 -4
  7. package/dist/test-utils/index.js +509 -37
  8. package/dist/types/worker/platform.d.ts +15 -1
  9. package/dist/worker/index.js +365 -37
  10. package/package.json +2 -2
  11. package/reference/_navigation.md +2 -1
  12. package/reference/_reference-manifest.json +14 -0
  13. package/reference/claude-config/registries/knowledge-flags.json +156 -0
  14. package/reference/claude-config/rules/agent-start-here.md +5 -5
  15. package/reference/claude-config/rules/deployment.md +4 -3
  16. package/reference/claude-config/rules/frontend.md +2 -2
  17. package/reference/claude-config/rules/operations.md +17 -13
  18. package/reference/claude-config/rules/organization-model.md +7 -5
  19. package/reference/claude-config/rules/organization-os.md +13 -11
  20. package/reference/claude-config/rules/ui.md +3 -3
  21. package/reference/claude-config/rules/vibe.md +4 -4
  22. package/reference/claude-config/skills/explore/SKILL.md +4 -4
  23. package/reference/claude-config/skills/knowledge/SKILL.md +8 -8
  24. package/reference/claude-config/skills/knowledge/operations/codify-level-a.md +7 -7
  25. package/reference/claude-config/skills/knowledge/operations/codify-level-b.md +13 -13
  26. package/reference/claude-config/skills/knowledge/operations/customers.md +1 -1
  27. package/reference/claude-config/skills/knowledge/operations/goals.md +1 -1
  28. package/reference/claude-config/skills/knowledge/operations/identity.md +1 -1
  29. package/reference/claude-config/skills/knowledge/operations/offerings.md +1 -1
  30. package/reference/claude-config/skills/knowledge/operations/roles.md +1 -1
  31. package/reference/claude-config/skills/knowledge/operations/techStack.md +19 -91
  32. package/reference/claude-config/skills/project/SKILL.md +73 -13
  33. package/reference/claude-config/skills/save/SKILL.md +5 -5
  34. package/reference/claude-config/skills/tutorial/technical.md +5 -6
  35. package/reference/claude-config/sync-notes/2026-05-07-sdk-changes-release-train.md +34 -0
  36. package/reference/claude-config/sync-notes/2026-05-08-resource-governance-scaffold-guidance.md +38 -0
  37. package/reference/claude-config/sync-notes/2026-05-09-clients-domain.md +32 -0
  38. package/reference/claude-config/sync-notes/2026-05-09-command-system.md +33 -0
  39. package/reference/claude-config/sync-notes/2026-05-09-resource-governance-and-misc.md +69 -0
  40. package/reference/examples/organization-model.ts +17 -5
  41. package/reference/framework/index.mdx +1 -1
  42. package/reference/framework/project-structure.mdx +10 -8
  43. package/reference/packages/core/src/business/README.md +2 -2
  44. package/reference/packages/core/src/organization-model/README.md +10 -3
  45. package/reference/resources/index.mdx +27 -17
  46. package/reference/scaffold/core/organization-model.mdx +33 -14
  47. package/reference/scaffold/operations/workflow-recipes.md +35 -29
  48. package/reference/scaffold/recipes/add-a-feature.md +18 -3
  49. package/reference/scaffold/recipes/add-a-resource.md +50 -10
  50. package/reference/scaffold/recipes/customize-crm-actions.md +12 -6
  51. package/reference/scaffold/recipes/customize-organization-model.md +18 -3
  52. package/reference/scaffold/recipes/extend-crm.md +17 -19
  53. package/reference/scaffold/recipes/extend-lead-gen.md +31 -31
  54. package/reference/scaffold/recipes/index.md +1 -1
  55. package/reference/scaffold/reference/contracts.md +501 -303
  56. package/reference/scaffold/reference/feature-registry.md +1 -1
  57. package/reference/scaffold/reference/glossary.md +8 -3
  58. package/reference/scaffold/ui/recipes.md +21 -6
@@ -6529,6 +6529,7 @@ var ORGANIZATION_MODEL_ICON_TOKENS = [
6529
6529
  "knowledge.reference",
6530
6530
  "feature.dashboard",
6531
6531
  "feature.calendar",
6532
+ "feature.business",
6532
6533
  "feature.sales",
6533
6534
  "feature.crm",
6534
6535
  "feature.finance",
@@ -6723,6 +6724,13 @@ var LEAD_GEN_STAGE_CATALOG = {
6723
6724
  order: 2,
6724
6725
  entity: "company"
6725
6726
  },
6727
+ crawled: {
6728
+ key: "crawled",
6729
+ label: "Websites crawled",
6730
+ description: "Company websites have been crawled (e.g. via Apify) and raw page content stored for downstream LLM analysis.",
6731
+ order: 2.5,
6732
+ entity: "company"
6733
+ },
6726
6734
  extracted: {
6727
6735
  key: "extracted",
6728
6736
  label: "Websites analyzed",
@@ -6742,7 +6750,9 @@ var LEAD_GEN_STAGE_CATALOG = {
6742
6750
  label: "Decision-makers found",
6743
6751
  description: "Decision-maker contacts discovered and attached to a qualified company.",
6744
6752
  order: 6,
6745
- entity: "company"
6753
+ entity: "company",
6754
+ recordEntity: "contact",
6755
+ recordStageKey: "discovered"
6746
6756
  },
6747
6757
  // Prospecting — contact discovery
6748
6758
  discovered: {
@@ -6780,7 +6790,8 @@ var LEAD_GEN_STAGE_CATALOG = {
6780
6790
  label: "Reviewed and exported",
6781
6791
  description: "Approved records have been reviewed and exported for handoff.",
6782
6792
  order: 10,
6783
- entity: "contact"
6793
+ entity: "company",
6794
+ additionalEntities: ["contact"]
6784
6795
  },
6785
6796
  interested: {
6786
6797
  key: "interested",
@@ -6794,18 +6805,47 @@ var LEAD_GEN_STAGE_CATALOG = {
6794
6805
  // ../core/src/organization-model/domains/prospecting.ts
6795
6806
  var ProspectingLifecycleStageSchema = DisplayMetadataSchema.extend({
6796
6807
  id: ModelIdSchema,
6797
- order: z.number().int().min(0)
6808
+ order: z.number().min(0)
6809
+ });
6810
+ var RecordColumnConfigSchema = z.object({
6811
+ key: ModelIdSchema,
6812
+ label: z.string().trim().min(1).max(120),
6813
+ path: z.string().trim().min(1).max(500),
6814
+ width: z.union([z.number().positive(), z.string().trim().min(1).max(100)]).optional(),
6815
+ renderType: z.enum(["text", "badge", "datetime", "count", "json"]).optional(),
6816
+ badgeColor: z.string().trim().min(1).max(40).optional()
6817
+ });
6818
+ var RecordColumnsConfigSchema = z.object({
6819
+ company: z.array(RecordColumnConfigSchema).optional(),
6820
+ contact: z.array(RecordColumnConfigSchema).optional()
6821
+ }).refine((columns) => Boolean(columns.company?.length || columns.contact?.length), {
6822
+ message: "recordColumns must include at least one entity column set"
6823
+ });
6824
+ var CredentialRequirementSchema = z.object({
6825
+ key: ModelIdSchema,
6826
+ provider: ModelIdSchema,
6827
+ credentialType: z.enum(["api-key", "api-key-secret", "oauth", "webhook-secret"]),
6828
+ label: z.string().trim().min(1).max(120),
6829
+ required: z.boolean(),
6830
+ selectionMode: z.enum(["single", "multiple"]).optional(),
6831
+ inputPath: z.string().trim().min(1).max(500),
6832
+ verifyOnRun: z.boolean().optional()
6798
6833
  });
6799
6834
  var ProspectingBuildTemplateStepSchema = DisplayMetadataSchema.extend({
6800
6835
  id: ModelIdSchema,
6801
6836
  primaryEntity: z.enum(["company", "contact"]),
6802
6837
  outputs: z.array(z.enum(["company", "contact", "export"])).min(1),
6803
6838
  stageKey: ModelIdSchema,
6839
+ recordEntity: z.enum(["company", "contact"]).optional(),
6840
+ recordsStageKey: ModelIdSchema.optional(),
6841
+ recordSourceStageKey: ModelIdSchema.optional(),
6804
6842
  dependsOn: z.array(ModelIdSchema).optional(),
6805
6843
  dependencyMode: z.literal("per-record-eligibility"),
6806
6844
  capabilityKey: ModelIdSchema,
6807
6845
  defaultBatchSize: z.number().int().positive(),
6808
- maxBatchSize: z.number().int().positive()
6846
+ maxBatchSize: z.number().int().positive(),
6847
+ recordColumns: RecordColumnsConfigSchema.optional(),
6848
+ credentialRequirements: z.array(CredentialRequirementSchema).optional()
6809
6849
  }).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
6810
6850
  message: "defaultBatchSize must be less than or equal to maxBatchSize",
6811
6851
  path: ["defaultBatchSize"]
@@ -6814,6 +6854,62 @@ var ProspectingBuildTemplateSchema = DisplayMetadataSchema.extend({
6814
6854
  id: ModelIdSchema,
6815
6855
  steps: z.array(ProspectingBuildTemplateStepSchema).min(1)
6816
6856
  });
6857
+ var DTC_RECORD_COLUMNS = {
6858
+ populated: {
6859
+ company: [
6860
+ { key: "name", label: "Company", path: "company.name" },
6861
+ { key: "domain", label: "Domain", path: "company.domain" },
6862
+ { key: "employee-count", label: "Employees", path: "company.numEmployees", renderType: "count" },
6863
+ { key: "apollo-industry", label: "Apollo industry", path: "company.category" },
6864
+ { key: "location", label: "Location", path: "company.locationState" }
6865
+ ]
6866
+ },
6867
+ crawled: {
6868
+ company: [
6869
+ { key: "name", label: "Company", path: "company.name" },
6870
+ { key: "domain", label: "Domain", path: "company.domain" },
6871
+ { key: "page-count", label: "Pages", path: "company.enrichmentData.websiteCrawl.pageCount", renderType: "count" },
6872
+ { key: "crawl-status", label: "Crawl status", path: "processingState.crawled.status", renderType: "badge" }
6873
+ ]
6874
+ },
6875
+ extracted: {
6876
+ company: [
6877
+ { key: "name", label: "Company", path: "company.name" },
6878
+ { key: "domain", label: "Domain", path: "company.domain" },
6879
+ { key: "description", label: "Description", path: "company.enrichmentData.websiteCrawl.companyDescription" },
6880
+ { key: "services", label: "Services", path: "company.enrichmentData.websiteCrawl.services", renderType: "json" },
6881
+ { key: "automation-gaps", label: "Automation gaps", path: "company.enrichmentData.websiteCrawl.automationGaps", renderType: "json" },
6882
+ { key: "contact-count", label: "Contacts", path: "company.enrichmentData.websiteCrawl.emailCount", renderType: "count" }
6883
+ ]
6884
+ },
6885
+ qualified: {
6886
+ company: [
6887
+ { key: "name", label: "Company", path: "company.name" },
6888
+ { key: "domain", label: "Domain", path: "company.domain" },
6889
+ { key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
6890
+ { key: "signals", label: "Signals", path: "company.qualificationSignals", renderType: "json" },
6891
+ { key: "disqualified-reason", label: "Disqualified reason", path: "processingState.qualified.data.disqualifiedReason" }
6892
+ ]
6893
+ },
6894
+ decisionMakers: {
6895
+ contact: [
6896
+ { key: "name", label: "Name", path: "contact.name" },
6897
+ { key: "title", label: "Title", path: "contact.title" },
6898
+ { key: "email", label: "Email", path: "contact.email" },
6899
+ { key: "linkedin", label: "LinkedIn", path: "contact.linkedinUrl" },
6900
+ { key: "priority-score", label: "Priority", path: "contact.enrichmentData.apollo.priorityScore", renderType: "badge" }
6901
+ ]
6902
+ },
6903
+ uploaded: {
6904
+ company: [
6905
+ { key: "name", label: "Company", path: "company.name" },
6906
+ { key: "domain", label: "Domain", path: "company.domain" },
6907
+ { key: "contacts", label: "Contacts", path: "company.enrichmentData.approvedLeadListExport.contacts", renderType: "json" },
6908
+ { key: "score", label: "Score", path: "company.qualificationScore", renderType: "badge", badgeColor: "green" },
6909
+ { key: "approval", label: "Approval", path: "company.enrichmentData.approvedLeadListExport.approvalStatus", renderType: "badge" }
6910
+ ]
6911
+ }
6912
+ };
6817
6913
  z.object({
6818
6914
  id: ModelIdSchema,
6819
6915
  label: z.string(),
@@ -6845,6 +6941,12 @@ var CAPABILITY_REGISTRY = [
6845
6941
  description: "Check email deliverability before outreach.",
6846
6942
  resourceId: "lgn-05-email-verification-workflow"
6847
6943
  },
6944
+ {
6945
+ id: "lead-gen.company.apify-crawl",
6946
+ label: "Crawl websites",
6947
+ description: "Crawl company websites via Apify and store raw page markdown in enrichmentData.websiteCrawl.pages for downstream LLM analysis.",
6948
+ resourceId: "lgn-02a-apify-website-crawl-workflow"
6949
+ },
6848
6950
  {
6849
6951
  id: "lead-gen.company.website-extract",
6850
6952
  label: "Extract website signals",
@@ -6991,7 +7093,45 @@ var PROSPECTING_STEPS = {
6991
7093
  dependencyMode: "per-record-eligibility",
6992
7094
  capabilityKey: "lead-gen.company.apollo-import",
6993
7095
  defaultBatchSize: 250,
6994
- maxBatchSize: 1e3
7096
+ maxBatchSize: 1e3,
7097
+ recordColumns: DTC_RECORD_COLUMNS.populated,
7098
+ credentialRequirements: [
7099
+ {
7100
+ key: "apollo",
7101
+ provider: "apollo",
7102
+ credentialType: "api-key-secret",
7103
+ label: "Apollo API key",
7104
+ required: true,
7105
+ selectionMode: "single",
7106
+ inputPath: "credential"
7107
+ }
7108
+ ]
7109
+ },
7110
+ apifyCrawl: {
7111
+ id: "apify-crawl",
7112
+ label: "Websites crawled",
7113
+ 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.",
7114
+ primaryEntity: "company",
7115
+ outputs: ["company"],
7116
+ stageKey: "crawled",
7117
+ dependsOn: ["import-apollo-search"],
7118
+ dependencyMode: "per-record-eligibility",
7119
+ capabilityKey: "lead-gen.company.apify-crawl",
7120
+ defaultBatchSize: 50,
7121
+ maxBatchSize: 100,
7122
+ recordColumns: DTC_RECORD_COLUMNS.crawled,
7123
+ credentialRequirements: [
7124
+ {
7125
+ key: "apify",
7126
+ provider: "apify",
7127
+ credentialType: "api-key-secret",
7128
+ label: "Apify API token",
7129
+ required: true,
7130
+ selectionMode: "single",
7131
+ inputPath: "credential",
7132
+ verifyOnRun: true
7133
+ }
7134
+ ]
6995
7135
  },
6996
7136
  analyzeWebsites: {
6997
7137
  id: "analyze-websites",
@@ -7000,11 +7140,12 @@ var PROSPECTING_STEPS = {
7000
7140
  primaryEntity: "company",
7001
7141
  outputs: ["company"],
7002
7142
  stageKey: "extracted",
7003
- dependsOn: ["import-apollo-search"],
7143
+ dependsOn: ["apify-crawl"],
7004
7144
  dependencyMode: "per-record-eligibility",
7005
7145
  capabilityKey: "lead-gen.company.website-extract",
7006
7146
  defaultBatchSize: 50,
7007
- maxBatchSize: 100
7147
+ maxBatchSize: 100,
7148
+ recordColumns: DTC_RECORD_COLUMNS.extracted
7008
7149
  },
7009
7150
  scoreDtcFit: {
7010
7151
  id: "score-dtc-fit",
@@ -7017,7 +7158,8 @@ var PROSPECTING_STEPS = {
7017
7158
  dependencyMode: "per-record-eligibility",
7018
7159
  capabilityKey: "lead-gen.company.dtc-subscription-qualify",
7019
7160
  defaultBatchSize: 100,
7020
- maxBatchSize: 250
7161
+ maxBatchSize: 250,
7162
+ recordColumns: DTC_RECORD_COLUMNS.qualified
7021
7163
  },
7022
7164
  enrichDecisionMakers: {
7023
7165
  id: "enrich-decision-makers",
@@ -7026,37 +7168,52 @@ var PROSPECTING_STEPS = {
7026
7168
  primaryEntity: "company",
7027
7169
  outputs: ["contact"],
7028
7170
  stageKey: "decision-makers-enriched",
7171
+ recordEntity: "contact",
7029
7172
  dependsOn: ["score-dtc-fit"],
7030
7173
  dependencyMode: "per-record-eligibility",
7031
7174
  capabilityKey: "lead-gen.contact.apollo-decision-maker-enrich",
7032
7175
  defaultBatchSize: 100,
7033
- maxBatchSize: 250
7034
- },
7035
- verifyEmails: {
7036
- id: "verify-emails",
7037
- label: "Emails verified",
7038
- description: "Verify deliverability before the QC and handoff step.",
7039
- primaryEntity: "contact",
7040
- outputs: ["contact"],
7041
- stageKey: "verified",
7042
- dependsOn: ["enrich-decision-makers"],
7043
- dependencyMode: "per-record-eligibility",
7044
- capabilityKey: "lead-gen.contact.verify-email",
7045
- defaultBatchSize: 250,
7046
- maxBatchSize: 500
7176
+ maxBatchSize: 250,
7177
+ recordColumns: DTC_RECORD_COLUMNS.decisionMakers,
7178
+ credentialRequirements: [
7179
+ {
7180
+ key: "apollo",
7181
+ provider: "apollo",
7182
+ credentialType: "api-key-secret",
7183
+ label: "Apollo API key",
7184
+ required: true,
7185
+ selectionMode: "single",
7186
+ inputPath: "credential"
7187
+ }
7188
+ ]
7047
7189
  },
7048
7190
  reviewAndExport: {
7049
7191
  id: "review-and-export",
7050
7192
  label: "Reviewed and exported",
7051
- description: "Operator QC approves or rejects leads, then approved records are exported as a lead list.",
7193
+ description: "Operator QC approves or rejects qualified companies, then approved records are exported as a lead list with unverified emails.",
7052
7194
  primaryEntity: "company",
7053
7195
  outputs: ["export"],
7054
7196
  stageKey: "uploaded",
7055
- dependsOn: ["verify-emails"],
7197
+ recordsStageKey: "uploaded",
7198
+ recordSourceStageKey: "qualified",
7199
+ dependsOn: ["enrich-decision-makers"],
7056
7200
  dependencyMode: "per-record-eligibility",
7057
7201
  capabilityKey: "lead-gen.export.list",
7058
7202
  defaultBatchSize: 100,
7059
- maxBatchSize: 250
7203
+ maxBatchSize: 250,
7204
+ recordColumns: DTC_RECORD_COLUMNS.uploaded,
7205
+ credentialRequirements: [
7206
+ {
7207
+ key: "clickup",
7208
+ provider: "clickup",
7209
+ credentialType: "api-key-secret",
7210
+ label: "ClickUp API token",
7211
+ required: true,
7212
+ selectionMode: "single",
7213
+ inputPath: "clickupCredential",
7214
+ verifyOnRun: true
7215
+ }
7216
+ ]
7060
7217
  }
7061
7218
  }
7062
7219
  };
@@ -7078,7 +7235,7 @@ function toProspectingLifecycleStage(stage) {
7078
7235
  };
7079
7236
  }
7080
7237
  function leadGenStagesForEntity(entity) {
7081
- return Object.values(LEAD_GEN_STAGE_CATALOG).filter((stage) => stage.entity === entity).sort((a3, b2) => a3.order - b2.order).map(toProspectingLifecycleStage);
7238
+ 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);
7082
7239
  }
7083
7240
  var DEFAULT_ORGANIZATION_MODEL_PROSPECTING = {
7084
7241
  companyStages: leadGenStagesForEntity("company"),
@@ -7104,10 +7261,10 @@ var DEFAULT_ORGANIZATION_MODEL_PROSPECTING = {
7104
7261
  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.",
7105
7262
  steps: [
7106
7263
  PROSPECTING_STEPS.dtcApolloClickup.importApolloSearch,
7264
+ PROSPECTING_STEPS.dtcApolloClickup.apifyCrawl,
7107
7265
  PROSPECTING_STEPS.dtcApolloClickup.analyzeWebsites,
7108
7266
  PROSPECTING_STEPS.dtcApolloClickup.scoreDtcFit,
7109
7267
  PROSPECTING_STEPS.dtcApolloClickup.enrichDecisionMakers,
7110
- PROSPECTING_STEPS.dtcApolloClickup.verifyEmails,
7111
7268
  PROSPECTING_STEPS.dtcApolloClickup.reviewAndExport
7112
7269
  ]
7113
7270
  }
@@ -7154,6 +7311,9 @@ z.object({
7154
7311
  });
7155
7312
  z.object({
7156
7313
  stage: DealStageSchema.optional(),
7314
+ list: UuidSchema.optional(),
7315
+ batch: z.string().trim().min(1).max(255).optional(),
7316
+ staleSince: z.string().datetime().optional(),
7157
7317
  search: z.string().optional(),
7158
7318
  limit: z.coerce.number().int().positive().default(50),
7159
7319
  offset: z.coerce.number().int().min(0).default(0)
@@ -7236,6 +7396,7 @@ var DealListItemSchema = z.object({
7236
7396
  // acq_deals columns
7237
7397
  id: z.string(),
7238
7398
  organization_id: z.string(),
7399
+ client_id: z.string().nullable().optional(),
7239
7400
  contact_id: z.string().nullable(),
7240
7401
  contact_email: z.string(),
7241
7402
  pipeline_key: z.string(),
@@ -7316,8 +7477,31 @@ var ConversationMessageSchema = z.object({
7316
7477
  var DealConversationSchema = z.object({
7317
7478
  messages: z.array(ConversationMessageSchema)
7318
7479
  });
7480
+ var DealLineageListRefSchema = z.object({
7481
+ id: z.string(),
7482
+ name: z.string(),
7483
+ status: z.string()
7484
+ });
7485
+ var DealLineageProjectRefSchema = z.object({
7486
+ id: z.string(),
7487
+ name: z.string(),
7488
+ kind: z.string(),
7489
+ status: z.string(),
7490
+ updatedAt: z.string()
7491
+ });
7492
+ var DealLineageClientRefSchema = z.object({
7493
+ id: z.string(),
7494
+ name: z.string(),
7495
+ status: z.string()
7496
+ });
7497
+ var DealLineageSchema = z.object({
7498
+ list: DealLineageListRefSchema.nullable(),
7499
+ projects: z.array(DealLineageProjectRefSchema),
7500
+ client: DealLineageClientRefSchema.nullable()
7501
+ });
7319
7502
  DealListItemSchema.extend({
7320
- conversation: DealConversationSchema
7503
+ conversation: DealConversationSchema,
7504
+ lineage: DealLineageSchema.optional()
7321
7505
  });
7322
7506
  var DealNoteResponseSchema = z.object({
7323
7507
  id: z.string(),
@@ -7378,11 +7562,19 @@ var BuildPlanSnapshotStepSchema = z.object({
7378
7562
  primaryEntity: z.enum(["company", "contact"]),
7379
7563
  outputs: z.array(z.enum(["company", "contact", "export"])).min(1),
7380
7564
  stageKey: LeadGenStageKeySchema,
7565
+ recordEntity: z.enum(["company", "contact"]).optional(),
7566
+ recordsStageKey: LeadGenStageKeySchema.optional(),
7567
+ recordSourceStageKey: LeadGenStageKeySchema.optional(),
7381
7568
  dependsOn: z.array(z.string().trim().min(1).max(100)).optional(),
7382
7569
  dependencyMode: z.literal("per-record-eligibility"),
7383
7570
  capabilityKey: LeadGenCapabilityKeySchema,
7384
7571
  defaultBatchSize: z.number().int().positive(),
7385
- maxBatchSize: z.number().int().positive()
7572
+ maxBatchSize: z.number().int().positive(),
7573
+ recordColumns: z.object({
7574
+ company: z.array(RecordColumnConfigSchema).optional(),
7575
+ contact: z.array(RecordColumnConfigSchema).optional()
7576
+ }).optional(),
7577
+ credentialRequirements: z.array(CredentialRequirementSchema).optional()
7386
7578
  }).refine((step) => step.defaultBatchSize <= step.maxBatchSize, {
7387
7579
  message: "defaultBatchSize must be less than or equal to maxBatchSize",
7388
7580
  path: ["defaultBatchSize"]
@@ -7521,6 +7713,23 @@ var AcqListResponseSchema = z.object({
7521
7713
  });
7522
7714
  z.array(AcqListResponseSchema);
7523
7715
  z.array(ListTelemetrySchema);
7716
+ var QueryBooleanSchema = z.preprocess((value) => {
7717
+ if (value === "true" || value === "1" || value === true) return true;
7718
+ if (value === "false" || value === "0" || value === false) return false;
7719
+ return value;
7720
+ }, z.boolean());
7721
+ z.object({
7722
+ status: ListStatusSchema.optional(),
7723
+ batch: z.string().trim().min(1).max(255).optional(),
7724
+ vertical: z.string().trim().min(1).max(255).optional(),
7725
+ limit: z.coerce.number().int().min(1).max(500).optional(),
7726
+ offset: z.coerce.number().int().min(0).optional()
7727
+ }).strict();
7728
+ z.object({
7729
+ includeDeals: QueryBooleanSchema.default(true),
7730
+ includeProgress: QueryBooleanSchema.default(false),
7731
+ dealLimit: z.coerce.number().int().min(0).max(100).default(25)
7732
+ }).strict();
7524
7733
  var ListStageProgressSchema = z.object({
7525
7734
  total: z.number().int().min(0),
7526
7735
  attempted: z.number().int().min(0),
@@ -7531,12 +7740,48 @@ var ListStageProgressSchema = z.object({
7531
7740
  other: z.number().int().min(0),
7532
7741
  notAttempted: z.number().int().min(0)
7533
7742
  });
7534
- z.object({
7743
+ var ListProgressResponseSchema = z.object({
7535
7744
  totalMembers: z.number().int().min(0),
7536
7745
  totalCompanies: z.number().int().min(0),
7537
7746
  byCompanyStage: z.record(z.string(), ListStageProgressSchema),
7538
7747
  byContactStage: z.record(z.string(), ListStageProgressSchema)
7539
7748
  });
7749
+ var AcqListDealRefSchema = z.object({
7750
+ id: z.string(),
7751
+ contactEmail: z.string(),
7752
+ stageKey: z.string().nullable(),
7753
+ stateKey: z.string().nullable(),
7754
+ sourceType: z.string().nullable(),
7755
+ lastActivityAt: z.string()
7756
+ });
7757
+ var AcqListLineageSchema = z.object({
7758
+ deals: z.object({
7759
+ total: z.number().int().min(0),
7760
+ refs: z.array(AcqListDealRefSchema),
7761
+ truncated: z.boolean()
7762
+ })
7763
+ });
7764
+ AcqListResponseSchema.extend({
7765
+ lineage: AcqListLineageSchema.optional(),
7766
+ progress: ListProgressResponseSchema.optional()
7767
+ });
7768
+ var AcqListStatusListItemSchema = z.object({
7769
+ listId: z.string(),
7770
+ name: z.string(),
7771
+ status: ListStatusSchema,
7772
+ totalCompanies: z.number().int().min(0),
7773
+ totalContacts: z.number().int().min(0),
7774
+ totalDeals: z.number().int().min(0),
7775
+ createdAt: z.string()
7776
+ });
7777
+ z.object({
7778
+ totalLists: z.number().int().min(0),
7779
+ totalCompanies: z.number().int().min(0),
7780
+ totalContacts: z.number().int().min(0),
7781
+ totalDeals: z.number().int().min(0),
7782
+ byStatus: z.record(z.string(), z.number().int().min(0)),
7783
+ lists: z.array(AcqListStatusListItemSchema)
7784
+ });
7540
7785
  var ListExecutionSummarySchema = z.object({
7541
7786
  executionId: z.string(),
7542
7787
  resourceId: z.string(),
@@ -7547,11 +7792,6 @@ var ListExecutionSummarySchema = z.object({
7547
7792
  input: z.unknown().nullable().optional()
7548
7793
  });
7549
7794
  z.array(ListExecutionSummarySchema);
7550
- var QueryBooleanSchema = z.preprocess((value) => {
7551
- if (value === "true" || value === "1" || value === true) return true;
7552
- if (value === "false" || value === "0" || value === false) return false;
7553
- return value;
7554
- }, z.boolean());
7555
7795
  var AcqCompanyStatusSchema = z.enum(["active", "invalid"]);
7556
7796
  var AcqContactStatusSchema = z.enum(["active", "invalid"]);
7557
7797
  var AcqEmailValidSchema = z.enum(["VALID", "INVALID", "RISKY", "UNKNOWN"]);
@@ -7586,6 +7826,7 @@ z.object({
7586
7826
  }).strict();
7587
7827
  z.object({
7588
7828
  name: z.string().trim().min(1).max(255),
7829
+ clientId: UuidSchema.nullable().optional(),
7589
7830
  domain: z.string().trim().min(1).max(255).optional(),
7590
7831
  linkedinUrl: z.string().trim().url().optional(),
7591
7832
  website: z.string().trim().url().optional(),
@@ -7601,6 +7842,7 @@ z.object({
7601
7842
  }).strict();
7602
7843
  z.object({
7603
7844
  name: z.string().trim().min(1).max(255).optional(),
7845
+ clientId: UuidSchema.nullable().optional(),
7604
7846
  domain: z.string().trim().min(1).max(255).optional(),
7605
7847
  linkedinUrl: z.string().trim().url().optional(),
7606
7848
  website: z.string().trim().url().optional(),
@@ -7618,13 +7860,14 @@ z.object({
7618
7860
  status: AcqCompanyStatusSchema.optional(),
7619
7861
  verticalResearch: z.string().trim().min(1).max(5e3).nullable().optional()
7620
7862
  }).strict().refine(
7621
- (data) => data.name !== void 0 || data.domain !== void 0 || data.linkedinUrl !== void 0 || data.website !== void 0 || data.numEmployees !== void 0 || data.foundedYear !== void 0 || data.locationCity !== void 0 || data.locationState !== void 0 || data.category !== void 0 || data.segment !== void 0 || data.processingState !== void 0 || data.pipelineStatus !== void 0 || data.enrichmentData !== void 0 || data.source !== void 0 || data.batchId !== void 0 || data.status !== void 0 || data.verticalResearch !== void 0,
7863
+ (data) => data.name !== void 0 || data.clientId !== void 0 || data.domain !== void 0 || data.linkedinUrl !== void 0 || data.website !== void 0 || data.numEmployees !== void 0 || data.foundedYear !== void 0 || data.locationCity !== void 0 || data.locationState !== void 0 || data.category !== void 0 || data.segment !== void 0 || data.processingState !== void 0 || data.pipelineStatus !== void 0 || data.enrichmentData !== void 0 || data.source !== void 0 || data.batchId !== void 0 || data.status !== void 0 || data.verticalResearch !== void 0,
7622
7864
  {
7623
7865
  message: "At least one field must be provided"
7624
7866
  }
7625
7867
  );
7626
7868
  z.object({
7627
7869
  email: z.string().trim().email(),
7870
+ clientId: UuidSchema.nullable().optional(),
7628
7871
  companyId: UuidSchema.optional(),
7629
7872
  firstName: z.string().trim().min(1).max(255).optional(),
7630
7873
  lastName: z.string().trim().min(1).max(255).optional(),
@@ -7637,6 +7880,7 @@ z.object({
7637
7880
  }).strict();
7638
7881
  z.object({
7639
7882
  companyId: UuidSchema.optional(),
7883
+ clientId: UuidSchema.nullable().optional(),
7640
7884
  emailValid: AcqEmailValidSchema.optional(),
7641
7885
  firstName: z.string().trim().min(1).max(255).optional(),
7642
7886
  lastName: z.string().trim().min(1).max(255).optional(),
@@ -7650,7 +7894,7 @@ z.object({
7650
7894
  enrichmentData: z.record(z.string(), z.unknown()).optional(),
7651
7895
  status: AcqContactStatusSchema.optional()
7652
7896
  }).strict().refine(
7653
- (data) => data.companyId !== void 0 || data.emailValid !== void 0 || data.firstName !== void 0 || data.lastName !== void 0 || data.linkedinUrl !== void 0 || data.title !== void 0 || data.headline !== void 0 || data.filterReason !== void 0 || data.openingLine !== void 0 || data.processingState !== void 0 || data.pipelineStatus !== void 0 || data.enrichmentData !== void 0 || data.status !== void 0,
7897
+ (data) => data.companyId !== void 0 || data.clientId !== void 0 || data.emailValid !== void 0 || data.firstName !== void 0 || data.lastName !== void 0 || data.linkedinUrl !== void 0 || data.title !== void 0 || data.headline !== void 0 || data.filterReason !== void 0 || data.openingLine !== void 0 || data.processingState !== void 0 || data.pipelineStatus !== void 0 || data.enrichmentData !== void 0 || data.status !== void 0,
7654
7898
  {
7655
7899
  message: "At least one field must be provided"
7656
7900
  }
@@ -7658,6 +7902,7 @@ z.object({
7658
7902
  var AcqCompanyResponseSchema = z.object({
7659
7903
  id: z.string(),
7660
7904
  organizationId: z.string(),
7905
+ clientId: z.string().nullable().optional(),
7661
7906
  name: z.string(),
7662
7907
  domain: z.string().nullable(),
7663
7908
  linkedinUrl: z.string().nullable(),
@@ -7704,6 +7949,7 @@ var AcqContactCompanySummarySchema = z.object({
7704
7949
  var AcqContactResponseSchema = z.object({
7705
7950
  id: z.string(),
7706
7951
  organizationId: z.string(),
7952
+ clientId: z.string().nullable().optional(),
7707
7953
  companyId: z.string().nullable(),
7708
7954
  email: z.string(),
7709
7955
  emailValid: AcqEmailValidSchema.nullable(),
@@ -7763,6 +8009,24 @@ z.object({
7763
8009
  limit: z.coerce.number().int().min(1).max(500).default(50),
7764
8010
  offset: z.coerce.number().int().min(0).default(0)
7765
8011
  }).strict();
8012
+ var ListRecordEntitySchema = z.enum(["company", "contact"]);
8013
+ z.object({
8014
+ entity: ListRecordEntitySchema,
8015
+ stage: LeadGenStageKeySchema.optional(),
8016
+ limit: z.coerce.number().int().min(1).max(500).default(50),
8017
+ offset: z.coerce.number().int().min(0).default(0)
8018
+ }).strict().superRefine((query, ctx) => {
8019
+ if (!query.stage) return;
8020
+ const stage = LEAD_GEN_STAGE_CATALOG[query.stage];
8021
+ const validEntity = stage?.entity === query.entity || stage?.additionalEntities?.includes(query.entity) || stage?.recordEntity === query.entity;
8022
+ if (!validEntity) {
8023
+ ctx.addIssue({
8024
+ code: z.ZodIssueCode.custom,
8025
+ message: `stage "${query.stage}" is not valid for ${query.entity} records`,
8026
+ path: ["stage"]
8027
+ });
8028
+ }
8029
+ });
7766
8030
  z.object({
7767
8031
  memberId: UuidSchema
7768
8032
  });
@@ -7791,6 +8055,70 @@ var AcqListMemberResponseSchema = z.object({
7791
8055
  z.object({
7792
8056
  members: z.array(AcqListMemberResponseSchema)
7793
8057
  });
8058
+ var AcqListRecordCompanySummarySchema = z.object({
8059
+ id: z.string(),
8060
+ name: z.string(),
8061
+ domain: z.string().nullable(),
8062
+ website: z.string().nullable(),
8063
+ linkedinUrl: z.string().nullable(),
8064
+ numEmployees: z.number().nullable(),
8065
+ foundedYear: z.number().nullable(),
8066
+ locationCity: z.string().nullable(),
8067
+ locationState: z.string().nullable(),
8068
+ category: z.string().nullable(),
8069
+ segment: z.string().nullable(),
8070
+ status: AcqCompanyStatusSchema,
8071
+ qualificationScore: z.number().nullable(),
8072
+ qualificationSignals: z.record(z.string(), z.unknown()).nullable(),
8073
+ qualificationRubricKey: z.string().nullable()
8074
+ });
8075
+ var AcqListRecordContactSummarySchema = z.object({
8076
+ id: z.string(),
8077
+ email: z.string(),
8078
+ firstName: z.string().nullable(),
8079
+ lastName: z.string().nullable(),
8080
+ title: z.string().nullable(),
8081
+ headline: z.string().nullable(),
8082
+ linkedinUrl: z.string().nullable(),
8083
+ companyId: z.string().nullable(),
8084
+ status: AcqContactStatusSchema,
8085
+ qualificationScore: z.number().nullable(),
8086
+ qualificationSignals: z.record(z.string(), z.unknown()).nullable(),
8087
+ qualificationRubricKey: z.string().nullable()
8088
+ });
8089
+ var ListRecordBaseSchema = z.object({
8090
+ id: z.string(),
8091
+ listId: z.string(),
8092
+ pipelineKey: z.string(),
8093
+ stageKey: z.string(),
8094
+ stateKey: z.string(),
8095
+ activityLog: z.unknown(),
8096
+ addedAt: z.string(),
8097
+ addedBy: z.string().nullable(),
8098
+ sourceExecutionId: z.string().nullable(),
8099
+ processingState: z.record(z.string(), z.unknown()).nullable(),
8100
+ enrichmentData: z.record(z.string(), z.unknown()).nullable()
8101
+ });
8102
+ var AcqListCompanyRecordRowSchema = ListRecordBaseSchema.extend({
8103
+ entity: z.literal("company"),
8104
+ companyId: z.string(),
8105
+ company: AcqListRecordCompanySummarySchema.nullable()
8106
+ });
8107
+ var AcqListContactRecordRowSchema = ListRecordBaseSchema.extend({
8108
+ entity: z.literal("contact"),
8109
+ contactId: z.string(),
8110
+ contact: AcqListRecordContactSummarySchema.nullable()
8111
+ });
8112
+ var ListRecordRowSchema = z.discriminatedUnion("entity", [
8113
+ AcqListCompanyRecordRowSchema,
8114
+ AcqListContactRecordRowSchema
8115
+ ]);
8116
+ z.object({
8117
+ data: z.array(ListRecordRowSchema),
8118
+ total: z.number().int().min(0),
8119
+ limit: z.number().int().min(1),
8120
+ offset: z.number().int().min(0)
8121
+ });
7794
8122
  z.object({
7795
8123
  listCompanyId: UuidSchema
7796
8124
  });
@@ -8166,6 +8494,149 @@ var RegistryValidationError = class extends Error {
8166
8494
  this.name = "RegistryValidationError";
8167
8495
  }
8168
8496
  };
8497
+ function getResourceValidatorMode(explicitMode) {
8498
+ if (explicitMode) return explicitMode;
8499
+ const env = globalThis.process?.env;
8500
+ return env?.ELEVASIS_RESOURCE_VALIDATOR === "warn-only" ? "warn-only" : "strict";
8501
+ }
8502
+ function addGovernanceIssue(issues, type3, orgName, resourceId, message) {
8503
+ issues.push({
8504
+ type: type3,
8505
+ orgName,
8506
+ resourceId,
8507
+ message
8508
+ });
8509
+ }
8510
+ function emitGovernanceIssues(issues, mode, onWarning) {
8511
+ if (issues.length === 0) return;
8512
+ if (mode === "strict") {
8513
+ const first = issues[0];
8514
+ throw new RegistryValidationError(first.orgName, first.resourceId, "organizationModel.resources", first.message);
8515
+ }
8516
+ const warn = onWarning ?? ((issue) => console.warn(issue.message));
8517
+ for (const issue of issues) {
8518
+ warn(issue);
8519
+ }
8520
+ }
8521
+ function getRuntimeResources(resources) {
8522
+ return [
8523
+ ...(resources.workflows ?? []).map((workflow) => ({
8524
+ resourceId: workflow.config.resourceId,
8525
+ type: workflow.config.type,
8526
+ descriptor: workflow.config.resource
8527
+ })),
8528
+ ...(resources.agents ?? []).map((agent) => ({
8529
+ resourceId: agent.config.resourceId,
8530
+ type: agent.config.type,
8531
+ descriptor: agent.config.resource
8532
+ })),
8533
+ ...(resources.integrations ?? []).map((integration) => ({
8534
+ resourceId: integration.resourceId,
8535
+ type: integration.type,
8536
+ descriptor: integration.resource
8537
+ }))
8538
+ ];
8539
+ }
8540
+ function validateResourceGovernance(orgName, deployment, organizationModel = deployment.organizationModel, options = {}) {
8541
+ const mode = getResourceValidatorMode(options.mode);
8542
+ const omResources = organizationModel?.resources?.entries;
8543
+ const omSystems = organizationModel?.systems?.systems;
8544
+ const issues = [];
8545
+ if (!omResources || !omSystems) {
8546
+ return { valid: true, mode, issues };
8547
+ }
8548
+ const systemsById = new Map(omSystems.map((system) => [system.id, system]));
8549
+ const activeOmResources = omResources.filter((resource) => resource.status === "active");
8550
+ const omResourcesById = new Map(activeOmResources.map((resource) => [resource.id, resource]));
8551
+ const runtimeResources = getRuntimeResources(deployment);
8552
+ const runtimeResourcesById = new Map(runtimeResources.map((resource) => [resource.resourceId, resource]));
8553
+ for (const resource of activeOmResources) {
8554
+ if (!systemsById.has(resource.systemId)) {
8555
+ addGovernanceIssue(
8556
+ issues,
8557
+ "missing-om-system",
8558
+ orgName,
8559
+ resource.id,
8560
+ `[${orgName}] OM resource '${resource.id}' references missing System '${resource.systemId}'.`
8561
+ );
8562
+ }
8563
+ const runtimeResource = runtimeResourcesById.get(resource.id);
8564
+ if (!runtimeResource) {
8565
+ addGovernanceIssue(
8566
+ issues,
8567
+ "missing-code-resource",
8568
+ orgName,
8569
+ resource.id,
8570
+ `[${orgName}] OM resource '${resource.id}' has no matching code-side resource.`
8571
+ );
8572
+ continue;
8573
+ }
8574
+ if (runtimeResource.type !== resource.kind) {
8575
+ addGovernanceIssue(
8576
+ issues,
8577
+ "type-mismatch",
8578
+ orgName,
8579
+ resource.id,
8580
+ `[${orgName}] Resource '${resource.id}' type mismatch: code has '${runtimeResource.type}', OM has '${resource.kind}'.`
8581
+ );
8582
+ }
8583
+ if (runtimeResource.descriptor && runtimeResource.descriptor.systemId !== resource.systemId) {
8584
+ addGovernanceIssue(
8585
+ issues,
8586
+ "system-mismatch",
8587
+ orgName,
8588
+ resource.id,
8589
+ `[${orgName}] Resource '${resource.id}' system mismatch: code descriptor has '${runtimeResource.descriptor.systemId}', OM has '${resource.systemId}'.`
8590
+ );
8591
+ }
8592
+ }
8593
+ for (const runtimeResource of runtimeResources) {
8594
+ const omResource = omResourcesById.get(runtimeResource.resourceId);
8595
+ if (!omResource) {
8596
+ addGovernanceIssue(
8597
+ issues,
8598
+ "missing-om-resource",
8599
+ orgName,
8600
+ runtimeResource.resourceId,
8601
+ `[${orgName}] Code-side resource '${runtimeResource.resourceId}' has no active OM Resource descriptor.`
8602
+ );
8603
+ }
8604
+ if (!runtimeResource.descriptor) {
8605
+ addGovernanceIssue(
8606
+ issues,
8607
+ "raw-resource-id",
8608
+ orgName,
8609
+ runtimeResource.resourceId,
8610
+ `[${orgName}] Code-side resource '${runtimeResource.resourceId}' authors raw resourceId/type values. Use an OM Resource descriptor and bindResourceDescriptor().`
8611
+ );
8612
+ continue;
8613
+ }
8614
+ if (runtimeResource.descriptor.id !== runtimeResource.resourceId) {
8615
+ addGovernanceIssue(
8616
+ issues,
8617
+ "raw-resource-id",
8618
+ orgName,
8619
+ runtimeResource.resourceId,
8620
+ `[${orgName}] Code-side resource '${runtimeResource.resourceId}' does not derive identity from its OM descriptor '${runtimeResource.descriptor.id}'.`
8621
+ );
8622
+ }
8623
+ if (runtimeResource.descriptor.kind !== runtimeResource.type) {
8624
+ addGovernanceIssue(
8625
+ issues,
8626
+ "type-mismatch",
8627
+ orgName,
8628
+ runtimeResource.resourceId,
8629
+ `[${orgName}] Code-side resource '${runtimeResource.resourceId}' descriptor kind '${runtimeResource.descriptor.kind}' does not match runtime type '${runtimeResource.type}'.`
8630
+ );
8631
+ }
8632
+ }
8633
+ emitGovernanceIssues(issues, mode, options.onWarning);
8634
+ return {
8635
+ valid: issues.length === 0,
8636
+ mode,
8637
+ issues
8638
+ };
8639
+ }
8169
8640
  function validateDeploymentSpec(orgName, resources) {
8170
8641
  const seenIds = /* @__PURE__ */ new Set();
8171
8642
  resources.workflows?.forEach((workflow) => {
@@ -8202,6 +8673,7 @@ function validateDeploymentSpec(orgName, resources) {
8202
8673
  validateExecutionInterface(orgName, id, agent.interface, agent.contract.inputSchema);
8203
8674
  }
8204
8675
  });
8676
+ validateResourceGovernance(orgName, resources);
8205
8677
  }
8206
8678
  function validateResourceModelConfig(orgName, resourceId, modelConfig) {
8207
8679
  try {