@classytic/crm 0.1.1 → 0.3.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.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":["createPrimitiveEvent"],"sources":["../src/domain/errors.ts","../src/domain/ports/clock.port.ts","../src/adapters/in-memory/id-generator.ts","../src/events/event-constants.ts","../src/events/publish.ts","../src/services/account.service.ts","../src/domain/enums/activity.ts","../src/services/activity.service.ts","../src/services/contact.service.ts","../src/domain/enums/lead-status.ts","../src/services/scoring.ts","../src/services/lead.service.ts","../src/domain/enums/opportunity-status.ts","../src/services/opportunity.service.ts","../src/services/pipeline.service.ts","../src/services/forecast.ts","../src/adapters/in-memory/account-repository.ts","../src/adapters/in-memory/activity-repository.ts","../src/adapters/in-memory/contact-repository.ts","../src/adapters/in-memory/event-transport.ts","../src/adapters/in-memory/lead-repository.ts","../src/adapters/in-memory/loss-reason-repository.ts","../src/adapters/in-memory/note-repository.ts","../src/adapters/in-memory/opportunity-repository.ts","../src/adapters/in-memory/pipeline-repository.ts","../src/adapters/in-memory/outreach-port.ts","../src/events/event-catalog.ts"],"sourcesContent":["/**\n * CRM error vocabulary. Hosts catch `CrmError` at API edges.\n */\nexport class CrmError extends Error {\n readonly code: string;\n readonly details?: Record<string, unknown>;\n constructor(code: string, message: string, details?: Record<string, unknown>) {\n super(message);\n this.name = 'CrmError';\n this.code = code;\n if (details !== undefined) this.details = details;\n }\n}\n\nexport class NotFoundError extends CrmError {\n constructor(kind: string, id: string) {\n super(`${kind.toUpperCase()}_NOT_FOUND`, `${kind} '${id}' not found`, { kind, id });\n }\n}\n\nexport class InvalidLeadTransitionError extends CrmError {\n constructor(details: { from: string; to: string; leadId: string }) {\n super(\n 'INVALID_LEAD_TRANSITION',\n `Lead ${details.leadId} cannot move from '${details.from}' to '${details.to}'`,\n details,\n );\n }\n}\n\nexport class InvalidOpportunityTransitionError extends CrmError {\n constructor(details: { from: string; to: string; opportunityId: string }) {\n super(\n 'INVALID_OPPORTUNITY_TRANSITION',\n `Opportunity ${details.opportunityId} cannot move from '${details.from}' to '${details.to}'`,\n details,\n );\n }\n}\n\nexport class InvalidActivityTransitionError extends CrmError {\n constructor(details: { from: string; to: string; activityId: string }) {\n super(\n 'INVALID_ACTIVITY_TRANSITION',\n `Activity ${details.activityId} cannot move from '${details.from}' to '${details.to}'`,\n details,\n );\n }\n}\n\nexport class StageNotInPipelineError extends CrmError {\n constructor(details: { pipelineId: string; stageId: string }) {\n super(\n 'STAGE_NOT_IN_PIPELINE',\n `Stage '${details.stageId}' is not defined on pipeline '${details.pipelineId}'`,\n details,\n );\n }\n}\n\nexport class LeadAlreadyConvertedError extends CrmError {\n constructor(leadId: string) {\n super('LEAD_ALREADY_CONVERTED', `Lead '${leadId}' is already converted`, { leadId });\n }\n}\n\nexport class DuplicateLeadError extends CrmError {\n constructor(details: { email?: string; phone?: string }) {\n super('DUPLICATE_LEAD', `A lead with this email / phone already exists`, details);\n }\n}\n\nexport class EmptyPipelineError extends CrmError {\n constructor(pipelineId: string) {\n super('EMPTY_PIPELINE', `Pipeline '${pipelineId}' has no stages`, { pipelineId });\n }\n}\n","export interface Clock {\n now(): Date;\n}\n\nexport const systemClock: Clock = { now: () => new Date() };\n","import { randomUUID } from 'node:crypto';\nimport type { IdGenerator } from '../../domain/ports/id-generator.port.js';\n\nexport const cryptoIdGenerator: IdGenerator = { next: () => randomUUID() };\n\nexport function createSequentialIdGenerator(prefix = 'id_'): IdGenerator {\n let n = 0;\n return { next: () => `${prefix}${++n}` };\n}\n","/** PACKAGE_RULES rule 12: `package:resource.verb`. */\nexport const CRM_EVENTS = {\n LEAD_CREATED: 'crm:lead.created',\n LEAD_STATUS_CHANGED: 'crm:lead.status_changed',\n LEAD_SCORED: 'crm:lead.scored',\n LEAD_CONVERTED: 'crm:lead.converted',\n LEAD_DISQUALIFIED: 'crm:lead.disqualified',\n\n ACCOUNT_CREATED: 'crm:account.created',\n ACCOUNT_UPDATED: 'crm:account.updated',\n\n CONTACT_CREATED: 'crm:contact.created',\n CONTACT_UPDATED: 'crm:contact.updated',\n\n OPPORTUNITY_CREATED: 'crm:opportunity.created',\n OPPORTUNITY_STAGE_ADVANCED: 'crm:opportunity.stage_advanced',\n OPPORTUNITY_STAGE_REGRESSED: 'crm:opportunity.stage_regressed',\n OPPORTUNITY_WON: 'crm:opportunity.won',\n OPPORTUNITY_LOST: 'crm:opportunity.lost',\n OPPORTUNITY_ABANDONED: 'crm:opportunity.abandoned',\n\n PIPELINE_CREATED: 'crm:pipeline.created',\n PIPELINE_ARCHIVED: 'crm:pipeline.archived',\n\n ACTIVITY_PLANNED: 'crm:activity.planned',\n ACTIVITY_COMPLETED: 'crm:activity.completed',\n ACTIVITY_CANCELLED: 'crm:activity.cancelled',\n\n NOTE_ADDED: 'crm:note.added',\n} as const;\n\nexport type CrmEventName = (typeof CRM_EVENTS)[keyof typeof CRM_EVENTS];\n","import {\n createEvent,\n type EventMeta,\n type EventTransport,\n} from '@classytic/primitives/events';\nimport type { OutboxStore } from '@classytic/primitives/outbox';\n\n/**\n * Emit a CRM domain event through the host's infrastructure.\n *\n * Three independent seams, all optional:\n *\n * - `transport` — `EventTransport` (Kafka / SQS / Redis / in-process).\n * When present, the event is delivered via `transport.publish(event)`.\n * - `outbox` — `OutboxStore` (any backend implementing the primitives\n * contract — a host-owned mongo `event_outbox` collection, an arc\n * `repositoryAsOutboxStore(repo)` adapter, or a custom adapter). When\n * present, the event is persisted via `outbox.save(event, { session })`\n * **before** the transport publish so durable at-least-once delivery\n * is guaranteed even when the transport is down.\n * - `session` — any DB transaction handle the host is running. Threaded\n * into `outbox.save(event, { session })` so the outbox row commits\n * atomically with the host's business write. Typed `unknown` to keep\n * crm framework-agnostic.\n *\n * Error semantics:\n *\n * - Outbox errors **propagate**. When the host wraps the whole call in\n * `session.withTransaction(...)`, an outbox-save failure will abort\n * the transaction (business write rolls back with the missing outbox\n * row) — this is the desired atomicity. For the no-session case, the\n * caller handles the error.\n * - Transport errors are **logged and swallowed**. When an outbox is\n * wired the host's relay guarantees redelivery, so a flaky transport\n * must not block the request.\n */\nexport async function emitCrmEvent<T>(\n transport: EventTransport | undefined,\n outbox: OutboxStore | undefined,\n type: string,\n payload: T,\n meta: Partial<EventMeta> = {},\n session?: unknown,\n): Promise<void> {\n if (!transport && !outbox) return;\n const event = createEvent(type, payload, {\n source: 'crm',\n ...meta,\n });\n if (outbox) {\n await outbox.save(event, session !== undefined ? { session } : {});\n }\n if (transport) {\n try {\n await transport.publish(event);\n } catch (err) {\n console.error(`[crm] events.publish failed for ${event.type}:`, err);\n }\n }\n}\n","import type { EventTransport } from '@classytic/primitives/events';\nimport type { OutboxStore } from '@classytic/primitives/outbox';\nimport type { Account } from '../domain/entities/account.js';\nimport { NotFoundError } from '../domain/errors.js';\nimport type { AccountRepository } from '../domain/ports/account-repository.port.js';\nimport type { Clock } from '../domain/ports/clock.port.js';\nimport { systemClock } from '../domain/ports/clock.port.js';\nimport type { IdGenerator } from '../domain/ports/id-generator.port.js';\nimport { cryptoIdGenerator } from '../adapters/in-memory/id-generator.js';\nimport { CRM_EVENTS } from '../events/event-constants.js';\nimport { emitCrmEvent } from '../events/publish.js';\nimport type { MutationOptions } from './mutation-options.js';\n\nexport interface AccountServiceConfig {\n repo: AccountRepository;\n events?: EventTransport | undefined;\n /**\n * Optional host-owned outbox. See `emitCrmEvent` for the dispatch contract:\n * outbox save (session-bound when `options.session` is passed) is issued\n * before the transport publish so durable at-least-once delivery works\n * even when the transport is down.\n */\n outbox?: OutboxStore | undefined;\n clock?: Clock;\n ids?: IdGenerator;\n}\n\nexport interface CreateAccountInput {\n name: string;\n domain?: string;\n industry?: string;\n sizeBucket?: string;\n annualRevenue?: { amount: number; currency: string };\n ownerId?: string;\n tags?: readonly string[];\n metadata?: Record<string, unknown>;\n}\n\nexport class AccountService {\n private readonly repo: AccountRepository;\n private readonly events: EventTransport | undefined;\n private readonly outbox: OutboxStore | undefined;\n private readonly clock: Clock;\n private readonly ids: IdGenerator;\n\n constructor(config: AccountServiceConfig) {\n this.repo = config.repo;\n this.events = config.events;\n this.outbox = config.outbox;\n this.clock = config.clock ?? systemClock;\n this.ids = config.ids ?? cryptoIdGenerator;\n }\n\n async create(input: CreateAccountInput, options: MutationOptions = {}): Promise<Account> {\n const account = await this.repo.create({\n id: this.ids.next(),\n name: input.name,\n ...(input.domain !== undefined ? { domain: input.domain } : {}),\n ...(input.industry !== undefined ? { industry: input.industry } : {}),\n ...(input.sizeBucket !== undefined ? { sizeBucket: input.sizeBucket } : {}),\n ...(input.annualRevenue !== undefined ? { annualRevenue: input.annualRevenue } : {}),\n ...(input.ownerId !== undefined ? { ownerId: input.ownerId } : {}),\n ...(input.tags !== undefined ? { tags: input.tags } : {}),\n ...(input.metadata !== undefined ? { metadata: input.metadata } : {}),\n });\n if (options.emitEvents !== false) {\n await this._emit(CRM_EVENTS.ACCOUNT_CREATED, { accountId: account.id }, { resource: 'account', resourceId: account.id }, options);\n }\n return account;\n }\n\n async update(id: string, patch: Partial<Account>, options: MutationOptions = {}): Promise<Account> {\n await this._require(id);\n const updated = await this.repo.update(id, patch);\n if (options.emitEvents !== false) {\n await this._emit(CRM_EVENTS.ACCOUNT_UPDATED, { accountId: id }, { resource: 'account', resourceId: id }, options);\n }\n return updated;\n }\n\n async delete(id: string): Promise<void> {\n await this._require(id);\n await this.repo.delete(id);\n }\n\n findById(id: string): Promise<Account | null> {\n return this.repo.findById(id);\n }\n\n findByDomain(domain: string): Promise<Account | null> {\n return this.repo.findByDomain(domain);\n }\n\n list(filter?: Parameters<AccountRepository['list']>[0]): Promise<Account[]> {\n return this.repo.list(filter);\n }\n\n private async _require(id: string): Promise<Account> {\n const a = await this.repo.findById(id);\n if (!a) throw new NotFoundError('account', id);\n return a;\n }\n\n private async _emit(\n event: string,\n payload: unknown,\n meta: { resource?: string; resourceId?: string } | undefined,\n options: MutationOptions = {},\n ): Promise<void> {\n await emitCrmEvent(this.events, this.outbox, event, payload, meta, options.session);\n }\n}\n","/**\n * Activity type vocabulary. The package stores `type` as free-form\n * string so hosts can extend; these constants cover the common\n * channels that automation tooling typically keys off.\n */\nexport const ACTIVITY_TYPES = [\n 'call',\n 'email',\n 'meeting',\n 'task',\n 'note',\n 'sms',\n 'social',\n 'demo',\n 'other',\n] as const;\nexport type ActivityType = (typeof ACTIVITY_TYPES)[number];\n\nexport const ACTIVITY_STATUSES = ['planned', 'in_progress', 'completed', 'cancelled'] as const;\nexport type ActivityStatus = (typeof ACTIVITY_STATUSES)[number];\n\nexport const ACTIVITY_TRANSITIONS: Record<ActivityStatus, readonly ActivityStatus[]> = {\n planned: ['in_progress', 'completed', 'cancelled'],\n in_progress: ['completed', 'cancelled'],\n completed: [],\n cancelled: [],\n};\n\nexport function canTransitionActivity(from: ActivityStatus, to: ActivityStatus): boolean {\n return ACTIVITY_TRANSITIONS[from].includes(to);\n}\n\n/**\n * Kinds of entity an Activity can reference. Polymorphic linking lets\n * hosts log a call against a Lead, an Opportunity, a Contact, or a\n * stand-alone Account.\n */\nexport const SUBJECT_KINDS = ['lead', 'opportunity', 'contact', 'account'] as const;\nexport type SubjectKind = (typeof SUBJECT_KINDS)[number];\n","import type { EventTransport } from '@classytic/primitives/events';\nimport type { OutboxStore } from '@classytic/primitives/outbox';\nimport type { Activity } from '../domain/entities/activity.js';\nimport type { Note } from '../domain/entities/note.js';\nimport {\n canTransitionActivity,\n type ActivityStatus,\n type ActivityType,\n type SubjectKind,\n} from '../domain/enums/activity.js';\nimport {\n InvalidActivityTransitionError,\n NotFoundError,\n} from '../domain/errors.js';\nimport type { ActivityRepository } from '../domain/ports/activity-repository.port.js';\nimport type { Clock } from '../domain/ports/clock.port.js';\nimport { systemClock } from '../domain/ports/clock.port.js';\nimport type { IdGenerator } from '../domain/ports/id-generator.port.js';\nimport type { NoteRepository } from '../domain/ports/note-repository.port.js';\nimport { cryptoIdGenerator } from '../adapters/in-memory/id-generator.js';\nimport { CRM_EVENTS } from '../events/event-constants.js';\nimport { emitCrmEvent } from '../events/publish.js';\nimport type { MutationOptions } from './mutation-options.js';\n\nexport interface ActivityServiceConfig {\n repo: ActivityRepository;\n notes: NoteRepository;\n events?: EventTransport | undefined;\n /** Optional host-owned outbox. See AccountServiceConfig.outbox. */\n outbox?: OutboxStore | undefined;\n clock?: Clock;\n ids?: IdGenerator;\n}\n\nexport interface CreateActivityInput {\n type: ActivityType | string;\n subjectKind: SubjectKind;\n subjectId: string;\n subject?: string;\n body?: string;\n scheduledAt?: Date;\n ownerId?: string;\n participantIds?: readonly string[];\n externalRef?: string;\n metadata?: Record<string, unknown>;\n}\n\nexport interface CreateNoteInput {\n subjectKind: SubjectKind;\n subjectId: string;\n body: string;\n authorId?: string;\n format?: 'plain' | 'markdown';\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Polymorphic activity / note service. Activities have a lifecycle\n * (`planned → in_progress → completed | cancelled`); notes are\n * immutable-ish (create + update body, no status).\n */\nexport class ActivityService {\n private readonly repo: ActivityRepository;\n private readonly noteRepo: NoteRepository;\n private readonly events: EventTransport | undefined;\n private readonly outbox: OutboxStore | undefined;\n private readonly clock: Clock;\n private readonly ids: IdGenerator;\n\n constructor(config: ActivityServiceConfig) {\n this.repo = config.repo;\n this.noteRepo = config.notes;\n this.events = config.events;\n this.outbox = config.outbox;\n this.clock = config.clock ?? systemClock;\n this.ids = config.ids ?? cryptoIdGenerator;\n }\n\n async plan(input: CreateActivityInput, options: MutationOptions = {}): Promise<Activity> {\n const activity = await this.repo.create({\n id: this.ids.next(),\n type: input.type,\n status: 'planned',\n subjectKind: input.subjectKind,\n subjectId: input.subjectId,\n ...(input.subject !== undefined ? { subject: input.subject } : {}),\n ...(input.body !== undefined ? { body: input.body } : {}),\n ...(input.scheduledAt !== undefined ? { scheduledAt: input.scheduledAt } : {}),\n ...(input.ownerId !== undefined ? { ownerId: input.ownerId } : {}),\n ...(input.participantIds !== undefined\n ? { participantIds: input.participantIds }\n : {}),\n ...(input.externalRef !== undefined ? { externalRef: input.externalRef } : {}),\n ...(input.metadata !== undefined ? { metadata: input.metadata } : {}),\n });\n await this._emit(CRM_EVENTS.ACTIVITY_PLANNED, {\n activityId: activity.id,\n type: activity.type,\n subjectKind: activity.subjectKind,\n subjectId: activity.subjectId,\n }, { resource: 'activity', resourceId: activity.id }, options);\n return activity;\n }\n\n async start(id: string, options: MutationOptions = {}): Promise<Activity> {\n return this._transition(id, 'in_progress', {}, options);\n }\n\n async complete(id: string, completedAt?: Date, options: MutationOptions = {}): Promise<Activity> {\n const now = completedAt ?? this.clock.now();\n const updated = await this._transition(id, 'completed', { completedAt: now }, options);\n await this._emit(CRM_EVENTS.ACTIVITY_COMPLETED, {\n activityId: id,\n completedAt: now,\n }, { resource: 'activity', resourceId: id }, options);\n return updated;\n }\n\n async cancel(id: string, reason?: string, options: MutationOptions = {}): Promise<Activity> {\n const now = this.clock.now();\n const patch: Partial<Activity> = { cancelledAt: now };\n if (reason !== undefined) {\n patch.metadata = { ...(patch.metadata ?? {}), cancelReason: reason };\n }\n const updated = await this._transition(id, 'cancelled', patch, options);\n await this._emit(CRM_EVENTS.ACTIVITY_CANCELLED, { activityId: id, reason }, { resource: 'activity', resourceId: id }, options);\n return updated;\n }\n\n async addNote(input: CreateNoteInput, options: MutationOptions = {}): Promise<Note> {\n const note = await this.noteRepo.create({\n id: this.ids.next(),\n subjectKind: input.subjectKind,\n subjectId: input.subjectId,\n body: input.body,\n format: input.format ?? 'plain',\n ...(input.authorId !== undefined ? { authorId: input.authorId } : {}),\n ...(input.metadata !== undefined ? { metadata: input.metadata } : {}),\n });\n await this._emit(CRM_EVENTS.NOTE_ADDED, {\n noteId: note.id,\n subjectKind: note.subjectKind,\n subjectId: note.subjectId,\n }, { resource: 'note', resourceId: note.id }, options);\n return note;\n }\n\n listBySubject(subjectKind: SubjectKind, subjectId: string): Promise<Activity[]> {\n return this.repo.list({ subjectKind, subjectId });\n }\n\n listNotesBySubject(subjectKind: SubjectKind, subjectId: string): Promise<Note[]> {\n return this.noteRepo.listBySubject(subjectKind, subjectId);\n }\n\n findById(id: string): Promise<Activity | null> {\n return this.repo.findById(id);\n }\n\n // ── Internals ─────────────────────────────────────────────────────\n\n private async _transition(\n id: string,\n target: ActivityStatus,\n patch: Partial<Activity> = {},\n _options: MutationOptions = {},\n ): Promise<Activity> {\n const existing = await this.repo.findById(id);\n if (!existing) throw new NotFoundError('activity', id);\n if (!canTransitionActivity(existing.status, target)) {\n throw new InvalidActivityTransitionError({\n from: existing.status,\n to: target,\n activityId: id,\n });\n }\n const updated = await this.repo.casStatus(id, existing.status, target, patch);\n if (!updated) {\n throw new InvalidActivityTransitionError({\n from: existing.status,\n to: target,\n activityId: id,\n });\n }\n return updated;\n }\n\n private async _emit(\n event: string,\n payload: unknown,\n meta: { resource?: string; resourceId?: string } | undefined,\n options: MutationOptions = {},\n ): Promise<void> {\n await emitCrmEvent(this.events, this.outbox, event, payload, meta, options.session);\n }\n}\n","import type { EventTransport } from '@classytic/primitives/events';\nimport type { OutboxStore } from '@classytic/primitives/outbox';\nimport type { ContactInfo, PersonName } from '@classytic/primitives/person';\nimport type { Contact } from '../domain/entities/contact.js';\nimport { NotFoundError } from '../domain/errors.js';\nimport type { Clock } from '../domain/ports/clock.port.js';\nimport { systemClock } from '../domain/ports/clock.port.js';\nimport type { ContactRepository } from '../domain/ports/contact-repository.port.js';\nimport type { IdGenerator } from '../domain/ports/id-generator.port.js';\nimport { cryptoIdGenerator } from '../adapters/in-memory/id-generator.js';\nimport { CRM_EVENTS } from '../events/event-constants.js';\nimport { emitCrmEvent } from '../events/publish.js';\nimport type { MutationOptions } from './mutation-options.js';\n\nexport interface ContactServiceConfig {\n repo: ContactRepository;\n events?: EventTransport | undefined;\n /** Optional host-owned outbox. See AccountServiceConfig.outbox. */\n outbox?: OutboxStore | undefined;\n clock?: Clock;\n ids?: IdGenerator;\n}\n\nexport interface CreateContactInput {\n name: PersonName;\n contact?: ContactInfo;\n jobTitle?: string;\n accountId?: string;\n ownerId?: string;\n tags?: readonly string[];\n metadata?: Record<string, unknown>;\n}\n\nexport class ContactService {\n private readonly repo: ContactRepository;\n private readonly events: EventTransport | undefined;\n private readonly outbox: OutboxStore | undefined;\n private readonly clock: Clock;\n private readonly ids: IdGenerator;\n\n constructor(config: ContactServiceConfig) {\n this.repo = config.repo;\n this.events = config.events;\n this.outbox = config.outbox;\n this.clock = config.clock ?? systemClock;\n this.ids = config.ids ?? cryptoIdGenerator;\n }\n\n async create(input: CreateContactInput, options: MutationOptions = {}): Promise<Contact> {\n const contact = await this.repo.create({\n id: this.ids.next(),\n name: input.name,\n contact: input.contact ?? {},\n ...(input.jobTitle !== undefined ? { jobTitle: input.jobTitle } : {}),\n ...(input.accountId !== undefined ? { accountId: input.accountId } : {}),\n ...(input.ownerId !== undefined ? { ownerId: input.ownerId } : {}),\n ...(input.tags !== undefined ? { tags: input.tags } : {}),\n ...(input.metadata !== undefined ? { metadata: input.metadata } : {}),\n });\n if (options.emitEvents !== false) {\n await this._emit(\n CRM_EVENTS.CONTACT_CREATED,\n {\n contactId: contact.id,\n email: contact.contact.email,\n },\n { resource: 'contact', resourceId: contact.id },\n options,\n );\n }\n return contact;\n }\n\n async update(id: string, patch: Partial<Contact>, options: MutationOptions = {}): Promise<Contact> {\n await this._require(id);\n const updated = await this.repo.update(id, patch);\n if (options.emitEvents !== false) {\n await this._emit(CRM_EVENTS.CONTACT_UPDATED, { contactId: id }, { resource: 'contact', resourceId: id }, options);\n }\n return updated;\n }\n\n async delete(id: string): Promise<void> {\n await this._require(id);\n await this.repo.delete(id);\n }\n\n findById(id: string): Promise<Contact | null> {\n return this.repo.findById(id);\n }\n\n findByEmail(email: string): Promise<Contact | null> {\n return this.repo.findByEmail(email);\n }\n\n list(filter?: Parameters<ContactRepository['list']>[0]): Promise<Contact[]> {\n return this.repo.list(filter);\n }\n\n private async _require(id: string): Promise<Contact> {\n const c = await this.repo.findById(id);\n if (!c) throw new NotFoundError('contact', id);\n return c;\n }\n\n private async _emit(\n event: string,\n payload: unknown,\n meta: { resource?: string; resourceId?: string } | undefined,\n options: MutationOptions = {},\n ): Promise<void> {\n await emitCrmEvent(this.events, this.outbox, event, payload, meta, options.session);\n }\n}\n","/**\n * Lead lifecycle — from initial inquiry through conversion.\n *\n * new — just captured (web form, import, referral)\n * contacted — SDR has reached out\n * qualified — meets ICP / BANT\n * converted — turned into Contact + Account + Opportunity\n * disqualified — rejected (bad fit, spam, duplicate)\n * nurturing — not ready now; parked for later outreach\n */\nexport const LEAD_STATUSES = [\n 'new',\n 'contacted',\n 'qualified',\n 'converted',\n 'disqualified',\n 'nurturing',\n] as const;\nexport type LeadStatus = (typeof LEAD_STATUSES)[number];\n\nexport const LEAD_TRANSITIONS: Record<LeadStatus, readonly LeadStatus[]> = {\n new: ['contacted', 'qualified', 'disqualified', 'nurturing'],\n contacted: ['qualified', 'disqualified', 'nurturing'],\n qualified: ['converted', 'disqualified', 'nurturing'],\n nurturing: ['contacted', 'qualified', 'disqualified'],\n converted: [],\n disqualified: [],\n};\n\nexport function canTransitionLead(from: LeadStatus, to: LeadStatus): boolean {\n return LEAD_TRANSITIONS[from].includes(to);\n}\n","import type { Lead } from '../domain/entities/lead.js';\n\n/**\n * Pluggable lead scorer. Hosts inject whatever rubric they need —\n * firmographic model, in-app signals, ML prediction, external enrichment.\n *\n * Stay pure: the scorer must not mutate anything, not hit I/O, and\n * be deterministic given its input. Side-effects belong in the\n * caller — `LeadService.recomputeScore` runs the scorer then persists.\n */\nexport type LeadScorer = (lead: Lead) => number;\n\n/**\n * Reference implementation. Intentionally simple so hosts read it and\n * understand the shape, then replace it.\n *\n * +20 if email is present\n * +20 if phone is present\n * +20 if companyName is present\n * +10 per populated tag up to 40\n * +10 if jobTitle looks director/manager/head (case-insensitive)\n */\nexport function defaultLeadScorer(lead: Lead): number {\n let score = 0;\n if (lead.email) score += 20;\n if (lead.phone) score += 20;\n if (lead.companyName) score += 20;\n score += Math.min(40, (lead.tags?.length ?? 0) * 10);\n if (lead.jobTitle && /(director|manager|head|chief|vp|founder)/i.test(lead.jobTitle)) {\n score += 10;\n }\n return score;\n}\n\n/**\n * Compose a scoring pipeline — each rule returns an increment\n * (positive or negative). Useful when host logic is a bunch of\n * small, testable rules.\n *\n * @example\n * ```ts\n * const scorer = composeScorers(\n * (l) => (l.email ? 20 : 0),\n * (l) => (l.source === 'referral' ? 30 : 0),\n * (l) => (l.tags?.includes('enterprise') ? 50 : 0),\n * );\n * ```\n */\nexport function composeScorers(...rules: readonly LeadScorer[]): LeadScorer {\n return (lead) => rules.reduce((acc, r) => acc + r(lead), 0);\n}\n","import type { EventTransport } from '@classytic/primitives/events';\nimport type { OutboxStore } from '@classytic/primitives/outbox';\nimport type { Money } from '@classytic/primitives/money';\nimport type { Account } from '../domain/entities/account.js';\nimport type { Contact } from '../domain/entities/contact.js';\nimport type { Lead, LeadStatusEntry } from '../domain/entities/lead.js';\nimport type { Opportunity } from '../domain/entities/opportunity.js';\nimport { canTransitionLead, type LeadStatus } from '../domain/enums/lead-status.js';\nimport {\n DuplicateLeadError,\n InvalidLeadTransitionError,\n LeadAlreadyConvertedError,\n NotFoundError,\n} from '../domain/errors.js';\nimport type { Clock } from '../domain/ports/clock.port.js';\nimport { systemClock } from '../domain/ports/clock.port.js';\nimport type { IdGenerator } from '../domain/ports/id-generator.port.js';\nimport type { LeadRepository } from '../domain/ports/lead-repository.port.js';\nimport { cryptoIdGenerator } from '../adapters/in-memory/id-generator.js';\nimport { CRM_EVENTS } from '../events/event-constants.js';\nimport { emitCrmEvent } from '../events/publish.js';\nimport type { CreateAccountInput } from './account.service.js';\nimport type { CreateContactInput } from './contact.service.js';\nimport type { MutationOptions } from './mutation-options.js';\nimport type { CreateOpportunityInput } from './opportunity.service.js';\nimport { defaultLeadScorer, type LeadScorer } from './scoring.js';\n\n/**\n * Derive a `PersonName` from a Lead's flat fields. Leads usually arrive from\n * web forms where the capture is either a split `firstName`/`lastName` or a\n * single `fullName` string — we support both without forcing callers to\n * normalise upstream.\n */\nfunction splitLeadName(lead: {\n firstName?: string;\n lastName?: string;\n fullName?: string;\n}): { given: string; family: string; preferred?: string } {\n if (lead.firstName || lead.lastName) {\n return {\n given: lead.firstName ?? '',\n family: lead.lastName ?? '',\n ...(lead.fullName && lead.fullName !== `${lead.firstName ?? ''} ${lead.lastName ?? ''}`.trim()\n ? { preferred: lead.fullName }\n : {}),\n };\n }\n const parts = (lead.fullName ?? '').trim().split(/\\s+/);\n if (parts.length <= 1) {\n return { given: parts[0] ?? 'Unknown', family: '' };\n }\n const family = parts.pop() ?? '';\n return { given: parts.join(' '), family };\n}\n\nexport interface LeadAccountWriter {\n create(input: CreateAccountInput, options?: MutationOptions): Promise<Account>;\n delete?(id: string): Promise<void>;\n}\n\nexport interface LeadContactWriter {\n create(input: CreateContactInput, options?: MutationOptions): Promise<Contact>;\n delete?(id: string): Promise<void>;\n}\n\nexport interface LeadOpportunityWriter {\n create(input: CreateOpportunityInput, options?: MutationOptions): Promise<Opportunity>;\n delete?(id: string): Promise<void>;\n}\n\nexport interface LeadServiceConfig {\n repo: LeadRepository;\n contacts: LeadContactWriter;\n accounts: LeadAccountWriter;\n opportunities: LeadOpportunityWriter;\n events?: EventTransport | undefined;\n /** Optional host-owned outbox. See AccountServiceConfig.outbox. */\n outbox?: OutboxStore | undefined;\n clock?: Clock;\n ids?: IdGenerator;\n /** Override the default scorer (`defaultLeadScorer`). */\n scorer?: LeadScorer;\n /** When true (default), `create()` rejects dup emails. */\n rejectDuplicates?: boolean;\n}\n\nexport interface CreateLeadInput {\n firstName?: string;\n lastName?: string;\n fullName?: string;\n email?: string;\n phone?: string;\n companyName?: string;\n jobTitle?: string;\n source?: string;\n campaignRef?: string;\n ownerId?: string;\n tags?: readonly string[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface ConvertLeadInput {\n /** Pipeline the resulting opportunity enters. */\n pipelineId: string;\n /** Opportunity name. Defaults to `<lead.companyName> — <lead.fullName>`. */\n opportunityName?: string;\n /** Optional deal amount. */\n amount?: Money;\n expectedCloseAt?: Date;\n by?: string;\n}\n\nexport interface ConvertResult {\n lead: Lead;\n contactId: string;\n accountId?: string;\n opportunityId: string;\n}\n\n/**\n * Lead lifecycle + the crown-jewel `convert()` verb that atomically\n * spawns a Contact + Account + Opportunity and transitions the lead\n * to `converted`.\n */\nexport class LeadService {\n private readonly repo: LeadRepository;\n private readonly contacts: LeadContactWriter;\n private readonly accounts: LeadAccountWriter;\n private readonly opportunities: LeadOpportunityWriter;\n private readonly events: EventTransport | undefined;\n private readonly outbox: OutboxStore | undefined;\n private readonly clock: Clock;\n private readonly ids: IdGenerator;\n private readonly scorer: LeadScorer;\n private readonly rejectDuplicates: boolean;\n\n constructor(config: LeadServiceConfig) {\n this.repo = config.repo;\n this.contacts = config.contacts;\n this.accounts = config.accounts;\n this.opportunities = config.opportunities;\n this.events = config.events;\n this.outbox = config.outbox;\n this.clock = config.clock ?? systemClock;\n this.ids = config.ids ?? cryptoIdGenerator;\n this.scorer = config.scorer ?? defaultLeadScorer;\n this.rejectDuplicates = config.rejectDuplicates ?? true;\n }\n\n async create(input: CreateLeadInput, options: MutationOptions = {}): Promise<Lead> {\n if (this.rejectDuplicates && input.email) {\n const existing = await this.repo.findByEmail(input.email);\n if (existing) throw new DuplicateLeadError({ email: input.email });\n }\n const now = this.clock.now();\n const fullName = input.fullName ?? `${input.firstName ?? ''} ${input.lastName ?? ''}`.trim();\n const draft: Omit<Lead, 'createdAt' | 'updatedAt'> = {\n id: this.ids.next(),\n fullName: fullName || input.email || input.phone || 'Unknown',\n status: 'new',\n statusHistory: [{ status: 'new', occurredAt: now }],\n ...(input.firstName !== undefined ? { firstName: input.firstName } : {}),\n ...(input.lastName !== undefined ? { lastName: input.lastName } : {}),\n ...(input.email !== undefined ? { email: input.email } : {}),\n ...(input.phone !== undefined ? { phone: input.phone } : {}),\n ...(input.companyName !== undefined ? { companyName: input.companyName } : {}),\n ...(input.jobTitle !== undefined ? { jobTitle: input.jobTitle } : {}),\n ...(input.source !== undefined ? { source: input.source } : {}),\n ...(input.campaignRef !== undefined ? { campaignRef: input.campaignRef } : {}),\n ...(input.ownerId !== undefined ? { ownerId: input.ownerId } : {}),\n ...(input.tags !== undefined ? { tags: input.tags } : {}),\n ...(input.metadata !== undefined ? { metadata: input.metadata } : {}),\n };\n const lead = await this.repo.create(draft);\n // Auto-score on create so hosts can route immediately.\n const scored = await this._updateScore(lead, options);\n await this._emit(CRM_EVENTS.LEAD_CREATED, {\n leadId: scored.id,\n email: scored.email,\n score: scored.score,\n }, { resource: 'lead', resourceId: scored.id }, options);\n return scored;\n }\n\n async markContacted(id: string, by?: string, note?: string, options: MutationOptions = {}): Promise<Lead> {\n return this._transition(id, 'contacted', {\n ...(by !== undefined ? { by } : {}),\n ...(note !== undefined ? { note } : {}),\n }, options);\n }\n\n async qualify(id: string, by?: string, note?: string, options: MutationOptions = {}): Promise<Lead> {\n return this._transition(id, 'qualified', {\n ...(by !== undefined ? { by } : {}),\n ...(note !== undefined ? { note } : {}),\n }, options);\n }\n\n async disqualify(id: string, reason: string, by?: string, options: MutationOptions = {}): Promise<Lead> {\n const updated = await this._transition(id, 'disqualified', {\n note: reason,\n patch: { disqualifyReason: reason },\n ...(by !== undefined ? { by } : {}),\n }, options);\n await this._emit(CRM_EVENTS.LEAD_DISQUALIFIED, { leadId: id, reason }, undefined, options);\n return updated;\n }\n\n async nurture(id: string, by?: string, options: MutationOptions = {}): Promise<Lead> {\n return this._transition(id, 'nurturing', {\n ...(by !== undefined ? { by } : {}),\n }, options);\n }\n\n async convert(id: string, input: ConvertLeadInput, options: MutationOptions = {}): Promise<ConvertResult> {\n const existing = await this._require(id);\n if (existing.status === 'converted') {\n throw new LeadAlreadyConvertedError(id);\n }\n if (!canTransitionLead(existing.status, 'converted')) {\n throw new InvalidLeadTransitionError({\n from: existing.status,\n to: 'converted',\n leadId: id,\n });\n }\n\n let account: Account | undefined;\n let contact: Contact | undefined;\n let opportunity: Opportunity | undefined;\n\n try {\n // Inner mutations share the caller's session so the whole convert is\n // one atomic commit + outbox row set when wrapped in withTransaction.\n const innerOpts: MutationOptions = {\n emitEvents: false,\n ...(options.session !== undefined ? { session: options.session } : {}),\n };\n if (existing.companyName) {\n account = await this.accounts.create(\n {\n name: existing.companyName,\n ...(existing.ownerId !== undefined ? { ownerId: existing.ownerId } : {}),\n },\n innerOpts,\n );\n }\n\n const { given, family, preferred } = splitLeadName(existing);\n contact = await this.contacts.create(\n {\n name: {\n given,\n family,\n ...(preferred ? { preferred } : {}),\n },\n contact: {\n ...(existing.email !== undefined ? { email: existing.email } : {}),\n ...(existing.phone !== undefined ? { phone: existing.phone } : {}),\n },\n ...(existing.jobTitle !== undefined ? { jobTitle: existing.jobTitle } : {}),\n ...(account !== undefined ? { accountId: account.id } : {}),\n ...(existing.ownerId !== undefined ? { ownerId: existing.ownerId } : {}),\n },\n innerOpts,\n );\n\n // 3. Opportunity in the requested pipeline.\n const opportunityName =\n input.opportunityName ??\n `${existing.companyName ?? existing.fullName} — ${existing.source ?? 'New'}`;\n opportunity = await this.opportunities.create(\n {\n name: opportunityName,\n pipelineId: input.pipelineId,\n ...(account !== undefined ? { accountId: account.id } : {}),\n primaryContactId: contact.id,\n sourceLeadId: id,\n ...(input.amount !== undefined ? { amount: input.amount } : {}),\n ...(input.expectedCloseAt !== undefined ? { expectedCloseAt: input.expectedCloseAt } : {}),\n ...(existing.ownerId !== undefined ? { ownerId: existing.ownerId } : {}),\n },\n innerOpts,\n );\n\n // 4. Mark the lead converted with all cross-refs.\n const convertedAt = this.clock.now();\n const lead = await this._transition(id, 'converted', {\n patch: {\n convertedContactId: contact.id,\n ...(account !== undefined ? { convertedAccountId: account.id } : {}),\n convertedOpportunityId: opportunity.id,\n convertedAt,\n },\n ...(input.by !== undefined ? { by: input.by } : {}),\n }, options);\n\n if (account) {\n await this._emit(CRM_EVENTS.ACCOUNT_CREATED, { accountId: account.id }, { resource: 'account', resourceId: account.id }, options);\n }\n await this._emit(\n CRM_EVENTS.CONTACT_CREATED,\n { contactId: contact.id, email: contact.contact.email },\n { resource: 'contact', resourceId: contact.id },\n options,\n );\n await this._emit(\n CRM_EVENTS.OPPORTUNITY_CREATED,\n {\n opportunityId: opportunity.id,\n pipelineId: opportunity.pipelineId,\n stageId: opportunity.stageId,\n },\n { resource: 'opportunity', resourceId: opportunity.id },\n options,\n );\n\n await this._emit(CRM_EVENTS.LEAD_CONVERTED, {\n leadId: id,\n contactId: contact.id,\n accountId: account?.id,\n opportunityId: opportunity.id,\n }, { resource: 'lead', resourceId: id }, options);\n\n return {\n lead,\n contactId: contact.id,\n ...(account !== undefined ? { accountId: account.id } : {}),\n opportunityId: opportunity.id,\n };\n } catch (error) {\n if (opportunity?.id && this.opportunities.delete) {\n await this.opportunities.delete(opportunity.id);\n }\n if (contact?.id && this.contacts.delete) {\n await this.contacts.delete(contact.id);\n }\n if (account?.id && this.accounts.delete) {\n await this.accounts.delete(account.id);\n }\n throw error;\n }\n }\n\n /** Recompute score and persist. Hosts can call on update or on demand. */\n async recomputeScore(id: string, options: MutationOptions = {}): Promise<Lead> {\n const lead = await this._require(id);\n return this._updateScore(lead, options);\n }\n\n findById(id: string): Promise<Lead | null> {\n return this.repo.findById(id);\n }\n\n list(filter?: Parameters<LeadRepository['list']>[0]): Promise<Lead[]> {\n return this.repo.list(filter);\n }\n\n // ── Internals ─────────────────────────────────────────────────────\n\n private async _updateScore(lead: Lead, options: MutationOptions = {}): Promise<Lead> {\n const score = this.scorer(lead);\n if (score === lead.score) return lead;\n const updated = await this.repo.update(lead.id, { score });\n await this._emit(CRM_EVENTS.LEAD_SCORED, { leadId: lead.id, score }, { resource: 'lead', resourceId: lead.id }, options);\n return updated;\n }\n\n private async _require(id: string): Promise<Lead> {\n const l = await this.repo.findById(id);\n if (!l) throw new NotFoundError('lead', id);\n return l;\n }\n\n private async _transition(\n id: string,\n target: LeadStatus,\n opts: { patch?: Partial<Lead>; by?: string; note?: string } = {},\n options: MutationOptions = {},\n ): Promise<Lead> {\n const existing = await this._require(id);\n if (!canTransitionLead(existing.status, target)) {\n throw new InvalidLeadTransitionError({ from: existing.status, to: target, leadId: id });\n }\n const now = this.clock.now();\n const entry: LeadStatusEntry = {\n status: target,\n occurredAt: now,\n ...(opts.by !== undefined ? { by: opts.by } : {}),\n ...(opts.note !== undefined ? { note: opts.note } : {}),\n };\n const patch: Partial<Lead> = {\n ...(opts.patch ?? {}),\n statusHistory: [...existing.statusHistory, entry],\n };\n const updated = await this.repo.casStatus(id, existing.status, target, patch);\n if (!updated) {\n const latest = await this.repo.findById(id);\n throw new InvalidLeadTransitionError({\n from: latest?.status ?? existing.status,\n to: target,\n leadId: id,\n });\n }\n await this._emit(CRM_EVENTS.LEAD_STATUS_CHANGED, {\n leadId: id,\n from: existing.status,\n to: target,\n }, { resource: 'lead', resourceId: id }, options);\n return updated;\n }\n\n private async _emit(\n event: string,\n payload: unknown,\n meta: { resource?: string; resourceId?: string } | undefined,\n options: MutationOptions = {},\n ): Promise<void> {\n await emitCrmEvent(this.events, this.outbox, event, payload, meta, options.session);\n }\n}\n","/**\n * Top-level opportunity status. Movement through pipeline STAGES\n * happens while status is `open`; `won` / `lost` are terminal\n * outcomes. Re-opening a lost deal is a host-level decision —\n * convention is to clone the opportunity rather than revive the\n * terminal record.\n */\nexport const OPPORTUNITY_STATUSES = ['open', 'won', 'lost', 'abandoned'] as const;\nexport type OpportunityStatus = (typeof OPPORTUNITY_STATUSES)[number];\n\nexport const OPPORTUNITY_TRANSITIONS: Record<OpportunityStatus, readonly OpportunityStatus[]> = {\n open: ['won', 'lost', 'abandoned'],\n won: [],\n lost: [],\n abandoned: [],\n};\n\nexport function canTransitionOpportunity(\n from: OpportunityStatus,\n to: OpportunityStatus,\n): boolean {\n return OPPORTUNITY_TRANSITIONS[from].includes(to);\n}\n","import type { EventTransport } from '@classytic/primitives/events';\nimport type { OutboxStore } from '@classytic/primitives/outbox';\nimport type { Money } from '@classytic/primitives/money';\nimport type {\n Opportunity,\n OpportunityStatusEntry,\n} from '../domain/entities/opportunity.js';\nimport {\n canTransitionOpportunity,\n type OpportunityStatus,\n} from '../domain/enums/opportunity-status.js';\nimport {\n EmptyPipelineError,\n InvalidOpportunityTransitionError,\n NotFoundError,\n StageNotInPipelineError,\n} from '../domain/errors.js';\nimport type { Clock } from '../domain/ports/clock.port.js';\nimport { systemClock } from '../domain/ports/clock.port.js';\nimport type { IdGenerator } from '../domain/ports/id-generator.port.js';\nimport type { OpportunityRepository } from '../domain/ports/opportunity-repository.port.js';\nimport { cryptoIdGenerator } from '../adapters/in-memory/id-generator.js';\nimport { CRM_EVENTS } from '../events/event-constants.js';\nimport { emitCrmEvent } from '../events/publish.js';\nimport type { MutationOptions } from './mutation-options.js';\n\nexport interface OpportunityPipelinePort {\n findById(id: string): Promise<{ id: string; stages: readonly { id: string }[] } | null>;\n getStage(pipelineId: string, stageId: string): Promise<{ id: string; sequence: number; defaultProbability: number }>;\n getFirstStage(pipelineId: string): Promise<{ id: string; sequence: number; defaultProbability: number }>;\n}\n\nexport interface OpportunityServiceConfig {\n repo: OpportunityRepository;\n pipelines: OpportunityPipelinePort;\n events?: EventTransport | undefined;\n /** Optional host-owned outbox. See AccountServiceConfig.outbox. */\n outbox?: OutboxStore | undefined;\n clock?: Clock;\n ids?: IdGenerator;\n}\n\nexport interface CreateOpportunityInput {\n name: string;\n pipelineId: string;\n /** Starting stage — defaults to the pipeline's first stage. */\n stageId?: string;\n accountId?: string;\n primaryContactId?: string;\n sourceLeadId?: string;\n amount?: Money;\n /** Override the stage default. Defaults to the stage's `defaultProbability`. */\n probability?: number;\n expectedCloseAt?: Date;\n ownerId?: string;\n tags?: readonly string[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface MoveStageInput {\n stageId: string;\n /** Override probability. Defaults to the target stage's `defaultProbability`. */\n probability?: number;\n by?: string;\n note?: string;\n}\n\nexport interface CloseInput {\n amount?: Money;\n closedAt?: Date;\n by?: string;\n note?: string;\n}\n\nexport interface LoseInput extends CloseInput {\n lostReasonId?: string;\n}\n\n/**\n * Opportunity lifecycle — stage movement + outcome resolution. Stage\n * changes call the pipeline service to validate membership + default\n * probability; status transitions (`won` / `lost` / `abandoned`) are\n * terminal.\n */\nexport class OpportunityService {\n private readonly repo: OpportunityRepository;\n private readonly pipelines: OpportunityPipelinePort;\n private readonly events: EventTransport | undefined;\n private readonly outbox: OutboxStore | undefined;\n private readonly clock: Clock;\n private readonly ids: IdGenerator;\n\n constructor(config: OpportunityServiceConfig) {\n this.repo = config.repo;\n this.pipelines = config.pipelines;\n this.events = config.events;\n this.outbox = config.outbox;\n this.clock = config.clock ?? systemClock;\n this.ids = config.ids ?? cryptoIdGenerator;\n }\n\n async create(input: CreateOpportunityInput, options: MutationOptions = {}): Promise<Opportunity> {\n const pipeline = await this.pipelines.findById(input.pipelineId);\n if (!pipeline) throw new NotFoundError('pipeline', input.pipelineId);\n if (pipeline.stages.length === 0) throw new EmptyPipelineError(pipeline.id);\n\n const stage = input.stageId\n ? await this.pipelines.getStage(pipeline.id, input.stageId)\n : await this.pipelines.getFirstStage(pipeline.id);\n\n const probability = input.probability ?? stage.defaultProbability;\n const now = this.clock.now();\n const opportunity = await this.repo.create({\n id: this.ids.next(),\n name: input.name,\n pipelineId: pipeline.id,\n stageId: stage.id,\n status: 'open',\n statusHistory: [{ status: 'open', stageId: stage.id, occurredAt: now }],\n probability,\n ...(input.accountId !== undefined ? { accountId: input.accountId } : {}),\n ...(input.primaryContactId !== undefined\n ? { primaryContactId: input.primaryContactId }\n : {}),\n ...(input.sourceLeadId !== undefined ? { sourceLeadId: input.sourceLeadId } : {}),\n ...(input.amount !== undefined ? { amount: input.amount } : {}),\n ...(input.expectedCloseAt !== undefined\n ? { expectedCloseAt: input.expectedCloseAt }\n : {}),\n ...(input.ownerId !== undefined ? { ownerId: input.ownerId } : {}),\n ...(input.tags !== undefined ? { tags: input.tags } : {}),\n ...(input.metadata !== undefined ? { metadata: input.metadata } : {}),\n });\n if (options.emitEvents !== false) {\n await this._emit(\n CRM_EVENTS.OPPORTUNITY_CREATED,\n {\n opportunityId: opportunity.id,\n pipelineId: pipeline.id,\n stageId: stage.id,\n },\n { resource: 'opportunity', resourceId: opportunity.id },\n options,\n );\n }\n return opportunity;\n }\n\n async moveToStage(id: string, input: MoveStageInput, options: MutationOptions = {}): Promise<Opportunity> {\n const existing = await this._require(id);\n if (existing.status !== 'open') {\n throw new InvalidOpportunityTransitionError({\n from: existing.status,\n to: existing.status,\n opportunityId: id,\n });\n }\n const target = await this.pipelines.getStage(existing.pipelineId, input.stageId);\n const currentStage = await this.pipelines.getStage(existing.pipelineId, existing.stageId);\n const probability = input.probability ?? target.defaultProbability;\n const now = this.clock.now();\n\n const entry: OpportunityStatusEntry = {\n status: 'open',\n stageId: target.id,\n occurredAt: now,\n ...(input.by !== undefined ? { by: input.by } : {}),\n ...(input.note !== undefined ? { note: input.note } : {}),\n };\n const patch: Partial<Opportunity> = {\n probability,\n statusHistory: [...existing.statusHistory, entry],\n };\n const updated = await this.repo.casStage(id, existing.stageId, target.id, patch);\n if (!updated) throw new StageNotInPipelineError({ pipelineId: existing.pipelineId, stageId: target.id });\n\n const eventName =\n target.sequence > currentStage.sequence\n ? CRM_EVENTS.OPPORTUNITY_STAGE_ADVANCED\n : CRM_EVENTS.OPPORTUNITY_STAGE_REGRESSED;\n await this._emit(eventName, {\n opportunityId: id,\n from: { stageId: currentStage.id, sequence: currentStage.sequence },\n to: { stageId: target.id, sequence: target.sequence },\n }, { resource: 'opportunity', resourceId: id }, options);\n return updated;\n }\n\n async win(id: string, input: CloseInput = {}, options: MutationOptions = {}): Promise<Opportunity> {\n const patch: Partial<Opportunity> = {\n closedAt: input.closedAt ?? this.clock.now(),\n probability: 1,\n ...(input.amount !== undefined ? { amount: input.amount } : {}),\n };\n const updated = await this._transitionStatus(id, 'won', patch, input.by, input.note);\n await this._emit(CRM_EVENTS.OPPORTUNITY_WON, {\n opportunityId: id,\n amount: updated.amount,\n }, { resource: 'opportunity', resourceId: id }, options);\n return updated;\n }\n\n async lose(id: string, input: LoseInput = {}, options: MutationOptions = {}): Promise<Opportunity> {\n const patch: Partial<Opportunity> = {\n closedAt: input.closedAt ?? this.clock.now(),\n probability: 0,\n ...(input.lostReasonId !== undefined ? { lostReasonId: input.lostReasonId } : {}),\n };\n const updated = await this._transitionStatus(id, 'lost', patch, input.by, input.note);\n await this._emit(CRM_EVENTS.OPPORTUNITY_LOST, {\n opportunityId: id,\n lostReasonId: input.lostReasonId,\n }, { resource: 'opportunity', resourceId: id }, options);\n return updated;\n }\n\n async abandon(id: string, by?: string, note?: string, options: MutationOptions = {}): Promise<Opportunity> {\n const patch: Partial<Opportunity> = {\n closedAt: this.clock.now(),\n probability: 0,\n };\n const updated = await this._transitionStatus(id, 'abandoned', patch, by, note);\n await this._emit(CRM_EVENTS.OPPORTUNITY_ABANDONED, { opportunityId: id }, { resource: 'opportunity', resourceId: id }, options);\n return updated;\n }\n\n async delete(id: string): Promise<void> {\n await this._require(id);\n await this.repo.delete(id);\n }\n\n findById(id: string): Promise<Opportunity | null> {\n return this.repo.findById(id);\n }\n\n list(filter?: Parameters<OpportunityRepository['list']>[0]): Promise<Opportunity[]> {\n return this.repo.list(filter);\n }\n\n // ── Internals ─────────────────────────────────────────────────────\n\n private async _require(id: string): Promise<Opportunity> {\n const o = await this.repo.findById(id);\n if (!o) throw new NotFoundError('opportunity', id);\n return o;\n }\n\n private async _transitionStatus(\n id: string,\n target: OpportunityStatus,\n patch: Partial<Opportunity>,\n by?: string,\n note?: string,\n ): Promise<Opportunity> {\n const existing = await this._require(id);\n if (!canTransitionOpportunity(existing.status, target)) {\n throw new InvalidOpportunityTransitionError({\n from: existing.status,\n to: target,\n opportunityId: id,\n });\n }\n const now = this.clock.now();\n const entry: OpportunityStatusEntry = {\n status: target,\n stageId: existing.stageId,\n occurredAt: now,\n ...(by !== undefined ? { by } : {}),\n ...(note !== undefined ? { note } : {}),\n };\n const fullPatch: Partial<Opportunity> = {\n ...patch,\n statusHistory: [...existing.statusHistory, entry],\n };\n const updated = await this.repo.casStatus(id, existing.status, target, fullPatch);\n if (!updated) {\n const latest = await this.repo.findById(id);\n throw new InvalidOpportunityTransitionError({\n from: latest?.status ?? existing.status,\n to: target,\n opportunityId: id,\n });\n }\n return updated;\n }\n\n private async _emit(\n event: string,\n payload: unknown,\n meta: { resource?: string; resourceId?: string } | undefined,\n options: MutationOptions = {},\n ): Promise<void> {\n await emitCrmEvent(this.events, this.outbox, event, payload, meta, options.session);\n }\n}\n","import type { EventTransport } from '@classytic/primitives/events';\nimport type { OutboxStore } from '@classytic/primitives/outbox';\nimport type { Pipeline, Stage } from '../domain/entities/pipeline.js';\nimport { EmptyPipelineError, NotFoundError, StageNotInPipelineError } from '../domain/errors.js';\nimport type { Clock } from '../domain/ports/clock.port.js';\nimport { systemClock } from '../domain/ports/clock.port.js';\nimport type { IdGenerator } from '../domain/ports/id-generator.port.js';\nimport type { PipelineRepository } from '../domain/ports/pipeline-repository.port.js';\nimport { cryptoIdGenerator } from '../adapters/in-memory/id-generator.js';\nimport { CRM_EVENTS } from '../events/event-constants.js';\nimport { emitCrmEvent } from '../events/publish.js';\nimport type { MutationOptions } from './mutation-options.js';\n\nexport interface PipelineServiceConfig {\n repo: PipelineRepository;\n events?: EventTransport | undefined;\n /** Optional host-owned outbox. See AccountServiceConfig.outbox. */\n outbox?: OutboxStore | undefined;\n clock?: Clock;\n ids?: IdGenerator;\n}\n\nexport interface CreatePipelineInput {\n name: string;\n stages: readonly Omit<Stage, 'id'>[];\n teamRef?: string;\n metadata?: Record<string, unknown>;\n}\n\n/**\n * Pipeline lifecycle + stage helpers. The service owns stage id\n * generation so callers don't have to — create a pipeline with an\n * array of stage seeds and the service hands back the persisted\n * pipeline with ids assigned.\n */\nexport class PipelineService {\n private readonly repo: PipelineRepository;\n private readonly events: EventTransport | undefined;\n private readonly outbox: OutboxStore | undefined;\n private readonly clock: Clock;\n private readonly ids: IdGenerator;\n\n constructor(config: PipelineServiceConfig) {\n this.repo = config.repo;\n this.events = config.events;\n this.outbox = config.outbox;\n this.clock = config.clock ?? systemClock;\n this.ids = config.ids ?? cryptoIdGenerator;\n }\n\n async create(input: CreatePipelineInput, options: MutationOptions = {}): Promise<Pipeline> {\n if (input.stages.length === 0) {\n throw new EmptyPipelineError('<new>');\n }\n const id = this.ids.next();\n const stages: Stage[] = input.stages.map((s) => ({\n id: this.ids.next(),\n ...s,\n }));\n const pipeline = await this.repo.create({\n id,\n name: input.name,\n isArchived: false,\n stages,\n ...(input.teamRef !== undefined ? { teamRef: input.teamRef } : {}),\n ...(input.metadata !== undefined ? { metadata: input.metadata } : {}),\n });\n await this._emit(CRM_EVENTS.PIPELINE_CREATED, { pipelineId: pipeline.id }, { resource: 'pipeline', resourceId: pipeline.id }, options);\n return pipeline;\n }\n\n async archive(id: string, options: MutationOptions = {}): Promise<Pipeline> {\n await this._require(id);\n const updated = await this.repo.update(id, { isArchived: true });\n await this._emit(CRM_EVENTS.PIPELINE_ARCHIVED, { pipelineId: id }, { resource: 'pipeline', resourceId: id }, options);\n return updated;\n }\n\n async getStage(pipelineId: string, stageId: string): Promise<Stage> {\n const pipeline = await this._require(pipelineId);\n const stage = pipeline.stages.find((s) => s.id === stageId);\n if (!stage) throw new StageNotInPipelineError({ pipelineId, stageId });\n return stage;\n }\n\n /** First stage in the ordered pipeline (minimum `sequence`). */\n async getFirstStage(pipelineId: string): Promise<Stage> {\n const pipeline = await this._require(pipelineId);\n const stages = [...pipeline.stages].sort((a, b) => a.sequence - b.sequence);\n if (stages.length === 0) throw new EmptyPipelineError(pipelineId);\n return stages[0]!;\n }\n\n /** Next stage after `stageId` in the ordered pipeline, or `null` at the end. */\n async getNextStage(pipelineId: string, stageId: string): Promise<Stage | null> {\n const pipeline = await this._require(pipelineId);\n const stages = [...pipeline.stages].sort((a, b) => a.sequence - b.sequence);\n const idx = stages.findIndex((s) => s.id === stageId);\n if (idx === -1) throw new StageNotInPipelineError({ pipelineId, stageId });\n return stages[idx + 1] ?? null;\n }\n\n findById(id: string): Promise<Pipeline | null> {\n return this.repo.findById(id);\n }\n\n list(includeArchived?: boolean): Promise<Pipeline[]> {\n return this.repo.list(includeArchived);\n }\n\n private async _require(id: string): Promise<Pipeline> {\n const p = await this.repo.findById(id);\n if (!p) throw new NotFoundError('pipeline', id);\n return p;\n }\n\n private async _emit(\n event: string,\n payload: unknown,\n meta: { resource?: string; resourceId?: string } | undefined,\n options: MutationOptions = {},\n ): Promise<void> {\n await emitCrmEvent(this.events, this.outbox, event, payload, meta, options.session);\n }\n}\n","import type { Money } from '@classytic/primitives/money';\nimport type { Opportunity } from '../domain/entities/opportunity.js';\n\nexport interface ForecastRow {\n /** Bucket key — typically ISO month `YYYY-MM` derived from `expectedCloseAt`. */\n bucket: string;\n /** Sum of unweighted `amount`. */\n committed: number;\n /** Sum of `amount × probability`. */\n weighted: number;\n /** Count of opportunities contributing. */\n count: number;\n currency: string;\n}\n\nexport interface ForecastOptions {\n /**\n * Bucket function — given an opportunity, return a string bucket\n * key. Default is ISO-month `YYYY-MM`. Custom buckets (quarter,\n * fiscal-year, custom periods) plug in here.\n */\n bucket?: (o: Opportunity) => string;\n /**\n * Filter opportunities before bucketing. Default includes only\n * `open` opportunities with `amount` and `expectedCloseAt`.\n */\n include?: (o: Opportunity) => boolean;\n}\n\n/**\n * Aggregate opportunities into a forecast table — one row per\n * bucket (month by default). Committed is `Σ amount`; weighted is\n * `Σ amount × probability`.\n *\n * Integer-safe: sums are computed on minor-unit amounts (consistent\n * with `@classytic/primitives/money`'s integer convention). Currency\n * mismatch across a bucket throws — hosts dealing in multi-currency\n * run this once per currency after partitioning.\n */\nexport function forecast(\n opportunities: readonly Opportunity[],\n options: ForecastOptions = {},\n): ForecastRow[] {\n const bucketFn = options.bucket ?? defaultBucket;\n const include = options.include ?? defaultInclude;\n\n const rows = new Map<string, ForecastRow>();\n for (const o of opportunities) {\n if (!include(o)) continue;\n const amt = o.amount!.amount;\n const bucket = bucketFn(o);\n const existing = rows.get(bucket);\n if (existing) {\n if (existing.currency !== o.amount!.currency) {\n throw new Error(\n `Forecast bucket '${bucket}' mixes currencies (${existing.currency} + ${o.amount!.currency}). Partition by currency before calling forecast().`,\n );\n }\n rows.set(bucket, {\n ...existing,\n committed: existing.committed + amt,\n weighted: existing.weighted + Math.round(amt * o.probability),\n count: existing.count + 1,\n });\n } else {\n rows.set(bucket, {\n bucket,\n committed: amt,\n weighted: Math.round(amt * o.probability),\n count: 1,\n currency: o.amount!.currency,\n });\n }\n }\n return [...rows.values()].sort((a, b) => a.bucket.localeCompare(b.bucket));\n}\n\nfunction defaultInclude(o: Opportunity): boolean {\n return o.status === 'open' && !!o.amount && !!o.expectedCloseAt;\n}\n\nfunction defaultBucket(o: Opportunity): string {\n const d = o.expectedCloseAt!;\n const yr = d.getUTCFullYear();\n const mo = String(d.getUTCMonth() + 1).padStart(2, '0');\n return `${yr}-${mo}`;\n}\n\n/**\n * Pipeline conversion summary — how opportunities partitioned across\n * stages and final outcome. Useful for \"where do deals die?\" analysis.\n */\nexport interface ConversionRow {\n stageId: string;\n currentCount: number;\n wonFromHere: number;\n lostFromHere: number;\n conversionRate: number;\n}\n\nexport function pipelineConversion(\n opportunities: readonly Opportunity[],\n stageIds: readonly string[],\n): ConversionRow[] {\n const rows = stageIds.map((stageId): ConversionRow => {\n let currentCount = 0;\n let wonFromHere = 0;\n let lostFromHere = 0;\n for (const o of opportunities) {\n if (o.stageId === stageId && o.status === 'open') currentCount++;\n if (o.status === 'won' || o.status === 'lost') {\n // Look back through history — did this opp pass through `stageId`?\n const passed = o.statusHistory.some((h) => h.stageId === stageId);\n if (passed || o.stageId === stageId) {\n if (o.status === 'won') wonFromHere++;\n else lostFromHere++;\n }\n }\n }\n const closed = wonFromHere + lostFromHere;\n return {\n stageId,\n currentCount,\n wonFromHere,\n lostFromHere,\n conversionRate: closed > 0 ? wonFromHere / closed : 0,\n };\n });\n return rows;\n}\n","import type { Account } from '../../domain/entities/account.js';\nimport type { Clock } from '../../domain/ports/clock.port.js';\nimport { systemClock } from '../../domain/ports/clock.port.js';\nimport type {\n AccountFilter,\n AccountRepository,\n} from '../../domain/ports/account-repository.port.js';\n\nexport class InMemoryAccountRepository implements AccountRepository {\n private readonly items = new Map<string, Account>();\n\n constructor(private readonly clock: Clock = systemClock) {}\n\n async findById(id: string): Promise<Account | null> {\n return this.items.get(id) ?? null;\n }\n\n async findByDomain(domain: string): Promise<Account | null> {\n for (const a of this.items.values()) {\n if (a.domain?.toLowerCase() === domain.toLowerCase()) return a;\n }\n return null;\n }\n\n async list(filter: AccountFilter = {}): Promise<Account[]> {\n return [...this.items.values()].filter((a) => {\n if (filter.ownerId !== undefined && a.ownerId !== filter.ownerId) return false;\n if (filter.industry !== undefined && a.industry !== filter.industry) return false;\n if (filter.domain !== undefined && a.domain?.toLowerCase() !== filter.domain.toLowerCase())\n return false;\n if (filter.tags && filter.tags.length > 0) {\n const at = new Set(a.tags ?? []);\n if (!filter.tags.every((t) => at.has(t))) return false;\n }\n return true;\n });\n }\n\n async create(input: Omit<Account, 'createdAt' | 'updatedAt'>): Promise<Account> {\n const now = this.clock.now();\n const a: Account = { ...input, createdAt: now, updatedAt: now };\n this.items.set(a.id, a);\n return a;\n }\n\n async update(id: string, patch: Partial<Account>): Promise<Account> {\n const e = this.items.get(id);\n if (!e) throw new Error(`Account '${id}' not found`);\n const a: Account = { ...e, ...patch, id, updatedAt: this.clock.now() };\n this.items.set(id, a);\n return a;\n }\n\n async delete(id: string): Promise<void> {\n this.items.delete(id);\n }\n}\n","import type { Activity } from '../../domain/entities/activity.js';\nimport type { ActivityStatus } from '../../domain/enums/activity.js';\nimport type { Clock } from '../../domain/ports/clock.port.js';\nimport { systemClock } from '../../domain/ports/clock.port.js';\nimport type {\n ActivityFilter,\n ActivityRepository,\n} from '../../domain/ports/activity-repository.port.js';\n\nexport class InMemoryActivityRepository implements ActivityRepository {\n private readonly items = new Map<string, Activity>();\n\n constructor(private readonly clock: Clock = systemClock) {}\n\n async findById(id: string): Promise<Activity | null> {\n return this.items.get(id) ?? null;\n }\n\n async list(filter: ActivityFilter = {}): Promise<Activity[]> {\n return [...this.items.values()].filter((a) => {\n if (filter.subjectKind !== undefined && a.subjectKind !== filter.subjectKind) return false;\n if (filter.subjectId !== undefined && a.subjectId !== filter.subjectId) return false;\n if (filter.status !== undefined) {\n const allowed = Array.isArray(filter.status) ? filter.status : [filter.status];\n if (!allowed.includes(a.status)) return false;\n }\n if (filter.ownerId !== undefined && a.ownerId !== filter.ownerId) return false;\n if (filter.scheduledBetween !== undefined) {\n if (!a.scheduledAt) return false;\n if (\n a.scheduledAt < filter.scheduledBetween.from ||\n a.scheduledAt > filter.scheduledBetween.to\n )\n return false;\n }\n return true;\n });\n }\n\n async create(input: Omit<Activity, 'createdAt' | 'updatedAt'>): Promise<Activity> {\n const now = this.clock.now();\n const a: Activity = { ...input, createdAt: now, updatedAt: now };\n this.items.set(a.id, a);\n return a;\n }\n\n async update(id: string, patch: Partial<Activity>): Promise<Activity> {\n const e = this.items.get(id);\n if (!e) throw new Error(`Activity '${id}' not found`);\n const a: Activity = { ...e, ...patch, id, updatedAt: this.clock.now() };\n this.items.set(id, a);\n return a;\n }\n\n async casStatus(\n id: string,\n expected: ActivityStatus,\n next: ActivityStatus,\n patch: Partial<Activity> = {},\n ): Promise<Activity | null> {\n const e = this.items.get(id);\n if (!e || e.status !== expected) return null;\n const updated: Activity = {\n ...e,\n ...patch,\n id,\n status: next,\n updatedAt: this.clock.now(),\n };\n this.items.set(id, updated);\n return updated;\n }\n}\n","import type { Contact } from '../../domain/entities/contact.js';\nimport type { Clock } from '../../domain/ports/clock.port.js';\nimport { systemClock } from '../../domain/ports/clock.port.js';\nimport type {\n ContactFilter,\n ContactRepository,\n} from '../../domain/ports/contact-repository.port.js';\n\nexport class InMemoryContactRepository implements ContactRepository {\n private readonly items = new Map<string, Contact>();\n\n constructor(private readonly clock: Clock = systemClock) {}\n\n async findById(id: string): Promise<Contact | null> {\n return this.items.get(id) ?? null;\n }\n\n async findByEmail(email: string): Promise<Contact | null> {\n const needle = email.toLowerCase();\n for (const c of this.items.values()) {\n if (c.contact.email?.toLowerCase() === needle) return c;\n }\n return null;\n }\n\n async list(filter: ContactFilter = {}): Promise<Contact[]> {\n const email = filter.email?.toLowerCase();\n return [...this.items.values()].filter((c) => {\n if (filter.accountId !== undefined && c.accountId !== filter.accountId) return false;\n if (filter.ownerId !== undefined && c.ownerId !== filter.ownerId) return false;\n if (email !== undefined && c.contact.email?.toLowerCase() !== email) return false;\n if (filter.tags && filter.tags.length > 0) {\n const ct = new Set(c.tags ?? []);\n if (!filter.tags.every((t) => ct.has(t))) return false;\n }\n return true;\n });\n }\n\n async create(input: Omit<Contact, 'createdAt' | 'updatedAt'>): Promise<Contact> {\n const now = this.clock.now();\n const c: Contact = { ...input, createdAt: now, updatedAt: now };\n this.items.set(c.id, c);\n return c;\n }\n\n async update(id: string, patch: Partial<Contact>): Promise<Contact> {\n const e = this.items.get(id);\n if (!e) throw new Error(`Contact '${id}' not found`);\n const c: Contact = { ...e, ...patch, id, updatedAt: this.clock.now() };\n this.items.set(id, c);\n return c;\n }\n\n async delete(id: string): Promise<void> {\n this.items.delete(id);\n }\n}\n","import type { DomainEvent, EventHandler, EventTransport } from '@classytic/primitives/events';\nimport { matchEventPattern } from '@classytic/primitives/events';\n\nexport type RecordedEvent = DomainEvent;\n\nexport class InMemoryEventTransport implements EventTransport {\n readonly name = 'crm-in-memory';\n readonly events: RecordedEvent[] = [];\n private readonly subscribers: Array<{ pattern: string; handler: EventHandler }> = [];\n\n async publish(event: DomainEvent): Promise<void> {\n this.events.push(event);\n for (const subscriber of this.subscribers) {\n if (!matchEventPattern(subscriber.pattern, event.type)) continue;\n await subscriber.handler(event);\n }\n }\n\n async subscribe(pattern: string, handler: EventHandler): Promise<() => void> {\n const entry = { pattern, handler };\n this.subscribers.push(entry);\n return async () => {\n const idx = this.subscribers.indexOf(entry);\n if (idx >= 0) this.subscribers.splice(idx, 1);\n };\n }\n}\n","import type { Lead } from '../../domain/entities/lead.js';\nimport type { LeadStatus } from '../../domain/enums/lead-status.js';\nimport type { Clock } from '../../domain/ports/clock.port.js';\nimport { systemClock } from '../../domain/ports/clock.port.js';\nimport type {\n LeadFilter,\n LeadRepository,\n} from '../../domain/ports/lead-repository.port.js';\n\nexport class InMemoryLeadRepository implements LeadRepository {\n private readonly items = new Map<string, Lead>();\n\n constructor(private readonly clock: Clock = systemClock) {}\n\n async findById(id: string): Promise<Lead | null> {\n return this.items.get(id) ?? null;\n }\n\n async findByEmail(email: string): Promise<Lead | null> {\n for (const l of this.items.values()) {\n if (l.email?.toLowerCase() === email.toLowerCase()) return l;\n }\n return null;\n }\n\n async list(filter: LeadFilter = {}): Promise<Lead[]> {\n return [...this.items.values()].filter((l) => {\n if (filter.status !== undefined) {\n const allowed = Array.isArray(filter.status) ? filter.status : [filter.status];\n if (!allowed.includes(l.status)) return false;\n }\n if (filter.ownerId !== undefined && l.ownerId !== filter.ownerId) return false;\n if (filter.source !== undefined && l.source !== filter.source) return false;\n if (filter.minScore !== undefined && (l.score ?? 0) < filter.minScore) return false;\n return true;\n });\n }\n\n async create(input: Omit<Lead, 'createdAt' | 'updatedAt'>): Promise<Lead> {\n const now = this.clock.now();\n const l: Lead = { ...input, createdAt: now, updatedAt: now };\n this.items.set(l.id, l);\n return l;\n }\n\n async update(id: string, patch: Partial<Lead>): Promise<Lead> {\n const e = this.items.get(id);\n if (!e) throw new Error(`Lead '${id}' not found`);\n const l: Lead = { ...e, ...patch, id, updatedAt: this.clock.now() };\n this.items.set(id, l);\n return l;\n }\n\n async casStatus(\n id: string,\n expected: LeadStatus,\n next: LeadStatus,\n patch: Partial<Lead> = {},\n ): Promise<Lead | null> {\n const e = this.items.get(id);\n if (!e || e.status !== expected) return null;\n const updated: Lead = {\n ...e,\n ...patch,\n id,\n status: next,\n updatedAt: this.clock.now(),\n };\n this.items.set(id, updated);\n return updated;\n }\n}\n","import type { LossReason } from '../../domain/entities/loss-reason.js';\nimport type { Clock } from '../../domain/ports/clock.port.js';\nimport { systemClock } from '../../domain/ports/clock.port.js';\nimport type { LossReasonRepository } from '../../domain/ports/loss-reason-repository.port.js';\n\nexport class InMemoryLossReasonRepository implements LossReasonRepository {\n private readonly items = new Map<string, LossReason>();\n\n constructor(private readonly clock: Clock = systemClock) {}\n\n async findById(id: string): Promise<LossReason | null> {\n return this.items.get(id) ?? null;\n }\n\n async list(activeOnly = true): Promise<LossReason[]> {\n return [...this.items.values()].filter((r) => (activeOnly ? r.active : true));\n }\n\n async create(input: Omit<LossReason, 'createdAt' | 'updatedAt'>): Promise<LossReason> {\n const now = this.clock.now();\n const r: LossReason = { ...input, createdAt: now, updatedAt: now };\n this.items.set(r.id, r);\n return r;\n }\n\n async update(id: string, patch: Partial<LossReason>): Promise<LossReason> {\n const e = this.items.get(id);\n if (!e) throw new Error(`LossReason '${id}' not found`);\n const r: LossReason = { ...e, ...patch, id, updatedAt: this.clock.now() };\n this.items.set(id, r);\n return r;\n }\n}\n","import type { Note } from '../../domain/entities/note.js';\nimport type { SubjectKind } from '../../domain/enums/activity.js';\nimport type { Clock } from '../../domain/ports/clock.port.js';\nimport { systemClock } from '../../domain/ports/clock.port.js';\nimport type { NoteRepository } from '../../domain/ports/note-repository.port.js';\n\nexport class InMemoryNoteRepository implements NoteRepository {\n private readonly items = new Map<string, Note>();\n\n constructor(private readonly clock: Clock = systemClock) {}\n\n async findById(id: string): Promise<Note | null> {\n return this.items.get(id) ?? null;\n }\n\n async listBySubject(subjectKind: SubjectKind, subjectId: string): Promise<Note[]> {\n return [...this.items.values()].filter(\n (n) => n.subjectKind === subjectKind && n.subjectId === subjectId,\n );\n }\n\n async create(input: Omit<Note, 'createdAt' | 'updatedAt'>): Promise<Note> {\n const now = this.clock.now();\n const n: Note = { ...input, createdAt: now, updatedAt: now };\n this.items.set(n.id, n);\n return n;\n }\n\n async update(id: string, patch: Partial<Note>): Promise<Note> {\n const e = this.items.get(id);\n if (!e) throw new Error(`Note '${id}' not found`);\n const n: Note = { ...e, ...patch, id, updatedAt: this.clock.now() };\n this.items.set(id, n);\n return n;\n }\n\n async delete(id: string): Promise<void> {\n this.items.delete(id);\n }\n}\n","import type { Opportunity } from '../../domain/entities/opportunity.js';\nimport type { OpportunityStatus } from '../../domain/enums/opportunity-status.js';\nimport type { Clock } from '../../domain/ports/clock.port.js';\nimport { systemClock } from '../../domain/ports/clock.port.js';\nimport type {\n OpportunityFilter,\n OpportunityRepository,\n} from '../../domain/ports/opportunity-repository.port.js';\n\nexport class InMemoryOpportunityRepository implements OpportunityRepository {\n private readonly items = new Map<string, Opportunity>();\n\n constructor(private readonly clock: Clock = systemClock) {}\n\n async findById(id: string): Promise<Opportunity | null> {\n return this.items.get(id) ?? null;\n }\n\n async list(filter: OpportunityFilter = {}): Promise<Opportunity[]> {\n return [...this.items.values()].filter((o) => {\n if (filter.status !== undefined) {\n const allowed = Array.isArray(filter.status) ? filter.status : [filter.status];\n if (!allowed.includes(o.status)) return false;\n }\n if (filter.pipelineId !== undefined && o.pipelineId !== filter.pipelineId) return false;\n if (filter.stageId !== undefined && o.stageId !== filter.stageId) return false;\n if (filter.ownerId !== undefined && o.ownerId !== filter.ownerId) return false;\n if (filter.accountId !== undefined && o.accountId !== filter.accountId) return false;\n if (filter.closingBetween !== undefined) {\n if (!o.expectedCloseAt) return false;\n if (\n o.expectedCloseAt < filter.closingBetween.from ||\n o.expectedCloseAt > filter.closingBetween.to\n )\n return false;\n }\n return true;\n });\n }\n\n async create(input: Omit<Opportunity, 'createdAt' | 'updatedAt'>): Promise<Opportunity> {\n const now = this.clock.now();\n const o: Opportunity = { ...input, createdAt: now, updatedAt: now };\n this.items.set(o.id, o);\n return o;\n }\n\n async update(id: string, patch: Partial<Opportunity>): Promise<Opportunity> {\n const e = this.items.get(id);\n if (!e) throw new Error(`Opportunity '${id}' not found`);\n const o: Opportunity = { ...e, ...patch, id, updatedAt: this.clock.now() };\n this.items.set(id, o);\n return o;\n }\n\n async delete(id: string): Promise<void> {\n this.items.delete(id);\n }\n\n async casStatus(\n id: string,\n expected: OpportunityStatus,\n next: OpportunityStatus,\n patch: Partial<Opportunity> = {},\n ): Promise<Opportunity | null> {\n const e = this.items.get(id);\n if (!e || e.status !== expected) return null;\n const updated: Opportunity = {\n ...e,\n ...patch,\n id,\n status: next,\n updatedAt: this.clock.now(),\n };\n this.items.set(id, updated);\n return updated;\n }\n\n async casStage(\n id: string,\n expectedStageId: string,\n nextStageId: string,\n patch: Partial<Opportunity> = {},\n ): Promise<Opportunity | null> {\n const e = this.items.get(id);\n if (!e || e.stageId !== expectedStageId) return null;\n const updated: Opportunity = {\n ...e,\n ...patch,\n id,\n stageId: nextStageId,\n updatedAt: this.clock.now(),\n };\n this.items.set(id, updated);\n return updated;\n }\n}\n","import type { Pipeline } from '../../domain/entities/pipeline.js';\nimport type { Clock } from '../../domain/ports/clock.port.js';\nimport { systemClock } from '../../domain/ports/clock.port.js';\nimport type { PipelineRepository } from '../../domain/ports/pipeline-repository.port.js';\n\nexport class InMemoryPipelineRepository implements PipelineRepository {\n private readonly items = new Map<string, Pipeline>();\n\n constructor(private readonly clock: Clock = systemClock) {}\n\n async findById(id: string): Promise<Pipeline | null> {\n return this.items.get(id) ?? null;\n }\n\n async list(includeArchived = false): Promise<Pipeline[]> {\n return [...this.items.values()].filter((p) => includeArchived || !p.isArchived);\n }\n\n async create(input: Omit<Pipeline, 'createdAt' | 'updatedAt'>): Promise<Pipeline> {\n const now = this.clock.now();\n const p: Pipeline = { ...input, createdAt: now, updatedAt: now };\n this.items.set(p.id, p);\n return p;\n }\n\n async update(id: string, patch: Partial<Pipeline>): Promise<Pipeline> {\n const e = this.items.get(id);\n if (!e) throw new Error(`Pipeline '${id}' not found`);\n const p: Pipeline = { ...e, ...patch, id, updatedAt: this.clock.now() };\n this.items.set(id, p);\n return p;\n }\n}\n","import type {\n OutreachPort,\n OutreachSendRequest,\n OutreachSendResult,\n} from '../../domain/ports/outreach.port.js';\n\nexport class NullOutreachPort implements OutreachPort {\n private counter = 0;\n async send(_request: OutreachSendRequest): Promise<OutreachSendResult> {\n return {\n providerMessageId: `null_msg_${++this.counter}`,\n acceptedAt: new Date(),\n };\n }\n}\n\nexport interface RecordedOutreach extends OutreachSendRequest, OutreachSendResult {}\n\nexport class InMemoryOutreachPort implements OutreachPort {\n readonly sent: RecordedOutreach[] = [];\n private counter = 0;\n constructor(private readonly nowMs: () => number = () => Date.now()) {}\n\n async send(request: OutreachSendRequest): Promise<OutreachSendResult> {\n const res: OutreachSendResult = {\n providerMessageId: `msg_${++this.counter}`,\n acceptedAt: new Date(this.nowMs()),\n };\n this.sent.push({ ...request, ...res });\n return res;\n }\n}\n","/**\n * CRM event catalog — Zod-source-of-truth definitions for every\n * `crm:*` event.\n *\n * Each definition exposes:\n * - `.zodSchema` — source of truth, used by host code's `.safeParse()`\n * - `.schema` — JSON Schema derived via `z.toJSONSchema()`, consumed\n * by Arc's EventRegistry + OpenAPI plugin\n * - `.create(...)` — DomainEvent envelope builder, structurally compatible\n * with `@classytic/arc`'s `EventDefinitionOutput`\n *\n * Structurally compatible with Arc 2.10's `EventRegistry` — hosts register\n * `crmEventDefinitions` directly, no adapter code. CRM does NOT import from\n * `@classytic/arc` (PACKAGE_RULES §11); compatibility is purely structural.\n *\n * Timestamps are modelled as `z.iso.datetime()` — events cross the wire and\n * JSON Schema cannot represent `Date` (PACKAGE_RULES §18.5 + §25). Subscribers\n * that need a `Date` instance call `new Date(payload.completedAt)`.\n *\n * @example Wiring into an Arc app\n * ```ts\n * import { createEventRegistry } from '@classytic/arc/events';\n * import { crmEventDefinitions } from '@classytic/crm';\n *\n * const registry = createEventRegistry();\n * for (const def of crmEventDefinitions) registry.register(def);\n *\n * const app = await createApp({\n * arcPlugins: { events: { registry, validateMode: 'reject' } },\n * });\n * ```\n */\nimport { z } from 'zod';\nimport type { DomainEvent } from '@classytic/primitives/events';\nimport { createEvent as createPrimitiveEvent } from '@classytic/primitives/events';\nimport { CRM_EVENTS } from './event-constants.js';\n\n// ─── Definition shape (structurally compatible with Arc EventRegistry) ────\n\nexport interface CrmEventSchema {\n type: 'object';\n properties?: Record<string, { type?: string; format?: string; [key: string]: unknown }>;\n required?: string[];\n [key: string]: unknown;\n}\n\nexport interface CrmEventDefinition<TSchema extends z.ZodType = z.ZodType> {\n readonly name: string;\n readonly version: number;\n readonly description?: string;\n readonly schema: CrmEventSchema;\n readonly zodSchema: TSchema;\n create(\n payload: z.infer<TSchema>,\n meta?: Partial<DomainEvent['meta']>,\n ): DomainEvent<z.infer<TSchema>>;\n readonly __payload?: z.infer<TSchema>;\n}\n\nexport type CrmEventPayloadOf<D> =\n D extends CrmEventDefinition<infer S> ? z.infer<S> : never;\n\nfunction defineCrmEvent<TSchema extends z.ZodType>(input: {\n name: string;\n version?: number;\n description?: string;\n zodSchema: TSchema;\n}): CrmEventDefinition<TSchema> {\n const { name, version = 1, description, zodSchema } = input;\n const def: CrmEventDefinition<TSchema> = {\n name,\n version,\n schema: z.toJSONSchema(zodSchema) as CrmEventSchema,\n zodSchema,\n create(payload, meta) {\n return createPrimitiveEvent(name, payload, { source: 'crm', ...meta });\n },\n };\n if (description !== undefined) {\n (def as { description: string }).description = description;\n }\n return def;\n}\n\n// ─── Reusable fragments ───────────────────────────────────────────────────\n\nconst money = z.object({\n amount: z.number().nonnegative(),\n currency: z.string().length(3),\n});\n\nconst subjectKind = z.enum(['lead', 'contact', 'account', 'opportunity']);\n\nconst stageRef = z.object({\n stageId: z.string(),\n sequence: z.number().int().nonnegative(),\n});\n\n// ─── Lead ─────────────────────────────────────────────────────────────────\n\nconst leadCreatedSchema = z.object({\n leadId: z.string(),\n email: z.string().optional(),\n score: z.number().optional(),\n});\n\nconst leadStatusChangedSchema = z.object({\n leadId: z.string(),\n from: z.string(),\n to: z.string(),\n});\n\nconst leadScoredSchema = z.object({\n leadId: z.string(),\n score: z.number(),\n});\n\nconst leadConvertedSchema = z.object({\n leadId: z.string(),\n contactId: z.string(),\n accountId: z.string().optional(),\n opportunityId: z.string(),\n});\n\nconst leadDisqualifiedSchema = z.object({\n leadId: z.string(),\n reason: z.string(),\n});\n\n// ─── Account ──────────────────────────────────────────────────────────────\n\nconst accountCreatedSchema = z.object({\n accountId: z.string(),\n});\n\nconst accountUpdatedSchema = z.object({\n accountId: z.string(),\n});\n\n// ─── Contact ──────────────────────────────────────────────────────────────\n\nconst contactCreatedSchema = z.object({\n contactId: z.string(),\n email: z.string().optional(),\n});\n\nconst contactUpdatedSchema = z.object({\n contactId: z.string(),\n});\n\n// ─── Opportunity ──────────────────────────────────────────────────────────\n\nconst opportunityCreatedSchema = z.object({\n opportunityId: z.string(),\n pipelineId: z.string(),\n stageId: z.string(),\n});\n\nconst opportunityStageAdvancedSchema = z.object({\n opportunityId: z.string(),\n from: stageRef,\n to: stageRef,\n});\n\nconst opportunityStageRegressedSchema = opportunityStageAdvancedSchema;\n\nconst opportunityWonSchema = z.object({\n opportunityId: z.string(),\n amount: money.optional(),\n});\n\nconst opportunityLostSchema = z.object({\n opportunityId: z.string(),\n lostReasonId: z.string().optional(),\n});\n\nconst opportunityAbandonedSchema = z.object({\n opportunityId: z.string(),\n});\n\n// ─── Pipeline ─────────────────────────────────────────────────────────────\n\nconst pipelineCreatedSchema = z.object({\n pipelineId: z.string(),\n});\n\nconst pipelineArchivedSchema = z.object({\n pipelineId: z.string(),\n});\n\n// ─── Activity / Note ──────────────────────────────────────────────────────\n\nconst activityPlannedSchema = z.object({\n activityId: z.string(),\n type: z.string(),\n subjectKind,\n subjectId: z.string(),\n});\n\nconst activityCompletedSchema = z.object({\n activityId: z.string(),\n completedAt: z.iso.datetime(),\n});\n\nconst activityCancelledSchema = z.object({\n activityId: z.string(),\n reason: z.string().optional(),\n});\n\nconst noteAddedSchema = z.object({\n noteId: z.string(),\n subjectKind,\n subjectId: z.string(),\n});\n\n// ─── Inferred payload types (exported for host subscribers) ──────────────\n\nexport type LeadCreatedPayload = z.infer<typeof leadCreatedSchema>;\nexport type LeadStatusChangedPayload = z.infer<typeof leadStatusChangedSchema>;\nexport type LeadScoredPayload = z.infer<typeof leadScoredSchema>;\nexport type LeadConvertedPayload = z.infer<typeof leadConvertedSchema>;\nexport type LeadDisqualifiedPayload = z.infer<typeof leadDisqualifiedSchema>;\nexport type AccountCreatedPayload = z.infer<typeof accountCreatedSchema>;\nexport type AccountUpdatedPayload = z.infer<typeof accountUpdatedSchema>;\nexport type ContactCreatedPayload = z.infer<typeof contactCreatedSchema>;\nexport type ContactUpdatedPayload = z.infer<typeof contactUpdatedSchema>;\nexport type OpportunityCreatedPayload = z.infer<typeof opportunityCreatedSchema>;\nexport type OpportunityStageAdvancedPayload = z.infer<typeof opportunityStageAdvancedSchema>;\nexport type OpportunityStageRegressedPayload = z.infer<typeof opportunityStageRegressedSchema>;\nexport type OpportunityWonPayload = z.infer<typeof opportunityWonSchema>;\nexport type OpportunityLostPayload = z.infer<typeof opportunityLostSchema>;\nexport type OpportunityAbandonedPayload = z.infer<typeof opportunityAbandonedSchema>;\nexport type PipelineCreatedPayload = z.infer<typeof pipelineCreatedSchema>;\nexport type PipelineArchivedPayload = z.infer<typeof pipelineArchivedSchema>;\nexport type ActivityPlannedPayload = z.infer<typeof activityPlannedSchema>;\nexport type ActivityCompletedPayload = z.infer<typeof activityCompletedSchema>;\nexport type ActivityCancelledPayload = z.infer<typeof activityCancelledSchema>;\nexport type NoteAddedPayload = z.infer<typeof noteAddedSchema>;\n\n// ─── Event definitions ────────────────────────────────────────────────────\n\nexport const LeadCreated = defineCrmEvent({\n name: CRM_EVENTS.LEAD_CREATED,\n description: 'A new lead was captured and initial score computed.',\n zodSchema: leadCreatedSchema,\n});\n\nexport const LeadStatusChanged = defineCrmEvent({\n name: CRM_EVENTS.LEAD_STATUS_CHANGED,\n description: 'A lead transitioned between lifecycle statuses.',\n zodSchema: leadStatusChangedSchema,\n});\n\nexport const LeadScored = defineCrmEvent({\n name: CRM_EVENTS.LEAD_SCORED,\n description: 'A lead score was recomputed and persisted.',\n zodSchema: leadScoredSchema,\n});\n\nexport const LeadConverted = defineCrmEvent({\n name: CRM_EVENTS.LEAD_CONVERTED,\n description: 'A lead was converted into a Contact + (optional) Account + Opportunity.',\n zodSchema: leadConvertedSchema,\n});\n\nexport const LeadDisqualified = defineCrmEvent({\n name: CRM_EVENTS.LEAD_DISQUALIFIED,\n description: 'A lead was disqualified with a reason.',\n zodSchema: leadDisqualifiedSchema,\n});\n\nexport const AccountCreated = defineCrmEvent({\n name: CRM_EVENTS.ACCOUNT_CREATED,\n description: 'A new account was created.',\n zodSchema: accountCreatedSchema,\n});\n\nexport const AccountUpdated = defineCrmEvent({\n name: CRM_EVENTS.ACCOUNT_UPDATED,\n description: 'An account record was updated.',\n zodSchema: accountUpdatedSchema,\n});\n\nexport const ContactCreated = defineCrmEvent({\n name: CRM_EVENTS.CONTACT_CREATED,\n description: 'A new contact was created.',\n zodSchema: contactCreatedSchema,\n});\n\nexport const ContactUpdated = defineCrmEvent({\n name: CRM_EVENTS.CONTACT_UPDATED,\n description: 'A contact record was updated.',\n zodSchema: contactUpdatedSchema,\n});\n\nexport const OpportunityCreated = defineCrmEvent({\n name: CRM_EVENTS.OPPORTUNITY_CREATED,\n description: 'A new opportunity was created in a pipeline at a starting stage.',\n zodSchema: opportunityCreatedSchema,\n});\n\nexport const OpportunityStageAdvanced = defineCrmEvent({\n name: CRM_EVENTS.OPPORTUNITY_STAGE_ADVANCED,\n description: 'An opportunity moved to a later stage in its pipeline.',\n zodSchema: opportunityStageAdvancedSchema,\n});\n\nexport const OpportunityStageRegressed = defineCrmEvent({\n name: CRM_EVENTS.OPPORTUNITY_STAGE_REGRESSED,\n description: 'An opportunity moved back to an earlier stage in its pipeline.',\n zodSchema: opportunityStageRegressedSchema,\n});\n\nexport const OpportunityWon = defineCrmEvent({\n name: CRM_EVENTS.OPPORTUNITY_WON,\n description: 'An opportunity closed as won.',\n zodSchema: opportunityWonSchema,\n});\n\nexport const OpportunityLost = defineCrmEvent({\n name: CRM_EVENTS.OPPORTUNITY_LOST,\n description: 'An opportunity closed as lost.',\n zodSchema: opportunityLostSchema,\n});\n\nexport const OpportunityAbandoned = defineCrmEvent({\n name: CRM_EVENTS.OPPORTUNITY_ABANDONED,\n description: 'An opportunity was abandoned without a close outcome.',\n zodSchema: opportunityAbandonedSchema,\n});\n\nexport const PipelineCreated = defineCrmEvent({\n name: CRM_EVENTS.PIPELINE_CREATED,\n description: 'A new pipeline was created.',\n zodSchema: pipelineCreatedSchema,\n});\n\nexport const PipelineArchived = defineCrmEvent({\n name: CRM_EVENTS.PIPELINE_ARCHIVED,\n description: 'A pipeline was archived.',\n zodSchema: pipelineArchivedSchema,\n});\n\nexport const ActivityPlanned = defineCrmEvent({\n name: CRM_EVENTS.ACTIVITY_PLANNED,\n description: 'An activity was planned against a polymorphic subject.',\n zodSchema: activityPlannedSchema,\n});\n\nexport const ActivityCompleted = defineCrmEvent({\n name: CRM_EVENTS.ACTIVITY_COMPLETED,\n description: 'An activity was marked completed.',\n zodSchema: activityCompletedSchema,\n});\n\nexport const ActivityCancelled = defineCrmEvent({\n name: CRM_EVENTS.ACTIVITY_CANCELLED,\n description: 'An activity was cancelled.',\n zodSchema: activityCancelledSchema,\n});\n\nexport const NoteAdded = defineCrmEvent({\n name: CRM_EVENTS.NOTE_ADDED,\n description: 'A note was attached to a polymorphic subject.',\n zodSchema: noteAddedSchema,\n});\n\n// ─── Aggregate catalog ────────────────────────────────────────────────────\n\n/**\n * Every CRM event defined in the package — pass to Arc's `EventRegistry`.\n * Hosts wire ONE array; the whole `crm:*` namespace becomes introspectable\n * via OpenAPI and auto-validated at publish time when\n * `eventPlugin({ validateMode: 'reject' })` is set.\n */\nexport const crmEventDefinitions: ReadonlyArray<CrmEventDefinition> = [\n LeadCreated,\n LeadStatusChanged,\n LeadScored,\n LeadConverted,\n LeadDisqualified,\n AccountCreated,\n AccountUpdated,\n ContactCreated,\n ContactUpdated,\n OpportunityCreated,\n OpportunityStageAdvanced,\n OpportunityStageRegressed,\n OpportunityWon,\n OpportunityLost,\n OpportunityAbandoned,\n PipelineCreated,\n PipelineArchived,\n ActivityPlanned,\n ActivityCompleted,\n ActivityCancelled,\n NoteAdded,\n];\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":["statusEntrySchema","statusEntrySchema","contactInfoSchema","statusEntrySchema","createPrimitiveEvent"],"sources":["../src/models/tenant-field.ts","../src/models/pipeline.schema.ts","../src/enums/lead-status.ts","../src/models/lead.schema.ts","../src/enums/opportunity-status.ts","../src/models/opportunity.schema.ts","../src/models/contact.schema.ts","../src/models/account.schema.ts","../src/enums/campaign-status.ts","../src/models/campaign.schema.ts","../src/enums/subscription-status.ts","../src/models/subscription.schema.ts","../src/enums/activity.ts","../src/models/activity.schema.ts","../src/models/note.schema.ts","../src/models/loss-reason.schema.ts","../src/enums/email-event-kind.ts","../src/models/email-event.schema.ts","../src/models/create-models.ts","../src/core/errors.ts","../src/events/event-constants.ts","../src/events/helpers.ts","../src/repositories/pipeline.repository.ts","../src/core/state-machines.ts","../src/shared/calculators/scoring.ts","../src/repositories/lead.repository.ts","../src/repositories/opportunity.repository.ts","../src/repositories/contact.repository.ts","../src/repositories/account.repository.ts","../src/repositories/campaign.repository.ts","../src/repositories/subscription.repository.ts","../src/repositories/activity.repository.ts","../src/repositories/note.repository.ts","../src/repositories/loss-reason.repository.ts","../src/repositories/email-event.repository.ts","../src/repositories/create-repositories.ts","../src/events/in-process-bus.ts","../src/engine/create-crm.ts","../src/services/lead.service.ts","../src/shared/calculators/forecast.ts","../src/validators/common.ts","../src/validators/pipeline.schema.ts","../src/validators/lead.schema.ts","../src/validators/opportunity.schema.ts","../src/validators/contact.schema.ts","../src/validators/account.schema.ts","../src/validators/campaign.schema.ts","../src/validators/subscription.schema.ts","../src/validators/activity.schema.ts","../src/validators/note.schema.ts","../src/validators/loss-reason.schema.ts","../src/validators/email-event.schema.ts","../src/validators/index.ts"],"sourcesContent":["/**\n * Per PACKAGE_RULES §9.2: never hardcode the tenant column's Mongoose\n * type — let the engine config drive both the schema and the\n * multiTenantPlugin so they stay in sync. Hosts with Better Auth pick\n * `'objectId'` (default for new packages — enables `$lookup`,\n * `.populate()`, QueryParser `?lookup=organizationId`); hosts with\n * UUID/slug auth pick `'string'`.\n */\n\nimport { Schema, type SchemaDefinitionProperty } from 'mongoose';\n\nexport type TenantFieldType = 'objectId' | 'string';\n\nexport interface SchemaBuildConfig {\n /** Schema type for the tenant column. Engine plumbs this everywhere. */\n tenantFieldType: TenantFieldType;\n}\n\n/**\n * Tenant-column schema definition. Use this anywhere a model has\n * `organizationId` — never write the raw type in a schema file.\n */\nexport function tenantFieldDef(config: SchemaBuildConfig): SchemaDefinitionProperty {\n return config.tenantFieldType === 'objectId'\n ? { type: Schema.Types.ObjectId, required: true, ref: 'organization', index: true }\n : { type: String, required: true, index: true };\n}\n","/**\n * Pipeline + embedded Stages.\n *\n * Sales motions are the cardinality consumers think in — \"new business\n * vs. expansion vs. partnerships.\" Each Pipeline owns its Stages\n * inline (embedded subdocs) because stages have no meaning outside a\n * pipeline and the read pattern is \"load the pipeline + all its\n * stages\" 99% of the time. Opportunities reference a `(pipelineId,\n * stageId)` pair to pin themselves.\n */\n\nimport { type Connection, type Model, Schema } from 'mongoose';\nimport type { SchemaBuildConfig } from './tenant-field.js';\nimport { tenantFieldDef } from './tenant-field.js';\n\n/** Mongoose document shape for a single embedded stage. */\nexport interface IStageDocument {\n _id: import('mongoose').Types.ObjectId;\n name: string;\n /** Ascending order in the pipeline. Treated as identifier on `moveToStage`. */\n sequence: number;\n /** Default win-probability assigned to opportunities entering this stage. */\n defaultProbability: number;\n color?: string;\n description?: string;\n}\n\n/** Mongoose document shape for a Pipeline. */\nexport interface IPipelineDocument {\n _id: import('mongoose').Types.ObjectId;\n organizationId: import('mongoose').Types.ObjectId | string;\n name: string;\n /** Deprecates the pipeline — existing opps still move, no new ones created. */\n isArchived: boolean;\n /** Embedded stages, kept ordered by `sequence`. */\n stages: IStageDocument[];\n /** Free-form label for the sales team / motion that owns this pipeline. */\n teamRef?: string;\n metadata?: Record<string, unknown>;\n createdAt: Date;\n updatedAt: Date;\n}\n\nconst stageSubSchema = new Schema<IStageDocument>(\n {\n name: { type: String, required: true, trim: true, maxlength: 100 },\n sequence: { type: Number, required: true, min: 1 },\n defaultProbability: { type: Number, required: true, min: 0, max: 1 },\n color: { type: String, trim: true, maxlength: 32 },\n description: { type: String, trim: true, maxlength: 500 },\n },\n { _id: true },\n);\n\nexport function buildPipelineSchema(config: SchemaBuildConfig): Schema<IPipelineDocument> {\n const schema = new Schema<IPipelineDocument>(\n {\n organizationId: tenantFieldDef(config),\n name: { type: String, required: true, trim: true, maxlength: 200 },\n isArchived: { type: Boolean, default: false, index: true },\n stages: { type: [stageSubSchema], default: [] },\n teamRef: { type: String, trim: true, maxlength: 100 },\n metadata: { type: Schema.Types.Mixed },\n },\n { timestamps: true },\n );\n\n schema.index({ organizationId: 1, isArchived: 1 });\n schema.index({ organizationId: 1, name: 1 });\n\n return schema;\n}\n\nexport function createPipelineModel(\n connection: Connection,\n config: SchemaBuildConfig,\n): Model<IPipelineDocument> {\n // Per PACKAGE_RULES §21: purge stale cached model on rebuild (hot reload, tests).\n if (connection.models.Pipeline) {\n connection.deleteModel('Pipeline');\n }\n return connection.model<IPipelineDocument>('Pipeline', buildPipelineSchema(config));\n}\n","/**\n * Lead lifecycle — from initial inquiry through conversion.\n *\n * new — just captured (web form, import, referral)\n * contacted — SDR has reached out\n * qualified — meets ICP / BANT\n * converted — turned into Contact + Account + Opportunity\n * disqualified — rejected (bad fit, spam, duplicate)\n * nurturing — not ready now; parked for later outreach\n */\nexport const LEAD_STATUSES = [\n 'new',\n 'contacted',\n 'qualified',\n 'converted',\n 'disqualified',\n 'nurturing',\n] as const;\nexport type LeadStatus = (typeof LEAD_STATUSES)[number];\n\nexport const LEAD_TRANSITIONS: Record<LeadStatus, readonly LeadStatus[]> = {\n new: ['contacted', 'qualified', 'disqualified', 'nurturing'],\n contacted: ['qualified', 'disqualified', 'nurturing'],\n qualified: ['converted', 'disqualified', 'nurturing'],\n nurturing: ['contacted', 'qualified', 'disqualified'],\n converted: [],\n disqualified: [],\n};\n\nexport function canTransitionLead(from: LeadStatus, to: LeadStatus): boolean {\n return LEAD_TRANSITIONS[from].includes(to);\n}\n","/**\n * Lead — top-of-funnel inquiry, pre-qualification.\n */\n\nimport { type Connection, type Model, Schema } from 'mongoose';\nimport { LEAD_STATUSES, type LeadStatus } from '../enums/lead-status.js';\nimport { tenantFieldDef, type SchemaBuildConfig } from './tenant-field.js';\n\nexport interface ILeadStatusEntry {\n status: LeadStatus;\n occurredAt: Date;\n by?: string;\n note?: string;\n}\n\nexport interface ILeadDocument {\n _id: import('mongoose').Types.ObjectId;\n organizationId: import('mongoose').Types.ObjectId | string;\n fullName: string;\n firstName?: string;\n lastName?: string;\n email?: string;\n phone?: string;\n companyName?: string;\n jobTitle?: string;\n source?: string;\n campaignRef?: string;\n score: number;\n status: LeadStatus;\n statusHistory: ILeadStatusEntry[];\n ownerId?: string;\n tags: string[];\n // Populated on convert.\n convertedContactId?: import('mongoose').Types.ObjectId | string;\n convertedAccountId?: import('mongoose').Types.ObjectId | string;\n convertedOpportunityId?: import('mongoose').Types.ObjectId | string;\n convertedAt?: Date;\n disqualifyReason?: string;\n metadata?: Record<string, unknown>;\n createdAt: Date;\n updatedAt: Date;\n}\n\nconst statusEntrySchema = new Schema<ILeadStatusEntry>(\n {\n status: { type: String, enum: LEAD_STATUSES, required: true },\n occurredAt: { type: Date, required: true },\n by: { type: String },\n note: { type: String },\n },\n { _id: false },\n);\n\nexport function buildLeadSchema(config: SchemaBuildConfig): Schema<ILeadDocument> {\n const schema = new Schema<ILeadDocument>(\n {\n organizationId: tenantFieldDef(config),\n fullName: { type: String, required: true, trim: true, maxlength: 200 },\n firstName: { type: String, trim: true, maxlength: 100 },\n lastName: { type: String, trim: true, maxlength: 100 },\n email: { type: String, trim: true, lowercase: true, maxlength: 255 },\n phone: { type: String, trim: true, maxlength: 50 },\n companyName: { type: String, trim: true, maxlength: 200 },\n jobTitle: { type: String, trim: true, maxlength: 150 },\n source: { type: String, trim: true, maxlength: 100 },\n campaignRef: { type: String, trim: true, maxlength: 100 },\n score: { type: Number, default: 0 },\n status: { type: String, enum: LEAD_STATUSES, default: 'new', index: true },\n statusHistory: { type: [statusEntrySchema], default: [] },\n ownerId: { type: String, index: true },\n tags: { type: [String], default: [] },\n convertedContactId: { type: Schema.Types.ObjectId, ref: 'Contact' },\n convertedAccountId: { type: Schema.Types.ObjectId, ref: 'Account' },\n convertedOpportunityId: { type: Schema.Types.ObjectId, ref: 'Opportunity' },\n convertedAt: { type: Date },\n disqualifyReason: { type: String, trim: true, maxlength: 500 },\n metadata: { type: Schema.Types.Mixed },\n },\n { timestamps: true },\n );\n\n schema.index({ organizationId: 1, email: 1 });\n schema.index({ organizationId: 1, createdAt: -1 });\n schema.index({ organizationId: 1, score: -1 });\n\n return schema;\n}\n\nexport function createLeadModel(connection: Connection, config: SchemaBuildConfig): Model<ILeadDocument> {\n if (connection.models.Lead) connection.deleteModel('Lead');\n return connection.model<ILeadDocument>('Lead', buildLeadSchema(config));\n}\n","/**\n * Top-level opportunity status. Movement through pipeline STAGES\n * happens while status is `open`; `won` / `lost` are terminal\n * outcomes. Re-opening a lost deal is a host-level decision —\n * convention is to clone the opportunity rather than revive the\n * terminal record.\n */\nexport const OPPORTUNITY_STATUSES = ['open', 'won', 'lost', 'abandoned'] as const;\nexport type OpportunityStatus = (typeof OPPORTUNITY_STATUSES)[number];\n\nexport const OPPORTUNITY_TRANSITIONS: Record<OpportunityStatus, readonly OpportunityStatus[]> = {\n open: ['won', 'lost', 'abandoned'],\n won: [],\n lost: [],\n abandoned: [],\n};\n\nexport function canTransitionOpportunity(\n from: OpportunityStatus,\n to: OpportunityStatus,\n): boolean {\n return OPPORTUNITY_TRANSITIONS[from].includes(to);\n}\n","/**\n * Opportunity — qualified deal moving through a Pipeline's stages.\n * Money amount lives flat (`amount` + `currency`) so `$sum` aggregates work; the repo\n * surface returns it that way too (no Money translation layer per PACKAGE_RULES §4).\n */\n\nimport { type Connection, type Model, Schema } from 'mongoose';\nimport { OPPORTUNITY_STATUSES, type OpportunityStatus } from '../enums/opportunity-status.js';\nimport { tenantFieldDef, type SchemaBuildConfig } from './tenant-field.js';\n\nexport interface IOpportunityStatusEntry {\n status: OpportunityStatus;\n stageId?: string;\n occurredAt: Date;\n by?: string;\n note?: string;\n}\n\nexport interface IOpportunityDocument {\n _id: import('mongoose').Types.ObjectId;\n organizationId: import('mongoose').Types.ObjectId | string;\n name: string;\n accountId?: import('mongoose').Types.ObjectId | string;\n primaryContactId?: import('mongoose').Types.ObjectId | string;\n pipelineId: import('mongoose').Types.ObjectId | string;\n stageId: string;\n status: OpportunityStatus;\n statusHistory: IOpportunityStatusEntry[];\n amount?: number;\n currency: string;\n probability: number;\n expectedCloseAt?: Date;\n closedAt?: Date;\n lostReasonId?: import('mongoose').Types.ObjectId | string;\n ownerId?: string;\n sourceLeadId?: import('mongoose').Types.ObjectId | string;\n tags: string[];\n metadata?: Record<string, unknown>;\n createdAt: Date;\n updatedAt: Date;\n}\n\nconst statusEntrySchema = new Schema<IOpportunityStatusEntry>(\n {\n status: { type: String, enum: OPPORTUNITY_STATUSES, required: true },\n stageId: { type: String },\n occurredAt: { type: Date, required: true },\n by: { type: String },\n note: { type: String },\n },\n { _id: false },\n);\n\nexport function buildOpportunitySchema(config: SchemaBuildConfig): Schema<IOpportunityDocument> {\n const schema = new Schema<IOpportunityDocument>(\n {\n organizationId: tenantFieldDef(config),\n name: { type: String, required: true, trim: true, maxlength: 200 },\n accountId: { type: Schema.Types.ObjectId, ref: 'Account' },\n primaryContactId: { type: Schema.Types.ObjectId, ref: 'Contact' },\n pipelineId: { type: Schema.Types.ObjectId, ref: 'Pipeline', required: true },\n stageId: { type: String, required: true, index: true },\n status: { type: String, enum: OPPORTUNITY_STATUSES, default: 'open', index: true },\n statusHistory: { type: [statusEntrySchema], default: [] },\n amount: { type: Number },\n currency: { type: String, default: 'USD' },\n probability: { type: Number, min: 0, max: 1, default: 0 },\n expectedCloseAt: { type: Date, index: true },\n closedAt: { type: Date },\n lostReasonId: { type: Schema.Types.ObjectId, ref: 'LossReason' },\n ownerId: { type: String, index: true },\n sourceLeadId: { type: Schema.Types.ObjectId, ref: 'Lead' },\n tags: { type: [String], default: [] },\n metadata: { type: Schema.Types.Mixed },\n },\n { timestamps: true },\n );\n\n schema.index({ organizationId: 1, pipelineId: 1, stageId: 1 });\n schema.index({ organizationId: 1, status: 1, expectedCloseAt: 1 });\n schema.index({ organizationId: 1, ownerId: 1, status: 1 });\n\n return schema;\n}\n\nexport function createOpportunityModel(connection: Connection, config: SchemaBuildConfig): Model<IOpportunityDocument> {\n if (connection.models.Opportunity) connection.deleteModel('Opportunity');\n return connection.model<IOpportunityDocument>('Opportunity', buildOpportunitySchema(config));\n}\n","/**\n * Contact — a person in the CRM.\n *\n * Per PACKAGE_RULES §4 (no envelopes / no translation): we store the\n * structured `PersonName` + `ContactInfo` from `@classytic/primitives/person`\n * verbatim, embedded. The host queries `contact.name.given`,\n * `contact.contact.email`, etc. directly — no flat-vs-structured\n * translation layer.\n */\n\nimport { type Connection, type Model, Schema } from 'mongoose';\nimport { tenantFieldDef, type SchemaBuildConfig } from './tenant-field.js';\n\nexport interface IContactName {\n given: string;\n family: string;\n middle?: string;\n prefix?: string;\n suffix?: string;\n preferred?: string;\n}\n\nexport interface IContactInfoEmbedded {\n email?: string;\n personalEmail?: string;\n phone?: string;\n alternatePhone?: string;\n}\n\nexport interface IContactDocument {\n _id: import('mongoose').Types.ObjectId;\n organizationId: import('mongoose').Types.ObjectId | string;\n name: IContactName;\n contact: IContactInfoEmbedded;\n jobTitle?: string;\n accountId?: import('mongoose').Types.ObjectId | string;\n ownerId?: string;\n tags: string[];\n metadata?: Record<string, unknown>;\n createdAt: Date;\n updatedAt: Date;\n}\n\nconst nameSchema = new Schema<IContactName>(\n {\n given: { type: String, required: true, trim: true, maxlength: 100 },\n family: { type: String, default: '', trim: true, maxlength: 100 },\n middle: { type: String, trim: true, maxlength: 100 },\n prefix: { type: String, trim: true, maxlength: 32 },\n suffix: { type: String, trim: true, maxlength: 32 },\n preferred: { type: String, trim: true, maxlength: 100 },\n },\n { _id: false },\n);\n\nconst contactInfoSchema = new Schema<IContactInfoEmbedded>(\n {\n email: { type: String, trim: true, lowercase: true, maxlength: 255 },\n personalEmail: { type: String, trim: true, lowercase: true, maxlength: 255 },\n phone: { type: String, trim: true, maxlength: 50 },\n alternatePhone: { type: String, trim: true, maxlength: 50 },\n },\n { _id: false },\n);\n\nexport function buildContactSchema(config: SchemaBuildConfig): Schema<IContactDocument> {\n const schema = new Schema<IContactDocument>(\n {\n organizationId: tenantFieldDef(config),\n name: { type: nameSchema, required: true },\n contact: { type: contactInfoSchema, default: {} },\n jobTitle: { type: String, trim: true, maxlength: 150 },\n accountId: { type: Schema.Types.ObjectId, ref: 'Account' },\n ownerId: { type: String, index: true },\n tags: { type: [String], default: [] },\n metadata: { type: Schema.Types.Mixed },\n },\n { timestamps: true, toJSON: { virtuals: true }, toObject: { virtuals: true } },\n );\n\n schema.index({ organizationId: 1, 'contact.email': 1 });\n schema.index({ organizationId: 1, accountId: 1 });\n schema.index({ organizationId: 1, createdAt: -1 });\n schema.index({ organizationId: 1, tags: 1 });\n\n schema.virtual('fullName').get(function () {\n const n = (this as unknown as IContactDocument).name;\n return n?.preferred?.trim() || [n?.given, n?.family].filter(Boolean).join(' ');\n });\n\n return schema;\n}\n\nexport function createContactModel(connection: Connection, config: SchemaBuildConfig): Model<IContactDocument> {\n if (connection.models.Contact) connection.deleteModel('Contact');\n return connection.model<IContactDocument>('Contact', buildContactSchema(config));\n}\n","/**\n * Account — the B2B customer org an Opportunity targets and Contacts belong to.\n * Flat `annualRevenue` (Number + currency) for $sum aggregations.\n */\n\nimport { type Connection, type Model, Schema } from 'mongoose';\nimport { tenantFieldDef, type SchemaBuildConfig } from './tenant-field.js';\n\nexport interface IAccountDocument {\n _id: import('mongoose').Types.ObjectId;\n organizationId: import('mongoose').Types.ObjectId | string;\n name: string;\n domain?: string;\n industry?: string;\n sizeBucket?: string;\n annualRevenueAmount?: number;\n annualRevenueCurrency: string;\n ownerId?: string;\n tags: string[];\n metadata?: Record<string, unknown>;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport function buildAccountSchema(config: SchemaBuildConfig): Schema<IAccountDocument> {\n const schema = new Schema<IAccountDocument>(\n {\n organizationId: tenantFieldDef(config),\n name: { type: String, required: true, trim: true, maxlength: 200 },\n domain: { type: String, trim: true, lowercase: true, maxlength: 255 },\n industry: { type: String, trim: true, maxlength: 100 },\n sizeBucket: { type: String, trim: true, maxlength: 20 },\n annualRevenueAmount: { type: Number },\n annualRevenueCurrency: { type: String, default: 'USD' },\n ownerId: { type: String, index: true },\n tags: { type: [String], default: [] },\n metadata: { type: Schema.Types.Mixed },\n },\n { timestamps: true },\n );\n\n schema.index({ organizationId: 1, domain: 1 });\n schema.index({ organizationId: 1, createdAt: -1 });\n schema.index({ organizationId: 1, tags: 1 });\n\n return schema;\n}\n\nexport function createAccountModel(connection: Connection, config: SchemaBuildConfig): Model<IAccountDocument> {\n if (connection.models.Account) connection.deleteModel('Account');\n return connection.model<IAccountDocument>('Account', buildAccountSchema(config));\n}\n","/**\n * Campaign lifecycle.\n *\n * draft — being built; not running, no sends, no UTM attribution counted\n * active — running; participating in attribution + automation\n * paused — temporarily halted; can be resumed; no sends fire\n * completed — finished its run; preserved for historical attribution\n * archived — soft-hidden from the default UI; still queryable\n */\nexport const CAMPAIGN_STATUSES = [\n 'draft',\n 'active',\n 'paused',\n 'completed',\n 'archived',\n] as const;\nexport type CampaignStatus = (typeof CAMPAIGN_STATUSES)[number];\n\nexport const CAMPAIGN_TRANSITIONS: Record<CampaignStatus, readonly CampaignStatus[]> = {\n draft: ['active', 'archived'],\n active: ['paused', 'completed', 'archived'],\n paused: ['active', 'completed', 'archived'],\n completed: ['archived'],\n archived: [],\n};\n\nexport function canTransitionCampaign(from: CampaignStatus, to: CampaignStatus): boolean {\n return CAMPAIGN_TRANSITIONS[from].includes(to);\n}\n","/**\n * Campaign — a marketing/sales motion targeting a contact list.\n * Money fields stored flat (amount + currency) for $sum aggregations.\n */\n\nimport { type Connection, type Model, Schema } from 'mongoose';\nimport { CAMPAIGN_STATUSES, type CampaignStatus } from '../enums/campaign-status.js';\nimport { tenantFieldDef, type SchemaBuildConfig } from './tenant-field.js';\n\nexport interface ICampaignStatusEntry {\n status: CampaignStatus;\n occurredAt: Date;\n by?: string;\n note?: string;\n}\n\nexport interface ICampaignDocument {\n _id: import('mongoose').Types.ObjectId;\n organizationId: import('mongoose').Types.ObjectId | string;\n name: string;\n description?: string;\n status: CampaignStatus;\n statusHistory: ICampaignStatusEntry[];\n utmSource?: string;\n utmMedium?: string;\n utmCampaign?: string;\n startDate?: Date;\n endDate?: Date;\n budgetAmount?: number;\n expectedRevenueAmount?: number;\n actualRevenueAmount?: number;\n currency: string;\n ownerId?: string;\n tags: string[];\n metadata?: Record<string, unknown>;\n createdAt: Date;\n updatedAt: Date;\n}\n\nconst statusEntrySchema = new Schema<ICampaignStatusEntry>(\n {\n status: { type: String, enum: CAMPAIGN_STATUSES, required: true },\n occurredAt: { type: Date, required: true },\n by: { type: String },\n note: { type: String },\n },\n { _id: false },\n);\n\nexport function buildCampaignSchema(config: SchemaBuildConfig): Schema<ICampaignDocument> {\n const schema = new Schema<ICampaignDocument>(\n {\n organizationId: tenantFieldDef(config),\n name: { type: String, required: true, trim: true, maxlength: 200 },\n description: { type: String, trim: true, maxlength: 2000 },\n status: { type: String, enum: CAMPAIGN_STATUSES, default: 'draft', index: true },\n statusHistory: { type: [statusEntrySchema], default: [] },\n utmSource: { type: String, trim: true, maxlength: 100 },\n utmMedium: { type: String, trim: true, maxlength: 100 },\n utmCampaign: { type: String, trim: true, maxlength: 100 },\n startDate: { type: Date },\n endDate: { type: Date },\n budgetAmount: { type: Number },\n expectedRevenueAmount: { type: Number },\n actualRevenueAmount: { type: Number },\n currency: { type: String, default: 'USD' },\n ownerId: { type: String, index: true },\n tags: { type: [String], default: [] },\n metadata: { type: Schema.Types.Mixed },\n },\n { timestamps: true },\n );\n\n schema.index({ organizationId: 1, status: 1 });\n schema.index({ organizationId: 1, startDate: 1 });\n schema.index({ organizationId: 1, createdAt: -1 });\n schema.index({ organizationId: 1, tags: 1 });\n\n return schema;\n}\n\nexport function createCampaignModel(connection: Connection, config: SchemaBuildConfig): Model<ICampaignDocument> {\n if (connection.models.Campaign) connection.deleteModel('Campaign');\n return connection.model<ICampaignDocument>('Campaign', buildCampaignSchema(config));\n}\n","/**\n * Subscription lifecycle.\n *\n * pending — double-opt-in pending confirmation\n * confirmed — actively subscribed; eligible to receive sends\n * unsubscribed — user opted out via unsubscribe link (or operator action)\n * bounced — provider reported hard bounce; permanent suppression\n * complained — recipient hit \"spam\" / \"report\" in their email client;\n * permanent suppression (CAN-SPAM + provider trust)\n *\n * All terminal states are non-reopenable. Re-subscribing creates a new\n * Subscription row — the audit trail of unsubscribes/bounces is preserved.\n */\nexport const SUBSCRIPTION_STATUSES = [\n 'pending',\n 'confirmed',\n 'unsubscribed',\n 'bounced',\n 'complained',\n] as const;\nexport type SubscriptionStatus = (typeof SUBSCRIPTION_STATUSES)[number];\n\nexport const SUBSCRIPTION_TRANSITIONS: Record<SubscriptionStatus, readonly SubscriptionStatus[]> = {\n pending: ['confirmed', 'unsubscribed', 'bounced'],\n confirmed: ['unsubscribed', 'bounced', 'complained'],\n unsubscribed: [],\n bounced: [],\n complained: [],\n};\n\nexport function canTransitionSubscription(\n from: SubscriptionStatus,\n to: SubscriptionStatus,\n): boolean {\n return SUBSCRIPTION_TRANSITIONS[from].includes(to);\n}\n","/**\n * Subscription — a Contact's opt-in to a Campaign. Double-opt-in tokens,\n * unsubscribe token, compliance audit fields.\n */\n\nimport { type Connection, type Model, Schema } from 'mongoose';\nimport { SUBSCRIPTION_STATUSES, type SubscriptionStatus } from '../enums/subscription-status.js';\nimport { tenantFieldDef, type SchemaBuildConfig } from './tenant-field.js';\n\nexport interface ISubscriptionStatusEntry {\n status: SubscriptionStatus;\n occurredAt: Date;\n by?: string;\n note?: string;\n}\n\nexport interface ISubscriptionDocument {\n _id: import('mongoose').Types.ObjectId;\n organizationId: import('mongoose').Types.ObjectId | string;\n contactId: import('mongoose').Types.ObjectId | string;\n campaignId: import('mongoose').Types.ObjectId | string;\n status: SubscriptionStatus;\n statusHistory: ISubscriptionStatusEntry[];\n source?: string;\n consentTimestamp: Date;\n consentIpAddress?: string;\n consentUserAgent?: string;\n confirmationToken?: string;\n unsubscribeToken: string;\n /** Audit timestamps for compliance — set on the matching transition. */\n confirmedAt?: Date;\n unsubscribedAt?: Date;\n unsubscribeReason?: string;\n bouncedAt?: Date;\n bounceReason?: string;\n complainedAt?: Date;\n metadata?: Record<string, unknown>;\n createdAt: Date;\n updatedAt: Date;\n}\n\nconst statusEntrySchema = new Schema<ISubscriptionStatusEntry>(\n {\n status: { type: String, enum: SUBSCRIPTION_STATUSES, required: true },\n occurredAt: { type: Date, required: true },\n by: { type: String },\n note: { type: String },\n },\n { _id: false },\n);\n\nexport function buildSubscriptionSchema(config: SchemaBuildConfig): Schema<ISubscriptionDocument> {\n const schema = new Schema<ISubscriptionDocument>(\n {\n organizationId: tenantFieldDef(config),\n contactId: { type: Schema.Types.ObjectId, ref: 'Contact', required: true },\n campaignId: { type: Schema.Types.ObjectId, ref: 'Campaign', required: true },\n status: { type: String, enum: SUBSCRIPTION_STATUSES, default: 'pending', index: true },\n statusHistory: { type: [statusEntrySchema], default: [] },\n source: { type: String, trim: true, maxlength: 100 },\n consentTimestamp: { type: Date, required: true },\n consentIpAddress: { type: String, trim: true, maxlength: 64 },\n consentUserAgent: { type: String, trim: true, maxlength: 500 },\n confirmationToken: { type: String, index: true },\n unsubscribeToken: { type: String, required: true, index: true },\n confirmedAt: { type: Date },\n unsubscribedAt: { type: Date },\n unsubscribeReason: { type: String, trim: true, maxlength: 500 },\n bouncedAt: { type: Date },\n bounceReason: { type: String, trim: true, maxlength: 500 },\n complainedAt: { type: Date },\n metadata: { type: Schema.Types.Mixed },\n },\n { timestamps: true },\n );\n\n schema.index({ organizationId: 1, campaignId: 1, status: 1 });\n schema.index({ organizationId: 1, contactId: 1, campaignId: 1 });\n schema.index({ organizationId: 1, createdAt: -1 });\n\n return schema;\n}\n\nexport function createSubscriptionModel(connection: Connection, config: SchemaBuildConfig): Model<ISubscriptionDocument> {\n if (connection.models.Subscription) connection.deleteModel('Subscription');\n return connection.model<ISubscriptionDocument>('Subscription', buildSubscriptionSchema(config));\n}\n","/**\n * Activity type vocabulary. The package stores `type` as free-form\n * string so hosts can extend; these constants cover the common\n * channels that automation tooling typically keys off.\n */\nexport const ACTIVITY_TYPES = [\n 'call',\n 'email',\n 'meeting',\n 'task',\n 'note',\n 'sms',\n 'social',\n 'demo',\n 'other',\n] as const;\nexport type ActivityType = (typeof ACTIVITY_TYPES)[number];\n\nexport const ACTIVITY_STATUSES = ['planned', 'in_progress', 'completed', 'cancelled'] as const;\nexport type ActivityStatus = (typeof ACTIVITY_STATUSES)[number];\n\nexport const ACTIVITY_TRANSITIONS: Record<ActivityStatus, readonly ActivityStatus[]> = {\n planned: ['in_progress', 'completed', 'cancelled'],\n in_progress: ['completed', 'cancelled'],\n completed: [],\n cancelled: [],\n};\n\nexport function canTransitionActivity(from: ActivityStatus, to: ActivityStatus): boolean {\n return ACTIVITY_TRANSITIONS[from].includes(to);\n}\n\n/**\n * Kinds of entity an Activity can reference. Polymorphic linking lets\n * hosts log a call against a Lead, an Opportunity, a Contact, or a\n * stand-alone Account.\n */\nexport const SUBJECT_KINDS = ['lead', 'opportunity', 'contact', 'account'] as const;\nexport type SubjectKind = (typeof SUBJECT_KINDS)[number];\n","/**\n * Activity — call / email / meeting / task tied polymorphically to a CRM subject\n * (Contact / Lead / Opportunity / Account).\n */\n\nimport { type Connection, type Model, Schema } from 'mongoose';\nimport {\n ACTIVITY_STATUSES,\n ACTIVITY_TYPES,\n SUBJECT_KINDS,\n type ActivityStatus,\n type ActivityType,\n type SubjectKind,\n} from '../enums/activity.js';\nimport { tenantFieldDef, type SchemaBuildConfig } from './tenant-field.js';\n\nexport interface IActivityDocument {\n _id: import('mongoose').Types.ObjectId;\n organizationId: import('mongoose').Types.ObjectId | string;\n type: ActivityType;\n status: ActivityStatus;\n subjectKind: SubjectKind;\n subjectId: import('mongoose').Types.ObjectId | string;\n title: string;\n description?: string;\n ownerId?: string;\n participantIds: string[];\n dueDate?: Date;\n completedAt?: Date;\n externalRef?: string;\n metadata?: Record<string, unknown>;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport function buildActivitySchema(config: SchemaBuildConfig): Schema<IActivityDocument> {\n const schema = new Schema<IActivityDocument>(\n {\n organizationId: tenantFieldDef(config),\n type: { type: String, enum: ACTIVITY_TYPES, required: true, index: true },\n status: { type: String, enum: ACTIVITY_STATUSES, default: 'planned', index: true },\n subjectKind: { type: String, enum: SUBJECT_KINDS, required: true },\n subjectId: { type: Schema.Types.ObjectId, required: true, index: true },\n title: { type: String, required: true, trim: true, maxlength: 200 },\n description: { type: String, trim: true, maxlength: 2000 },\n ownerId: { type: String, index: true },\n participantIds: { type: [String], default: [] },\n dueDate: { type: Date, index: true },\n completedAt: { type: Date },\n externalRef: { type: String, trim: true, maxlength: 200 },\n metadata: { type: Schema.Types.Mixed },\n },\n { timestamps: true },\n );\n\n schema.index({ organizationId: 1, subjectKind: 1, subjectId: 1 });\n schema.index({ organizationId: 1, status: 1, dueDate: 1 });\n schema.index({ organizationId: 1, ownerId: 1, status: 1 });\n schema.index({ organizationId: 1, type: 1 });\n schema.index({ organizationId: 1, createdAt: -1 });\n\n return schema;\n}\n\nexport function createActivityModel(connection: Connection, config: SchemaBuildConfig): Model<IActivityDocument> {\n if (connection.models.Activity) connection.deleteModel('Activity');\n return connection.model<IActivityDocument>('Activity', buildActivitySchema(config));\n}\n","/**\n * Note — free-form annotation tied polymorphically to a CRM subject.\n * Separate from Activity because notes don't have a lifecycle (no\n * planned/completed/cancelled).\n */\n\nimport { type Connection, type Model, Schema } from 'mongoose';\nimport { SUBJECT_KINDS, type SubjectKind } from '../enums/activity.js';\nimport { tenantFieldDef, type SchemaBuildConfig } from './tenant-field.js';\n\nexport interface INoteDocument {\n _id: import('mongoose').Types.ObjectId;\n organizationId: import('mongoose').Types.ObjectId | string;\n subjectKind: SubjectKind;\n subjectId: import('mongoose').Types.ObjectId | string;\n body: string;\n authorId?: string;\n pinned: boolean;\n metadata?: Record<string, unknown>;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport function buildNoteSchema(config: SchemaBuildConfig): Schema<INoteDocument> {\n const schema = new Schema<INoteDocument>(\n {\n organizationId: tenantFieldDef(config),\n subjectKind: { type: String, enum: SUBJECT_KINDS, required: true },\n subjectId: { type: Schema.Types.ObjectId, required: true, index: true },\n body: { type: String, required: true, trim: true, maxlength: 10000 },\n authorId: { type: String, index: true },\n pinned: { type: Boolean, default: false, index: true },\n metadata: { type: Schema.Types.Mixed },\n },\n { timestamps: true },\n );\n\n schema.index({ organizationId: 1, subjectKind: 1, subjectId: 1, pinned: -1, createdAt: -1 });\n\n return schema;\n}\n\nexport function createNoteModel(connection: Connection, config: SchemaBuildConfig): Model<INoteDocument> {\n if (connection.models.Note) connection.deleteModel('Note');\n return connection.model<INoteDocument>('Note', buildNoteSchema(config));\n}\n","/**\n * LossReason — per-org taxonomy for \"why did this deal die?\" Referenced\n * by `Opportunity.lostReasonId` on `lose()` transitions for forecast +\n * win-loss reporting.\n */\n\nimport { type Connection, type Model, Schema } from 'mongoose';\nimport { tenantFieldDef, type SchemaBuildConfig } from './tenant-field.js';\n\nexport interface ILossReasonDocument {\n _id: import('mongoose').Types.ObjectId;\n organizationId: import('mongoose').Types.ObjectId | string;\n name: string;\n description?: string;\n isActive: boolean;\n /** Display ordering in admin UIs. */\n sequence: number;\n metadata?: Record<string, unknown>;\n createdAt: Date;\n updatedAt: Date;\n}\n\nexport function buildLossReasonSchema(config: SchemaBuildConfig): Schema<ILossReasonDocument> {\n const schema = new Schema<ILossReasonDocument>(\n {\n organizationId: tenantFieldDef(config),\n name: { type: String, required: true, trim: true, maxlength: 200 },\n description: { type: String, trim: true, maxlength: 1000 },\n isActive: { type: Boolean, default: true, index: true },\n sequence: { type: Number, default: 0 },\n metadata: { type: Schema.Types.Mixed },\n },\n { timestamps: true },\n );\n\n schema.index({ organizationId: 1, isActive: 1, sequence: 1 });\n\n return schema;\n}\n\nexport function createLossReasonModel(connection: Connection, config: SchemaBuildConfig): Model<ILossReasonDocument> {\n if (connection.models.LossReason) connection.deleteModel('LossReason');\n return connection.model<ILossReasonDocument>('LossReason', buildLossReasonSchema(config));\n}\n","/**\n * Email engagement event kinds, recorded against a Contact / Campaign /\n * Subscription tuple as the recipient interacts with a sent message.\n *\n * open — recipient's mail client loaded the tracking pixel.\n * Imperfect signal: image-block clients suppress it, some\n * clients pre-fetch and inflate counts. Useful in aggregate.\n *\n * click — recipient followed a tracked link. High-signal: actual\n * user action, not background fetch.\n *\n * bounce — provider reported delivery failed. Pair with the\n * `bounce` status on Subscription for permanent suppression.\n *\n * complaint — recipient hit \"spam\" / \"report\" in their inbox. Pair\n * with `complained` Subscription status.\n *\n * unsubscribe — recipient hit the unsubscribe link in the email. May\n * fire BEFORE the Subscription itself is marked unsubscribed\n * (the host can choose to confirm before flipping status).\n *\n * Open and click are \"engagement signal\"; bounce/complaint/unsubscribe are\n * \"suppression signal\". The service exposes aggregates over both\n * categories so consumers can compute open rate, click rate, bounce rate\n * without filtering kind themselves.\n */\nexport const EMAIL_EVENT_KINDS = [\n 'open',\n 'click',\n 'bounce',\n 'complaint',\n 'unsubscribe',\n] as const;\nexport type EmailEventKind = (typeof EMAIL_EVENT_KINDS)[number];\n\n/** Engagement (positive signal). */\nexport const ENGAGEMENT_KINDS: ReadonlySet<EmailEventKind> = new Set(['open', 'click']);\n\n/** Suppression (negative signal — never send again). */\nexport const SUPPRESSION_KINDS: ReadonlySet<EmailEventKind> = new Set([\n 'bounce',\n 'complaint',\n 'unsubscribe',\n]);\n","/**\n * EmailEvent — append-only engagement / suppression log per recipient.\n *\n * Open / click / bounce / complaint / unsubscribe — all surface against\n * a polymorphic subject (Contact OR Subscription). Aggregates power\n * drip-sequence branches (\"if opened\") + campaign analytics.\n */\n\nimport { type Connection, type Model, Schema } from 'mongoose';\nimport { EMAIL_EVENT_KINDS, type EmailEventKind } from '../enums/email-event-kind.js';\nimport { tenantFieldDef, type SchemaBuildConfig } from './tenant-field.js';\n\nexport const EMAIL_EVENT_SUBJECT_KINDS = ['contact', 'subscription'] as const;\nexport type EmailEventSubjectKind = (typeof EMAIL_EVENT_SUBJECT_KINDS)[number];\n\nexport interface IEmailEventDocument {\n _id: import('mongoose').Types.ObjectId;\n organizationId: import('mongoose').Types.ObjectId | string;\n kind: EmailEventKind;\n subjectKind: EmailEventSubjectKind;\n subjectId: import('mongoose').Types.ObjectId | string;\n campaignId?: import('mongoose').Types.ObjectId | string;\n messageId?: string;\n url?: string;\n userAgent?: string;\n ip?: string;\n metadata?: Record<string, unknown>;\n createdAt: Date;\n}\n\nexport function buildEmailEventSchema(config: SchemaBuildConfig): Schema<IEmailEventDocument> {\n const schema = new Schema<IEmailEventDocument>(\n {\n organizationId: tenantFieldDef(config),\n kind: { type: String, enum: EMAIL_EVENT_KINDS, required: true, index: true },\n subjectKind: { type: String, enum: EMAIL_EVENT_SUBJECT_KINDS, required: true },\n subjectId: { type: Schema.Types.ObjectId, required: true, index: true },\n campaignId: { type: Schema.Types.ObjectId, ref: 'Campaign', index: true },\n messageId: { type: String, trim: true, maxlength: 200 },\n url: { type: String, trim: true, maxlength: 2048 },\n userAgent: { type: String, trim: true, maxlength: 500 },\n ip: { type: String, trim: true, maxlength: 64 },\n metadata: { type: Schema.Types.Mixed },\n },\n { timestamps: { createdAt: true, updatedAt: false } },\n );\n\n schema.index({ organizationId: 1, createdAt: -1 });\n schema.index({ organizationId: 1, subjectKind: 1, subjectId: 1, createdAt: -1 });\n schema.index({ organizationId: 1, campaignId: 1, kind: 1, createdAt: -1 });\n schema.index({ organizationId: 1, messageId: 1 });\n\n return schema;\n}\n\nexport function createEmailEventModel(connection: Connection, config: SchemaBuildConfig): Model<IEmailEventDocument> {\n if (connection.models.EmailEvent) connection.deleteModel('EmailEvent');\n return connection.model<IEmailEventDocument>('EmailEvent', buildEmailEventSchema(config));\n}\n","/**\n * Model Factory — creates all CRM Mongoose models on the host's\n * connection. Package owns its models (PACKAGE_RULES §20); each\n * `createXxxModel` purges stale cached models on rebuild (§21) so hot\n * reload and test re-runs stay clean.\n *\n * The factory takes a `SchemaBuildConfig` (driven by `tenantFieldType`)\n * so the tenant column matches the host's Better Auth / UUID choice.\n */\n\nimport type { Connection, Model } from 'mongoose';\nimport type { SchemaBuildConfig } from './tenant-field.js';\nimport { type IPipelineDocument, createPipelineModel } from './pipeline.schema.js';\nimport { type ILeadDocument, createLeadModel } from './lead.schema.js';\nimport { type IOpportunityDocument, createOpportunityModel } from './opportunity.schema.js';\nimport { type IContactDocument, createContactModel } from './contact.schema.js';\nimport { type IAccountDocument, createAccountModel } from './account.schema.js';\nimport { type ICampaignDocument, createCampaignModel } from './campaign.schema.js';\nimport { type ISubscriptionDocument, createSubscriptionModel } from './subscription.schema.js';\nimport { type IActivityDocument, createActivityModel } from './activity.schema.js';\nimport { type INoteDocument, createNoteModel } from './note.schema.js';\nimport { type ILossReasonDocument, createLossReasonModel } from './loss-reason.schema.js';\nimport { type IEmailEventDocument, createEmailEventModel } from './email-event.schema.js';\n\nexport interface CrmModels {\n Pipeline: Model<IPipelineDocument>;\n Lead: Model<ILeadDocument>;\n Opportunity: Model<IOpportunityDocument>;\n Contact: Model<IContactDocument>;\n Account: Model<IAccountDocument>;\n Campaign: Model<ICampaignDocument>;\n Subscription: Model<ISubscriptionDocument>;\n Activity: Model<IActivityDocument>;\n Note: Model<INoteDocument>;\n LossReason: Model<ILossReasonDocument>;\n EmailEvent: Model<IEmailEventDocument>;\n}\n\nexport function createCrmModels(\n connection: Connection,\n config: SchemaBuildConfig,\n): CrmModels {\n return Object.freeze({\n Pipeline: createPipelineModel(connection, config),\n Lead: createLeadModel(connection, config),\n Opportunity: createOpportunityModel(connection, config),\n Contact: createContactModel(connection, config),\n Account: createAccountModel(connection, config),\n Campaign: createCampaignModel(connection, config),\n Subscription: createSubscriptionModel(connection, config),\n Activity: createActivityModel(connection, config),\n Note: createNoteModel(connection, config),\n LossReason: createLossReasonModel(connection, config),\n EmailEvent: createEmailEventModel(connection, config),\n });\n}\n","/**\n * CRM error vocabulary. Hosts catch `CrmError` at API edges.\n */\nexport class CrmError extends Error {\n readonly code: string;\n readonly details?: Record<string, unknown>;\n constructor(code: string, message: string, details?: Record<string, unknown>) {\n super(message);\n this.name = 'CrmError';\n this.code = code;\n if (details !== undefined) this.details = details;\n }\n}\n\nexport class NotFoundError extends CrmError {\n constructor(kind: string, id: string) {\n super(`${kind.toUpperCase()}_NOT_FOUND`, `${kind} '${id}' not found`, { kind, id });\n }\n}\n\nexport class InvalidLeadTransitionError extends CrmError {\n constructor(details: { from: string; to: string; leadId: string }) {\n super(\n 'INVALID_LEAD_TRANSITION',\n `Lead ${details.leadId} cannot move from '${details.from}' to '${details.to}'`,\n details,\n );\n }\n}\n\nexport class InvalidOpportunityTransitionError extends CrmError {\n constructor(details: { from: string; to: string; opportunityId: string }) {\n super(\n 'INVALID_OPPORTUNITY_TRANSITION',\n `Opportunity ${details.opportunityId} cannot move from '${details.from}' to '${details.to}'`,\n details,\n );\n }\n}\n\nexport class InvalidActivityTransitionError extends CrmError {\n constructor(details: { from: string; to: string; activityId: string }) {\n super(\n 'INVALID_ACTIVITY_TRANSITION',\n `Activity ${details.activityId} cannot move from '${details.from}' to '${details.to}'`,\n details,\n );\n }\n}\n\nexport class StageNotInPipelineError extends CrmError {\n constructor(details: { pipelineId: string; stageId: string }) {\n super(\n 'STAGE_NOT_IN_PIPELINE',\n `Stage '${details.stageId}' is not defined on pipeline '${details.pipelineId}'`,\n details,\n );\n }\n}\n\nexport class LeadAlreadyConvertedError extends CrmError {\n constructor(leadId: string) {\n super('LEAD_ALREADY_CONVERTED', `Lead '${leadId}' is already converted`, { leadId });\n }\n}\n\nexport class DuplicateLeadError extends CrmError {\n constructor(details: { email?: string; phone?: string }) {\n super('DUPLICATE_LEAD', `A lead with this email / phone already exists`, details);\n }\n}\n\nexport class EmptyPipelineError extends CrmError {\n constructor(pipelineId: string) {\n super('EMPTY_PIPELINE', `Pipeline '${pipelineId}' has no stages`, { pipelineId });\n }\n}\n\nexport class InvalidCampaignTransitionError extends CrmError {\n constructor(details: { from: string; to: string; campaignId: string }) {\n super(\n 'INVALID_CAMPAIGN_TRANSITION',\n `Campaign ${details.campaignId} cannot move from '${details.from}' to '${details.to}'`,\n details,\n );\n }\n}\n\nexport class DuplicateCampaignError extends CrmError {\n constructor(name: string) {\n super(\n 'DUPLICATE_CAMPAIGN',\n `A campaign named '${name}' already exists`,\n { name },\n );\n }\n}\n\nexport class InvalidSubscriptionTransitionError extends CrmError {\n constructor(details: { from: string; to: string; subscriptionId: string }) {\n super(\n 'INVALID_SUBSCRIPTION_TRANSITION',\n `Subscription ${details.subscriptionId} cannot move from '${details.from}' to '${details.to}'`,\n details,\n );\n }\n}\n\nexport class DuplicateSubscriptionError extends CrmError {\n constructor(details: { contactId: string; campaignId: string }) {\n super(\n 'DUPLICATE_SUBSCRIPTION',\n `Contact '${details.contactId}' already has a live subscription on campaign '${details.campaignId}'`,\n details,\n );\n }\n}\n\nexport class InvalidConfirmationTokenError extends CrmError {\n constructor() {\n super(\n 'INVALID_CONFIRMATION_TOKEN',\n 'No subscription matches the supplied confirmation token, or it has already been used',\n );\n }\n}\n\nexport class InvalidUnsubscribeTokenError extends CrmError {\n constructor() {\n super(\n 'INVALID_UNSUBSCRIBE_TOKEN',\n 'No subscription matches the supplied unsubscribe token',\n );\n }\n}\n","/** PACKAGE_RULES rule 12: `package:resource.verb`. */\nexport const CRM_EVENTS = {\n LEAD_CREATED: 'crm:lead.created',\n LEAD_STATUS_CHANGED: 'crm:lead.status_changed',\n LEAD_SCORED: 'crm:lead.scored',\n LEAD_CONVERTED: 'crm:lead.converted',\n LEAD_DISQUALIFIED: 'crm:lead.disqualified',\n\n ACCOUNT_CREATED: 'crm:account.created',\n ACCOUNT_UPDATED: 'crm:account.updated',\n\n CONTACT_CREATED: 'crm:contact.created',\n CONTACT_UPDATED: 'crm:contact.updated',\n\n OPPORTUNITY_CREATED: 'crm:opportunity.created',\n OPPORTUNITY_STAGE_ADVANCED: 'crm:opportunity.stage_advanced',\n OPPORTUNITY_STAGE_REGRESSED: 'crm:opportunity.stage_regressed',\n OPPORTUNITY_WON: 'crm:opportunity.won',\n OPPORTUNITY_LOST: 'crm:opportunity.lost',\n OPPORTUNITY_ABANDONED: 'crm:opportunity.abandoned',\n\n PIPELINE_CREATED: 'crm:pipeline.created',\n PIPELINE_ARCHIVED: 'crm:pipeline.archived',\n\n ACTIVITY_PLANNED: 'crm:activity.planned',\n ACTIVITY_COMPLETED: 'crm:activity.completed',\n ACTIVITY_CANCELLED: 'crm:activity.cancelled',\n\n NOTE_ADDED: 'crm:note.added',\n\n CAMPAIGN_CREATED: 'crm:campaign.created',\n CAMPAIGN_ACTIVATED: 'crm:campaign.activated',\n CAMPAIGN_PAUSED: 'crm:campaign.paused',\n CAMPAIGN_RESUMED: 'crm:campaign.resumed',\n CAMPAIGN_COMPLETED: 'crm:campaign.completed',\n CAMPAIGN_ARCHIVED: 'crm:campaign.archived',\n\n SUBSCRIPTION_CREATED: 'crm:subscription.created',\n SUBSCRIPTION_CONFIRMED: 'crm:subscription.confirmed',\n SUBSCRIPTION_UNSUBSCRIBED: 'crm:subscription.unsubscribed',\n SUBSCRIPTION_BOUNCED: 'crm:subscription.bounced',\n SUBSCRIPTION_COMPLAINED: 'crm:subscription.complained',\n\n // ─── Email engagement events (0.3.0) ──────────────────────────────────\n EMAIL_EVENT_OPENED: 'crm:email_event.opened',\n EMAIL_EVENT_CLICKED: 'crm:email_event.clicked',\n EMAIL_EVENT_BOUNCED: 'crm:email_event.bounced',\n EMAIL_EVENT_COMPLAINED: 'crm:email_event.complained',\n EMAIL_EVENT_UNSUBSCRIBED: 'crm:email_event.unsubscribed',\n} as const;\n\nexport type CrmEventName = (typeof CRM_EVENTS)[keyof typeof CRM_EVENTS];\n","/**\n * Event creation helper.\n *\n * Thin wrapper around `@classytic/primitives`' `createEvent` that fills the\n * shared `EventMeta` from a `CrmContext` (userId/actorId, organizationId,\n * correlationId). Use this instead of importing `createEvent` directly so\n * the `source: 'crm'` stamp + tenant scoping stay consistent.\n */\n\nimport {\n createEvent as createPrimitiveEvent,\n type DomainEvent,\n type EventMeta,\n} from '@classytic/primitives/events';\nimport type { CrmContext } from '../engine/engine-types.js';\n\nexport function createEvent<T>(\n type: string,\n payload: T,\n ctx?: CrmContext,\n meta?: Partial<EventMeta>,\n): DomainEvent<T> {\n return createPrimitiveEvent<T>(type, payload, {\n source: 'crm',\n ...(ctx?.actorId !== undefined ? { actorId: String(ctx.actorId) } : {}),\n ...(ctx?.organizationId !== undefined\n ? { organizationId: String(ctx.organizationId) }\n : {}),\n ...(ctx?.correlationId !== undefined ? { correlationId: ctx.correlationId } : {}),\n ...meta,\n });\n}\n","/**\n * PipelineRepository — extends `mongokit.Repository`.\n *\n * Domain verbs (`getStage`, `getFirstStage`, `getNextStage`, `archive`)\n * read or mutate the embedded stages array. No `findById` / `findByName`\n * proxies (Rule §3) — callers use inherited `getById` / `getOne` directly.\n */\n\nimport type { Model } from 'mongoose';\nimport {\n Repository,\n type PluginType,\n type PaginationConfig,\n} from '@classytic/mongokit';\nimport type { EventTransport } from '@classytic/primitives/events';\nimport type { IPipelineDocument, IStageDocument } from '../models/pipeline.schema.js';\nimport {\n NotFoundError,\n EmptyPipelineError,\n StageNotInPipelineError,\n} from '../core/errors.js';\nimport { CRM_EVENTS } from '../events/event-constants.js';\nimport { createEvent } from '../events/helpers.js';\nimport type { CrmContext } from '../engine/engine-types.js';\n\nexport interface PipelineRepositoryDeps {\n events: EventTransport;\n}\n\nexport class PipelineRepository extends Repository<IPipelineDocument> {\n private readonly events: EventTransport;\n\n constructor(\n model: Model<IPipelineDocument>,\n plugins: PluginType[],\n deps: PipelineRepositoryDeps,\n pagination?: PaginationConfig,\n ) {\n super(model, plugins, pagination);\n this.events = deps.events;\n }\n\n /**\n * Read a single embedded stage. Used by Opportunity create / move to\n * validate stage membership + pick up `defaultProbability`.\n */\n async getStage(\n pipelineId: string,\n stageId: string,\n ctx?: CrmContext,\n ): Promise<IStageDocument> {\n const pipeline = await this.getById(pipelineId, ctx as any);\n if (!pipeline) throw new NotFoundError('Pipeline', pipelineId);\n if (pipeline.stages.length === 0) throw new EmptyPipelineError(pipelineId);\n const stage = pipeline.stages.find((s) => String(s._id) === stageId);\n if (!stage) throw new StageNotInPipelineError({ pipelineId, stageId });\n return stage;\n }\n\n /** First stage by `sequence` ascending. */\n async getFirstStage(pipelineId: string, ctx?: CrmContext): Promise<IStageDocument> {\n const pipeline = await this.getById(pipelineId, ctx as any);\n if (!pipeline) throw new NotFoundError('Pipeline', pipelineId);\n if (pipeline.stages.length === 0) throw new EmptyPipelineError(pipelineId);\n return [...pipeline.stages].sort((a, b) => a.sequence - b.sequence)[0]!;\n }\n\n /** Stage immediately after the given one. `null` at terminal stage. */\n async getNextStage(\n pipelineId: string,\n stageId: string,\n ctx?: CrmContext,\n ): Promise<IStageDocument | null> {\n const pipeline = await this.getById(pipelineId, ctx as any);\n if (!pipeline) throw new NotFoundError('Pipeline', pipelineId);\n const ordered = [...pipeline.stages].sort((a, b) => a.sequence - b.sequence);\n const idx = ordered.findIndex((s) => String(s._id) === stageId);\n if (idx === -1) throw new StageNotInPipelineError({ pipelineId, stageId });\n return ordered[idx + 1] ?? null;\n }\n\n /** Soft-deprecate — existing opps still move; no new ones can be created. */\n async archive(id: string, ctx?: CrmContext): Promise<IPipelineDocument> {\n const updated = await this.update(id, { isArchived: true } as any, ctx as any);\n if (!updated) throw new NotFoundError('Pipeline', id);\n await this.events.publish(\n createEvent(CRM_EVENTS.PIPELINE_ARCHIVED, { pipelineId: id }, ctx),\n );\n return updated;\n }\n}\n","/**\n * Declarative state machines for every CRM aggregate that has lifecycle\n * transitions. Single source of truth for what `from -> to` moves are\n * legal — the repositories' domain verbs (`qualify`, `convert`, `win`,\n * `lose`, `confirm`, `unsubscribe`, ...) call `assertTransition` before\n * they touch Mongo.\n *\n * Per PACKAGE_RULES §30: \"State machines map to Arc Actions\". The host\n * exposes each domain verb as an arc Action (`POST /:id/action` with\n * `{ action: 'qualify' }`); the verb's implementation lives on the\n * Repository class and uses these machines internally.\n *\n * Built on `@classytic/primitives/state-machine` so the same shape lights\n * up across kits (mongokit's `claim()` pairing, sqlitekit follow-ups).\n */\n\nimport { defineStateMachine } from '@classytic/primitives/state-machine';\nimport { LEAD_STATUSES, LEAD_TRANSITIONS, type LeadStatus } from '../enums/lead-status.js';\nimport {\n OPPORTUNITY_STATUSES,\n OPPORTUNITY_TRANSITIONS,\n type OpportunityStatus,\n} from '../enums/opportunity-status.js';\nimport {\n CAMPAIGN_STATUSES,\n CAMPAIGN_TRANSITIONS,\n type CampaignStatus,\n} from '../enums/campaign-status.js';\nimport {\n SUBSCRIPTION_STATUSES,\n SUBSCRIPTION_TRANSITIONS,\n type SubscriptionStatus,\n} from '../enums/subscription-status.js';\nimport { ACTIVITY_STATUSES, ACTIVITY_TRANSITIONS, type ActivityStatus } from '../enums/activity.js';\nimport {\n InvalidLeadTransitionError,\n InvalidOpportunityTransitionError,\n InvalidCampaignTransitionError,\n InvalidSubscriptionTransitionError,\n InvalidActivityTransitionError,\n} from './errors.js';\n\n// Quiet \"all variants used in transitions table\" exhaustiveness.\nvoid LEAD_STATUSES;\nvoid OPPORTUNITY_STATUSES;\nvoid CAMPAIGN_STATUSES;\nvoid SUBSCRIPTION_STATUSES;\nvoid ACTIVITY_STATUSES;\n\nexport const LEAD_MACHINE = defineStateMachine<LeadStatus>({\n name: 'Lead',\n transitions: LEAD_TRANSITIONS,\n errorFactory: ({ entityId, from, to }) =>\n new InvalidLeadTransitionError({ from, to, leadId: entityId }),\n});\n\nexport const OPPORTUNITY_MACHINE = defineStateMachine<OpportunityStatus>({\n name: 'Opportunity',\n transitions: OPPORTUNITY_TRANSITIONS,\n errorFactory: ({ entityId, from, to }) =>\n new InvalidOpportunityTransitionError({ from, to, opportunityId: entityId }),\n});\n\nexport const CAMPAIGN_MACHINE = defineStateMachine<CampaignStatus>({\n name: 'Campaign',\n transitions: CAMPAIGN_TRANSITIONS,\n errorFactory: ({ entityId, from, to }) =>\n new InvalidCampaignTransitionError({ from, to, campaignId: entityId }),\n});\n\nexport const SUBSCRIPTION_MACHINE = defineStateMachine<SubscriptionStatus>({\n name: 'Subscription',\n transitions: SUBSCRIPTION_TRANSITIONS,\n errorFactory: ({ entityId, from, to }) =>\n new InvalidSubscriptionTransitionError({ from, to, subscriptionId: entityId }),\n});\n\nexport const ACTIVITY_MACHINE = defineStateMachine<ActivityStatus>({\n name: 'Activity',\n transitions: ACTIVITY_TRANSITIONS,\n errorFactory: ({ entityId, from, to }) =>\n new InvalidActivityTransitionError({ from, to, activityId: entityId }),\n});\n","/**\n * Pluggable lead scorer. Hosts inject whatever rubric they need —\n * firmographic model, in-app signals, ML prediction, external enrichment.\n *\n * Stay pure: the scorer must not mutate anything, not hit I/O, and be\n * deterministic for its input. `LeadRepository.recomputeScore` runs the\n * scorer then persists.\n */\n\nimport type { ILeadDocument } from '../../models/lead.schema.js';\n\n/** Minimal Lead shape the scorer reads. */\nexport type LeadInput = Pick<\n ILeadDocument,\n 'email' | 'phone' | 'companyName' | 'tags' | 'jobTitle'\n>;\n\nexport type LeadScorer = (lead: LeadInput) => number;\n\n/**\n * Reference implementation. Intentionally simple — hosts read it and\n * replace it.\n *\n * +20 if email is present\n * +20 if phone is present\n * +20 if companyName is present\n * +10 per populated tag up to 40\n * +10 if jobTitle hints senior (director / manager / head / chief / vp / founder)\n */\nexport function defaultLeadScorer(lead: LeadInput): number {\n let score = 0;\n if (lead.email) score += 20;\n if (lead.phone) score += 20;\n if (lead.companyName) score += 20;\n score += Math.min(40, (lead.tags?.length ?? 0) * 10);\n if (lead.jobTitle && /(director|manager|head|chief|vp|founder)/i.test(lead.jobTitle)) {\n score += 10;\n }\n return score;\n}\n\n/** Compose multiple small rules into one scorer. */\nexport function composeScorers(...rules: readonly LeadScorer[]): LeadScorer {\n return (lead) => rules.reduce((acc, r) => acc + r(lead), 0);\n}\n","/**\n * LeadRepository — extends mongokit `Repository<ILeadDocument>`.\n *\n * Domain verbs (`markContacted`, `qualify`, `disqualify`, `nurture`,\n * `recomputeScore`) live on this class. Multi-entity orchestration\n * (`convert` — spawns Contact + Account + Opportunity) is the one\n * legitimate `LeadService` (Rule §2 — service only when multi-repo+tx).\n *\n * Status transitions are guarded by `LEAD_MACHINE` + atomic\n * `repo.claim()` so two concurrent qualifiers can't both win.\n */\n\nimport type { Model } from 'mongoose';\nimport { Repository, type PluginType, type PaginationConfig } from '@classytic/mongokit';\nimport { assertAndClaim } from '@classytic/primitives/state-machine';\nimport type { EventTransport } from '@classytic/primitives/events';\nimport type { ILeadDocument, ILeadStatusEntry } from '../models/lead.schema.js';\nimport type { LeadStatus } from '../enums/lead-status.js';\nimport { LEAD_MACHINE } from '../core/state-machines.js';\nimport {\n NotFoundError,\n DuplicateLeadError,\n InvalidLeadTransitionError,\n} from '../core/errors.js';\nimport { CRM_EVENTS } from '../events/event-constants.js';\nimport { createEvent } from '../events/helpers.js';\nimport { defaultLeadScorer, type LeadScorer } from '../shared/calculators/scoring.js';\nimport type { CrmContext } from '../engine/engine-types.js';\n\nexport interface LeadRepositoryDeps {\n events: EventTransport;\n /** Override the default lead scorer. */\n scorer?: LeadScorer;\n /** Reject `create()` when an email already exists in-tenant (default true). */\n rejectDuplicates?: boolean;\n}\n\ntype TransitionExtras = { by?: string; note?: string; patch?: Partial<ILeadDocument> };\n\nexport class LeadRepository extends Repository<ILeadDocument> {\n private readonly events: EventTransport;\n private readonly scorer: LeadScorer;\n private readonly rejectDuplicates: boolean;\n\n constructor(\n model: Model<ILeadDocument>,\n plugins: PluginType[],\n deps: LeadRepositoryDeps,\n pagination?: PaginationConfig,\n ) {\n super(model, plugins, pagination);\n this.events = deps.events;\n this.scorer = deps.scorer ?? defaultLeadScorer;\n this.rejectDuplicates = deps.rejectDuplicates ?? true;\n }\n\n /**\n * Create a Lead. Auto-scores on insert so hosts can route immediately.\n * Rejects duplicate emails inside the same tenant unless\n * `rejectDuplicates: false` was set at engine boot.\n */\n async createLead(\n input: Partial<ILeadDocument>,\n ctx?: CrmContext,\n ): Promise<ILeadDocument> {\n if (this.rejectDuplicates && input.email) {\n const existing = await this.getOne({ email: input.email } as any, ctx as any);\n if (existing) throw new DuplicateLeadError({ email: input.email });\n }\n const now = new Date();\n const computedFullName =\n input.fullName ??\n ([input.firstName, input.lastName].filter(Boolean).join(' ').trim() ||\n input.email ||\n input.phone);\n const draft: Partial<ILeadDocument> = {\n ...input,\n fullName: computedFullName,\n status: input.status ?? 'new',\n score: 0,\n statusHistory: [{ status: input.status ?? 'new', occurredAt: now }],\n };\n const created = await this.create(draft as any, ctx as any);\n\n // Score on insert; persist only if non-zero to avoid a no-op write.\n const score = this.scorer(created);\n let result = created;\n if (score !== 0) {\n result = (await this.update(String(created._id), { score } as any, ctx as any)) ?? created;\n await this.events.publish(\n createEvent(CRM_EVENTS.LEAD_SCORED, { leadId: String(created._id), score }, ctx),\n );\n }\n\n await this.events.publish(\n createEvent(\n CRM_EVENTS.LEAD_CREATED,\n { leadId: String(result._id), email: result.email, score: result.score },\n ctx,\n ),\n );\n return result;\n }\n\n async markContacted(id: string, extras: TransitionExtras = {}, ctx?: CrmContext) {\n return this._transition(id, 'contacted', extras, ctx);\n }\n\n async qualify(id: string, extras: TransitionExtras = {}, ctx?: CrmContext) {\n return this._transition(id, 'qualified', extras, ctx);\n }\n\n async disqualify(\n id: string,\n reason: string,\n extras: Omit<TransitionExtras, 'patch'> = {},\n ctx?: CrmContext,\n ) {\n const updated = await this._transition(\n id,\n 'disqualified',\n { ...extras, note: reason, patch: { disqualifyReason: reason } as Partial<ILeadDocument> },\n ctx,\n );\n await this.events.publish(\n createEvent(CRM_EVENTS.LEAD_DISQUALIFIED, { leadId: id, reason }, ctx),\n );\n return updated;\n }\n\n async nurture(id: string, extras: TransitionExtras = {}, ctx?: CrmContext) {\n return this._transition(id, 'nurturing', extras, ctx);\n }\n\n /**\n * Recompute + persist the lead's score. Called from `createLead`\n * automatically; hosts also call this after enrichment writes.\n */\n async recomputeScore(id: string, ctx?: CrmContext): Promise<ILeadDocument> {\n const lead = await this.getById(id, ctx as any);\n if (!lead) throw new NotFoundError('Lead', id);\n const score = this.scorer(lead);\n if (score === lead.score) return lead;\n const updated = await this.update(id, { score } as any, ctx as any);\n if (!updated) throw new NotFoundError('Lead', id);\n await this.events.publish(\n createEvent(CRM_EVENTS.LEAD_SCORED, { leadId: id, score }, ctx),\n );\n return updated;\n }\n\n // ── Internals ─────────────────────────────────────────────────────\n\n private async _transition(\n id: string,\n target: LeadStatus,\n extras: TransitionExtras,\n ctx?: CrmContext,\n ): Promise<ILeadDocument> {\n const existing = await this.getById(id, ctx as any);\n if (!existing) throw new NotFoundError('Lead', id);\n\n // Sync rejection on illegal transitions — feed the same error\n // assertAndClaim would throw if we let it try.\n LEAD_MACHINE.assertTransition(id, existing.status, target);\n\n const entry: ILeadStatusEntry = {\n status: target,\n occurredAt: new Date(),\n ...(extras.by !== undefined ? { by: extras.by } : {}),\n ...(extras.note !== undefined ? { note: extras.note } : {}),\n };\n\n const updated = await assertAndClaim(LEAD_MACHINE, this as any, id, {\n from: existing.status,\n to: target,\n patch: {\n ...(extras.patch ?? {}),\n statusHistory: [...(existing.statusHistory ?? []), entry],\n } as any,\n options: ctx as any,\n });\n if (!updated) {\n // Race-loss — another writer claimed the row first.\n const latest = await this.getById(id, ctx as any);\n throw new InvalidLeadTransitionError({\n from: latest?.status ?? existing.status,\n to: target,\n leadId: id,\n });\n }\n\n await this.events.publish(\n createEvent(\n CRM_EVENTS.LEAD_STATUS_CHANGED,\n { leadId: id, from: existing.status, to: target },\n ctx,\n ),\n );\n return updated as ILeadDocument;\n }\n}\n","/**\n * OpportunityRepository — extends mongokit Repository.\n *\n * Domain verbs:\n * - `openOpportunity` — creates a new opp in a pipeline (resolves stage)\n * - `moveToStage` — atomic CAS on `(pipelineId, stageId)`\n * - `win` / `lose` / `abandon` — terminal transitions via state machine\n *\n * Stage probabilities come from the embedded Stage on the Pipeline doc\n * (read via `PipelineRepository.getStage`).\n */\n\nimport type { Model } from 'mongoose';\nimport { Repository, type PluginType, type PaginationConfig } from '@classytic/mongokit';\nimport { assertAndClaim } from '@classytic/primitives/state-machine';\nimport type { EventTransport } from '@classytic/primitives/events';\nimport type {\n IOpportunityDocument,\n IOpportunityStatusEntry,\n} from '../models/opportunity.schema.js';\nimport type { OpportunityStatus } from '../enums/opportunity-status.js';\nimport { OPPORTUNITY_MACHINE } from '../core/state-machines.js';\nimport {\n NotFoundError,\n InvalidOpportunityTransitionError,\n StageNotInPipelineError,\n} from '../core/errors.js';\nimport { CRM_EVENTS } from '../events/event-constants.js';\nimport { createEvent } from '../events/helpers.js';\nimport type { CrmContext } from '../engine/engine-types.js';\nimport type { PipelineRepository } from './pipeline.repository.js';\n\nexport interface OpportunityRepositoryDeps {\n events: EventTransport;\n /** Cross-repo reference: read embedded stages from Pipeline. */\n pipelines: PipelineRepository;\n}\n\nexport interface OpenOpportunityInput {\n name: string;\n pipelineId: string;\n /** When omitted, opp enters the pipeline's first stage. */\n stageId?: string;\n accountId?: string;\n primaryContactId?: string;\n sourceLeadId?: string;\n amount?: number;\n currency?: string;\n /** Override the stage's `defaultProbability`. */\n probability?: number;\n expectedCloseAt?: Date;\n ownerId?: string;\n tags?: readonly string[];\n metadata?: Record<string, unknown>;\n}\n\nexport interface MoveStageInput {\n stageId: string;\n by?: string;\n note?: string;\n /** Override the target stage's `defaultProbability`. */\n probability?: number;\n}\n\nexport interface CloseInput {\n by?: string;\n note?: string;\n closedAt?: Date;\n amount?: number;\n lostReasonId?: string;\n}\n\nexport class OpportunityRepository extends Repository<IOpportunityDocument> {\n private readonly events: EventTransport;\n private readonly pipelines: PipelineRepository;\n\n constructor(\n model: Model<IOpportunityDocument>,\n plugins: PluginType[],\n deps: OpportunityRepositoryDeps,\n pagination?: PaginationConfig,\n ) {\n super(model, plugins, pagination);\n this.events = deps.events;\n this.pipelines = deps.pipelines;\n }\n\n async openOpportunity(\n input: OpenOpportunityInput,\n ctx?: CrmContext,\n ): Promise<IOpportunityDocument> {\n const stage = input.stageId\n ? await this.pipelines.getStage(input.pipelineId, input.stageId, ctx as any)\n : await this.pipelines.getFirstStage(input.pipelineId, ctx as any);\n\n const now = new Date();\n const draft: Partial<IOpportunityDocument> = {\n name: input.name,\n pipelineId: input.pipelineId,\n stageId: String(stage._id),\n status: 'open',\n probability: input.probability ?? stage.defaultProbability,\n currency: input.currency ?? 'USD',\n statusHistory: [{ status: 'open', stageId: String(stage._id), occurredAt: now }],\n ...(input.accountId !== undefined ? { accountId: input.accountId } : {}),\n ...(input.primaryContactId !== undefined\n ? { primaryContactId: input.primaryContactId }\n : {}),\n ...(input.sourceLeadId !== undefined ? { sourceLeadId: input.sourceLeadId } : {}),\n ...(input.amount !== undefined ? { amount: input.amount } : {}),\n ...(input.expectedCloseAt !== undefined ? { expectedCloseAt: input.expectedCloseAt } : {}),\n ...(input.ownerId !== undefined ? { ownerId: input.ownerId } : {}),\n ...(input.tags !== undefined ? { tags: [...input.tags] } : {}),\n ...(input.metadata !== undefined ? { metadata: input.metadata } : {}),\n };\n\n const created = await this.create(draft as any, ctx as any);\n await this.events.publish(\n createEvent(\n CRM_EVENTS.OPPORTUNITY_CREATED,\n {\n opportunityId: String(created._id),\n pipelineId: input.pipelineId,\n stageId: String(stage._id),\n },\n ctx,\n ),\n );\n return created;\n }\n\n /**\n * Atomic stage move. CAS on `(status='open', stageId=current)` so two\n * concurrent moves can't both win. Emits `stage_advanced` or\n * `stage_regressed` based on `sequence` ordering of the embedded stages.\n */\n async moveToStage(\n id: string,\n input: MoveStageInput,\n ctx?: CrmContext,\n ): Promise<IOpportunityDocument> {\n const existing = await this.getById(id, ctx as any);\n if (!existing) throw new NotFoundError('Opportunity', id);\n if (existing.status !== 'open') {\n throw new InvalidOpportunityTransitionError({\n from: existing.status,\n to: existing.status,\n opportunityId: id,\n });\n }\n const target = await this.pipelines.getStage(\n String(existing.pipelineId),\n input.stageId,\n ctx as any,\n );\n const current = await this.pipelines.getStage(\n String(existing.pipelineId),\n existing.stageId,\n ctx as any,\n );\n\n const probability = input.probability ?? target.defaultProbability;\n const entry: IOpportunityStatusEntry = {\n status: 'open',\n stageId: String(target._id),\n occurredAt: new Date(),\n ...(input.by !== undefined ? { by: input.by } : {}),\n ...(input.note !== undefined ? { note: input.note } : {}),\n };\n const updated = await this.claim(\n id,\n {\n field: 'stageId',\n from: existing.stageId,\n to: String(target._id),\n where: { status: 'open' },\n },\n {\n probability,\n statusHistory: [...(existing.statusHistory ?? []), entry],\n },\n ctx as any,\n );\n if (!updated) {\n throw new StageNotInPipelineError({\n pipelineId: String(existing.pipelineId),\n stageId: String(target._id),\n });\n }\n\n const event =\n target.sequence > current.sequence\n ? CRM_EVENTS.OPPORTUNITY_STAGE_ADVANCED\n : CRM_EVENTS.OPPORTUNITY_STAGE_REGRESSED;\n await this.events.publish(\n createEvent(\n event,\n {\n opportunityId: id,\n from: { stageId: String(current._id), sequence: current.sequence },\n to: { stageId: String(target._id), sequence: target.sequence },\n },\n ctx,\n ),\n );\n return updated as IOpportunityDocument;\n }\n\n async win(id: string, input: CloseInput = {}, ctx?: CrmContext): Promise<IOpportunityDocument> {\n const updated = await this._closeStatus(\n id,\n 'won',\n {\n closedAt: input.closedAt ?? new Date(),\n probability: 1,\n ...(input.amount !== undefined ? { amount: input.amount } : {}),\n },\n { ...(input.by !== undefined ? { by: input.by } : {}), ...(input.note !== undefined ? { note: input.note } : {}) },\n ctx,\n );\n await this.events.publish(\n createEvent(\n CRM_EVENTS.OPPORTUNITY_WON,\n { opportunityId: id, amount: updated.amount },\n ctx,\n ),\n );\n return updated;\n }\n\n async lose(id: string, input: CloseInput = {}, ctx?: CrmContext): Promise<IOpportunityDocument> {\n const updated = await this._closeStatus(\n id,\n 'lost',\n {\n closedAt: input.closedAt ?? new Date(),\n probability: 0,\n ...(input.lostReasonId !== undefined ? { lostReasonId: input.lostReasonId } : {}),\n },\n { ...(input.by !== undefined ? { by: input.by } : {}), ...(input.note !== undefined ? { note: input.note } : {}) },\n ctx,\n );\n await this.events.publish(\n createEvent(\n CRM_EVENTS.OPPORTUNITY_LOST,\n { opportunityId: id, lostReasonId: updated.lostReasonId },\n ctx,\n ),\n );\n return updated;\n }\n\n async abandon(\n id: string,\n by?: string,\n note?: string,\n ctx?: CrmContext,\n ): Promise<IOpportunityDocument> {\n const updated = await this._closeStatus(\n id,\n 'abandoned',\n { closedAt: new Date(), probability: 0 },\n { ...(by !== undefined ? { by } : {}), ...(note !== undefined ? { note } : {}) },\n ctx,\n );\n await this.events.publish(\n createEvent(CRM_EVENTS.OPPORTUNITY_ABANDONED, { opportunityId: id }, ctx),\n );\n return updated;\n }\n\n // ── Internals ─────────────────────────────────────────────────────\n\n private async _closeStatus(\n id: string,\n target: OpportunityStatus,\n patch: Partial<IOpportunityDocument>,\n extras: { by?: string; note?: string },\n ctx?: CrmContext,\n ): Promise<IOpportunityDocument> {\n const existing = await this.getById(id, ctx as any);\n if (!existing) throw new NotFoundError('Opportunity', id);\n\n OPPORTUNITY_MACHINE.assertTransition(id, existing.status, target);\n\n const entry: IOpportunityStatusEntry = {\n status: target,\n stageId: existing.stageId,\n occurredAt: new Date(),\n ...(extras.by !== undefined ? { by: extras.by } : {}),\n ...(extras.note !== undefined ? { note: extras.note } : {}),\n };\n const updated = await assertAndClaim(OPPORTUNITY_MACHINE, this as any, id, {\n from: existing.status,\n to: target,\n patch: {\n ...patch,\n statusHistory: [...(existing.statusHistory ?? []), entry],\n } as any,\n options: ctx as any,\n });\n if (!updated) {\n const latest = await this.getById(id, ctx as any);\n throw new InvalidOpportunityTransitionError({\n from: latest?.status ?? existing.status,\n to: target,\n opportunityId: id,\n });\n }\n return updated as IOpportunityDocument;\n }\n}\n","/**\n * ContactRepository — thin wrapper around mongokit `Repository`.\n *\n * Contacts have no lifecycle transitions of their own (Activity/Note\n * lifecycle hangs off the Activity repo, not Contact). CRUD is fully\n * served by the inherited mongokit surface.\n *\n * Per PACKAGE_RULES §3 we do NOT add proxy methods like\n * `findByEmail` / `findByAccount` — call `getOne({ 'contact.email': … })`\n * directly. The class still exists so hosts can attach a Contact-shaped\n * surface (`engine.repositories.contact`) and so future domain verbs\n * (`merge`, `archive`) have a stable home.\n */\n\nimport type { Model } from 'mongoose';\nimport { Repository, type PluginType, type PaginationConfig } from '@classytic/mongokit';\nimport type { EventTransport } from '@classytic/primitives/events';\nimport type { IContactDocument } from '../models/contact.schema.js';\nimport { CRM_EVENTS } from '../events/event-constants.js';\nimport { createEvent } from '../events/helpers.js';\nimport type { CrmContext } from '../engine/engine-types.js';\n\nexport interface ContactRepositoryDeps {\n events: EventTransport;\n}\n\nexport class ContactRepository extends Repository<IContactDocument> {\n private readonly events: EventTransport;\n\n constructor(\n model: Model<IContactDocument>,\n plugins: PluginType[],\n deps: ContactRepositoryDeps,\n pagination?: PaginationConfig,\n ) {\n super(model, plugins, pagination);\n this.events = deps.events;\n }\n\n /**\n * Create + emit `crm:contact.created`. Hosts call this instead of\n * `create()` when they want the event side-effect (e.g. webhook fan-out).\n */\n async createContact(\n input: Partial<IContactDocument>,\n ctx?: CrmContext,\n ): Promise<IContactDocument> {\n const created = await this.create(input as any, ctx as any);\n await this.events.publish(\n createEvent(\n CRM_EVENTS.CONTACT_CREATED,\n { contactId: String(created._id), email: created.contact?.email },\n ctx,\n ),\n );\n return created;\n }\n}\n","/**\n * AccountRepository — thin wrapper around mongokit `Repository`.\n *\n * Like Contact, Account has no lifecycle. Domain verb `createAccount`\n * emits `crm:account.created` so the host's webhook plumbing fires\n * without callers reaching for events directly.\n */\n\nimport type { Model } from 'mongoose';\nimport { Repository, type PluginType, type PaginationConfig } from '@classytic/mongokit';\nimport type { EventTransport } from '@classytic/primitives/events';\nimport type { IAccountDocument } from '../models/account.schema.js';\nimport { CRM_EVENTS } from '../events/event-constants.js';\nimport { createEvent } from '../events/helpers.js';\nimport type { CrmContext } from '../engine/engine-types.js';\n\nexport interface AccountRepositoryDeps {\n events: EventTransport;\n}\n\nexport class AccountRepository extends Repository<IAccountDocument> {\n private readonly events: EventTransport;\n\n constructor(\n model: Model<IAccountDocument>,\n plugins: PluginType[],\n deps: AccountRepositoryDeps,\n pagination?: PaginationConfig,\n ) {\n super(model, plugins, pagination);\n this.events = deps.events;\n }\n\n async createAccount(\n input: Partial<IAccountDocument>,\n ctx?: CrmContext,\n ): Promise<IAccountDocument> {\n const created = await this.create(input as any, ctx as any);\n await this.events.publish(\n createEvent(\n CRM_EVENTS.ACCOUNT_CREATED,\n { accountId: String(created._id), name: created.name },\n ctx,\n ),\n );\n return created;\n }\n}\n","/**\n * CampaignRepository — extends mongokit Repository.\n *\n * Lifecycle: draft → active ⇄ paused → completed → archived. Each\n * transition lands through `CAMPAIGN_MACHINE` + atomic CAS so concurrent\n * activate/pause calls don't both win.\n */\n\nimport type { Model } from 'mongoose';\nimport { Repository, type PluginType, type PaginationConfig } from '@classytic/mongokit';\nimport { assertAndClaim } from '@classytic/primitives/state-machine';\nimport type { EventTransport } from '@classytic/primitives/events';\nimport type {\n ICampaignDocument,\n ICampaignStatusEntry,\n} from '../models/campaign.schema.js';\nimport type { CampaignStatus } from '../enums/campaign-status.js';\nimport { CAMPAIGN_MACHINE } from '../core/state-machines.js';\nimport {\n NotFoundError,\n DuplicateCampaignError,\n InvalidCampaignTransitionError,\n} from '../core/errors.js';\nimport { CRM_EVENTS } from '../events/event-constants.js';\nimport { createEvent } from '../events/helpers.js';\nimport type { CrmContext } from '../engine/engine-types.js';\n\nexport interface CampaignRepositoryDeps {\n events: EventTransport;\n /** Reject `createCampaign` on duplicate names per-tenant (default true). */\n rejectDuplicates?: boolean;\n}\n\ntype ExtrasWithRevenue = {\n by?: string;\n note?: string;\n actualRevenueAmount?: number;\n};\n\nexport class CampaignRepository extends Repository<ICampaignDocument> {\n private readonly events: EventTransport;\n private readonly rejectDuplicates: boolean;\n\n constructor(\n model: Model<ICampaignDocument>,\n plugins: PluginType[],\n deps: CampaignRepositoryDeps,\n pagination?: PaginationConfig,\n ) {\n super(model, plugins, pagination);\n this.events = deps.events;\n this.rejectDuplicates = deps.rejectDuplicates ?? true;\n }\n\n async createCampaign(\n input: Partial<ICampaignDocument>,\n ctx?: CrmContext,\n ): Promise<ICampaignDocument> {\n if (this.rejectDuplicates && input.name) {\n const existing = await this.getOne({ name: input.name } as any, ctx as any);\n if (existing) throw new DuplicateCampaignError(input.name);\n }\n const now = new Date();\n const draft: Partial<ICampaignDocument> = {\n ...input,\n status: input.status ?? 'draft',\n currency: input.currency ?? 'USD',\n statusHistory: [{ status: input.status ?? 'draft', occurredAt: now }],\n };\n const created = await this.create(draft as any, ctx as any);\n await this.events.publish(\n createEvent(\n CRM_EVENTS.CAMPAIGN_CREATED,\n { campaignId: String(created._id), name: created.name },\n ctx,\n ),\n );\n return created;\n }\n\n async activate(id: string, by?: string, ctx?: CrmContext) {\n const updated = await this._transition(id, 'active', { ...(by !== undefined ? { by } : {}) }, ctx);\n await this.events.publish(\n createEvent(CRM_EVENTS.CAMPAIGN_ACTIVATED, { campaignId: id }, ctx),\n );\n return updated;\n }\n\n async pause(id: string, reason?: string, by?: string, ctx?: CrmContext) {\n const updated = await this._transition(\n id,\n 'paused',\n {\n ...(by !== undefined ? { by } : {}),\n ...(reason !== undefined ? { note: reason } : {}),\n },\n ctx,\n );\n await this.events.publish(\n createEvent(CRM_EVENTS.CAMPAIGN_PAUSED, { campaignId: id, reason }, ctx),\n );\n return updated;\n }\n\n async resume(id: string, by?: string, ctx?: CrmContext) {\n const updated = await this._transition(id, 'active', { ...(by !== undefined ? { by } : {}) }, ctx);\n await this.events.publish(\n createEvent(CRM_EVENTS.CAMPAIGN_RESUMED, { campaignId: id }, ctx),\n );\n return updated;\n }\n\n async complete(id: string, extras: ExtrasWithRevenue = {}, ctx?: CrmContext) {\n const patch: Partial<ICampaignDocument> =\n extras.actualRevenueAmount !== undefined\n ? { actualRevenueAmount: extras.actualRevenueAmount }\n : {};\n const updated = await this._transition(id, 'completed', extras, ctx, patch);\n await this.events.publish(\n createEvent(\n CRM_EVENTS.CAMPAIGN_COMPLETED,\n { campaignId: id, actualRevenueAmount: updated.actualRevenueAmount },\n ctx,\n ),\n );\n return updated;\n }\n\n async archive(id: string, by?: string, ctx?: CrmContext) {\n const updated = await this._transition(id, 'archived', { ...(by !== undefined ? { by } : {}) }, ctx);\n await this.events.publish(\n createEvent(CRM_EVENTS.CAMPAIGN_ARCHIVED, { campaignId: id }, ctx),\n );\n return updated;\n }\n\n // ── Internals ─────────────────────────────────────────────────────\n\n private async _transition(\n id: string,\n target: CampaignStatus,\n extras: { by?: string; note?: string },\n ctx?: CrmContext,\n patch: Partial<ICampaignDocument> = {},\n ): Promise<ICampaignDocument> {\n const existing = await this.getById(id, ctx as any);\n if (!existing) throw new NotFoundError('Campaign', id);\n\n CAMPAIGN_MACHINE.assertTransition(id, existing.status, target);\n\n const entry: ICampaignStatusEntry = {\n status: target,\n occurredAt: new Date(),\n ...(extras.by !== undefined ? { by: extras.by } : {}),\n ...(extras.note !== undefined ? { note: extras.note } : {}),\n };\n const updated = await assertAndClaim(CAMPAIGN_MACHINE, this as any, id, {\n from: existing.status,\n to: target,\n patch: {\n ...patch,\n statusHistory: [...(existing.statusHistory ?? []), entry],\n } as any,\n options: ctx as any,\n });\n if (!updated) {\n const latest = await this.getById(id, ctx as any);\n throw new InvalidCampaignTransitionError({\n from: latest?.status ?? existing.status,\n to: target,\n campaignId: id,\n });\n }\n return updated as ICampaignDocument;\n }\n}\n","/**\n * SubscriptionRepository — extends mongokit Repository.\n *\n * Double opt-in flow:\n * subscribe() → status `pending` (or `confirmed` when DOI off)\n * confirm(token) → `pending → confirmed`\n * unsubscribe() → terminal `unsubscribed`\n * markBounced() → terminal `bounced`\n * markComplained() → terminal `complained`\n *\n * Token lookups (confirm, unsubscribe) use `getOne({ token })` — no\n * proxy `findByConfirmationToken` (Rule §3).\n */\n\nimport { randomUUID } from 'node:crypto';\nimport type { Model } from 'mongoose';\nimport { Repository, type PluginType, type PaginationConfig } from '@classytic/mongokit';\nimport { assertAndClaim } from '@classytic/primitives/state-machine';\nimport type { EventTransport } from '@classytic/primitives/events';\nimport type {\n ISubscriptionDocument,\n ISubscriptionStatusEntry,\n} from '../models/subscription.schema.js';\nimport type { SubscriptionStatus } from '../enums/subscription-status.js';\nimport { SUBSCRIPTION_MACHINE } from '../core/state-machines.js';\nimport {\n NotFoundError,\n DuplicateSubscriptionError,\n InvalidSubscriptionTransitionError,\n InvalidConfirmationTokenError,\n InvalidUnsubscribeTokenError,\n} from '../core/errors.js';\nimport { CRM_EVENTS } from '../events/event-constants.js';\nimport { createEvent } from '../events/helpers.js';\nimport type { CrmContext } from '../engine/engine-types.js';\n\nexport interface SubscriptionRepositoryDeps {\n events: EventTransport;\n /** Default DOI policy when `subscribe` doesn't pass `requireDoubleOptIn`. */\n defaultRequireDoubleOptIn?: boolean;\n}\n\nexport interface SubscribeInput {\n contactId: string;\n campaignId: string;\n source?: string;\n consentIpAddress?: string;\n consentUserAgent?: string;\n metadata?: Record<string, unknown>;\n /** Override the engine-level default. */\n requireDoubleOptIn?: boolean;\n}\n\nexport class SubscriptionRepository extends Repository<ISubscriptionDocument> {\n private readonly events: EventTransport;\n private readonly defaultRequireDoubleOptIn: boolean;\n\n constructor(\n model: Model<ISubscriptionDocument>,\n plugins: PluginType[],\n deps: SubscriptionRepositoryDeps,\n pagination?: PaginationConfig,\n ) {\n super(model, plugins, pagination);\n this.events = deps.events;\n this.defaultRequireDoubleOptIn = deps.defaultRequireDoubleOptIn ?? true;\n }\n\n async subscribe(\n input: SubscribeInput,\n ctx?: CrmContext,\n ): Promise<ISubscriptionDocument> {\n // Reject a duplicate live subscription on the same (contact, campaign).\n const existing = await this.getOne(\n {\n contactId: input.contactId,\n campaignId: input.campaignId,\n status: { $in: ['pending', 'confirmed'] },\n } as any,\n ctx as any,\n );\n if (existing) {\n throw new DuplicateSubscriptionError({\n contactId: input.contactId,\n campaignId: input.campaignId,\n });\n }\n\n const doubleOptIn = input.requireDoubleOptIn ?? this.defaultRequireDoubleOptIn;\n const now = new Date();\n const status: SubscriptionStatus = doubleOptIn ? 'pending' : 'confirmed';\n\n const draft: Partial<ISubscriptionDocument> = {\n contactId: input.contactId,\n campaignId: input.campaignId,\n status,\n statusHistory: [{ status, occurredAt: now }],\n consentTimestamp: now,\n unsubscribeToken: randomUUID(),\n ...(doubleOptIn ? { confirmationToken: randomUUID() } : { confirmedAt: now }),\n ...(input.source !== undefined ? { source: input.source } : {}),\n ...(input.consentIpAddress !== undefined ? { consentIpAddress: input.consentIpAddress } : {}),\n ...(input.consentUserAgent !== undefined ? { consentUserAgent: input.consentUserAgent } : {}),\n ...(input.metadata !== undefined ? { metadata: input.metadata } : {}),\n };\n const sub = await this.create(draft as any, ctx as any);\n await this.events.publish(\n createEvent(\n CRM_EVENTS.SUBSCRIPTION_CREATED,\n {\n subscriptionId: String(sub._id),\n contactId: sub.contactId,\n campaignId: sub.campaignId,\n requiresConfirmation: doubleOptIn,\n },\n ctx,\n ),\n );\n return sub;\n }\n\n async confirm(token: string, ctx?: CrmContext): Promise<ISubscriptionDocument> {\n const sub = await this.getOne({ confirmationToken: token } as any, ctx as any);\n if (!sub || sub.status !== 'pending') {\n throw new InvalidConfirmationTokenError();\n }\n const confirmedAt = new Date();\n const updated = await this._transition(\n String(sub._id),\n 'confirmed',\n { patch: { confirmedAt } as Partial<ISubscriptionDocument> },\n ctx,\n );\n await this.events.publish(\n createEvent(\n CRM_EVENTS.SUBSCRIPTION_CONFIRMED,\n {\n subscriptionId: String(sub._id),\n contactId: sub.contactId,\n campaignId: sub.campaignId,\n confirmedAt: confirmedAt.toISOString(),\n },\n ctx,\n ),\n );\n return updated;\n }\n\n async unsubscribe(\n token: string,\n reason?: string,\n ctx?: CrmContext,\n ): Promise<ISubscriptionDocument> {\n const sub = await this.getOne({ unsubscribeToken: token } as any, ctx as any);\n if (!sub) throw new InvalidUnsubscribeTokenError();\n if (sub.status === 'unsubscribed') return sub; // idempotent\n\n const unsubscribedAt = new Date();\n const updated = await this._transition(\n String(sub._id),\n 'unsubscribed',\n {\n ...(reason !== undefined ? { note: reason } : {}),\n patch: {\n unsubscribedAt,\n ...(reason !== undefined ? { unsubscribeReason: reason } : {}),\n } as Partial<ISubscriptionDocument>,\n },\n ctx,\n );\n await this.events.publish(\n createEvent(\n CRM_EVENTS.SUBSCRIPTION_UNSUBSCRIBED,\n {\n subscriptionId: String(sub._id),\n contactId: sub.contactId,\n campaignId: sub.campaignId,\n ...(reason !== undefined ? { reason } : {}),\n },\n ctx,\n ),\n );\n return updated;\n }\n\n async markBounced(\n id: string,\n reason?: string,\n ctx?: CrmContext,\n ): Promise<ISubscriptionDocument> {\n const existing = await this.getById(id, ctx as any);\n if (!existing) throw new NotFoundError('Subscription', id);\n if (existing.status === 'bounced') return existing;\n\n const bouncedAt = new Date();\n const updated = await this._transition(\n id,\n 'bounced',\n {\n ...(reason !== undefined ? { note: reason } : {}),\n patch: {\n bouncedAt,\n ...(reason !== undefined ? { bounceReason: reason } : {}),\n } as Partial<ISubscriptionDocument>,\n },\n ctx,\n );\n await this.events.publish(\n createEvent(\n CRM_EVENTS.SUBSCRIPTION_BOUNCED,\n {\n subscriptionId: id,\n contactId: existing.contactId,\n campaignId: existing.campaignId,\n ...(reason !== undefined ? { reason } : {}),\n },\n ctx,\n ),\n );\n return updated;\n }\n\n async markComplained(id: string, ctx?: CrmContext): Promise<ISubscriptionDocument> {\n const existing = await this.getById(id, ctx as any);\n if (!existing) throw new NotFoundError('Subscription', id);\n if (existing.status === 'complained') return existing;\n\n const complainedAt = new Date();\n const updated = await this._transition(\n id,\n 'complained',\n { patch: { complainedAt } as Partial<ISubscriptionDocument> },\n ctx,\n );\n await this.events.publish(\n createEvent(\n CRM_EVENTS.SUBSCRIPTION_COMPLAINED,\n {\n subscriptionId: id,\n contactId: existing.contactId,\n campaignId: existing.campaignId,\n },\n ctx,\n ),\n );\n return updated;\n }\n\n // ── Internals ─────────────────────────────────────────────────────\n\n private async _transition(\n id: string,\n target: SubscriptionStatus,\n opts: { patch?: Partial<ISubscriptionDocument>; by?: string; note?: string },\n ctx?: CrmContext,\n ): Promise<ISubscriptionDocument> {\n const existing = await this.getById(id, ctx as any);\n if (!existing) throw new NotFoundError('Subscription', id);\n\n SUBSCRIPTION_MACHINE.assertTransition(id, existing.status, target);\n\n const entry: ISubscriptionStatusEntry = {\n status: target,\n occurredAt: new Date(),\n ...(opts.by !== undefined ? { by: opts.by } : {}),\n ...(opts.note !== undefined ? { note: opts.note } : {}),\n };\n const updated = await assertAndClaim(SUBSCRIPTION_MACHINE, this as any, id, {\n from: existing.status,\n to: target,\n patch: {\n ...(opts.patch ?? {}),\n statusHistory: [...(existing.statusHistory ?? []), entry],\n } as any,\n options: ctx as any,\n });\n if (!updated) {\n const latest = await this.getById(id, ctx as any);\n throw new InvalidSubscriptionTransitionError({\n from: latest?.status ?? existing.status,\n to: target,\n subscriptionId: id,\n });\n }\n return updated as ISubscriptionDocument;\n }\n}\n","/**\n * ActivityRepository — extends mongokit Repository.\n *\n * Lifecycle: planned → in_progress → completed | cancelled. Each\n * transition flows through `ACTIVITY_MACHINE` + atomic CAS.\n *\n * No proxy `listBySubject` (Rule §3) — callers use the polymorphic\n * index directly: `repo.list({ filter: { subjectKind, subjectId } })`.\n */\n\nimport type { Model } from 'mongoose';\nimport { Repository, type PluginType, type PaginationConfig } from '@classytic/mongokit';\nimport { assertAndClaim } from '@classytic/primitives/state-machine';\nimport type { EventTransport } from '@classytic/primitives/events';\nimport type { IActivityDocument } from '../models/activity.schema.js';\nimport type { ActivityStatus } from '../enums/activity.js';\nimport { ACTIVITY_MACHINE } from '../core/state-machines.js';\nimport {\n NotFoundError,\n InvalidActivityTransitionError,\n} from '../core/errors.js';\nimport { CRM_EVENTS } from '../events/event-constants.js';\nimport { createEvent } from '../events/helpers.js';\nimport type { CrmContext } from '../engine/engine-types.js';\n\nexport interface ActivityRepositoryDeps {\n events: EventTransport;\n}\n\nexport class ActivityRepository extends Repository<IActivityDocument> {\n private readonly events: EventTransport;\n\n constructor(\n model: Model<IActivityDocument>,\n plugins: PluginType[],\n deps: ActivityRepositoryDeps,\n pagination?: PaginationConfig,\n ) {\n super(model, plugins, pagination);\n this.events = deps.events;\n }\n\n async plan(input: Partial<IActivityDocument>, ctx?: CrmContext): Promise<IActivityDocument> {\n const draft: Partial<IActivityDocument> = {\n ...input,\n status: 'planned',\n };\n const created = await this.create(draft as any, ctx as any);\n await this.events.publish(\n createEvent(\n CRM_EVENTS.ACTIVITY_PLANNED,\n {\n activityId: String(created._id),\n type: created.type,\n subjectKind: created.subjectKind,\n subjectId: String(created.subjectId),\n },\n ctx,\n ),\n );\n return created;\n }\n\n async start(id: string, ctx?: CrmContext): Promise<IActivityDocument> {\n return this._transition(id, 'in_progress', {}, ctx);\n }\n\n async complete(\n id: string,\n completedAt?: Date,\n ctx?: CrmContext,\n ): Promise<IActivityDocument> {\n const ts = completedAt ?? new Date();\n const updated = await this._transition(\n id,\n 'completed',\n { completedAt: ts } as Partial<IActivityDocument>,\n ctx,\n );\n await this.events.publish(\n createEvent(\n CRM_EVENTS.ACTIVITY_COMPLETED,\n { activityId: id, completedAt: ts.toISOString() },\n ctx,\n ),\n );\n return updated;\n }\n\n async cancel(id: string, reason?: string, ctx?: CrmContext): Promise<IActivityDocument> {\n const updated = await this._transition(\n id,\n 'cancelled',\n reason\n ? ({ metadata: { cancelReason: reason } } as Partial<IActivityDocument>)\n : {},\n ctx,\n );\n await this.events.publish(\n createEvent(\n CRM_EVENTS.ACTIVITY_CANCELLED,\n { activityId: id, ...(reason !== undefined ? { reason } : {}) },\n ctx,\n ),\n );\n return updated;\n }\n\n // ── Internals ─────────────────────────────────────────────────────\n\n private async _transition(\n id: string,\n target: ActivityStatus,\n patch: Partial<IActivityDocument>,\n ctx?: CrmContext,\n ): Promise<IActivityDocument> {\n const existing = await this.getById(id, ctx as any);\n if (!existing) throw new NotFoundError('Activity', id);\n\n ACTIVITY_MACHINE.assertTransition(id, existing.status, target);\n\n const updated = await assertAndClaim(ACTIVITY_MACHINE, this as any, id, {\n from: existing.status,\n to: target,\n patch: patch as any,\n options: ctx as any,\n });\n if (!updated) {\n const latest = await this.getById(id, ctx as any);\n throw new InvalidActivityTransitionError({\n from: latest?.status ?? existing.status,\n to: target,\n activityId: id,\n });\n }\n return updated as IActivityDocument;\n }\n}\n","/**\n * NoteRepository — extends mongokit Repository.\n *\n * Notes have no lifecycle (separated from Activity exactly for that\n * reason). The domain verb `addNote` exists only to emit\n * `crm:note.added`; CRUD is fully served by inherited mongokit methods.\n */\n\nimport type { Model } from 'mongoose';\nimport { Repository, type PluginType, type PaginationConfig } from '@classytic/mongokit';\nimport type { EventTransport } from '@classytic/primitives/events';\nimport type { INoteDocument } from '../models/note.schema.js';\nimport { CRM_EVENTS } from '../events/event-constants.js';\nimport { createEvent } from '../events/helpers.js';\nimport type { CrmContext } from '../engine/engine-types.js';\n\nexport interface NoteRepositoryDeps {\n events: EventTransport;\n}\n\nexport class NoteRepository extends Repository<INoteDocument> {\n private readonly events: EventTransport;\n\n constructor(\n model: Model<INoteDocument>,\n plugins: PluginType[],\n deps: NoteRepositoryDeps,\n pagination?: PaginationConfig,\n ) {\n super(model, plugins, pagination);\n this.events = deps.events;\n }\n\n async addNote(input: Partial<INoteDocument>, ctx?: CrmContext): Promise<INoteDocument> {\n const created = await this.create(input as any, ctx as any);\n await this.events.publish(\n createEvent(\n CRM_EVENTS.NOTE_ADDED,\n {\n noteId: String(created._id),\n subjectKind: created.subjectKind,\n subjectId: String(created.subjectId),\n },\n ctx,\n ),\n );\n return created;\n }\n}\n","/**\n * LossReasonRepository — extends mongokit Repository.\n *\n * Per-org taxonomy with no lifecycle. CRUD + ordering helpers; `archive`\n * just toggles `isActive` so the entry survives for historical\n * opportunity references but disappears from new-loss pickers.\n */\n\nimport type { Model } from 'mongoose';\nimport { Repository, type PluginType, type PaginationConfig } from '@classytic/mongokit';\nimport type { EventTransport } from '@classytic/primitives/events';\nimport type { ILossReasonDocument } from '../models/loss-reason.schema.js';\nimport { NotFoundError } from '../core/errors.js';\nimport type { CrmContext } from '../engine/engine-types.js';\n\nexport interface LossReasonRepositoryDeps {\n events: EventTransport;\n}\n\nexport class LossReasonRepository extends Repository<ILossReasonDocument> {\n private readonly events: EventTransport;\n\n constructor(\n model: Model<ILossReasonDocument>,\n plugins: PluginType[],\n deps: LossReasonRepositoryDeps,\n pagination?: PaginationConfig,\n ) {\n super(model, plugins, pagination);\n this.events = deps.events;\n }\n\n /** Hide from pickers without breaking historical FKs. */\n async archive(id: string, ctx?: CrmContext): Promise<ILossReasonDocument> {\n const updated = await this.update(id, { isActive: false } as any, ctx as any);\n if (!updated) throw new NotFoundError('LossReason', id);\n return updated;\n }\n}\n","/**\n * EmailEventRepository — extends mongokit Repository.\n *\n * Append-only engagement log per recipient (Contact OR Subscription).\n * Each `record*` verb writes one row + emits the matching CRM event.\n * Aggregates (open-rate, click-rate per campaign) are computed via\n * `aggregateHelpersPlugin` on the inherited repo surface; this class\n * doesn't bake them in (PACKAGE_RULES §3 — no proxy methods).\n */\n\nimport type { Model } from 'mongoose';\nimport { Repository, type PluginType, type PaginationConfig } from '@classytic/mongokit';\nimport type { EventTransport } from '@classytic/primitives/events';\nimport type { IEmailEventDocument, EmailEventSubjectKind } from '../models/email-event.schema.js';\nimport type { EmailEventKind } from '../enums/email-event-kind.js';\nimport { CRM_EVENTS } from '../events/event-constants.js';\nimport { createEvent } from '../events/helpers.js';\nimport type { CrmContext } from '../engine/engine-types.js';\n\nexport interface EmailEventRepositoryDeps {\n events: EventTransport;\n}\n\nexport interface RecordEmailEventInput {\n subjectKind: EmailEventSubjectKind;\n subjectId: string;\n campaignId?: string;\n messageId?: string;\n url?: string;\n userAgent?: string;\n ip?: string;\n metadata?: Record<string, unknown>;\n}\n\nconst KIND_TO_EVENT: Record<EmailEventKind, string> = {\n open: CRM_EVENTS.EMAIL_EVENT_OPENED,\n click: CRM_EVENTS.EMAIL_EVENT_CLICKED,\n bounce: CRM_EVENTS.EMAIL_EVENT_BOUNCED,\n complaint: CRM_EVENTS.EMAIL_EVENT_COMPLAINED,\n unsubscribe: CRM_EVENTS.EMAIL_EVENT_UNSUBSCRIBED,\n};\n\nexport class EmailEventRepository extends Repository<IEmailEventDocument> {\n private readonly events: EventTransport;\n\n constructor(\n model: Model<IEmailEventDocument>,\n plugins: PluginType[],\n deps: EmailEventRepositoryDeps,\n pagination?: PaginationConfig,\n ) {\n super(model, plugins, pagination);\n this.events = deps.events;\n }\n\n async recordOpen(input: RecordEmailEventInput, ctx?: CrmContext) {\n return this._record('open', input, ctx);\n }\n\n async recordClick(input: RecordEmailEventInput, ctx?: CrmContext) {\n return this._record('click', input, ctx);\n }\n\n async recordBounce(input: RecordEmailEventInput, ctx?: CrmContext) {\n return this._record('bounce', input, ctx);\n }\n\n async recordComplaint(input: RecordEmailEventInput, ctx?: CrmContext) {\n return this._record('complaint', input, ctx);\n }\n\n async recordUnsubscribe(input: RecordEmailEventInput, ctx?: CrmContext) {\n return this._record('unsubscribe', input, ctx);\n }\n\n // ── Internals ─────────────────────────────────────────────────────\n\n private async _record(\n kind: EmailEventKind,\n input: RecordEmailEventInput,\n ctx?: CrmContext,\n ): Promise<IEmailEventDocument> {\n const draft: Partial<IEmailEventDocument> = {\n kind,\n subjectKind: input.subjectKind,\n subjectId: input.subjectId,\n ...(input.campaignId !== undefined ? { campaignId: input.campaignId } : {}),\n ...(input.messageId !== undefined ? { messageId: input.messageId } : {}),\n ...(input.url !== undefined ? { url: input.url } : {}),\n ...(input.userAgent !== undefined ? { userAgent: input.userAgent } : {}),\n ...(input.ip !== undefined ? { ip: input.ip } : {}),\n ...(input.metadata !== undefined ? { metadata: input.metadata } : {}),\n };\n const created = await this.create(draft as any, ctx as any);\n await this.events.publish(\n createEvent(\n KIND_TO_EVENT[kind],\n {\n eventId: String(created._id),\n kind,\n subjectKind: input.subjectKind,\n subjectId: input.subjectId,\n campaignId: input.campaignId,\n },\n ctx,\n ),\n );\n return created;\n }\n}\n","/**\n * Repository factory — composes the shared mongokit plugin stack and\n * constructs every CRM repository on the host's models.\n *\n * Plugins applied (in order, per PACKAGE_RULES §9 / §22):\n * 1. methodRegistryPlugin — required wiring for other plugins\n * 2. multiTenantPlugin — when `multiTenant !== false`\n * 3. aggregateHelpersPlugin\n * 4. host-supplied `plugins[]` — appended last so hosts can override\n */\n\nimport {\n multiTenantPlugin,\n methodRegistryPlugin,\n aggregateHelpersPlugin,\n type PluginType,\n} from '@classytic/mongokit';\nimport type { CrmModels } from '../models/create-models.js';\nimport type { CrmRepositories, ResolvedCrmConfig } from '../engine/engine-types.js';\nimport type { EventTransport } from '@classytic/primitives/events';\nimport { PipelineRepository } from './pipeline.repository.js';\nimport { LeadRepository } from './lead.repository.js';\nimport { OpportunityRepository } from './opportunity.repository.js';\nimport { ContactRepository } from './contact.repository.js';\nimport { AccountRepository } from './account.repository.js';\nimport { CampaignRepository } from './campaign.repository.js';\nimport { SubscriptionRepository } from './subscription.repository.js';\nimport { ActivityRepository } from './activity.repository.js';\nimport { NoteRepository } from './note.repository.js';\nimport { LossReasonRepository } from './loss-reason.repository.js';\nimport { EmailEventRepository } from './email-event.repository.js';\n\nexport interface CreateCrmRepositoriesDeps {\n events: EventTransport;\n config: ResolvedCrmConfig;\n}\n\nexport function createCrmRepositories(\n models: CrmModels,\n deps: CreateCrmRepositoriesDeps,\n): CrmRepositories {\n const { events, config } = deps;\n const pagination = config.pagination;\n\n const plugins: PluginType[] = [methodRegistryPlugin()];\n if (config.multiTenant) {\n plugins.push(\n multiTenantPlugin({\n tenantField: 'organizationId',\n contextKey: 'organizationId',\n required: true,\n fieldType: config.tenantFieldType,\n }),\n );\n }\n plugins.push(aggregateHelpersPlugin());\n if (config.plugins.length > 0) plugins.push(...config.plugins);\n\n const pipeline = new PipelineRepository(models.Pipeline, plugins, { events }, pagination);\n const lead = new LeadRepository(models.Lead, plugins, { events }, pagination);\n const opportunity = new OpportunityRepository(\n models.Opportunity,\n plugins,\n { events, pipelines: pipeline },\n pagination,\n );\n const contact = new ContactRepository(models.Contact, plugins, { events }, pagination);\n const account = new AccountRepository(models.Account, plugins, { events }, pagination);\n const campaign = new CampaignRepository(models.Campaign, plugins, { events }, pagination);\n const subscription = new SubscriptionRepository(\n models.Subscription,\n plugins,\n { events },\n pagination,\n );\n const activity = new ActivityRepository(models.Activity, plugins, { events }, pagination);\n const note = new NoteRepository(models.Note, plugins, { events }, pagination);\n const lossReason = new LossReasonRepository(models.LossReason, plugins, { events }, pagination);\n const emailEvent = new EmailEventRepository(models.EmailEvent, plugins, { events }, pagination);\n\n return Object.freeze({\n pipeline,\n lead,\n opportunity,\n contact,\n account,\n campaign,\n subscription,\n activity,\n note,\n lossReason,\n emailEvent,\n });\n}\n","/**\n * In-process event bus — default fallback when no `eventTransport` is\n * provided to `createCrm`. Structurally identical to arc's\n * `MemoryEventTransport`; pattern matching is delegated to primitives.\n * Handler errors are swallowed — event emission never blocks writes.\n */\n\nimport {\n matchEventPattern,\n type DomainEvent,\n type EventHandler,\n type EventTransport,\n} from '@classytic/primitives/events';\nimport type { CrmLogger } from '../engine/engine-types.js';\n\ninterface Sub {\n pattern: string;\n handler: EventHandler;\n}\n\nexport class InProcessCrmBus implements EventTransport {\n readonly name = 'in-process-crm';\n private subs: Sub[] = [];\n private logger?: CrmLogger;\n\n constructor(options?: { logger?: CrmLogger }) {\n if (options?.logger) this.logger = options.logger;\n }\n\n async publish(event: DomainEvent): Promise<void> {\n const matching = this.subs.filter((s) => matchEventPattern(s.pattern, event.type));\n for (const sub of matching) {\n try {\n await sub.handler(event);\n } catch (err) {\n this.logger?.error?.(`[crm] event handler error [${event.type}]`, {\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n }\n\n async subscribe(pattern: string, handler: EventHandler): Promise<() => void> {\n const sub: Sub = { pattern, handler };\n this.subs.push(sub);\n return () => {\n this.subs = this.subs.filter((s) => s !== sub);\n };\n }\n\n async close(): Promise<void> {\n this.subs = [];\n }\n}\n","/**\n * createCrm — Engine factory for @classytic/crm v0.3.\n *\n * Flow:\n * 1. Validate `connection` is present\n * 2. Resolve defaults (tenantFieldType=objectId, multiTenant=true, …)\n * 3. Create Mongoose models on the connection (purges stale caches)\n * 4. Resolve EventTransport (or default to in-process bus)\n * 5. Build the repository graph (plugins shared across repos)\n * 6. Return a frozen CrmEngine\n *\n * @example\n * ```ts\n * import mongoose from 'mongoose';\n * import { createCrm } from '@classytic/crm';\n *\n * const crm = await createCrm({\n * connection: mongoose.connection,\n * tenantFieldType: 'objectId',\n * });\n *\n * const lead = await crm.repositories.lead.createLead(\n * { fullName: 'Ada Lovelace', email: 'ada@example.com' },\n * { organizationId: orgId },\n * );\n *\n * crm.events.subscribe('crm:lead.*', async (e) => console.log(e.type));\n * ```\n */\n\nimport type { EventTransport } from '@classytic/primitives/events';\nimport type { CrmConfig, CrmEngine, ResolvedCrmConfig } from './engine-types.js';\nimport { createCrmModels } from '../models/create-models.js';\nimport { createCrmRepositories } from '../repositories/create-repositories.js';\nimport { InProcessCrmBus } from '../events/in-process-bus.js';\n\nexport async function createCrm(config: CrmConfig): Promise<CrmEngine> {\n if (!config.connection) {\n throw new Error('[crm] CrmConfig.connection is required');\n }\n\n const resolved: ResolvedCrmConfig = {\n connection: config.connection,\n tenantFieldType: config.tenantFieldType ?? 'objectId',\n multiTenant: config.multiTenant ?? true,\n ...(config.logger !== undefined ? { logger: config.logger } : {}),\n ...(config.pagination !== undefined ? { pagination: config.pagination } : {}),\n plugins: config.plugins ?? [],\n };\n\n const events: EventTransport =\n config.eventTransport ??\n new InProcessCrmBus(config.logger ? { logger: config.logger } : undefined);\n\n const models = createCrmModels(config.connection, resolved);\n const repositories = createCrmRepositories(models, { events, config: resolved });\n\n const engine: CrmEngine = Object.freeze({\n models,\n repositories,\n events,\n config: Object.freeze(resolved),\n async dispose(): Promise<void> {\n await events.close?.();\n },\n });\n\n return engine;\n}\n\nexport default createCrm;\n","/**\n * LeadService — the ONE multi-repo orchestrator the package ships\n * (PACKAGE_RULES §2 — service only when crossing repos with a single\n * atomic intent). Everything else lives on the repositories.\n *\n * The crown jewel is `convert()`: a Lead becomes an Account + Contact\n * + Opportunity, then transitions to `converted`. The four writes hit\n * four repositories — so we expose this on a service rather than on\n * `LeadRepository`. The caller can wrap the whole thing in\n * `connection.transaction(...)` and pass the `session` through `ctx`,\n * making the conversion atomic.\n */\n\nimport type { ILeadDocument } from '../models/lead.schema.js';\nimport type { IContactDocument, IContactName } from '../models/contact.schema.js';\nimport type { IAccountDocument } from '../models/account.schema.js';\nimport type { IOpportunityDocument } from '../models/opportunity.schema.js';\nimport {\n NotFoundError,\n LeadAlreadyConvertedError,\n InvalidLeadTransitionError,\n} from '../core/errors.js';\nimport { LEAD_MACHINE } from '../core/state-machines.js';\nimport { CRM_EVENTS } from '../events/event-constants.js';\nimport { createEvent } from '../events/helpers.js';\nimport type { LeadRepository } from '../repositories/lead.repository.js';\nimport type { ContactRepository } from '../repositories/contact.repository.js';\nimport type { AccountRepository } from '../repositories/account.repository.js';\nimport type { OpportunityRepository } from '../repositories/opportunity.repository.js';\nimport type { CrmContext, CrmEngine } from '../engine/engine-types.js';\nimport type { EventTransport } from '@classytic/primitives/events';\n\nexport interface ConvertLeadInput {\n pipelineId: string;\n /** Defaults to `<companyName> — <source>` / `<fullName> — New`. */\n opportunityName?: string;\n /** Stored flat on the opportunity (`amount` + `currency`). */\n amount?: number;\n currency?: string;\n expectedCloseAt?: Date;\n by?: string;\n}\n\nexport interface ConvertResult {\n lead: ILeadDocument;\n contact: IContactDocument;\n account?: IAccountDocument;\n opportunity: IOpportunityDocument;\n /** @deprecated use contact._id */\n contactId: string;\n /** @deprecated use account._id */\n accountId?: string;\n /** @deprecated use opportunity._id */\n opportunityId: string;\n}\n\nexport interface LeadServiceDeps {\n lead: LeadRepository;\n contact: ContactRepository;\n account: AccountRepository;\n opportunity: OpportunityRepository;\n events: EventTransport;\n}\n\nexport class LeadService {\n private readonly leads: LeadRepository;\n private readonly contacts: ContactRepository;\n private readonly accounts: AccountRepository;\n private readonly opportunities: OpportunityRepository;\n private readonly events: EventTransport;\n\n constructor(deps: LeadServiceDeps) {\n this.leads = deps.lead;\n this.contacts = deps.contact;\n this.accounts = deps.account;\n this.opportunities = deps.opportunity;\n this.events = deps.events;\n }\n\n /**\n * Construct from an already-built CrmEngine — the host's preferred path.\n * Avoids manually wiring four repositories.\n */\n static fromEngine(engine: CrmEngine): LeadService {\n return new LeadService({\n lead: engine.repositories.lead,\n contact: engine.repositories.contact,\n account: engine.repositories.account,\n opportunity: engine.repositories.opportunity,\n events: engine.events,\n });\n }\n\n /**\n * Convert a Lead into Account + Contact + Opportunity, then transition\n * the lead. Wrap the call in `connection.transaction()` and pass the\n * session via `ctx.session` for atomicity — all four writes commit or\n * roll back together.\n *\n * Best-effort compensation: if a downstream write fails, already-\n * created docs are deleted in reverse order. The reverse delete may\n * itself fail (e.g. transient DB issues) — when transactions are\n * active, prefer that path; compensation is the no-transaction\n * fallback.\n */\n async convert(\n leadId: string,\n input: ConvertLeadInput,\n ctx?: CrmContext,\n ): Promise<ConvertResult> {\n const lead = await this.leads.getById(leadId, ctx as any);\n if (!lead) throw new NotFoundError('Lead', leadId);\n if (lead.status === 'converted') throw new LeadAlreadyConvertedError(leadId);\n if (!LEAD_MACHINE.canTransition(lead.status, 'converted')) {\n throw new InvalidLeadTransitionError({\n from: lead.status,\n to: 'converted',\n leadId,\n });\n }\n\n let account: IAccountDocument | undefined;\n let contact: IContactDocument | undefined;\n let opportunity: IOpportunityDocument | undefined;\n\n try {\n if (lead.companyName) {\n account = await this.accounts.createAccount(\n {\n name: lead.companyName,\n ...(lead.ownerId !== undefined ? { ownerId: lead.ownerId } : {}),\n },\n ctx,\n );\n }\n\n const name = splitLeadName(lead);\n const contactInfo: IContactDocument['contact'] = {\n ...(lead.email !== undefined ? { email: lead.email } : {}),\n ...(lead.phone !== undefined ? { phone: lead.phone } : {}),\n };\n contact = await this.contacts.createContact(\n {\n name,\n contact: contactInfo,\n ...(lead.jobTitle !== undefined ? { jobTitle: lead.jobTitle } : {}),\n ...(account !== undefined ? { accountId: String(account._id) } : {}),\n ...(lead.ownerId !== undefined ? { ownerId: lead.ownerId } : {}),\n },\n ctx,\n );\n\n const opportunityName =\n input.opportunityName ??\n `${lead.companyName ?? lead.fullName} — ${lead.source ?? 'New'}`;\n\n opportunity = await this.opportunities.openOpportunity(\n {\n name: opportunityName,\n pipelineId: input.pipelineId,\n ...(account !== undefined ? { accountId: String(account._id) } : {}),\n primaryContactId: String(contact._id),\n sourceLeadId: leadId,\n ...(input.amount !== undefined ? { amount: input.amount } : {}),\n ...(input.currency !== undefined ? { currency: input.currency } : {}),\n ...(input.expectedCloseAt !== undefined\n ? { expectedCloseAt: input.expectedCloseAt }\n : {}),\n ...(lead.ownerId !== undefined ? { ownerId: lead.ownerId } : {}),\n },\n ctx,\n );\n\n // Transition the lead — patch carries the cross-refs.\n const convertedLead = await this.leads.qualify(leadId, {}, ctx).catch(() => null);\n // If lead wasn't qualified, force the converted transition via\n // `_transition` semantics. Since `qualify` may fail when lead is\n // already qualified, do the converted hop directly.\n const finalLead = convertedLead ?? lead;\n const converted = await this._markConverted(\n String(finalLead._id),\n finalLead.status,\n {\n contactId: String(contact._id),\n ...(account !== undefined ? { accountId: String(account._id) } : {}),\n opportunityId: String(opportunity._id),\n ...(input.by !== undefined ? { by: input.by } : {}),\n },\n ctx,\n );\n\n await this.events.publish(\n createEvent(\n CRM_EVENTS.LEAD_CONVERTED,\n {\n leadId,\n contactId: String(contact._id),\n accountId: account ? String(account._id) : undefined,\n opportunityId: String(opportunity._id),\n },\n ctx,\n ),\n );\n\n return {\n lead: converted,\n contact,\n ...(account !== undefined ? { account } : {}),\n opportunity,\n contactId: String(contact._id),\n ...(account !== undefined ? { accountId: String(account._id) } : {}),\n opportunityId: String(opportunity._id),\n };\n } catch (err) {\n // Best-effort compensation when not running inside a transaction.\n // When a session is present, the caller is expected to roll back —\n // we still emit the deletes for the no-session case (test fixtures,\n // single-node deployments without txn support).\n if (!ctx?.session) {\n try {\n if (opportunity?._id) {\n await this.opportunities.delete(String(opportunity._id), ctx as any);\n }\n if (contact?._id) {\n await this.contacts.delete(String(contact._id), ctx as any);\n }\n if (account?._id) {\n await this.accounts.delete(String(account._id), ctx as any);\n }\n } catch {\n // Swallow — original error is what matters.\n }\n }\n throw err;\n }\n }\n\n /**\n * The state-machine hop from whichever status the lead is in to\n * `converted`. We do this directly (instead of calling\n * `LeadRepository.qualify` first then a hypothetical `complete`)\n * because the conversion is \"this lead is done\" regardless of where\n * it started — bypassing the `qualified` waypoint is intentional when\n * a Lead is converted directly from `new` (importers, webhooks).\n */\n private async _markConverted(\n leadId: string,\n fromStatus: ILeadDocument['status'],\n crossRefs: {\n contactId: string;\n accountId?: string;\n opportunityId: string;\n by?: string;\n },\n ctx?: CrmContext,\n ): Promise<ILeadDocument> {\n if (!LEAD_MACHINE.canTransition(fromStatus, 'converted')) {\n // Surface the illegal transition explicitly — host must `qualify`\n // first when going from `new`/`contacted`.\n throw new InvalidLeadTransitionError({\n from: fromStatus,\n to: 'converted',\n leadId,\n });\n }\n const patch: Partial<ILeadDocument> = {\n convertedContactId: crossRefs.contactId,\n convertedOpportunityId: crossRefs.opportunityId,\n convertedAt: new Date(),\n ...(crossRefs.accountId !== undefined ? { convertedAccountId: crossRefs.accountId } : {}),\n };\n const entry = {\n status: 'converted' as const,\n occurredAt: new Date(),\n ...(crossRefs.by !== undefined ? { by: crossRefs.by } : {}),\n };\n const current = await this.leads.getById(leadId, ctx as any);\n const updated = await this.leads.claim(\n leadId,\n { field: 'status', from: fromStatus, to: 'converted' },\n {\n ...patch,\n statusHistory: [...(current?.statusHistory ?? []), entry],\n },\n ctx as any,\n );\n if (!updated) throw new NotFoundError('Lead', leadId);\n return updated as ILeadDocument;\n }\n}\n\n/**\n * Derive a `PersonName` from a Lead's flat fields. Web forms capture\n * either split `firstName`/`lastName` or a single `fullName`.\n */\nfunction splitLeadName(lead: ILeadDocument): IContactName {\n if (lead.firstName || lead.lastName) {\n const out: IContactName = {\n given: lead.firstName ?? '',\n family: lead.lastName ?? '',\n };\n const combined = `${lead.firstName ?? ''} ${lead.lastName ?? ''}`.trim();\n if (lead.fullName && lead.fullName !== combined) out.preferred = lead.fullName;\n return out;\n }\n const parts = (lead.fullName ?? '').trim().split(/\\s+/);\n if (parts.length <= 1) {\n return { given: parts[0] ?? 'Unknown', family: '' };\n }\n const family = parts.pop() ?? '';\n return { given: parts.join(' '), family };\n}\n","/**\n * Pure forecast calculators — no I/O, no Mongo. Hosts call these after\n * loading opportunities via `repositories.opportunity.list(...)`.\n *\n * Amount is flat (`amount` Number + `currency` String per PACKAGE_RULES\n * §4) — same shape the opportunity schema stores.\n */\n\nimport type { IOpportunityDocument } from '../../models/opportunity.schema.js';\n\nexport type OpportunityForecast = Pick<\n IOpportunityDocument,\n 'amount' | 'currency' | 'probability' | 'status' | 'expectedCloseAt' | 'stageId' | 'statusHistory'\n>;\n\nexport interface ForecastRow {\n /** Bucket key — ISO month `YYYY-MM` by default. */\n bucket: string;\n /** Σ amount. */\n committed: number;\n /** Σ amount × probability. */\n weighted: number;\n /** Number of opportunities in the bucket. */\n count: number;\n currency: string;\n}\n\nexport interface ForecastOptions {\n /** Bucket function. Default: ISO month from `expectedCloseAt`. */\n bucket?: (o: OpportunityForecast) => string;\n /** Filter before bucketing. Default: open + has amount + has expectedCloseAt. */\n include?: (o: OpportunityForecast) => boolean;\n}\n\n/**\n * Aggregate opportunities into a forecast table — one row per bucket.\n * Currency mismatch within a bucket throws — partition by currency\n * upstream when multi-currency.\n */\nexport function forecast(\n opportunities: readonly OpportunityForecast[],\n options: ForecastOptions = {},\n): ForecastRow[] {\n const bucketFn = options.bucket ?? defaultBucket;\n const include = options.include ?? defaultInclude;\n\n const rows = new Map<string, ForecastRow>();\n for (const o of opportunities) {\n if (!include(o)) continue;\n const amt = o.amount as number;\n const bucket = bucketFn(o);\n const existing = rows.get(bucket);\n if (existing) {\n if (existing.currency !== o.currency) {\n throw new Error(\n `Forecast bucket '${bucket}' mixes currencies (${existing.currency} + ${o.currency}). Partition by currency before calling forecast().`,\n );\n }\n rows.set(bucket, {\n ...existing,\n committed: existing.committed + amt,\n weighted: existing.weighted + Math.round(amt * o.probability),\n count: existing.count + 1,\n });\n } else {\n rows.set(bucket, {\n bucket,\n committed: amt,\n weighted: Math.round(amt * o.probability),\n count: 1,\n currency: o.currency,\n });\n }\n }\n return [...rows.values()].sort((a, b) => a.bucket.localeCompare(b.bucket));\n}\n\nfunction defaultInclude(o: OpportunityForecast): boolean {\n return o.status === 'open' && o.amount !== undefined && !!o.expectedCloseAt;\n}\n\nfunction defaultBucket(o: OpportunityForecast): string {\n const d = o.expectedCloseAt as Date;\n const yr = d.getUTCFullYear();\n const mo = String(d.getUTCMonth() + 1).padStart(2, '0');\n return `${yr}-${mo}`;\n}\n\n// ── Pipeline conversion ────────────────────────────────────────────\n\nexport interface ConversionRow {\n stageId: string;\n currentCount: number;\n wonFromHere: number;\n lostFromHere: number;\n conversionRate: number;\n}\n\n/**\n * \"Where do deals die?\" summary — opportunities partitioned across\n * stages with current count + won/lost-from-here.\n */\nexport function pipelineConversion(\n opportunities: readonly OpportunityForecast[],\n stageIds: readonly string[],\n): ConversionRow[] {\n return stageIds.map((stageId): ConversionRow => {\n let currentCount = 0;\n let wonFromHere = 0;\n let lostFromHere = 0;\n for (const o of opportunities) {\n if (o.stageId === stageId && o.status === 'open') currentCount++;\n if (o.status === 'won' || o.status === 'lost') {\n const passed = o.statusHistory?.some((h) => h.stageId === stageId);\n if (passed || o.stageId === stageId) {\n if (o.status === 'won') wonFromHere++;\n else lostFromHere++;\n }\n }\n }\n const closed = wonFromHere + lostFromHere;\n return {\n stageId,\n currentCount,\n wonFromHere,\n lostFromHere,\n conversionRate: closed > 0 ? wonFromHere / closed : 0,\n };\n });\n}\n","/**\n * Shared zod primitives — `objectIdLike` (string-or-objectId), metadata\n * record, tag list. Centralised so every resource validator is consistent.\n */\n\nimport { z } from 'zod';\n\nexport const objectIdLike = z.union([z.string().min(1), z.string()]);\n\nexport const metadataSchema = z.record(z.string(), z.unknown()).optional();\n\nexport const tagsSchema = z.array(z.string().min(1).max(64)).max(50).optional();\n\nexport const moneyAmountSchema = z.number().int().min(0).max(Number.MAX_SAFE_INTEGER);\nexport const currencyCodeSchema = z.string().regex(/^[A-Z]{3}$/, 'Currency must be a 3-letter ISO code');\n","import { z } from 'zod';\nimport { metadataSchema } from './common.js';\n\nconst stageInputSchema = z.object({\n name: z.string().min(1).max(100),\n sequence: z.number().int().min(1),\n defaultProbability: z.number().min(0).max(1),\n color: z.string().max(32).optional(),\n description: z.string().max(500).optional(),\n});\n\nexport const createPipelineSchema = z.object({\n name: z.string().min(1).max(200),\n stages: z.array(stageInputSchema).default([]),\n teamRef: z.string().max(100).optional(),\n metadata: metadataSchema,\n});\n\nexport const updatePipelineSchema = createPipelineSchema.partial();\n\nexport const stageInputSchemaExport = stageInputSchema;\n\nexport const pipelineFilterSchema = z.object({\n isArchived: z.coerce.boolean().optional(),\n teamRef: z.string().optional(),\n});\n\nexport type CreatePipelineDto = z.infer<typeof createPipelineSchema>;\nexport type UpdatePipelineDto = z.infer<typeof updatePipelineSchema>;\nexport type StageInputDto = z.infer<typeof stageInputSchema>;\n","import { z } from 'zod';\nimport { LEAD_STATUSES } from '../enums/lead-status.js';\nimport { metadataSchema, objectIdLike, tagsSchema } from './common.js';\n\nconst leadFieldsSchema = z.object({\n fullName: z.string().min(1).max(200).optional(),\n firstName: z.string().min(1).max(100).optional(),\n lastName: z.string().min(1).max(100).optional(),\n email: z.string().email().max(255).optional(),\n phone: z.string().min(3).max(50).optional(),\n companyName: z.string().min(1).max(200).optional(),\n jobTitle: z.string().min(1).max(150).optional(),\n source: z.string().min(1).max(100).optional(),\n campaignRef: z.string().min(1).max(100).optional(),\n ownerId: z.string().optional(),\n tags: tagsSchema,\n metadata: metadataSchema,\n});\n\nexport const createLeadSchema = leadFieldsSchema.refine(\n (v) => v.fullName || v.firstName || v.lastName || v.email || v.phone,\n 'Lead must have at least one of fullName, firstName/lastName, email, phone',\n);\n\nexport const updateLeadSchema = leadFieldsSchema.partial().refine(\n (v) => Object.keys(v).length > 0,\n 'updateLead requires at least one field',\n);\n\nexport const leadFilterSchema = z.object({\n status: z.enum(LEAD_STATUSES).optional(),\n ownerId: z.string().optional(),\n email: z.string().optional(),\n tags: z.array(z.string()).optional(),\n source: z.string().optional(),\n campaignRef: z.string().optional(),\n scoreMin: z.number().int().optional(),\n scoreMax: z.number().int().optional(),\n});\n\nexport const convertLeadSchema = z.object({\n pipelineId: objectIdLike,\n opportunityName: z.string().min(1).max(200).optional(),\n amount: z.number().nonnegative().optional(),\n currency: z.string().regex(/^[A-Z]{3}$/).optional(),\n expectedCloseAt: z.coerce.date().optional(),\n by: z.string().optional(),\n});\n\nexport type CreateLeadDto = z.infer<typeof createLeadSchema>;\nexport type UpdateLeadDto = z.infer<typeof updateLeadSchema>;\nexport type ConvertLeadDto = z.infer<typeof convertLeadSchema>;\nexport type LeadFilterDto = z.infer<typeof leadFilterSchema>;\n","import { z } from 'zod';\nimport { OPPORTUNITY_STATUSES } from '../enums/opportunity-status.js';\nimport { currencyCodeSchema, metadataSchema, objectIdLike, tagsSchema } from './common.js';\n\nexport const openOpportunitySchema = z.object({\n name: z.string().min(1).max(200),\n pipelineId: objectIdLike,\n stageId: z.string().optional(),\n accountId: objectIdLike.optional(),\n primaryContactId: objectIdLike.optional(),\n sourceLeadId: objectIdLike.optional(),\n amount: z.number().nonnegative().optional(),\n currency: currencyCodeSchema.optional(),\n probability: z.number().min(0).max(1).optional(),\n expectedCloseAt: z.coerce.date().optional(),\n ownerId: z.string().optional(),\n tags: tagsSchema,\n metadata: metadataSchema,\n});\n\nexport const moveStageSchema = z.object({\n stageId: z.string().min(1),\n by: z.string().optional(),\n note: z.string().max(500).optional(),\n probability: z.number().min(0).max(1).optional(),\n});\n\nexport const closeWinSchema = z.object({\n by: z.string().optional(),\n note: z.string().max(500).optional(),\n closedAt: z.coerce.date().optional(),\n amount: z.number().nonnegative().optional(),\n});\n\nexport const closeLossSchema = z.object({\n by: z.string().optional(),\n note: z.string().max(500).optional(),\n closedAt: z.coerce.date().optional(),\n lostReasonId: objectIdLike.optional(),\n});\n\nexport const opportunityFilterSchema = z.object({\n status: z.enum(OPPORTUNITY_STATUSES).optional(),\n pipelineId: objectIdLike.optional(),\n stageId: z.string().optional(),\n ownerId: z.string().optional(),\n accountId: objectIdLike.optional(),\n expectedCloseFrom: z.coerce.date().optional(),\n expectedCloseTo: z.coerce.date().optional(),\n});\n\nexport type OpenOpportunityDto = z.infer<typeof openOpportunitySchema>;\nexport type MoveStageDto = z.infer<typeof moveStageSchema>;\nexport type CloseWinDto = z.infer<typeof closeWinSchema>;\nexport type CloseLossDto = z.infer<typeof closeLossSchema>;\nexport type OpportunityFilterDto = z.infer<typeof opportunityFilterSchema>;\n","import { z } from 'zod';\nimport { metadataSchema, objectIdLike, tagsSchema } from './common.js';\n\nconst contactNameSchema = z.object({\n given: z.string().min(1).max(100),\n family: z.string().min(0).max(100).default(''),\n middle: z.string().max(100).optional(),\n prefix: z.string().max(32).optional(),\n suffix: z.string().max(32).optional(),\n preferred: z.string().max(100).optional(),\n});\n\nconst contactInfoSchema = z.object({\n email: z.string().email().max(255).optional(),\n personalEmail: z.string().email().max(255).optional(),\n phone: z.string().max(50).optional(),\n alternatePhone: z.string().max(50).optional(),\n});\n\nexport const createContactSchema = z.object({\n name: contactNameSchema,\n contact: contactInfoSchema.default({}),\n jobTitle: z.string().max(150).optional(),\n accountId: objectIdLike.optional(),\n ownerId: z.string().optional(),\n tags: tagsSchema,\n metadata: metadataSchema,\n});\n\nexport const updateContactSchema = createContactSchema.partial();\n\nexport const contactFilterSchema = z.object({\n accountId: objectIdLike.optional(),\n ownerId: z.string().optional(),\n email: z.string().optional(),\n tags: z.array(z.string()).optional(),\n});\n\nexport type CreateContactDto = z.infer<typeof createContactSchema>;\nexport type UpdateContactDto = z.infer<typeof updateContactSchema>;\n","import { z } from 'zod';\nimport { currencyCodeSchema, metadataSchema, tagsSchema } from './common.js';\n\nexport const createAccountSchema = z.object({\n name: z.string().min(1).max(200),\n domain: z.string().max(255).optional(),\n industry: z.string().max(100).optional(),\n sizeBucket: z.string().max(20).optional(),\n annualRevenueAmount: z.number().nonnegative().optional(),\n annualRevenueCurrency: currencyCodeSchema.optional(),\n ownerId: z.string().optional(),\n tags: tagsSchema,\n metadata: metadataSchema,\n});\n\nexport const updateAccountSchema = createAccountSchema.partial();\n\nexport const accountFilterSchema = z.object({\n domain: z.string().optional(),\n industry: z.string().optional(),\n ownerId: z.string().optional(),\n tags: z.array(z.string()).optional(),\n});\n\nexport type CreateAccountDto = z.infer<typeof createAccountSchema>;\nexport type UpdateAccountDto = z.infer<typeof updateAccountSchema>;\n","import { z } from 'zod';\nimport { CAMPAIGN_STATUSES } from '../enums/campaign-status.js';\nimport { currencyCodeSchema, metadataSchema, tagsSchema } from './common.js';\n\nexport const createCampaignSchema = z.object({\n name: z.string().min(1).max(200),\n description: z.string().max(2000).optional(),\n utmSource: z.string().max(100).optional(),\n utmMedium: z.string().max(100).optional(),\n utmCampaign: z.string().max(100).optional(),\n startDate: z.coerce.date().optional(),\n endDate: z.coerce.date().optional(),\n budgetAmount: z.number().nonnegative().optional(),\n expectedRevenueAmount: z.number().nonnegative().optional(),\n currency: currencyCodeSchema.optional(),\n ownerId: z.string().optional(),\n tags: tagsSchema,\n metadata: metadataSchema,\n});\n\nexport const updateCampaignSchema = createCampaignSchema.partial();\n\nexport const completeCampaignSchema = z.object({\n by: z.string().optional(),\n note: z.string().max(500).optional(),\n actualRevenueAmount: z.number().nonnegative().optional(),\n});\n\nexport const campaignFilterSchema = z.object({\n status: z.enum(CAMPAIGN_STATUSES).optional(),\n ownerId: z.string().optional(),\n tags: z.array(z.string()).optional(),\n startDateFrom: z.coerce.date().optional(),\n startDateTo: z.coerce.date().optional(),\n});\n\nexport type CreateCampaignDto = z.infer<typeof createCampaignSchema>;\nexport type UpdateCampaignDto = z.infer<typeof updateCampaignSchema>;\nexport type CompleteCampaignDto = z.infer<typeof completeCampaignSchema>;\n","import { z } from 'zod';\nimport { SUBSCRIPTION_STATUSES } from '../enums/subscription-status.js';\nimport { metadataSchema, objectIdLike } from './common.js';\n\nexport const subscribeSchema = z.object({\n contactId: objectIdLike,\n campaignId: objectIdLike,\n source: z.string().max(100).optional(),\n consentIpAddress: z.string().max(64).optional(),\n consentUserAgent: z.string().max(500).optional(),\n metadata: metadataSchema,\n requireDoubleOptIn: z.boolean().optional(),\n});\n\nexport const confirmSubscriptionSchema = z.object({\n token: z.string().min(1).max(200),\n});\n\nexport const unsubscribeSchema = z.object({\n token: z.string().min(1).max(200),\n reason: z.string().max(500).optional(),\n});\n\nexport const subscriptionFilterSchema = z.object({\n status: z.enum(SUBSCRIPTION_STATUSES).optional(),\n contactId: objectIdLike.optional(),\n campaignId: objectIdLike.optional(),\n});\n\nexport type SubscribeDto = z.infer<typeof subscribeSchema>;\nexport type ConfirmSubscriptionDto = z.infer<typeof confirmSubscriptionSchema>;\nexport type UnsubscribeDto = z.infer<typeof unsubscribeSchema>;\n","import { z } from 'zod';\nimport {\n ACTIVITY_STATUSES,\n ACTIVITY_TYPES,\n SUBJECT_KINDS,\n} from '../enums/activity.js';\nimport { metadataSchema, objectIdLike } from './common.js';\n\nexport const planActivitySchema = z.object({\n type: z.enum(ACTIVITY_TYPES),\n subjectKind: z.enum(SUBJECT_KINDS),\n subjectId: objectIdLike,\n title: z.string().min(1).max(200),\n description: z.string().max(2000).optional(),\n ownerId: z.string().optional(),\n participantIds: z.array(z.string()).max(50).optional(),\n dueDate: z.coerce.date().optional(),\n externalRef: z.string().max(200).optional(),\n metadata: metadataSchema,\n});\n\nexport const updateActivitySchema = planActivitySchema.partial();\n\nexport const cancelActivitySchema = z.object({\n reason: z.string().max(500).optional(),\n});\n\nexport const activityFilterSchema = z.object({\n type: z.enum(ACTIVITY_TYPES).optional(),\n status: z.enum(ACTIVITY_STATUSES).optional(),\n subjectKind: z.enum(SUBJECT_KINDS).optional(),\n subjectId: objectIdLike.optional(),\n ownerId: z.string().optional(),\n dueDateFrom: z.coerce.date().optional(),\n dueDateTo: z.coerce.date().optional(),\n});\n\nexport type PlanActivityDto = z.infer<typeof planActivitySchema>;\nexport type CancelActivityDto = z.infer<typeof cancelActivitySchema>;\n","import { z } from 'zod';\nimport { SUBJECT_KINDS } from '../enums/activity.js';\nimport { metadataSchema, objectIdLike } from './common.js';\n\nexport const addNoteSchema = z.object({\n subjectKind: z.enum(SUBJECT_KINDS),\n subjectId: objectIdLike,\n body: z.string().min(1).max(10000),\n authorId: z.string().optional(),\n pinned: z.boolean().optional(),\n metadata: metadataSchema,\n});\n\nexport const updateNoteSchema = z.object({\n body: z.string().min(1).max(10000).optional(),\n pinned: z.boolean().optional(),\n metadata: metadataSchema,\n});\n\nexport const noteFilterSchema = z.object({\n subjectKind: z.enum(SUBJECT_KINDS).optional(),\n subjectId: objectIdLike.optional(),\n authorId: z.string().optional(),\n pinned: z.coerce.boolean().optional(),\n});\n\nexport type AddNoteDto = z.infer<typeof addNoteSchema>;\nexport type UpdateNoteDto = z.infer<typeof updateNoteSchema>;\n","import { z } from 'zod';\nimport { metadataSchema } from './common.js';\n\nexport const createLossReasonSchema = z.object({\n name: z.string().min(1).max(200),\n description: z.string().max(1000).optional(),\n isActive: z.boolean().optional(),\n sequence: z.number().int().min(0).optional(),\n metadata: metadataSchema,\n});\n\nexport const updateLossReasonSchema = createLossReasonSchema.partial();\n\nexport const lossReasonFilterSchema = z.object({\n isActive: z.coerce.boolean().optional(),\n});\n\nexport type CreateLossReasonDto = z.infer<typeof createLossReasonSchema>;\nexport type UpdateLossReasonDto = z.infer<typeof updateLossReasonSchema>;\n","import { z } from 'zod';\nimport { EMAIL_EVENT_KINDS } from '../enums/email-event-kind.js';\nimport { EMAIL_EVENT_SUBJECT_KINDS } from '../models/email-event.schema.js';\nimport { metadataSchema, objectIdLike } from './common.js';\n\nexport const recordEmailEventSchema = z.object({\n subjectKind: z.enum(EMAIL_EVENT_SUBJECT_KINDS),\n subjectId: objectIdLike,\n campaignId: objectIdLike.optional(),\n messageId: z.string().max(200).optional(),\n url: z.string().max(2048).optional(),\n userAgent: z.string().max(500).optional(),\n ip: z.string().max(64).optional(),\n metadata: metadataSchema,\n});\n\nexport const emailEventFilterSchema = z.object({\n kind: z.enum(EMAIL_EVENT_KINDS).optional(),\n subjectKind: z.enum(EMAIL_EVENT_SUBJECT_KINDS).optional(),\n subjectId: objectIdLike.optional(),\n campaignId: objectIdLike.optional(),\n messageId: z.string().optional(),\n});\n\nexport type RecordEmailEventDto = z.infer<typeof recordEmailEventSchema>;\n","export * from './common.js';\nexport * from './pipeline.schema.js';\nexport * from './lead.schema.js';\nexport * from './opportunity.schema.js';\nexport * from './contact.schema.js';\nexport * from './account.schema.js';\nexport * from './campaign.schema.js';\nexport * from './subscription.schema.js';\nexport * from './activity.schema.js';\nexport * from './note.schema.js';\nexport * from './loss-reason.schema.js';\nexport * from './email-event.schema.js';\n"],"mappings":"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"}