@classytic/crm 0.5.1 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -6,7 +6,59 @@ import * as _$_classytic_primitives_state_machine0 from "@classytic/primitives/s
6
6
  import { z } from "zod";
7
7
  import { StatusChangeEntry, StatusHistory, appendStatus, lastTransitionTo, latestEntry, timeInStatus } from "@classytic/primitives/status-history";
8
8
  import { OperationContext } from "@classytic/primitives/context";
9
+ import { OutboxStore } from "@classytic/primitives/outbox";
9
10
 
11
+ //#region src/events/dispatch.d.ts
12
+ /**
13
+ * Context key for the post-commit event queue. `Symbol.for` so the host
14
+ * and the package agree on the key even across duplicated installs.
15
+ */
16
+ declare const PENDING_EVENTS: unique symbol;
17
+ /** CrmContext as seen inside a unit of work — carries the deferred queue. */
18
+ type InternalCrmContext = CrmContext & {
19
+ [PENDING_EVENTS]?: DomainEvent[];
20
+ };
21
+ interface CrmEventDispatcherOptions {
22
+ /** Underlying transport (host-supplied or the in-process bus). */
23
+ transport: EventTransport;
24
+ /**
25
+ * Transactional outbox. When wired, every domain event is persisted via
26
+ * `outbox.save(event, { session })` in the SAME session as the business
27
+ * write; the host's relay publishes committed rows.
28
+ */
29
+ outbox?: OutboxStore | undefined;
30
+ logger?: CrmLogger | undefined;
31
+ }
32
+ /**
33
+ * EventTransport-compatible wrapper the engine hands to repositories.
34
+ * `publish`/`subscribe` delegate straight to the underlying transport
35
+ * (host-facing surface unchanged); domain verbs call `dispatch(ctx, event)`
36
+ * so session/outbox/queue routing happens in ONE place.
37
+ */
38
+ declare class CrmEventDispatcher implements EventTransport {
39
+ readonly transport: EventTransport;
40
+ private readonly outbox;
41
+ private readonly logger;
42
+ constructor(options: CrmEventDispatcherOptions);
43
+ get name(): string;
44
+ /** Raw immediate publish — post-commit flushes and host-side use only. */
45
+ publish(event: DomainEvent): Promise<void>;
46
+ subscribe(pattern: string, handler: EventHandler): Promise<() => void>;
47
+ close(): Promise<void>;
48
+ /**
49
+ * Session-bound dispatch (see module doc for the full contract).
50
+ * `ctx` comes first so call sites read `dispatch(ctx, createEvent(...))`.
51
+ */
52
+ dispatch(ctx: CrmContext | undefined, event: DomainEvent): Promise<void>;
53
+ }
54
+ /**
55
+ * Drain a `[PENDING_EVENTS]` queue through a transport after commit,
56
+ * swallowing per-event errors (durable delivery is the outbox's job).
57
+ * Hosts composing their own outer transaction call this after commit;
58
+ * most should use `engine.withTransaction(ctx, fn)` instead.
59
+ */
60
+ declare function flushPending(transport: Pick<EventTransport, 'publish'> | undefined, events: DomainEvent[], logger?: CrmLogger): Promise<void>;
61
+ //#endregion
10
62
  //#region src/models/tenant-field.d.ts
11
63
  type TenantFieldType = 'objectId' | 'string';
12
64
  interface SchemaBuildConfig {
@@ -72,6 +124,19 @@ interface ILeadStatusEntry {
72
124
  by?: string;
73
125
  note?: string;
74
126
  }
127
+ /**
128
+ * Behavioural engagement counters — fed by the host from CRM events
129
+ * (email opens/clicks, inbound replies, logged activities) via
130
+ * `LeadRepository.recordEngagement`. Read by the lead scorer alongside
131
+ * the firmographic fields. Zero-valued on old rows (nested default).
132
+ */
133
+ interface ILeadEngagement {
134
+ opens: number;
135
+ clicks: number;
136
+ replies: number;
137
+ activities: number;
138
+ lastEngagedAt?: Date;
139
+ }
75
140
  interface ILeadDocument {
76
141
  _id: _$mongoose.Types.ObjectId;
77
142
  organizationId: _$mongoose.Types.ObjectId | string;
@@ -85,6 +150,7 @@ interface ILeadDocument {
85
150
  source?: string;
86
151
  campaignRef?: string;
87
152
  score: number;
153
+ engagement: ILeadEngagement;
88
154
  status: LeadStatus;
89
155
  statusHistory: ILeadStatusEntry[];
90
156
  ownerId?: string;
@@ -302,6 +368,31 @@ interface ISubscriptionDocument {
302
368
  declare function buildSubscriptionSchema(config: SchemaBuildConfig): Schema<ISubscriptionDocument>;
303
369
  declare function createSubscriptionModel(connection: Connection, config: SchemaBuildConfig): Model<ISubscriptionDocument>;
304
370
  //#endregion
371
+ //#region src/enums/suppression-reason.d.ts
372
+ /** Reasons derived 1:1 from an email engagement event kind. */
373
+ declare const EVENT_DERIVED_SUPPRESSION_REASONS: readonly ["bounce", "complaint", "unsubscribe"];
374
+ declare const SUPPRESSION_REASONS: readonly ["bounce", "complaint", "unsubscribe", "manual"];
375
+ type SuppressionReason = (typeof SUPPRESSION_REASONS)[number];
376
+ //#endregion
377
+ //#region src/models/suppression.schema.d.ts
378
+ interface ISuppressionDocument {
379
+ _id: _$mongoose.Types.ObjectId;
380
+ organizationId: _$mongoose.Types.ObjectId | string;
381
+ /** Stored lowercase-normalized (schema `lowercase: true` + repo trims). */
382
+ email: string;
383
+ reason: SuppressionReason;
384
+ /** Free-form origin: 'campaign:<id>', 'sequence:<id>', 'api', 'import', … */
385
+ source?: string;
386
+ /** Optional polymorphic external ref to the suppressed party (rule 7). */
387
+ subjectKind?: string;
388
+ subjectId?: string;
389
+ suppressedAt: Date;
390
+ metadata?: Record<string, unknown>;
391
+ createdAt: Date;
392
+ updatedAt: Date;
393
+ }
394
+ declare function buildSuppressionSchema(config: SchemaBuildConfig): Schema<ISuppressionDocument>;
395
+ //#endregion
305
396
  //#region src/enums/activity.d.ts
306
397
  /**
307
398
  * Activity type vocabulary. The package stores `type` as free-form
@@ -502,6 +593,124 @@ interface IMessageDocument {
502
593
  declare function buildMessageSchema(config: SchemaBuildConfig): Schema<IMessageDocument>;
503
594
  declare function createMessageModel(connection: Connection, config: SchemaBuildConfig): Model<IMessageDocument>;
504
595
  //#endregion
596
+ //#region src/enums/sequence-status.d.ts
597
+ /**
598
+ * Email sequence lifecycle.
599
+ *
600
+ * draft — being built; no enrollments can be created
601
+ * active — accepting new enrollments; steps are executing
602
+ * paused — no new enrollments; running enrollments pause at next step
603
+ * archived — soft-hidden; historical data preserved
604
+ */
605
+ declare const SEQUENCE_STATUSES: readonly ["draft", "active", "paused", "archived"];
606
+ type SequenceStatus = (typeof SEQUENCE_STATUSES)[number];
607
+ declare const SEQUENCE_TRANSITIONS: Record<SequenceStatus, readonly SequenceStatus[]>;
608
+ declare function canTransitionSequence(from: SequenceStatus, to: SequenceStatus): boolean;
609
+ //#endregion
610
+ //#region src/models/sequence.schema.d.ts
611
+ interface ISendEmailStep {
612
+ id: string;
613
+ type: 'SEND_EMAIL';
614
+ name?: string;
615
+ subject: string;
616
+ htmlBody: string;
617
+ fromName?: string;
618
+ fromEmail?: string;
619
+ }
620
+ interface IDelayStep {
621
+ id: string;
622
+ type: 'DELAY';
623
+ name?: string;
624
+ settings: {
625
+ days?: number;
626
+ hours?: number;
627
+ minutes?: number;
628
+ };
629
+ }
630
+ type SequenceStep = ISendEmailStep | IDelayStep;
631
+ interface ISequenceStatusEntry {
632
+ status: SequenceStatus;
633
+ occurredAt: Date;
634
+ by?: string;
635
+ note?: string;
636
+ }
637
+ interface ISequenceDocument {
638
+ _id: _$mongoose.Types.ObjectId;
639
+ organizationId: _$mongoose.Types.ObjectId | string;
640
+ name: string;
641
+ description?: string;
642
+ status: SequenceStatus;
643
+ fromName?: string;
644
+ fromEmail?: string;
645
+ /** Ordered list of steps — each step has a unique `id`. */
646
+ steps: SequenceStep[];
647
+ /** Exit enrollment when a reply is detected. Default true. */
648
+ replyDetectionEnabled: boolean;
649
+ tags: string[];
650
+ ownerId?: string;
651
+ metadata?: Record<string, unknown>;
652
+ statusHistory: ISequenceStatusEntry[];
653
+ createdAt: Date;
654
+ updatedAt: Date;
655
+ }
656
+ declare function buildSequenceSchema(config: SchemaBuildConfig): Schema<ISequenceDocument>;
657
+ //#endregion
658
+ //#region src/enums/enrollment-status.d.ts
659
+ /**
660
+ * Enrollment lifecycle.
661
+ *
662
+ * active — steps are executing (or waiting on a delay)
663
+ * paused — execution halted; can be resumed
664
+ * completed — all steps ran to completion
665
+ * exited — removed early (reply, unsubscribe, bounce, manual)
666
+ */
667
+ declare const ENROLLMENT_STATUSES: readonly ["active", "paused", "completed", "exited"];
668
+ type EnrollmentStatus = (typeof ENROLLMENT_STATUSES)[number];
669
+ declare const ENROLLMENT_TRANSITIONS: Record<EnrollmentStatus, readonly EnrollmentStatus[]>;
670
+ declare function canTransitionEnrollment(from: EnrollmentStatus, to: EnrollmentStatus): boolean;
671
+ //#endregion
672
+ //#region src/models/enrollment.schema.d.ts
673
+ type EnrollmentExitReason = 'completed' | 'reply' | 'unsubscribe' | 'bounce' | 'manual';
674
+ type StepResultStatus = 'pending' | 'sent' | 'failed' | 'skipped';
675
+ declare const ENROLLMENT_SUBJECT_KINDS: readonly ["lead", "contact"];
676
+ type EnrollmentSubjectKind = (typeof ENROLLMENT_SUBJECT_KINDS)[number];
677
+ interface IStepResult {
678
+ stepId: string;
679
+ stepType: string;
680
+ status: StepResultStatus;
681
+ sentAt?: Date;
682
+ error?: string;
683
+ }
684
+ interface IEnrollmentStatusEntry {
685
+ status: EnrollmentStatus;
686
+ occurredAt: Date;
687
+ by?: string;
688
+ }
689
+ interface IEnrollmentDocument {
690
+ _id: _$mongoose.Types.ObjectId;
691
+ organizationId: _$mongoose.Types.ObjectId | string;
692
+ sequenceId: _$mongoose.Types.ObjectId | string;
693
+ subjectKind: EnrollmentSubjectKind;
694
+ subjectId: _$mongoose.Types.ObjectId | string;
695
+ status: EnrollmentStatus;
696
+ /** Index into sequence.steps[] — 0-based. */
697
+ currentStepIndex: number;
698
+ stepResults: IStepResult[];
699
+ /** When a DELAY step will expire (informational — streamline owns the actual timer). */
700
+ resumeAt?: Date;
701
+ /** Streamline workflow run ID — used for idempotency checks. */
702
+ workflowRunId?: string;
703
+ exitReason?: EnrollmentExitReason;
704
+ enrolledAt: Date;
705
+ completedAt?: Date;
706
+ ownerId?: string;
707
+ metadata?: Record<string, unknown>;
708
+ statusHistory: IEnrollmentStatusEntry[];
709
+ createdAt: Date;
710
+ updatedAt: Date;
711
+ }
712
+ declare function buildEnrollmentSchema(config: SchemaBuildConfig): Schema<IEnrollmentDocument>;
713
+ //#endregion
505
714
  //#region src/models/create-models.d.ts
506
715
  interface CrmModels {
507
716
  Pipeline: Model<IPipelineDocument>;
@@ -511,15 +720,18 @@ interface CrmModels {
511
720
  Account: Model<IAccountDocument>;
512
721
  Campaign: Model<ICampaignDocument>;
513
722
  Subscription: Model<ISubscriptionDocument>;
723
+ Suppression: Model<ISuppressionDocument>;
514
724
  Activity: Model<IActivityDocument>;
515
725
  Note: Model<INoteDocument>;
516
726
  LossReason: Model<ILossReasonDocument>;
517
727
  EmailEvent: Model<IEmailEventDocument>;
518
728
  Conversation: Model<IConversationDocument>;
519
729
  Message: Model<IMessageDocument>;
730
+ Sequence: Model<ISequenceDocument>;
731
+ Enrollment: Model<IEnrollmentDocument>;
520
732
  }
521
733
  /** Mongoose model names this package registers — drives the §21 collision check. */
522
- declare const CRM_MODEL_NAMES: readonly ["Pipeline", "Lead", "Opportunity", "Contact", "Account", "Campaign", "EmailSubscription", "Activity", "Note", "LossReason", "EmailEvent", "Conversation", "Message"];
734
+ declare const CRM_MODEL_NAMES: readonly ["Pipeline", "Lead", "Opportunity", "Contact", "Account", "Campaign", "EmailSubscription", "Suppression", "Activity", "Note", "LossReason", "EmailEvent", "Conversation", "Message", "Sequence", "Enrollment"];
523
735
  interface CreateModelsOptions extends SchemaBuildConfig {
524
736
  /**
525
737
  * On a model-name collision: `false` (default) throws
@@ -534,7 +746,7 @@ declare function createCrmModels(connection: Connection, config: CreateModelsOpt
534
746
  //#endregion
535
747
  //#region src/repositories/pipeline.repository.d.ts
536
748
  interface PipelineRepositoryDeps {
537
- events: EventTransport;
749
+ events: CrmEventDispatcher;
538
750
  }
539
751
  declare class PipelineRepository extends Repository<IPipelineDocument> {
540
752
  private readonly events;
@@ -553,26 +765,31 @@ declare class PipelineRepository extends Repository<IPipelineDocument> {
553
765
  }
554
766
  //#endregion
555
767
  //#region src/shared/calculators/scoring.d.ts
556
- /** Minimal Lead shape the scorer reads. */
557
- type LeadInput = Pick<ILeadDocument, 'email' | 'phone' | 'companyName' | 'tags' | 'jobTitle'>;
768
+ /** Minimal Lead shape the scorer reads — firmographic + engagement counters. */
769
+ type LeadInput = Pick<ILeadDocument, 'email' | 'phone' | 'companyName' | 'tags' | 'jobTitle' | 'engagement'>;
558
770
  type LeadScorer = (lead: LeadInput) => number;
559
771
  /**
560
772
  * Reference implementation. Intentionally simple — hosts read it and
561
- * replace it.
773
+ * replace it. Deterministic + pure (no I/O, no wall-clock).
562
774
  *
563
- * +20 if email is present
564
- * +20 if phone is present
565
- * +20 if companyName is present
566
- * +10 per populated tag up to 40
567
- * +10 if jobTitle hints senior (director / manager / head / chief / vp / founder)
775
+ * Firmographic fit (max 110):
776
+ * +20 email · +20 phone · +20 companyName
777
+ * +10 per populated tag, up to +40
778
+ * +10 if jobTitle hints senior (director/manager/head/chief/vp/founder)
779
+ *
780
+ * Behavioural engagement, capped at +80 so a run of opens can't dominate a
781
+ * genuine reply: reply ×25 · click ×8 · open ×2 · activity ×5. Counters are
782
+ * fed by the host via `LeadRepository.recordEngagement`; absent on old rows.
568
783
  */
569
784
  declare function defaultLeadScorer(lead: LeadInput): number;
570
785
  /** Compose multiple small rules into one scorer. */
571
786
  declare function composeScorers(...rules: readonly LeadScorer[]): LeadScorer;
572
787
  //#endregion
573
788
  //#region src/repositories/lead.repository.d.ts
789
+ /** Behavioural engagement signals fed via `recordEngagement`. */
790
+ type LeadEngagementSignal = 'open' | 'click' | 'reply' | 'activity';
574
791
  interface LeadRepositoryDeps {
575
- events: EventTransport;
792
+ events: CrmEventDispatcher;
576
793
  /** Override the default lead scorer. */
577
794
  scorer?: LeadScorer;
578
795
  /** Reject `create()` when an email already exists in-tenant (default true). */
@@ -615,6 +832,14 @@ declare class LeadRepository extends Repository<ILeadDocument> {
615
832
  * the previous owner so audit consumers can compute hand-off chains.
616
833
  */
617
834
  assign(id: string, ownerId: string, ctx?: CrmContext): Promise<ILeadDocument>;
835
+ /**
836
+ * Record a behavioural engagement signal, then re-score. The host feeds
837
+ * these off CRM events (`crm:message.received` → reply, `crm:activity.*` →
838
+ * activity, and email open/click tracking → open/click). Atomic `$inc`
839
+ * on the counter (single round-trip, no lost-update window under
840
+ * concurrent signals), then `recomputeScore` re-reads the fresh counters.
841
+ */
842
+ recordEngagement(id: string, signal: LeadEngagementSignal, ctx?: CrmContext): Promise<ILeadDocument>;
618
843
  /**
619
844
  * Recompute + persist the lead's score. Called from `createLead`
620
845
  * automatically; hosts also call this after enrichment writes.
@@ -634,7 +859,7 @@ declare class LeadRepository extends Repository<ILeadDocument> {
634
859
  //#endregion
635
860
  //#region src/repositories/opportunity.repository.d.ts
636
861
  interface OpportunityRepositoryDeps {
637
- events: EventTransport;
862
+ events: CrmEventDispatcher;
638
863
  /** Cross-repo reference: read embedded stages from Pipeline. */
639
864
  pipelines: PipelineRepository;
640
865
  }
@@ -727,7 +952,7 @@ declare class OpportunityRepository extends Repository<IOpportunityDocument> {
727
952
  //#endregion
728
953
  //#region src/repositories/contact.repository.d.ts
729
954
  interface ContactRepositoryDeps {
730
- events: EventTransport;
955
+ events: CrmEventDispatcher;
731
956
  }
732
957
  interface MergeContactInput {
733
958
  /** Surviving contact id. Receives merged fields. */
@@ -776,7 +1001,7 @@ declare class ContactRepository extends Repository<IContactDocument> {
776
1001
  //#endregion
777
1002
  //#region src/repositories/account.repository.d.ts
778
1003
  interface AccountRepositoryDeps {
779
- events: EventTransport;
1004
+ events: CrmEventDispatcher;
780
1005
  }
781
1006
  interface MergeAccountInput {
782
1007
  primaryId: string;
@@ -796,7 +1021,7 @@ declare class AccountRepository extends Repository<IAccountDocument> {
796
1021
  //#endregion
797
1022
  //#region src/repositories/campaign.repository.d.ts
798
1023
  interface CampaignRepositoryDeps {
799
- events: EventTransport;
1024
+ events: CrmEventDispatcher;
800
1025
  /** Reject `createCampaign` on duplicate names per-tenant (default true). */
801
1026
  rejectDuplicates?: boolean;
802
1027
  }
@@ -820,7 +1045,7 @@ declare class CampaignRepository extends Repository<ICampaignDocument> {
820
1045
  //#endregion
821
1046
  //#region src/repositories/subscription.repository.d.ts
822
1047
  interface SubscriptionRepositoryDeps {
823
- events: EventTransport;
1048
+ events: CrmEventDispatcher;
824
1049
  /** Default DOI policy when `subscribe` doesn't pass `requireDoubleOptIn`. */
825
1050
  defaultRequireDoubleOptIn?: boolean;
826
1051
  }
@@ -846,9 +1071,53 @@ declare class SubscriptionRepository extends Repository<ISubscriptionDocument> {
846
1071
  private _transition;
847
1072
  }
848
1073
  //#endregion
1074
+ //#region src/repositories/suppression.repository.d.ts
1075
+ interface SuppressionRepositoryDeps {
1076
+ events: CrmEventDispatcher;
1077
+ }
1078
+ interface SuppressInput {
1079
+ reason: SuppressionReason;
1080
+ /** Free-form origin: 'campaign:<id>', 'sequence:<id>', 'api', 'import', … */
1081
+ source?: string;
1082
+ /** Optional polymorphic external ref to the suppressed party (rule 7). */
1083
+ subjectKind?: string;
1084
+ subjectId?: string;
1085
+ metadata?: Record<string, unknown>;
1086
+ }
1087
+ declare class SuppressionRepository extends Repository<ISuppressionDocument> {
1088
+ private readonly events;
1089
+ constructor(model: Model<ISuppressionDocument>, plugins: PluginType[], deps: SuppressionRepositoryDeps, pagination?: PaginationConfig);
1090
+ /**
1091
+ * Idempotently add `email` to the org's suppression list. Atomic
1092
+ * `getOrCreate` on the unique (org, email) index — of N concurrent
1093
+ * calls exactly one inserts. Emits `crm:suppression.added` only for
1094
+ * the inserting call; an existing row is returned unchanged, no event.
1095
+ */
1096
+ suppress(email: string, input: SuppressInput, ctx?: CrmContext): Promise<ISuppressionDocument>;
1097
+ /** True when `email` is on the org's suppression list. */
1098
+ isSuppressed(email: string, ctx?: CrmContext): Promise<boolean>;
1099
+ /**
1100
+ * Return the suppressed subset of `emails` (normalized) as a Set —
1101
+ * ONE `$in` query, built for the campaign-fanout hot path:
1102
+ *
1103
+ * ```ts
1104
+ * const blocked = await suppression.filterSuppressed(recipients, ctx);
1105
+ * const sendable = recipients.filter((e) => !blocked.has(e.toLowerCase()));
1106
+ * ```
1107
+ */
1108
+ filterSuppressed(emails: string[], ctx?: CrmContext): Promise<Set<string>>;
1109
+ /**
1110
+ * Remove `email` from the org's suppression list. Single atomic
1111
+ * `deleteMany` on the (unique) email key — emits
1112
+ * `crm:suppression.removed` only when a row was actually removed.
1113
+ * Returns whether a row was removed.
1114
+ */
1115
+ unsuppress(email: string, ctx?: CrmContext): Promise<boolean>;
1116
+ }
1117
+ //#endregion
849
1118
  //#region src/repositories/activity.repository.d.ts
850
1119
  interface ActivityRepositoryDeps {
851
- events: EventTransport;
1120
+ events: CrmEventDispatcher;
852
1121
  }
853
1122
  declare class ActivityRepository extends Repository<IActivityDocument> {
854
1123
  private readonly events;
@@ -885,7 +1154,7 @@ declare class ActivityRepository extends Repository<IActivityDocument> {
885
1154
  //#endregion
886
1155
  //#region src/repositories/note.repository.d.ts
887
1156
  interface NoteRepositoryDeps {
888
- events: EventTransport;
1157
+ events: CrmEventDispatcher;
889
1158
  }
890
1159
  declare class NoteRepository extends Repository<INoteDocument> {
891
1160
  private readonly events;
@@ -895,7 +1164,7 @@ declare class NoteRepository extends Repository<INoteDocument> {
895
1164
  //#endregion
896
1165
  //#region src/repositories/loss-reason.repository.d.ts
897
1166
  interface LossReasonRepositoryDeps {
898
- events: EventTransport;
1167
+ events: CrmEventDispatcher;
899
1168
  }
900
1169
  declare class LossReasonRepository extends Repository<ILossReasonDocument> {
901
1170
  private readonly events;
@@ -906,7 +1175,7 @@ declare class LossReasonRepository extends Repository<ILossReasonDocument> {
906
1175
  //#endregion
907
1176
  //#region src/repositories/email-event.repository.d.ts
908
1177
  interface EmailEventRepositoryDeps {
909
- events: EventTransport;
1178
+ events: CrmEventDispatcher;
910
1179
  }
911
1180
  interface RecordEmailEventInput {
912
1181
  subjectKind: EmailEventSubjectKind;
@@ -931,7 +1200,7 @@ declare class EmailEventRepository extends Repository<IEmailEventDocument> {
931
1200
  //#endregion
932
1201
  //#region src/repositories/conversation.repository.d.ts
933
1202
  interface ConversationRepositoryDeps {
934
- events: EventTransport;
1203
+ events: CrmEventDispatcher;
935
1204
  }
936
1205
  interface OpenConversationInput {
937
1206
  channel: ConversationChannel;
@@ -965,7 +1234,7 @@ declare class ConversationRepository extends Repository<IConversationDocument> {
965
1234
  //#endregion
966
1235
  //#region src/repositories/message.repository.d.ts
967
1236
  interface MessageRepositoryDeps {
968
- events: EventTransport;
1237
+ events: CrmEventDispatcher;
969
1238
  conversations: ConversationRepository;
970
1239
  }
971
1240
  interface RecordMessageInput {
@@ -991,6 +1260,81 @@ declare class MessageRepository extends Repository<IMessageDocument> {
991
1260
  findRecentForFeed(limit: number, ctx?: CrmContext): Promise<IMessageDocument[]>;
992
1261
  }
993
1262
  //#endregion
1263
+ //#region src/repositories/sequence.repository.d.ts
1264
+ interface SequenceRepositoryDeps {
1265
+ events: CrmEventDispatcher;
1266
+ }
1267
+ declare class SequenceRepository extends Repository<ISequenceDocument> {
1268
+ private readonly events;
1269
+ constructor(model: Model<ISequenceDocument>, plugins: PluginType[], deps: SequenceRepositoryDeps, pagination?: PaginationConfig);
1270
+ activate(id: string, ctx?: CrmContext): Promise<ISequenceDocument>;
1271
+ activateFromPaused(id: string, ctx?: CrmContext): Promise<ISequenceDocument>;
1272
+ pause(id: string, ctx?: CrmContext): Promise<ISequenceDocument>;
1273
+ archive(id: string, ctx?: CrmContext): Promise<ISequenceDocument>;
1274
+ private _transition;
1275
+ }
1276
+ //#endregion
1277
+ //#region src/repositories/enrollment.repository.d.ts
1278
+ interface EnrollmentRepositoryDeps {
1279
+ events: CrmEventDispatcher;
1280
+ /** Cross-repo reference: read `replyDetectionEnabled` from Sequence. */
1281
+ sequences: SequenceRepository;
1282
+ }
1283
+ /** A subject that just replied — input to `exitActiveOnReply()`. */
1284
+ interface ReplySubject {
1285
+ subjectKind: EnrollmentSubjectKind;
1286
+ subjectId: string;
1287
+ }
1288
+ interface EnrollInput {
1289
+ sequenceId: string;
1290
+ subjectKind: EnrollmentSubjectKind;
1291
+ subjectId: string;
1292
+ workflowRunId?: string;
1293
+ ownerId?: string;
1294
+ metadata?: Record<string, unknown>;
1295
+ }
1296
+ declare class EnrollmentRepository extends Repository<IEnrollmentDocument> {
1297
+ private readonly events;
1298
+ private readonly sequences;
1299
+ constructor(model: Model<IEnrollmentDocument>, plugins: PluginType[], deps: EnrollmentRepositoryDeps, pagination?: PaginationConfig);
1300
+ /** Create a new enrollment — throws AlreadyEnrolledError if an active one exists. */
1301
+ enroll(input: EnrollInput, ctx?: CrmContext): Promise<IEnrollmentDocument>;
1302
+ /** Set workflowRunId after the workflow has started. */
1303
+ setWorkflowRunId(id: string, workflowRunId: string, ctx?: CrmContext): Promise<void>;
1304
+ /** Atomically advance to the next step and record the result (CAS). */
1305
+ advanceStep(id: string, nextStepIndex: number, stepResult: IStepResult | null, ctx?: CrmContext): Promise<IEnrollmentDocument | null>;
1306
+ pause(id: string, ctx?: CrmContext): Promise<IEnrollmentDocument>;
1307
+ resume(id: string, ctx?: CrmContext): Promise<IEnrollmentDocument>;
1308
+ complete(id: string, ctx?: CrmContext): Promise<IEnrollmentDocument>;
1309
+ exit(id: string, exitReason: IEnrollmentDocument['exitReason'], ctx?: CrmContext): Promise<IEnrollmentDocument>;
1310
+ /**
1311
+ * Reply detection: exit every ACTIVE enrollment of the given subjects
1312
+ * with reason `'reply'` — the one method a host's
1313
+ * `crm:message.received` subscriber calls:
1314
+ *
1315
+ * ```ts
1316
+ * crm.events.subscribe('crm:message.received', async (e) => {
1317
+ * await crm.repositories.enrollment.exitActiveOnReply(
1318
+ * [{ subjectKind: 'contact', subjectId: e.payload.participantId }],
1319
+ * { organizationId: e.meta.organizationId },
1320
+ * );
1321
+ * });
1322
+ * ```
1323
+ *
1324
+ * Sequences are batch-loaded in ONE `$in` query; enrollments whose
1325
+ * sequence has `replyDetectionEnabled === false` are skipped (a missing
1326
+ * sequence — e.g. deleted — does NOT skip: the default is to exit).
1327
+ * Each exit goes through `exit()` (state-machine CAS + statusHistory +
1328
+ * ENROLLMENT_EXITED event). An enrollment that a concurrent transition
1329
+ * already moved out of `active` loses the CAS and is skipped — the
1330
+ * desired end state ("not active") already holds.
1331
+ *
1332
+ * Returns the enrollments this call actually exited.
1333
+ */
1334
+ exitActiveOnReply(subjects: ReplySubject[], ctx?: CrmContext): Promise<IEnrollmentDocument[]>;
1335
+ private _transition;
1336
+ }
1337
+ //#endregion
994
1338
  //#region src/engine/engine-types.d.ts
995
1339
  interface CrmLogger {
996
1340
  info?(msg: string, meta?: Record<string, unknown>): void;
@@ -1016,6 +1360,14 @@ interface CrmConfig {
1016
1360
  multiTenant?: boolean;
1017
1361
  /** Arc-compatible event transport. Default: in-process bus. */
1018
1362
  eventTransport?: EventTransport;
1363
+ /**
1364
+ * Transactional outbox (PACKAGE_RULES §P8). When wired, every domain
1365
+ * event is persisted via `outbox.save(event, { session })` in the SAME
1366
+ * session as the business write — the host's relay publishes committed
1367
+ * rows. Without it, events publish post-write (or defer to a
1368
+ * `ctx[PENDING_EVENTS]` queue inside `engine.withTransaction`).
1369
+ */
1370
+ outbox?: OutboxStore;
1019
1371
  /** Logger surface used by the in-process bus + repositories. */
1020
1372
  logger?: CrmLogger;
1021
1373
  /** Pagination defaults for every repository (mongokit). */
@@ -1059,22 +1411,43 @@ interface CrmRepositories {
1059
1411
  account: AccountRepository;
1060
1412
  campaign: CampaignRepository;
1061
1413
  subscription: SubscriptionRepository;
1414
+ suppression: SuppressionRepository;
1062
1415
  activity: ActivityRepository;
1063
1416
  note: NoteRepository;
1064
1417
  lossReason: LossReasonRepository;
1065
1418
  emailEvent: EmailEventRepository;
1066
1419
  conversation: ConversationRepository;
1067
1420
  message: MessageRepository;
1421
+ sequence: SequenceRepository;
1422
+ enrollment: EnrollmentRepository;
1068
1423
  }
1069
1424
  interface CrmEngine {
1070
1425
  /** Repositories ARE the API surface (PACKAGE_RULES §1). */
1071
1426
  readonly repositories: Readonly<CrmRepositories>;
1072
- /** Arc-compatible event transport. */
1073
- readonly events: EventTransport;
1427
+ /**
1428
+ * Arc-compatible event transport (a `CrmEventDispatcher` wrapping the
1429
+ * configured transport — `publish`/`subscribe` behave exactly like the
1430
+ * raw transport for hosts).
1431
+ */
1432
+ readonly events: CrmEventDispatcher;
1074
1433
  /** Mongoose models — for arc adapter wiring. */
1075
1434
  readonly models: Readonly<CrmModels>;
1076
1435
  /** Resolved configuration (frozen). */
1077
1436
  readonly config: Readonly<ResolvedCrmConfig>;
1437
+ /**
1438
+ * Run `body` inside a MongoDB transaction with post-commit event
1439
+ * discipline (PACKAGE_RULES §P8.1): events dispatched through `txCtx`
1440
+ * are queued and flushed to the transport only AFTER commit — an abort
1441
+ * leaks nothing to in-process subscribers. When `ctx.session` is already
1442
+ * set, the caller's transaction (and queue, if attached) is reused.
1443
+ *
1444
+ * ```ts
1445
+ * await engine.withTransaction(ctx, async (txCtx) => {
1446
+ * return leadService.convert(leadId, input, txCtx);
1447
+ * });
1448
+ * ```
1449
+ */
1450
+ withTransaction<T>(ctx: CrmContext, body: (txCtx: CrmContext) => Promise<T>): Promise<T>;
1078
1451
  /**
1079
1452
  * Build/align every model's indexes against its schema. Call once per
1080
1453
  * deploy when booted with `autoIndex: false` (§35). Idempotent.
@@ -1102,7 +1475,7 @@ declare function createCrm(config: CrmConfig): Promise<CrmEngine>;
1102
1475
  //#endregion
1103
1476
  //#region src/repositories/create-repositories.d.ts
1104
1477
  interface CreateCrmRepositoriesDeps {
1105
- events: EventTransport;
1478
+ events: CrmEventDispatcher;
1106
1479
  config: ResolvedCrmConfig;
1107
1480
  }
1108
1481
  declare function createCrmRepositories(models: CrmModels, deps: CreateCrmRepositoriesDeps): CrmRepositories;
@@ -1135,7 +1508,7 @@ interface LeadServiceDeps {
1135
1508
  contact: ContactRepository;
1136
1509
  account: AccountRepository;
1137
1510
  opportunity: OpportunityRepository;
1138
- events: EventTransport;
1511
+ events: CrmEventDispatcher;
1139
1512
  }
1140
1513
  declare class LeadService {
1141
1514
  private readonly leads;
@@ -1208,6 +1581,16 @@ declare const CRM_EVENTS: {
1208
1581
  readonly SUBSCRIPTION_UNSUBSCRIBED: "crm:subscription.unsubscribed";
1209
1582
  readonly SUBSCRIPTION_BOUNCED: "crm:subscription.bounced";
1210
1583
  readonly SUBSCRIPTION_COMPLAINED: "crm:subscription.complained";
1584
+ readonly SEQUENCE_CREATED: "crm:sequence.created";
1585
+ readonly SEQUENCE_ACTIVATED: "crm:sequence.active";
1586
+ readonly SEQUENCE_PAUSED: "crm:sequence.paused";
1587
+ readonly SEQUENCE_ARCHIVED: "crm:sequence.archived";
1588
+ readonly ENROLLMENT_CREATED: "crm:enrollment.created";
1589
+ readonly ENROLLMENT_STEP_SENT: "crm:enrollment.step_sent";
1590
+ readonly ENROLLMENT_PAUSED: "crm:enrollment.paused";
1591
+ readonly ENROLLMENT_RESUMED: "crm:enrollment.resumed";
1592
+ readonly ENROLLMENT_COMPLETED: "crm:enrollment.completed";
1593
+ readonly ENROLLMENT_EXITED: "crm:enrollment.exited";
1211
1594
  readonly EMAIL_EVENT_OPENED: "crm:email_event.opened";
1212
1595
  readonly EMAIL_EVENT_CLICKED: "crm:email_event.clicked";
1213
1596
  readonly EMAIL_EVENT_BOUNCED: "crm:email_event.bounced";
@@ -1226,6 +1609,8 @@ declare const CRM_EVENTS: {
1226
1609
  readonly OPPORTUNITY_EXTENDED: "crm:opportunity.extended";
1227
1610
  readonly ACTIVITY_RESCHEDULED: "crm:activity.rescheduled";
1228
1611
  readonly ACTIVITY_OUTCOME_RECORDED: "crm:activity.outcome_recorded";
1612
+ readonly SUPPRESSION_ADDED: "crm:suppression.added";
1613
+ readonly SUPPRESSION_REMOVED: "crm:suppression.removed";
1229
1614
  readonly CONVERSATION_CREATED: "crm:conversation.created";
1230
1615
  readonly CONVERSATION_ASSIGNED: "crm:conversation.assigned";
1231
1616
  readonly CONVERSATION_RESOLVED: "crm:conversation.resolved";
@@ -1474,6 +1859,19 @@ declare const SubscriptionComplained: CrmEventDefinition<z.ZodObject<{
1474
1859
  contactId: z.ZodString;
1475
1860
  campaignId: z.ZodString;
1476
1861
  }, z.core.$strip>>;
1862
+ declare const SuppressionAdded: CrmEventDefinition<z.ZodObject<{
1863
+ email: z.ZodString;
1864
+ reason: z.ZodEnum<{
1865
+ bounce: "bounce";
1866
+ complaint: "complaint";
1867
+ unsubscribe: "unsubscribe";
1868
+ manual: "manual";
1869
+ }>;
1870
+ source: z.ZodOptional<z.ZodString>;
1871
+ }, z.core.$strip>>;
1872
+ declare const SuppressionRemoved: CrmEventDefinition<z.ZodObject<{
1873
+ email: z.ZodString;
1874
+ }, z.core.$strip>>;
1477
1875
  declare const EmailEventOpened: CrmEventDefinition<z.ZodObject<{
1478
1876
  eventId: z.ZodString;
1479
1877
  kind: z.ZodString;
@@ -1542,6 +1940,44 @@ declare const MessageSent: CrmEventDefinition<z.ZodObject<{
1542
1940
  direction: z.ZodString;
1543
1941
  externalMessageId: z.ZodOptional<z.ZodString>;
1544
1942
  }, z.core.$strip>>;
1943
+ declare const SequenceCreated: CrmEventDefinition<z.ZodObject<{
1944
+ sequenceId: z.ZodString;
1945
+ name: z.ZodOptional<z.ZodString>;
1946
+ }, z.core.$strip>>;
1947
+ declare const SequenceActivated: CrmEventDefinition<z.ZodObject<{
1948
+ sequenceId: z.ZodString;
1949
+ }, z.core.$strip>>;
1950
+ declare const SequencePaused: CrmEventDefinition<z.ZodObject<{
1951
+ sequenceId: z.ZodString;
1952
+ }, z.core.$strip>>;
1953
+ declare const SequenceArchived: CrmEventDefinition<z.ZodObject<{
1954
+ sequenceId: z.ZodString;
1955
+ }, z.core.$strip>>;
1956
+ declare const EnrollmentCreated: CrmEventDefinition<z.ZodObject<{
1957
+ enrollmentId: z.ZodString;
1958
+ sequenceId: z.ZodString;
1959
+ subjectId: z.ZodString;
1960
+ subjectKind: z.ZodString;
1961
+ }, z.core.$strip>>;
1962
+ declare const EnrollmentStepSent: CrmEventDefinition<z.ZodObject<{
1963
+ enrollmentId: z.ZodString;
1964
+ sequenceId: z.ZodOptional<z.ZodString>;
1965
+ stepIndex: z.ZodNumber;
1966
+ channel: z.ZodOptional<z.ZodString>;
1967
+ }, z.core.$strip>>;
1968
+ declare const EnrollmentPaused: CrmEventDefinition<z.ZodObject<{
1969
+ enrollmentId: z.ZodString;
1970
+ }, z.core.$strip>>;
1971
+ declare const EnrollmentResumed: CrmEventDefinition<z.ZodObject<{
1972
+ enrollmentId: z.ZodString;
1973
+ }, z.core.$strip>>;
1974
+ declare const EnrollmentCompleted: CrmEventDefinition<z.ZodObject<{
1975
+ enrollmentId: z.ZodString;
1976
+ }, z.core.$strip>>;
1977
+ declare const EnrollmentExited: CrmEventDefinition<z.ZodObject<{
1978
+ enrollmentId: z.ZodString;
1979
+ exitReason: z.ZodOptional<z.ZodString>;
1980
+ }, z.core.$strip>>;
1545
1981
  declare const crmEventDefinitions: ReadonlyArray<CrmEventDefinition>;
1546
1982
  //#endregion
1547
1983
  //#region src/events/helpers.d.ts
@@ -1560,6 +1996,17 @@ declare class InProcessCrmBus implements EventTransport {
1560
1996
  close(): Promise<void>;
1561
1997
  }
1562
1998
  //#endregion
1999
+ //#region src/engine/run-unit.d.ts
2000
+ interface RunUnitConfig {
2001
+ connection: Connection;
2002
+ /** Transport used for the post-commit flush. */
2003
+ events: Pick<EventTransport, 'publish'> | undefined;
2004
+ logger?: CrmLogger | undefined;
2005
+ /** Standalone-Mongo fallback (local dev) — partial-write risk, explicit opt-in. */
2006
+ allowNonTransactional: boolean;
2007
+ }
2008
+ declare function runUnit<T>(config: RunUnitConfig, ctx: CrmContext, body: (innerCtx: CrmContext) => Promise<T>): Promise<T>;
2009
+ //#endregion
1563
2010
  //#region src/core/state-machines.d.ts
1564
2011
  /**
1565
2012
  * Declarative state machines for every CRM aggregate that has lifecycle
@@ -1581,6 +2028,8 @@ declare const OPPORTUNITY_MACHINE: _$_classytic_primitives_state_machine0.StateM
1581
2028
  declare const CAMPAIGN_MACHINE: _$_classytic_primitives_state_machine0.StateMachine<"draft" | "active" | "paused" | "completed" | "archived">;
1582
2029
  declare const SUBSCRIPTION_MACHINE: _$_classytic_primitives_state_machine0.StateMachine<"pending" | "confirmed" | "unsubscribed" | "bounced" | "complained">;
1583
2030
  declare const ACTIVITY_MACHINE: _$_classytic_primitives_state_machine0.StateMachine<"completed" | "planned" | "in_progress" | "cancelled">;
2031
+ declare const SEQUENCE_MACHINE: _$_classytic_primitives_state_machine0.StateMachine<"draft" | "active" | "paused" | "archived">;
2032
+ declare const ENROLLMENT_MACHINE: _$_classytic_primitives_state_machine0.StateMachine<"active" | "paused" | "completed" | "exited">;
1584
2033
  //#endregion
1585
2034
  //#region src/core/errors.d.ts
1586
2035
  /**
@@ -1630,6 +2079,9 @@ declare class DuplicateLeadError extends CrmError {
1630
2079
  phone?: string;
1631
2080
  });
1632
2081
  }
2082
+ declare class UnmanagedSessionError extends CrmError {
2083
+ constructor(eventType?: string);
2084
+ }
1633
2085
  declare class EmptyPipelineError extends CrmError {
1634
2086
  constructor(pipelineId: string);
1635
2087
  }
@@ -1662,6 +2114,26 @@ declare class InvalidConfirmationTokenError extends CrmError {
1662
2114
  declare class InvalidUnsubscribeTokenError extends CrmError {
1663
2115
  constructor();
1664
2116
  }
2117
+ declare class InvalidSequenceTransitionError extends CrmError {
2118
+ constructor(details: {
2119
+ from: string;
2120
+ to: string;
2121
+ sequenceId: string;
2122
+ });
2123
+ }
2124
+ declare class InvalidEnrollmentTransitionError extends CrmError {
2125
+ constructor(details: {
2126
+ from: string;
2127
+ to: string;
2128
+ enrollmentId: string;
2129
+ });
2130
+ }
2131
+ declare class AlreadyEnrolledError extends CrmError {
2132
+ constructor(details: {
2133
+ sequenceId: string;
2134
+ subjectId: string;
2135
+ });
2136
+ }
1665
2137
  //#endregion
1666
2138
  //#region src/shared/calculators/forecast.d.ts
1667
2139
  type OpportunityForecast = Pick<IOpportunityDocument, 'amount' | 'currency' | 'probability' | 'status' | 'expectedCloseAt' | 'stageId' | 'statusHistory'>;
@@ -1681,6 +2153,14 @@ interface ForecastOptions {
1681
2153
  bucket?: (o: OpportunityForecast) => string;
1682
2154
  /** Filter before bucketing. Default: open + has amount + has expectedCloseAt. */
1683
2155
  include?: (o: OpportunityForecast) => boolean;
2156
+ /**
2157
+ * IANA zone for the default month bucket (e.g. `'Asia/Dhaka'`). Without
2158
+ * it, months are cut at UTC boundaries — a deal expected to close
2159
+ * July 1, 02:00 Dhaka time (June 30, 20:00 UTC) lands in the JUNE
2160
+ * bucket. Ignored when a custom `bucket` fn is supplied. Invalid zones
2161
+ * throw (same contract as `@classytic/primitives/timezone`).
2162
+ */
2163
+ timeZone?: string;
1684
2164
  }
1685
2165
  /**
1686
2166
  * Aggregate opportunities into a forecast table — one row per bucket.
@@ -2045,6 +2525,35 @@ type SubscribeDto = z.infer<typeof subscribeSchema>;
2045
2525
  type ConfirmSubscriptionDto = z.infer<typeof confirmSubscriptionSchema>;
2046
2526
  type UnsubscribeDto = z.infer<typeof unsubscribeSchema>;
2047
2527
  //#endregion
2528
+ //#region src/validators/suppression.schema.d.ts
2529
+ declare const suppressSchema: z.ZodObject<{
2530
+ email: z.ZodString;
2531
+ reason: z.ZodEnum<{
2532
+ bounce: "bounce";
2533
+ complaint: "complaint";
2534
+ unsubscribe: "unsubscribe";
2535
+ manual: "manual";
2536
+ }>;
2537
+ source: z.ZodOptional<z.ZodString>;
2538
+ subjectKind: z.ZodOptional<z.ZodString>;
2539
+ subjectId: z.ZodOptional<z.ZodString>;
2540
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2541
+ }, z.core.$strip>;
2542
+ declare const unsuppressSchema: z.ZodObject<{
2543
+ email: z.ZodString;
2544
+ }, z.core.$strip>;
2545
+ declare const suppressionFilterSchema: z.ZodObject<{
2546
+ email: z.ZodOptional<z.ZodString>;
2547
+ reason: z.ZodOptional<z.ZodEnum<{
2548
+ bounce: "bounce";
2549
+ complaint: "complaint";
2550
+ unsubscribe: "unsubscribe";
2551
+ manual: "manual";
2552
+ }>>;
2553
+ }, z.core.$strip>;
2554
+ type SuppressDto = z.infer<typeof suppressSchema>;
2555
+ type UnsuppressDto = z.infer<typeof unsuppressSchema>;
2556
+ //#endregion
2048
2557
  //#region src/validators/activity.schema.d.ts
2049
2558
  declare const planActivitySchema: z.ZodObject<{
2050
2559
  type: z.ZodEnum<{
@@ -2220,8 +2729,101 @@ declare const emailEventFilterSchema: z.ZodObject<{
2220
2729
  messageId: z.ZodOptional<z.ZodString>;
2221
2730
  }, z.core.$strip>;
2222
2731
  type RecordEmailEventDto = z.infer<typeof recordEmailEventSchema>;
2732
+ //#endregion
2733
+ //#region src/validators/sequence.schema.d.ts
2734
+ declare const sequenceStepSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
2735
+ id: z.ZodString;
2736
+ type: z.ZodLiteral<"SEND_EMAIL">;
2737
+ name: z.ZodOptional<z.ZodString>;
2738
+ subject: z.ZodString;
2739
+ htmlBody: z.ZodString;
2740
+ fromName: z.ZodOptional<z.ZodString>;
2741
+ fromEmail: z.ZodOptional<z.ZodString>;
2742
+ }, z.core.$strip>, z.ZodObject<{
2743
+ id: z.ZodString;
2744
+ type: z.ZodLiteral<"DELAY">;
2745
+ name: z.ZodOptional<z.ZodString>;
2746
+ settings: z.ZodObject<{
2747
+ days: z.ZodOptional<z.ZodNumber>;
2748
+ hours: z.ZodOptional<z.ZodNumber>;
2749
+ minutes: z.ZodOptional<z.ZodNumber>;
2750
+ }, z.core.$strip>;
2751
+ }, z.core.$strip>], "type">;
2752
+ declare const createSequenceSchema: z.ZodObject<{
2753
+ name: z.ZodString;
2754
+ description: z.ZodOptional<z.ZodString>;
2755
+ fromName: z.ZodOptional<z.ZodString>;
2756
+ fromEmail: z.ZodOptional<z.ZodString>;
2757
+ steps: z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
2758
+ id: z.ZodString;
2759
+ type: z.ZodLiteral<"SEND_EMAIL">;
2760
+ name: z.ZodOptional<z.ZodString>;
2761
+ subject: z.ZodString;
2762
+ htmlBody: z.ZodString;
2763
+ fromName: z.ZodOptional<z.ZodString>;
2764
+ fromEmail: z.ZodOptional<z.ZodString>;
2765
+ }, z.core.$strip>, z.ZodObject<{
2766
+ id: z.ZodString;
2767
+ type: z.ZodLiteral<"DELAY">;
2768
+ name: z.ZodOptional<z.ZodString>;
2769
+ settings: z.ZodObject<{
2770
+ days: z.ZodOptional<z.ZodNumber>;
2771
+ hours: z.ZodOptional<z.ZodNumber>;
2772
+ minutes: z.ZodOptional<z.ZodNumber>;
2773
+ }, z.core.$strip>;
2774
+ }, z.core.$strip>], "type">>>;
2775
+ replyDetectionEnabled: z.ZodDefault<z.ZodBoolean>;
2776
+ tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
2777
+ ownerId: z.ZodOptional<z.ZodString>;
2778
+ metadata: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
2779
+ }, z.core.$strip>;
2780
+ declare const updateSequenceSchema: z.ZodObject<{
2781
+ name: z.ZodOptional<z.ZodString>;
2782
+ description: z.ZodOptional<z.ZodOptional<z.ZodString>>;
2783
+ fromName: z.ZodOptional<z.ZodOptional<z.ZodString>>;
2784
+ fromEmail: z.ZodOptional<z.ZodOptional<z.ZodString>>;
2785
+ steps: z.ZodOptional<z.ZodDefault<z.ZodArray<z.ZodDiscriminatedUnion<[z.ZodObject<{
2786
+ id: z.ZodString;
2787
+ type: z.ZodLiteral<"SEND_EMAIL">;
2788
+ name: z.ZodOptional<z.ZodString>;
2789
+ subject: z.ZodString;
2790
+ htmlBody: z.ZodString;
2791
+ fromName: z.ZodOptional<z.ZodString>;
2792
+ fromEmail: z.ZodOptional<z.ZodString>;
2793
+ }, z.core.$strip>, z.ZodObject<{
2794
+ id: z.ZodString;
2795
+ type: z.ZodLiteral<"DELAY">;
2796
+ name: z.ZodOptional<z.ZodString>;
2797
+ settings: z.ZodObject<{
2798
+ days: z.ZodOptional<z.ZodNumber>;
2799
+ hours: z.ZodOptional<z.ZodNumber>;
2800
+ minutes: z.ZodOptional<z.ZodNumber>;
2801
+ }, z.core.$strip>;
2802
+ }, z.core.$strip>], "type">>>>;
2803
+ replyDetectionEnabled: z.ZodOptional<z.ZodDefault<z.ZodBoolean>>;
2804
+ tags: z.ZodOptional<z.ZodOptional<z.ZodArray<z.ZodString>>>;
2805
+ ownerId: z.ZodOptional<z.ZodOptional<z.ZodString>>;
2806
+ metadata: z.ZodOptional<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>>;
2807
+ }, z.core.$strip>;
2808
+ declare const sequenceFilterSchema: z.ZodObject<{
2809
+ status: z.ZodOptional<z.ZodEnum<{
2810
+ draft: "draft";
2811
+ active: "active";
2812
+ paused: "paused";
2813
+ archived: "archived";
2814
+ }>>;
2815
+ ownerId: z.ZodOptional<z.ZodString>;
2816
+ tags: z.ZodOptional<z.ZodString>;
2817
+ search: z.ZodOptional<z.ZodString>;
2818
+ page: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
2819
+ limit: z.ZodOptional<z.ZodCoercedNumber<unknown>>;
2820
+ sort: z.ZodOptional<z.ZodString>;
2821
+ }, z.core.$strip>;
2822
+ type CreateSequenceInput = z.infer<typeof createSequenceSchema>;
2823
+ type UpdateSequenceInput = z.infer<typeof updateSequenceSchema>;
2824
+ type SequenceFilterInput = z.infer<typeof sequenceFilterSchema>;
2223
2825
  declare namespace index_d_exports {
2224
- export { AddNoteDto, CancelActivityDto, CloseLossDto, CloseWinDto, CompleteCampaignDto, ConfirmSubscriptionDto, ConvertLeadDto, CreateAccountDto, CreateCampaignDto, CreateContactDto, CreateLeadDto, CreateLossReasonDto, CreatePipelineDto, LeadFilterDto, MoveStageDto, OpenOpportunityDto, OpportunityFilterDto, PlanActivityDto, RecordEmailEventDto, StageInputDto, SubscribeDto, UnsubscribeDto, UpdateAccountDto, UpdateCampaignDto, UpdateContactDto, UpdateLeadDto, UpdateLossReasonDto, UpdateNoteDto, UpdatePipelineDto, accountFilterSchema, activityFilterSchema, addNoteSchema, campaignFilterSchema, cancelActivitySchema, closeLossSchema, closeWinSchema, completeCampaignSchema, confirmSubscriptionSchema, contactFilterSchema, convertLeadSchema, createAccountSchema, createCampaignSchema, createContactSchema, createLeadSchema, createLossReasonSchema, createPipelineSchema, currencyCodeSchema, emailEventFilterSchema, leadFilterSchema, lossReasonFilterSchema, metadataSchema, moneyAmountSchema, moveStageSchema, noteFilterSchema, objectIdLike, openOpportunitySchema, opportunityFilterSchema, pipelineFilterSchema, planActivitySchema, recordEmailEventSchema, stageInputSchemaExport, subscribeSchema, subscriptionFilterSchema, tagsSchema, unsubscribeSchema, updateAccountSchema, updateActivitySchema, updateCampaignSchema, updateContactSchema, updateLeadSchema, updateLossReasonSchema, updateNoteSchema, updatePipelineSchema };
2826
+ export { AddNoteDto, CancelActivityDto, CloseLossDto, CloseWinDto, CompleteCampaignDto, ConfirmSubscriptionDto, ConvertLeadDto, CreateAccountDto, CreateCampaignDto, CreateContactDto, CreateLeadDto, CreateLossReasonDto, CreatePipelineDto, CreateSequenceInput, LeadFilterDto, MoveStageDto, OpenOpportunityDto, OpportunityFilterDto, PlanActivityDto, RecordEmailEventDto, SequenceFilterInput, StageInputDto, SubscribeDto, SuppressDto, UnsubscribeDto, UnsuppressDto, UpdateAccountDto, UpdateCampaignDto, UpdateContactDto, UpdateLeadDto, UpdateLossReasonDto, UpdateNoteDto, UpdatePipelineDto, UpdateSequenceInput, accountFilterSchema, activityFilterSchema, addNoteSchema, campaignFilterSchema, cancelActivitySchema, closeLossSchema, closeWinSchema, completeCampaignSchema, confirmSubscriptionSchema, contactFilterSchema, convertLeadSchema, createAccountSchema, createCampaignSchema, createContactSchema, createLeadSchema, createLossReasonSchema, createPipelineSchema, createSequenceSchema, currencyCodeSchema, emailEventFilterSchema, leadFilterSchema, lossReasonFilterSchema, metadataSchema, moneyAmountSchema, moveStageSchema, noteFilterSchema, objectIdLike, openOpportunitySchema, opportunityFilterSchema, pipelineFilterSchema, planActivitySchema, recordEmailEventSchema, sequenceFilterSchema, sequenceStepSchema, stageInputSchemaExport, subscribeSchema, subscriptionFilterSchema, suppressSchema, suppressionFilterSchema, tagsSchema, unsubscribeSchema, unsuppressSchema, updateAccountSchema, updateActivitySchema, updateCampaignSchema, updateContactSchema, updateLeadSchema, updateLossReasonSchema, updateNoteSchema, updatePipelineSchema, updateSequenceSchema };
2225
2827
  }
2226
2828
  //#endregion
2227
- export { ACTIVITY_MACHINE, ACTIVITY_STATUSES, ACTIVITY_TRANSITIONS, ACTIVITY_TYPES, AccountAssigned, AccountCreated, AccountEnriched, AccountMerged, AccountRepository, AccountRepositoryDeps, AccountUpdated, ActivityCancelled, ActivityCompleted, ActivityOutcomeRecorded, ActivityPlanned, ActivityRepository, ActivityRepositoryDeps, ActivityRescheduled, type ActivityStatus, type ActivityType, CAMPAIGN_MACHINE, CAMPAIGN_STATUSES, CAMPAIGN_TRANSITIONS, CONVERSATION_CHANNELS, CONVERSATION_PARTICIPANT_KINDS, CONVERSATION_STATUSES, CRM_EVENTS, CRM_MODEL_NAMES, CampaignActivated, CampaignArchived, CampaignCompleted, CampaignCreated, CampaignPaused, CampaignRepository, CampaignRepositoryDeps, CampaignResumed, type CampaignStatus, CloseInput, ContactAssigned, ContactCreated, ContactEnriched, ContactMerged, ContactRepository, ContactRepositoryDeps, ContactUpdated, ConversationAssigned, type ConversationChannel, ConversationCreated, type ConversationParticipantKind, ConversationReopened, ConversationRepository, ConversationRepositoryDeps, ConversationResolved, type ConversationStatus, ConversionRow, ConvertLeadInput, ConvertResult, CreateCrmRepositoriesDeps, CreateModelsOptions, CrmConfig, CrmContext, CrmEngine, CrmError, CrmEventDefinition, CrmEventName, CrmEventSchema, CrmLogger, CrmModels, CrmRepositories, DuplicateCampaignError, DuplicateLeadError, DuplicateSubscriptionError, EMAIL_EVENT_KINDS, EMAIL_EVENT_SUBJECT_KINDS, EmailEventBounced, EmailEventClicked, EmailEventComplained, type EmailEventKind, EmailEventOpened, EmailEventRepository, EmailEventRepositoryDeps, EmailEventSubjectKind, EmailEventUnsubscribed, EmptyPipelineError, ForecastOptions, ForecastRow, type IAccountDocument, type IActivityDocument, type ICampaignDocument, ICampaignStatusEntry, type IContactDocument, IContactInfoEmbedded, IContactName, type IConversationDocument, type IEmailEventDocument, type ILeadDocument, ILeadStatusEntry, type ILossReasonDocument, IMessageAttachment, type IMessageDocument, type INoteDocument, type IOpportunityDocument, IOpportunityStatusEntry, type IPipelineDocument, IStageDocument, type ISubscriptionDocument, ISubscriptionStatusEntry, InProcessCrmBus, InvalidActivityTransitionError, InvalidCampaignTransitionError, InvalidConfirmationTokenError, InvalidLeadTransitionError, InvalidOpportunityTransitionError, InvalidSubscriptionTransitionError, InvalidUnsubscribeTokenError, LEAD_MACHINE, LEAD_STATUSES, LEAD_TRANSITIONS, LeadAlreadyConvertedError, LeadAssigned, LeadConverted, LeadCreated, LeadDisqualified, LeadEnriched, LeadInput, LeadRepository, LeadRepositoryDeps, LeadScored, LeadScorer, LeadService, LeadServiceDeps, type LeadStatus, LeadStatusChanged, LossReasonRepository, LossReasonRepositoryDeps, MESSAGE_DELIVERY_STATUSES, MESSAGE_DIRECTIONS, MergeAccountInput, MergeContactInput, type MessageDeliveryStatus, type MessageDirection, MessageReceived, MessageRepository, MessageRepositoryDeps, MessageSent, MoveStageInput, NotFoundError, NoteAdded, NoteRepository, NoteRepositoryDeps, OPPORTUNITY_MACHINE, OPPORTUNITY_STATUSES, OPPORTUNITY_TRANSITIONS, OpenConversationInput, OpenOpportunityInput, OpportunityAbandoned, OpportunityAmountChanged, OpportunityAssigned, OpportunityCreated, OpportunityExtended, OpportunityForecast, OpportunityLost, OpportunityRepository, OpportunityRepositoryDeps, OpportunityStageAdvanced, OpportunityStageRegressed, type OpportunityStatus, OpportunityWon, PipelineArchived, PipelineCreated, PipelineRepository, PipelineRepositoryDeps, RecordEmailEventInput, RecordMessageInput, ResolvedCrmConfig, SUBJECT_KINDS, SUBSCRIPTION_MACHINE, SUBSCRIPTION_STATUSES, SUBSCRIPTION_TRANSITIONS, SchemaBuildConfig, StageNotInPipelineError, type StatusChangeEntry, type StatusHistory, type SubjectKind, SubscribeInput, SubscriptionBounced, SubscriptionComplained, SubscriptionConfirmed, SubscriptionCreated, SubscriptionRepository, SubscriptionRepositoryDeps, type SubscriptionStatus, SubscriptionUnsubscribed, TenantFieldType, _ModelTypes, appendStatus, buildAccountSchema, buildActivitySchema, buildCampaignSchema, buildContactSchema, buildConversationSchema, buildEmailEventSchema, buildLeadSchema, buildLossReasonSchema, buildMessageSchema, buildNoteSchema, buildOpportunitySchema, buildPipelineSchema, buildSubscriptionSchema, canTransitionActivity, canTransitionCampaign, canTransitionLead, canTransitionOpportunity, canTransitionSubscription, composeScorers, createAccountModel, createActivityModel, createCampaignModel, createContactModel, createConversationModel, createCrm, createCrmModels, createCrmRepositories, createEmailEventModel, createEvent, createLeadModel, createLossReasonModel, createMessageModel, createNoteModel, createOpportunityModel, createPipelineModel, createSubscriptionModel, crmEventDefinitions, defaultLeadScorer, forecast, lastTransitionTo, latestEntry, pipelineConversion, tenantFieldDef, timeInStatus, index_d_exports as validators };
2829
+ export { ACTIVITY_MACHINE, ACTIVITY_STATUSES, ACTIVITY_TRANSITIONS, ACTIVITY_TYPES, AccountAssigned, AccountCreated, AccountEnriched, AccountMerged, AccountRepository, AccountRepositoryDeps, AccountUpdated, ActivityCancelled, ActivityCompleted, ActivityOutcomeRecorded, ActivityPlanned, ActivityRepository, ActivityRepositoryDeps, ActivityRescheduled, type ActivityStatus, type ActivityType, AlreadyEnrolledError, CAMPAIGN_MACHINE, CAMPAIGN_STATUSES, CAMPAIGN_TRANSITIONS, CONVERSATION_CHANNELS, CONVERSATION_PARTICIPANT_KINDS, CONVERSATION_STATUSES, CRM_EVENTS, CRM_MODEL_NAMES, CampaignActivated, CampaignArchived, CampaignCompleted, CampaignCreated, CampaignPaused, CampaignRepository, CampaignRepositoryDeps, CampaignResumed, type CampaignStatus, CloseInput, ContactAssigned, ContactCreated, ContactEnriched, ContactMerged, ContactRepository, ContactRepositoryDeps, ContactUpdated, ConversationAssigned, type ConversationChannel, ConversationCreated, type ConversationParticipantKind, ConversationReopened, ConversationRepository, ConversationRepositoryDeps, ConversationResolved, type ConversationStatus, ConversionRow, ConvertLeadInput, ConvertResult, CreateCrmRepositoriesDeps, CreateModelsOptions, CrmConfig, CrmContext, CrmEngine, CrmError, CrmEventDefinition, CrmEventDispatcher, type CrmEventDispatcherOptions, CrmEventName, CrmEventSchema, CrmLogger, CrmModels, CrmRepositories, DuplicateCampaignError, DuplicateLeadError, DuplicateSubscriptionError, EMAIL_EVENT_KINDS, EMAIL_EVENT_SUBJECT_KINDS, ENROLLMENT_MACHINE, ENROLLMENT_STATUSES, ENROLLMENT_SUBJECT_KINDS, ENROLLMENT_TRANSITIONS, EVENT_DERIVED_SUPPRESSION_REASONS, EmailEventBounced, EmailEventClicked, EmailEventComplained, type EmailEventKind, EmailEventOpened, EmailEventRepository, EmailEventRepositoryDeps, EmailEventSubjectKind, EmailEventUnsubscribed, EmptyPipelineError, EnrollInput, EnrollmentCompleted, EnrollmentCreated, EnrollmentExitReason, EnrollmentExited, EnrollmentPaused, EnrollmentRepository, EnrollmentRepositoryDeps, EnrollmentResumed, type EnrollmentStatus, EnrollmentStepSent, EnrollmentSubjectKind, ForecastOptions, ForecastRow, type IAccountDocument, type IActivityDocument, type ICampaignDocument, ICampaignStatusEntry, type IContactDocument, IContactInfoEmbedded, IContactName, type IConversationDocument, IDelayStep, type IEmailEventDocument, type IEnrollmentDocument, IEnrollmentStatusEntry, type ILeadDocument, ILeadEngagement, ILeadStatusEntry, type ILossReasonDocument, IMessageAttachment, type IMessageDocument, type INoteDocument, type IOpportunityDocument, IOpportunityStatusEntry, type IPipelineDocument, ISendEmailStep, type ISequenceDocument, ISequenceStatusEntry, IStageDocument, IStepResult, type ISubscriptionDocument, ISubscriptionStatusEntry, type ISuppressionDocument, InProcessCrmBus, type InternalCrmContext, InvalidActivityTransitionError, InvalidCampaignTransitionError, InvalidConfirmationTokenError, InvalidEnrollmentTransitionError, InvalidLeadTransitionError, InvalidOpportunityTransitionError, InvalidSequenceTransitionError, InvalidSubscriptionTransitionError, InvalidUnsubscribeTokenError, LEAD_MACHINE, LEAD_STATUSES, LEAD_TRANSITIONS, LeadAlreadyConvertedError, LeadAssigned, LeadConverted, LeadCreated, LeadDisqualified, LeadEngagementSignal, LeadEnriched, LeadInput, LeadRepository, LeadRepositoryDeps, LeadScored, LeadScorer, LeadService, LeadServiceDeps, type LeadStatus, LeadStatusChanged, LossReasonRepository, LossReasonRepositoryDeps, MESSAGE_DELIVERY_STATUSES, MESSAGE_DIRECTIONS, MergeAccountInput, MergeContactInput, type MessageDeliveryStatus, type MessageDirection, MessageReceived, MessageRepository, MessageRepositoryDeps, MessageSent, MoveStageInput, NotFoundError, NoteAdded, NoteRepository, NoteRepositoryDeps, OPPORTUNITY_MACHINE, OPPORTUNITY_STATUSES, OPPORTUNITY_TRANSITIONS, OpenConversationInput, OpenOpportunityInput, OpportunityAbandoned, OpportunityAmountChanged, OpportunityAssigned, OpportunityCreated, OpportunityExtended, OpportunityForecast, OpportunityLost, OpportunityRepository, OpportunityRepositoryDeps, OpportunityStageAdvanced, OpportunityStageRegressed, type OpportunityStatus, OpportunityWon, PENDING_EVENTS, PipelineArchived, PipelineCreated, PipelineRepository, PipelineRepositoryDeps, RecordEmailEventInput, RecordMessageInput, ReplySubject, ResolvedCrmConfig, type RunUnitConfig, SEQUENCE_MACHINE, SEQUENCE_STATUSES, SEQUENCE_TRANSITIONS, SUBJECT_KINDS, SUBSCRIPTION_MACHINE, SUBSCRIPTION_STATUSES, SUBSCRIPTION_TRANSITIONS, SUPPRESSION_REASONS, SchemaBuildConfig, SequenceActivated, SequenceArchived, SequenceCreated, SequencePaused, SequenceRepository, SequenceRepositoryDeps, type SequenceStatus, SequenceStep, StageNotInPipelineError, type StatusChangeEntry, type StatusHistory, StepResultStatus, type SubjectKind, SubscribeInput, SubscriptionBounced, SubscriptionComplained, SubscriptionConfirmed, SubscriptionCreated, SubscriptionRepository, SubscriptionRepositoryDeps, type SubscriptionStatus, SubscriptionUnsubscribed, SuppressInput, SuppressionAdded, type SuppressionReason, SuppressionRemoved, SuppressionRepository, SuppressionRepositoryDeps, TenantFieldType, UnmanagedSessionError, _ModelTypes, appendStatus, buildAccountSchema, buildActivitySchema, buildCampaignSchema, buildContactSchema, buildConversationSchema, buildEmailEventSchema, buildEnrollmentSchema, buildLeadSchema, buildLossReasonSchema, buildMessageSchema, buildNoteSchema, buildOpportunitySchema, buildPipelineSchema, buildSequenceSchema, buildSubscriptionSchema, buildSuppressionSchema, canTransitionActivity, canTransitionCampaign, canTransitionEnrollment, canTransitionLead, canTransitionOpportunity, canTransitionSequence, canTransitionSubscription, composeScorers, createAccountModel, createActivityModel, createCampaignModel, createContactModel, createConversationModel, createCrm, createCrmModels, createCrmRepositories, createEmailEventModel, createEvent, createLeadModel, createLossReasonModel, createMessageModel, createNoteModel, createOpportunityModel, createPipelineModel, createSubscriptionModel, crmEventDefinitions, defaultLeadScorer, flushPending, forecast, lastTransitionTo, latestEntry, pipelineConversion, runUnit, tenantFieldDef, timeInStatus, index_d_exports as validators };