import { ChannelType } from "../Common/Channels/ChannelType"; import { ITicketAuditedEntity, ITicketProperty, TicketPriority, TicketPropertyValue } from "./Common"; import { ITicketMessageReference } from "./Conversation"; import type { ITicketCursorResponse } from "./Api"; import type { ITicketAttachmentUploadSession } from "./AdvancedApi"; import type { ITicketFieldOption, ITicketFieldValidation, ITicketObjectField, TicketFieldType } from "./Fields"; export declare enum TicketPortalAuthenticationMode { PUBLIC = "PUBLIC", OPTIONAL = "OPTIONAL", REQUIRED = "REQUIRED" } export declare enum TicketRequestDraftStatus { DRAFT = "DRAFT", VALIDATING = "VALIDATING", READY = "READY", SUBMITTED = "SUBMITTED", EXPIRED = "EXPIRED", CANCELLED = "CANCELLED" } export declare enum TicketCustomerAction { COMMENT = "COMMENT", ADD_ATTACHMENT = "ADD_ATTACHMENT", CANCEL = "CANCEL", REOPEN = "REOPEN", COMPLETE_FORM = "COMPLETE_FORM", APPROVE = "APPROVE" } export declare enum TicketAudienceRuleEffect { ALLOW = "ALLOW", DENY = "DENY" } export declare enum TicketNotificationEvent { CREATED = "CREATED", PUBLIC_REPLY = "PUBLIC_REPLY", PUBLIC_STATUS_CHANGED = "PUBLIC_STATUS_CHANGED", ACTION_REQUIRED = "ACTION_REQUIRED", RESOLVED = "RESOLVED", REOPENED = "REOPENED", SATISFACTION_REQUESTED = "SATISFACTION_REQUESTED" } export declare enum TicketDeflectionOutcome { SUGGESTION_SHOWN = "SUGGESTION_SHOWN", ARTICLE_OPENED = "ARTICLE_OPENED", KNOWN_ISSUE_OPENED = "KNOWN_ISSUE_OPENED", ABANDONED = "ABANDONED", TICKET_CREATED = "TICKET_CREATED" } export declare enum TicketKnowledgeReferenceType { ARTICLE = "ARTICLE", COLLECTION = "COLLECTION", FOLDER = "FOLDER" } export interface ITicketPortal extends ITicketAuditedEntity { name: string; slug: string; title: string; description?: string; logoUrl?: string; faviconUrl?: string; primaryColor?: string; defaultLocale: string; supportedLocales?: string[]; authenticationMode: TicketPortalAuthenticationMode; allowTicketCreation: boolean; allowTicketTracking: boolean; allowComments: boolean; allowReopen: boolean; allowCancellation: boolean; allowAttachments: boolean; termsDocumentId?: string; privacyDocumentId?: string; enabled: boolean; } export interface ICreateTicketPortalDto { name: string; slug: string; title: string; description?: string; logoUrl?: string; faviconUrl?: string; primaryColor?: string; defaultLocale: string; supportedLocales?: string[]; authenticationMode: TicketPortalAuthenticationMode; allowTicketCreation?: boolean; allowTicketTracking?: boolean; allowComments?: boolean; allowReopen?: boolean; allowCancellation?: boolean; allowAttachments?: boolean; termsDocumentId?: string; privacyDocumentId?: string; enabled?: boolean; } export interface IUpdateTicketPortalDto { name?: string; slug?: string; title?: string; description?: string | null; logoUrl?: string | null; faviconUrl?: string | null; primaryColor?: string | null; defaultLocale?: string; supportedLocales?: string[] | null; authenticationMode?: TicketPortalAuthenticationMode; allowTicketCreation?: boolean; allowTicketTracking?: boolean; allowComments?: boolean; allowReopen?: boolean; allowCancellation?: boolean; allowAttachments?: boolean; termsDocumentId?: string | null; privacyDocumentId?: string | null; enabled?: boolean; } export interface ITicketRequestType extends ITicketAuditedEntity { name: string; description?: string; categoryId: string; icon?: string; formId: string; formVersion?: number; workflowId?: string; defaultPriority?: TicketPriority; defaultAssignedGroupId?: string; slaPolicyId?: string; /** * @deprecated Never used. Public status resolution is space-level, not per * request type - see the public portal surface. Always undefined; will be * removed in a later release. */ publicStatusSchemeId?: string; fieldDefinitionIds?: string[]; layoutIds?: string[]; audiencePolicyId?: string; enabled: boolean; } export interface ICreateTicketRequestTypeDto { name: string; description?: string; categoryId: string; icon?: string; formId?: string; formVersion?: number; workflowId?: string; defaultPriority?: TicketPriority; defaultAssignedGroupId?: string; slaPolicyId?: string; fieldDefinitionIds?: string[]; layoutIds?: string[]; audiencePolicyId?: string; enabled?: boolean; } export interface IUpdateTicketRequestTypeDto { name?: string; description?: string | null; categoryId?: string; icon?: string | null; formId?: string; formVersion?: number | null; workflowId?: string | null; defaultPriority?: TicketPriority | null; defaultAssignedGroupId?: string | null; slaPolicyId?: string | null; fieldDefinitionIds?: string[] | null; layoutIds?: string[] | null; audiencePolicyId?: string | null; enabled?: boolean; } export interface IServiceCatalog extends ITicketAuditedEntity { portalId: string; name: string; description?: string; order?: number; enabled: boolean; } export interface ICreateServiceCatalogDto { portalId: string; name: string; description?: string; order?: number; enabled?: boolean; } export interface IUpdateServiceCatalogDto { portalId?: string; name?: string; description?: string | null; order?: number | null; enabled?: boolean; } export interface IServiceCatalogSection extends ITicketAuditedEntity { catalogId: string; parentSectionId?: string; name: string; description?: string; icon?: string; order: number; enabled: boolean; } export interface ICreateServiceCatalogSectionDto { catalogId: string; parentSectionId?: string; name: string; description?: string; icon?: string; order?: number; enabled?: boolean; } export interface IUpdateServiceCatalogSectionDto { catalogId?: string; parentSectionId?: string | null; name?: string; description?: string | null; icon?: string | null; order?: number; enabled?: boolean; } export interface IServiceCatalogItem extends ITicketAuditedEntity { catalogId: string; sectionId?: string; requestTypeId: string; name: string; shortDescription?: string; imageUrl?: string; order: number; estimatedDeliveryMinutes?: number; audiencePolicyId?: string; enabled: boolean; } export interface ICreateServiceCatalogItemDto { catalogId: string; sectionId?: string; requestTypeId: string; name: string; shortDescription?: string; imageUrl?: string; order?: number; estimatedDeliveryMinutes?: number; audiencePolicyId?: string; enabled?: boolean; } export interface IUpdateServiceCatalogItemDto { catalogId?: string; sectionId?: string | null; requestTypeId?: string; name?: string; shortDescription?: string | null; imageUrl?: string | null; order?: number; estimatedDeliveryMinutes?: number | null; audiencePolicyId?: string | null; enabled?: boolean; } export interface ITicketAudienceRule { id: string; effect: TicketAudienceRuleEffect; authenticatedOnly?: boolean; organizationIds?: string[]; contactSegmentIds?: string[]; contactIds?: string[]; roleIds?: string[]; countries?: string[]; } export interface ITicketAudiencePolicy extends ITicketAuditedEntity { name: string; description?: string; defaultEffect: TicketAudienceRuleEffect; rules: ITicketAudienceRule[]; enabled: boolean; } export interface ICreateTicketAudiencePolicyDto { name: string; description?: string; defaultEffect: TicketAudienceRuleEffect; rules?: ITicketAudienceRule[]; enabled?: boolean; } export interface IUpdateTicketAudiencePolicyDto { name?: string; description?: string | null; defaultEffect?: TicketAudienceRuleEffect; rules?: ITicketAudienceRule[]; enabled?: boolean; } export interface ITicketRequestDraft { id: string; spaceId: string; portalId: string; requestTypeId: string; contactId?: string; formId: string; formVersion?: number; formSubmissionId?: string; status: TicketRequestDraftStatus; createdAt: Date; updatedAt?: Date; expiresAt: Date; submittedTicketId?: string; } export interface ITicketPublicStatus extends ITicketAuditedEntity { name: string; description?: string; color?: string; icon?: string; order: number; } export interface ITicketPublicStatusMapping extends ITicketAuditedEntity { schemeId: string; publicStatusId: string; internalStatusIds: string[]; } export interface ITicketPublicStatusScheme extends ITicketAuditedEntity { name: string; description?: string; defaultPublicStatusId?: string; enabled: boolean; } export interface ICreateTicketPublicStatusDto { name: string; description?: string; color?: string; icon?: string; order: number; } export interface IUpdateTicketPublicStatusDto extends Partial { } export interface ICreateTicketPublicStatusSchemeDto { name: string; description?: string; defaultPublicStatusId?: string; enabled?: boolean; } export interface IUpdateTicketPublicStatusSchemeDto extends Partial { } /** * `schemeId` is absent on purpose: mappings are a sub-resource of a scheme * (`/public-status-schemes/:schemeId/mappings`), so the parent id comes from the * path. */ export interface ICreateTicketPublicStatusMappingDto { publicStatusId: string; internalStatusIds: string[]; } export interface IUpdateTicketPublicStatusMappingDto extends Partial { } /** Customer-facing projection of ITicketPublicStatus: no audit or tenant fields. */ export interface ICustomerPublicStatusView { id: string; name: string; description?: string; color?: string; icon?: string; order: number; } /** Safe customer projection; internal activity, notes, routing and SLA details are intentionally excluded. */ export interface ICustomerTicketView { id: string; number: number; title: string; description?: string; contactId: string; requestTypeId?: string; categoryId: string; publicStatus: ICustomerPublicStatusView; priority?: TicketPriority; publicProperties?: ITicketProperty[]; version: number; createdAt: Date; updatedAt?: Date; resolvedAt?: Date; messages?: ITicketMessageReference[]; availableActions: TicketCustomerAction[]; } export interface ICustomerTicketFilter { /** Mandatory. The surface never serves tickets across contacts. */ contactId: string; search?: string; publicStatusIds?: string[]; requestTypeIds?: string[]; categoryIds?: string[]; createdFrom?: Date; createdTo?: Date; } export declare enum CustomerTicketSortField { CREATED_AT = "CREATED_AT", UPDATED_AT = "UPDATED_AT", NUMBER = "NUMBER" } export interface ICustomerTicketQuery { filter: ICustomerTicketFilter; sort?: { field: CustomerTicketSortField; direction: 'ASC' | 'DESC'; }[]; cursor?: string; limit?: number; } export type CustomerTicketPage = ITicketCursorResponse; /** Reference only. Article content and lifecycle remain authoritative in Docs/Knowledge. */ export interface ITicketKnowledgeReference extends ITicketAuditedEntity { referenceType: TicketKnowledgeReferenceType; documentId: string; portalIds?: string[]; requestTypeIds?: string[]; categoryIds?: string[]; locales?: string[]; audiencePolicyId?: string; order?: number; enabled: boolean; } export interface ICreateTicketKnowledgeReferenceDto { referenceType: TicketKnowledgeReferenceType; documentId: string; portalIds?: string[]; requestTypeIds?: string[]; categoryIds?: string[]; locales?: string[]; audiencePolicyId?: string; order?: number; enabled?: boolean; } export interface IUpdateTicketKnowledgeReferenceDto { referenceType?: TicketKnowledgeReferenceType; documentId?: string; portalIds?: string[] | null; requestTypeIds?: string[] | null; categoryIds?: string[] | null; locales?: string[] | null; audiencePolicyId?: string | null; order?: number | null; enabled?: boolean; } /** Rules may work globally at portal level and become more specific by request type/category. */ export interface ITicketDeflectionRule extends ITicketAuditedEntity { name: string; portalId: string; requestTypeIds?: string[]; categoryIds?: string[]; knowledgeReferenceIds?: string[]; includeKnownIssues?: boolean; minimumScore?: number; maximumSuggestions?: number; audiencePolicyId?: string; enabled: boolean; } export interface ICreateTicketDeflectionRuleDto { name: string; portalId: string; requestTypeIds?: string[]; categoryIds?: string[]; knowledgeReferenceIds?: string[]; includeKnownIssues?: boolean; minimumScore?: number; maximumSuggestions?: number; audiencePolicyId?: string; enabled?: boolean; } export interface IUpdateTicketDeflectionRuleDto { name?: string; portalId?: string; requestTypeIds?: string[] | null; categoryIds?: string[] | null; knowledgeReferenceIds?: string[] | null; includeKnownIssues?: boolean; minimumScore?: number | null; maximumSuggestions?: number | null; audiencePolicyId?: string | null; enabled?: boolean; } export interface ITicketDeflectionSuggestion { knowledgeReferenceId?: string; knownIssueTicketId?: string; score?: number; position: number; } export interface ITicketDeflectionEvent { id: string; spaceId: string; portalId: string; sessionId: string; contactId?: string; requestTypeId?: string; categoryId?: string; query: string; suggestions: ITicketDeflectionSuggestion[]; selectedKnowledgeReferenceId?: string; selectedKnownIssueTicketId?: string; outcome: TicketDeflectionOutcome; createdTicketId?: string; occurredAt: Date; } export interface ITicketCustomerNotificationPreference { id: string; spaceId: string; contactId: string; portalId?: string; locale?: string; channelTypes: ChannelType[]; enabledEvents: TicketNotificationEvent[]; mutedTicketIds?: string[]; updatedAt: Date; } export interface ICreateTicketRequestDraftDto { portalId: string; requestTypeId: string; contactId?: string; } export interface ISubmitTicketRequestDto { draftId: string; formSubmissionId: string; idempotencyKey: string; } /** Just enough of the category to render a grouped catalog: a heading, its order, * and the id the portal has to send back in ICreateCustomerTicketDto. */ export interface ICustomerRequestTypeCategoryView { id: string; name: string; description?: string; order: number; } /** * One entry of the portal's catalog. * * A customer-safe projection of ITicketRequestType, built as an allowlist rather * than by removing keys: the agent shape carries defaultAssignedGroupId (which * internal group handles what), workflowId, slaPolicyId, audiencePolicyId, * fieldDefinitionIds, layoutIds and the createdBy/updatedBy uuids of agents, * none of which belong on a public surface. * * `formId` / `formVersion` travel because the portal renders the form. * `defaultPriority` is a hint for preselection; the create endpoint applies its * own default regardless. */ export interface ICustomerRequestTypeView { id: string; name: string; description?: string; icon?: string; formId?: string; formVersion?: number; defaultPriority?: TicketPriority; category: ICustomerRequestTypeCategoryView; } /** * One field of the portal's create form. * * Allowlist over ITicketFieldDefinition: classification, maskingStrategy, * containsPii, readRoleIds, writeRoleIds, retentionPolicyId, conditions and the * scope arrays stay server-side. `validation`, `options` and `objectFields` do * travel — without them the portal cannot render a select or give the customer * feedback before a round trip that ends in a 422. * * `required` is the EFFECTIVE value for the creation context, not the field's * own flag: it already folds in requiredForStatusIds for the initial status and * any condition that makes the field mandatory. */ export interface ICustomerFormFieldView { nameKey: string; label: string; description?: string; placeholder?: string; type: TicketFieldType; required: boolean; defaultValue?: TicketPropertyValue; options?: ITicketFieldOption[]; objectFields?: ITicketObjectField[]; validation?: ITicketFieldValidation; } /** * What the portal renders so a customer can fill in `properties` on * ICreateCustomerTicketDto. * * NO LAYOUT, unlike the agent form schema: layouts are selected by roleIds and a * contact has no role, so "the effective layout for a customer" is not a * question the layout model can answer. Presentation belongs to the portal; this * answers membership, obligation and shape. */ export interface ICustomerFormSchemaView { requestTypeId: string; categoryId: string; fields: ICustomerFormFieldView[]; } /** * One file the portal declares BEFORE any byte exists in storage. * * `sizeBytes` and `mimeType` are the client's DECLARATION and stay that way for * the life of the attachment: tickets-api never sees the bytes (media-api owns * storage), so there is nothing to compare them against. */ export interface ICreateCustomerTicketAttachmentDto { fileName: string; mimeType: string; sizeBytes: number; checksum?: string; } /** * Direct ticket creation from a portal, without going through a request draft. * * What is ABSENT is the contract, not an oversight: there is no channelType, * channelId, primaryConversationId, assigneeId, assigneeName, assignedGroupId, * statusId, origin, tagIds or externalReferences. Routing, channel provenance * and the internal taxonomy are decisions of the agent side; the server fills * them in (origin WEB_FORM, the space's initial status, the routing defaults of * the category and the request type). */ export interface ICreateCustomerTicketDto { /** Mongo ObjectId of the contact opening the ticket. Row-level authorisation * of the whole customer surface: required, never defaulted. */ contactId: string; title: string; description?: string; categoryId: string; requestTypeId?: string; /** Optional: a portal may or may not let the customer choose. Absent means the * server default (MEDIUM). */ priority?: TicketPriority; properties?: ITicketProperty[]; /** Files the customer is about to upload. Declaring them here is what puts the * upload destinations inside the create transaction. */ attachments?: ICreateCustomerTicketAttachmentDto[]; /** REQUIRED, unlike ICreateTicketDto where it is optional: a portal submit is * the canonical double-click. `source` is NOT part of the contract - the * server derives it from the portal slug, so one portal's keys cannot collide * with another's. */ idempotencyKey: string; } /** * The answer to a create, and the reason the flow is ordered ticket-first. * * `attachmentUploads` carries one session per declared attachment, in the order * they were declared, each already bound to the new ticket. The portal uploads * the bytes to `uploadUrl` and then completes each session. Until it does, the * ticket has no attachments - the deliberate trade: no byte is ever uploaded for * a ticket that failed to be created. */ export interface ICustomerTicketCreatedView { ticket: ICustomerTicketView; attachmentUploads: ITicketAttachmentUploadSession[]; } export interface ICustomerTicketActionDto { expectedVersion: number; action: TicketCustomerAction; comment?: string; attachmentIds?: string[]; formSubmissionId?: string; } /** * Confirmation that an uploaded file became an attachment of the ticket. * * An allowlist over ITicketAttachment, and note the two absences: * * - `storageKey` is the blob layout tickets-api and media-api agree on. It is * internal plumbing, and a client that learned to build one could address * blobs of tickets it never saw. * - `downloadUrl` is omitted because there is NO customer read path for * attachments yet: ICustomerTicketView has no attachments field, and the url * the agent surface hands out is an unsigned blob url that only resolves with * a container SAS this surface has never discussed. Returning one would be * offering a link that 403s. * * `createdBy` is absent too, for a duller reason: on this path it is the nil * uuid marker, which says nothing to anyone. */ export interface ICustomerTicketAttachmentView { id: string; fileName: string; mimeType: string; sizeBytes: number; createdAt: Date; }