import { SmrtCollection, SmrtObject } from '@happyvertical/smrt-core'; import { SupportCaseStatus } from '../types.js'; /** Generate a short human-facing case number (unique enough per tenant). */ export declare function generateCaseNumber(now?: Date): string; export declare class SupportCase extends SmrtObject { tenantId: string | null; /** Human-facing case reference (e.g. `SUP-…`), generated at open time. */ caseNumber: string; /** Short client-facing summary of the request. */ subject: string; /** Initial request text (the first inbound interaction's body). */ description: string; status: SupportCaseStatus; /** Queue ordering priority: `low` | `normal` | `high` | `urgent`. */ priority: string; /** * Severity key resolved against the plan's severity definitions (e.g. * `sev1`…`sev4`). Empty until triage/classification assigns one. */ severity: string; /** Classification category (AI- or human-assigned). Free vocabulary. */ category: string; /** Whether the subject matter was flagged sensitive (handoff trigger). */ sensitive: boolean; /** Origin transport kind (`chat` | `email` | …). */ channelKind: string; /** * The Client this Case belongs to (FR-29) — a `Person` or `Organization` * Profile. Nullable so unmatched inbound email can park a Case for triage; * intake marks those with `metadata.unresolvedClient`. */ clientProfileId: string | null; /** The person who opened the request, when distinct from the Client. */ openedByProfileId: string | null; /** * App-defined Project reference (a client initiative, not a repo board). * Deliberately a plain string — the consuming app owns the Project concept. */ projectId: string | null; /** Channel binding that created this case, when intake-created. */ bindingId: string | null; /** * Deterministic conversation key used by create-or-join intake dedup * (e.g. `chat:[:]` or `email:`). */ threadKey: string; /** Managed Support Plan governing this case, when one applies. */ planId: string | null; /** * JSON snapshot of the plan terms captured when the plan was applied, so * later plan edits never rewrite the terms a case was handled under. * Read through {@link getPlanSnapshot}. */ planSnapshot: string; assignedSpecialistId: string | null; assignedAt: Date | null; /** Client/plan preferred specialist considered first by routing (FR-30). */ preferredSpecialistId: string | null; /** Current escalation level (0 = never escalated). */ escalationLevel: number; escalatedAt: Date | null; /** First outbound acknowledgement of any kind (starts as `null`). */ acknowledgedAt: Date | null; /** First substantive outbound response (specialist or agent). */ firstRespondedAt: Date | null; /** Set when the client explicitly requested a human (FR-28b). */ humanRequestedAt: Date | null; resolvedAt: Date | null; resolvedByProfileId: string | null; /** How the case was resolved: `automated` | `human` | `delivery`. */ resolutionKind: string; resolutionSummary: string; closedAt: Date | null; /** Times this case was reopened; prior resolutions live in case events. */ reopenCount: number; lastReopenedAt: Date | null; /** Per-case escape hatch: disable the AI workflow for this case only. */ aiEnabled: boolean; metadata: string; /** Whether the case is in an open (not resolved/closed) state. */ isOpen(): boolean; getMetadata(): Record; setMetadata(value: Record): void; updateMetadata(patch: Record): void; getPlanSnapshot(): Record; setPlanSnapshot(value: Record): void; /** * Capture the status the row was loaded with so the save-time guard can * reject illegal flips made via raw field assignment. */ initialize(): Promise; /** Validate the status transition before persisting, then save. */ save(): Promise; protected assertStatusTransition(prior: SupportCaseStatus | undefined): void; /** * Resolve the AUTHORITATIVE prior status. The WeakMap only covers rows * hydrated through {@link initialize}; a `create({ id, _skipLoad: true })` * upsert would otherwise look brand-new and skip the guard, so when the * instance carries an id, read the persisted row directly (S5 #1390 idiom). */ protected resolvePriorStatus(): Promise; } export declare class SupportCaseCollection extends SmrtCollection { static readonly _itemClass: typeof SupportCase; /** * Find the open case an inbound interaction should join, by conversation * key (create-or-join dedup, FR-28). Returns the most recently updated open * case for the key, or `null` when a new case should be created. */ findOpenByThreadKey(threadKey: string, options?: { bindingId?: string | null; }): Promise; /** Queue listing with common filters, newest first. */ findQueue(options?: { status?: SupportCaseStatus | SupportCaseStatus[]; assignedSpecialistId?: string | null; clientProfileId?: string; projectId?: string; openOnly?: boolean; limit?: number; offset?: number; }): Promise; } export default SupportCase; //# sourceMappingURL=support-case.d.ts.map