@consilioweb/payload-support 2.0.0 → 3.0.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.
Files changed (222) hide show
  1. package/README.md +656 -355
  2. package/dist/components/RichTextEditor/index.d.ts +19 -0
  3. package/dist/components/TicketConversation/RewriteDropdown.d.ts +6 -0
  4. package/dist/components/TicketConversation/SkeletonText.d.ts +4 -0
  5. package/dist/components/TicketConversation/components/AISummaryPanel.d.ts +14 -0
  6. package/dist/components/TicketConversation/components/ActionPanels.d.ts +47 -0
  7. package/dist/components/TicketConversation/components/ActivityLog.d.ts +5 -0
  8. package/dist/components/TicketConversation/components/ClientBar.d.ts +5 -0
  9. package/dist/components/TicketConversation/components/ClientHistory.d.ts +24 -0
  10. package/dist/components/TicketConversation/components/CodeBlock.d.ts +26 -0
  11. package/dist/components/TicketConversation/components/CodeBlockInserter.d.ts +12 -0
  12. package/dist/components/TicketConversation/components/QuickActions.d.ts +32 -0
  13. package/dist/components/TicketConversation/components/TicketHeader.d.ts +19 -0
  14. package/dist/components/TicketConversation/components/TimeTrackingPanel.d.ts +24 -0
  15. package/dist/components/TicketConversation/config.d.ts +10 -0
  16. package/dist/components/TicketConversation/config.js +1 -40
  17. package/dist/components/TicketConversation/constants.d.ts +56 -0
  18. package/dist/components/TicketConversation/context.d.ts +53 -0
  19. package/dist/components/TicketConversation/hooks/useAI.d.ts +21 -0
  20. package/dist/components/TicketConversation/hooks/useDocumentIdFromUrl.d.ts +3 -0
  21. package/dist/components/TicketConversation/hooks/useFeatures.d.ts +23 -0
  22. package/dist/components/TicketConversation/hooks/useFeatures.js +61 -0
  23. package/dist/components/TicketConversation/hooks/useMessageActions.d.ts +20 -0
  24. package/dist/components/TicketConversation/hooks/useReply.d.ts +27 -0
  25. package/dist/components/TicketConversation/hooks/useTicketActions.d.ts +58 -0
  26. package/dist/components/TicketConversation/hooks/useTimeTracking.d.ts +18 -0
  27. package/dist/components/TicketConversation/hooks/useTranslation.d.ts +33 -0
  28. package/dist/components/TicketConversation/hooks/useTranslation.js +22 -3
  29. package/dist/components/TicketConversation/index.d.ts +4 -0
  30. package/dist/components/TicketConversation/index.js +2 -2
  31. package/dist/components/TicketConversation/types.d.ts +56 -0
  32. package/dist/components/TicketConversation/utils.d.ts +2 -0
  33. package/dist/index.cjs +392 -320
  34. package/dist/index.d.cts +100 -3
  35. package/dist/index.d.ts +100 -3
  36. package/dist/index.js +388 -321
  37. package/dist/utils/features.d.ts +123 -0
  38. package/dist/utils/features.js +147 -0
  39. package/dist/views/BillingView/client.d.ts +2 -0
  40. package/dist/views/BillingView/index.d.ts +4 -0
  41. package/dist/views/ChatView/client.d.ts +2 -0
  42. package/dist/views/ChatView/client.js +9 -9
  43. package/dist/views/ChatView/index.d.ts +4 -0
  44. package/dist/views/CrmView/client.d.ts +2 -0
  45. package/dist/views/CrmView/client.js +6 -9
  46. package/dist/views/CrmView/index.d.ts +4 -0
  47. package/dist/views/EmailTrackingView/client.d.ts +2 -0
  48. package/dist/views/EmailTrackingView/index.d.ts +4 -0
  49. package/dist/views/ImportConversationView/client.d.ts +2 -0
  50. package/dist/views/ImportConversationView/index.d.ts +4 -0
  51. package/dist/views/LogsView/client.d.ts +2 -0
  52. package/dist/views/LogsView/index.d.ts +4 -0
  53. package/dist/views/NewTicketView/client.d.ts +2 -0
  54. package/dist/views/NewTicketView/index.d.ts +4 -0
  55. package/dist/views/PendingEmailsView/client.d.ts +2 -0
  56. package/dist/views/PendingEmailsView/index.d.ts +4 -0
  57. package/dist/views/SupportDashboardView/client.d.ts +2 -0
  58. package/dist/views/SupportDashboardView/client.js +1 -1
  59. package/dist/views/SupportDashboardView/index.d.ts +4 -0
  60. package/dist/views/TicketDetailView/NextActionItem.d.ts +6 -0
  61. package/dist/views/TicketDetailView/RewriteDropdown.d.ts +7 -0
  62. package/dist/views/TicketDetailView/client.d.ts +2 -0
  63. package/dist/views/TicketDetailView/client.js +2 -2
  64. package/dist/views/TicketDetailView/constants.d.ts +13 -0
  65. package/dist/views/TicketDetailView/helpers.d.ts +2 -0
  66. package/dist/views/TicketDetailView/index.d.ts +4 -0
  67. package/dist/views/TicketDetailView/types.d.ts +40 -0
  68. package/dist/views/TicketInboxView/client.d.ts +2 -0
  69. package/dist/views/TicketInboxView/client.js +5 -5
  70. package/dist/views/TicketInboxView/index.d.ts +4 -0
  71. package/dist/views/TicketingSettingsView/client.d.ts +2 -0
  72. package/dist/views/TicketingSettingsView/client.js +6 -5
  73. package/dist/views/TicketingSettingsView/index.d.ts +4 -0
  74. package/dist/views/TimeDashboardView/client.d.ts +2 -0
  75. package/dist/views/TimeDashboardView/index.d.ts +4 -0
  76. package/dist/views/shared/AdminViewHeader.d.ts +13 -0
  77. package/dist/views/shared/ErrorBoundary.d.ts +17 -0
  78. package/dist/views/shared/Skeleton.d.ts +21 -0
  79. package/dist/views/shared/StatusPill.d.ts +8 -0
  80. package/dist/views/shared/adminTokens.d.ts +19 -0
  81. package/dist/views/shared/config.d.ts +8 -0
  82. package/dist/views/shared/config.js +1 -40
  83. package/dist/views/shared/dateLocale.d.ts +5 -0
  84. package/dist/views/shared/index.d.ts +12 -0
  85. package/dist/views/shared/index.js +2 -1
  86. package/dist/views/shared/locales/en.json +708 -0
  87. package/dist/views/shared/locales/fr.json +708 -0
  88. package/dist/views/shared/sla.d.ts +14 -0
  89. package/dist/views.d.ts +13 -13
  90. package/package.json +26 -41
  91. package/src/collections/SupportClients.ts +29 -0
  92. package/src/collections/TicketCollaborators.ts +6 -1
  93. package/src/collections/TicketMessages.ts +46 -24
  94. package/src/collections/Tickets.ts +117 -79
  95. package/src/collections/TimeEntries.ts +57 -32
  96. package/src/components/TicketConversation/config.ts +16 -80
  97. package/src/components/TicketConversation/hooks/useFeatures.ts +109 -0
  98. package/src/components/TicketConversation/hooks/useTranslation.ts +38 -4
  99. package/src/components/TicketConversation/index.tsx +2 -2
  100. package/src/endpoints/ai.ts +2 -1
  101. package/src/endpoints/client-intelligence.ts +2 -1
  102. package/src/endpoints/process-scheduled.ts +13 -8
  103. package/src/endpoints/round-robin-config.ts +30 -20
  104. package/src/endpoints/settings.ts +28 -77
  105. package/src/index.ts +6 -2
  106. package/src/portal/LiveChat.tsx +33 -22
  107. package/src/portal/auth/tickets/detail/TicketPolling.tsx +5 -1
  108. package/src/types/lucide-react.d.ts +10 -2
  109. package/src/utils/aiAgent.ts +2 -1
  110. package/src/utils/aiProvider.ts +21 -0
  111. package/src/utils/features.ts +297 -0
  112. package/src/utils/fireWebhooks.ts +6 -0
  113. package/src/utils/generateTicketSynthesis.ts +2 -1
  114. package/src/utils/index.ts +4 -2
  115. package/src/utils/readSettings.ts +82 -9
  116. package/src/utils/webhookDispatcher.ts +19 -7
  117. package/src/views/ChatView/client.tsx +13 -9
  118. package/src/views/CrmView/client.tsx +10 -11
  119. package/src/views/SupportDashboardView/client.tsx +1 -1
  120. package/src/views/TicketDetailView/client.tsx +2 -2
  121. package/src/views/TicketInboxView/client.tsx +10 -5
  122. package/src/views/TicketingSettingsView/client.tsx +9 -7
  123. package/src/views/shared/config.ts +14 -80
  124. package/src/views/shared/index.ts +3 -1
  125. package/src/views/shared/locales/en.json +2 -2
  126. package/src/views/shared/locales/fr.json +2 -2
  127. package/dist/components/RichTextEditor/index.cjs +0 -279
  128. package/dist/components/TicketConversation/RewriteDropdown.cjs +0 -98
  129. package/dist/components/TicketConversation/SkeletonText.cjs +0 -21
  130. package/dist/components/TicketConversation/components/AISummaryPanel.cjs +0 -85
  131. package/dist/components/TicketConversation/components/ActionPanels.cjs +0 -193
  132. package/dist/components/TicketConversation/components/ActivityLog.cjs +0 -24
  133. package/dist/components/TicketConversation/components/ClientBar.cjs +0 -43
  134. package/dist/components/TicketConversation/components/ClientHistory.cjs +0 -138
  135. package/dist/components/TicketConversation/components/CodeBlock.cjs +0 -171
  136. package/dist/components/TicketConversation/components/CodeBlockInserter.cjs +0 -156
  137. package/dist/components/TicketConversation/components/QuickActions.cjs +0 -87
  138. package/dist/components/TicketConversation/components/TicketHeader.cjs +0 -93
  139. package/dist/components/TicketConversation/components/TimeTrackingPanel.cjs +0 -134
  140. package/dist/components/TicketConversation/config.cjs +0 -44
  141. package/dist/components/TicketConversation/constants.cjs +0 -127
  142. package/dist/components/TicketConversation/context.cjs +0 -13
  143. package/dist/components/TicketConversation/hooks/useAI.cjs +0 -196
  144. package/dist/components/TicketConversation/hooks/useDocumentIdFromUrl.cjs +0 -20
  145. package/dist/components/TicketConversation/hooks/useMessageActions.cjs +0 -136
  146. package/dist/components/TicketConversation/hooks/useReply.cjs +0 -188
  147. package/dist/components/TicketConversation/hooks/useTicketActions.cjs +0 -290
  148. package/dist/components/TicketConversation/hooks/useTimeTracking.cjs +0 -123
  149. package/dist/components/TicketConversation/hooks/useTranslation.cjs +0 -78
  150. package/dist/components/TicketConversation/index.cjs +0 -1114
  151. package/dist/components/TicketConversation/types.cjs +0 -2
  152. package/dist/components/TicketConversation/utils.cjs +0 -27
  153. package/dist/views/BillingView/client.cjs +0 -469
  154. package/dist/views/BillingView/index.cjs +0 -34
  155. package/dist/views/ChatView/client.cjs +0 -301
  156. package/dist/views/ChatView/index.cjs +0 -34
  157. package/dist/views/CrmView/client.cjs +0 -458
  158. package/dist/views/CrmView/index.cjs +0 -34
  159. package/dist/views/EmailTrackingView/client.cjs +0 -171
  160. package/dist/views/EmailTrackingView/index.cjs +0 -34
  161. package/dist/views/ImportConversationView/client.cjs +0 -238
  162. package/dist/views/ImportConversationView/index.cjs +0 -34
  163. package/dist/views/LogsView/client.cjs +0 -148
  164. package/dist/views/LogsView/index.cjs +0 -32
  165. package/dist/views/NewTicketView/client.cjs +0 -213
  166. package/dist/views/NewTicketView/index.cjs +0 -32
  167. package/dist/views/PendingEmailsView/client.cjs +0 -471
  168. package/dist/views/PendingEmailsView/index.cjs +0 -34
  169. package/dist/views/SupportDashboardView/client.cjs +0 -437
  170. package/dist/views/SupportDashboardView/index.cjs +0 -34
  171. package/dist/views/TicketDetailView/NextActionItem.cjs +0 -40
  172. package/dist/views/TicketDetailView/RewriteDropdown.cjs +0 -80
  173. package/dist/views/TicketDetailView/client.cjs +0 -1412
  174. package/dist/views/TicketDetailView/constants.cjs +0 -20
  175. package/dist/views/TicketDetailView/helpers.cjs +0 -23
  176. package/dist/views/TicketDetailView/index.cjs +0 -34
  177. package/dist/views/TicketDetailView/types.cjs +0 -2
  178. package/dist/views/TicketInboxView/client.cjs +0 -359
  179. package/dist/views/TicketInboxView/index.cjs +0 -32
  180. package/dist/views/TicketingSettingsView/client.cjs +0 -740
  181. package/dist/views/TicketingSettingsView/index.cjs +0 -34
  182. package/dist/views/TimeDashboardView/client.cjs +0 -180
  183. package/dist/views/TimeDashboardView/index.cjs +0 -34
  184. package/dist/views/shared/AdminViewHeader.cjs +0 -68
  185. package/dist/views/shared/ErrorBoundary.cjs +0 -55
  186. package/dist/views/shared/Skeleton.cjs +0 -77
  187. package/dist/views/shared/StatusPill.cjs +0 -47
  188. package/dist/views/shared/adminTokens.cjs +0 -34
  189. package/dist/views/shared/config.cjs +0 -44
  190. package/dist/views/shared/dateLocale.cjs +0 -5
  191. package/dist/views/shared/index.cjs +0 -72
  192. package/dist/views/shared/sla.cjs +0 -37
  193. package/dist/views.cjs +0 -86
  194. package/dist/views.d.cts +0 -13
  195. package/src/__tests__/aiSummaryRendering.test.ts +0 -21
  196. package/src/__tests__/authResponses.test.ts +0 -69
  197. package/src/__tests__/capabilities.test.ts +0 -71
  198. package/src/__tests__/generateTrackingToken.test.ts +0 -67
  199. package/src/__tests__/integration/ai-agent.test.ts +0 -46
  200. package/src/__tests__/integration/auth.test.ts +0 -43
  201. package/src/__tests__/integration/automation-rules.test.ts +0 -68
  202. package/src/__tests__/integration/buildTestPayload.ts +0 -52
  203. package/src/__tests__/integration/channels.test.ts +0 -52
  204. package/src/__tests__/integration/core-behaviors.test.ts +0 -81
  205. package/src/__tests__/integration/dashboard-volume.test.ts +0 -31
  206. package/src/__tests__/integration/digest.test.ts +0 -48
  207. package/src/__tests__/integration/invoice-pdf.test.ts +0 -30
  208. package/src/__tests__/integration/isolation.test.ts +0 -81
  209. package/src/__tests__/integration/mentions-invoice.test.ts +0 -50
  210. package/src/__tests__/integration/nps.test.ts +0 -37
  211. package/src/__tests__/integration/per-team-sla.test.ts +0 -44
  212. package/src/__tests__/integration/push.test.ts +0 -75
  213. package/src/__tests__/integration/sanitization.test.ts +0 -35
  214. package/src/__tests__/integration/sla-pause.test.ts +0 -39
  215. package/src/__tests__/integration/smoke.test.ts +0 -26
  216. package/src/__tests__/integration/snooze.test.ts +0 -68
  217. package/src/__tests__/integration/teams.test.ts +0 -38
  218. package/src/__tests__/rateLimiter.test.ts +0 -83
  219. package/src/__tests__/sanitizeHtml.test.ts +0 -165
  220. package/src/__tests__/sla.test.ts +0 -258
  221. package/src/__tests__/trackOpenEndpoint.test.ts +0 -54
  222. package/src/__tests__/webhookSecurity.test.ts +0 -58
package/dist/index.d.cts CHANGED
@@ -381,6 +381,87 @@ declare const DEFAULT_SLUGS: CollectionSlugs;
381
381
  */
382
382
  declare function resolveSlugs(overrides?: Partial<CollectionSlugs>): CollectionSlugs;
383
383
 
384
+ /**
385
+ * Ticketing feature flags — single source of truth (client + server).
386
+ *
387
+ * Flags are stored SERVER-side, in the `support-settings` row of
388
+ * `payload-preferences` (see `readSettings.ts` and `endpoints/settings.ts`).
389
+ * A flag toggled on one machine therefore applies to every browser and to
390
+ * server-side code (hooks, cron endpoints) alike.
391
+ *
392
+ * `localStorage` is still used, but demoted to a plain CACHE: it lets admin
393
+ * views paint synchronously on first render and keeps them usable when the
394
+ * settings endpoint is unreachable. It is never authoritative.
395
+ *
396
+ * Two flags are *projections* of settings that already lived server-side long
397
+ * before this module, and are deliberately NOT stored twice:
398
+ * - `autoClose` ← `settings.autoClose.enabled`
399
+ * - `autoCloseDays` ← `settings.autoClose.daysBeforeClose`
400
+ * The `autoClose` block stays authoritative; the flags are recomputed on read
401
+ * and dropped on write. See `projectAutoClose` / `stripProjectedFeatures`.
402
+ */
403
+ /**
404
+ * Feature flags for the ticketing module.
405
+ * Each feature can be enabled/disabled by the admin.
406
+ * When disabled, the corresponding UI section is hidden entirely.
407
+ */
408
+ interface TicketingFeatures {
409
+ /** Time tracking: timer, manual entries, billing */
410
+ timeTracking: boolean;
411
+ /** AI features: sentiment, synthesis, suggestion, rewrite */
412
+ ai: boolean;
413
+ /** Satisfaction surveys: CSAT rating after resolution */
414
+ satisfaction: boolean;
415
+ /** Live chat integration: chat → ticket conversion */
416
+ chat: boolean;
417
+ /** Email tracking: pixel tracking, open/sent status per message */
418
+ emailTracking: boolean;
419
+ /** Canned responses: quick reply templates */
420
+ canned: boolean;
421
+ /** Ticket merge: combine two tickets into one */
422
+ merge: boolean;
423
+ /** Snooze: temporarily hide a ticket */
424
+ snooze: boolean;
425
+ /** External messages: add messages received outside the system */
426
+ externalMessages: boolean;
427
+ /** Client history: past tickets, projects, notes sidebar */
428
+ clientHistory: boolean;
429
+ /** Activity log: audit trail of actions on the ticket */
430
+ activityLog: boolean;
431
+ /** Split ticket: extract a message into a new ticket */
432
+ splitTicket: boolean;
433
+ /** Scheduled replies: send a message at a future date */
434
+ scheduledReplies: boolean;
435
+ /** Auto-close: automatically resolve inactive tickets (projection of settings.autoClose.enabled) */
436
+ autoClose: boolean;
437
+ /** Auto-close delay in days (projection of settings.autoClose.daysBeforeClose) */
438
+ autoCloseDays: number;
439
+ /** Round-robin: distribute new tickets evenly among agents */
440
+ roundRobin: boolean;
441
+ }
442
+ /** Default features — all enabled except round-robin */
443
+ declare const DEFAULT_TICKETING_FEATURES: TicketingFeatures;
444
+ /** Flags derived from another settings block — never persisted inside `features`. */
445
+ declare const PROJECTED_FEATURE_KEYS: readonly ["autoClose", "autoCloseDays"];
446
+ /**
447
+ * Coerce arbitrary input (stale localStorage, hand-edited preference row, older
448
+ * plugin version) into a complete, well-typed feature set. Unknown keys are
449
+ * dropped and wrongly-typed values fall back to their default.
450
+ */
451
+ declare function normalizeFeatures(raw: unknown): TicketingFeatures;
452
+ /** Shape of the `autoClose` settings block the two projected flags mirror. */
453
+ interface AutoCloseProjectionSource {
454
+ enabled?: boolean;
455
+ daysBeforeClose?: number;
456
+ }
457
+ /** Recompute the projected flags from the authoritative `autoClose` block. */
458
+ declare function projectAutoClose(features: TicketingFeatures, autoClose: AutoCloseProjectionSource | undefined): TicketingFeatures;
459
+ /**
460
+ * Drop the projected flags before persisting, so `features` and the `autoClose`
461
+ * block can never disagree.
462
+ */
463
+ declare function stripProjectedFeatures(features: TicketingFeatures): Omit<TicketingFeatures, (typeof PROJECTED_FEATURE_KEYS)[number]>;
464
+
384
465
  interface SupportSettings {
385
466
  email: {
386
467
  fromAddress: string;
@@ -406,6 +487,8 @@ interface SupportSettings {
406
487
  daysBeforeClose: number;
407
488
  reminderDaysBefore: number;
408
489
  };
490
+ /** Ticketing feature flags — server-authoritative since 2.1 (used to be per-browser localStorage). */
491
+ features: TicketingFeatures;
409
492
  }
410
493
  interface UserPrefs {
411
494
  locale: 'fr' | 'en';
@@ -413,6 +496,16 @@ interface UserPrefs {
413
496
  }
414
497
  declare const DEFAULT_SETTINGS: SupportSettings;
415
498
  declare const DEFAULT_USER_PREFS: UserPrefs;
499
+ interface SupportSettingsState {
500
+ settings: SupportSettings;
501
+ /**
502
+ * False when the preference row carries no `features` object yet — a
503
+ * pre-2.1 install, or a fresh one. Clients use it to decide whether their
504
+ * legacy `localStorage` flags should seed the server.
505
+ */
506
+ featuresConfigured: boolean;
507
+ }
508
+ declare function readSupportSettingsState(payload: Payload): Promise<SupportSettingsState>;
416
509
  declare function readSupportSettings(payload: Payload): Promise<SupportSettings>;
417
510
  declare function readUserPrefs(payload: Payload, userId: string | number): Promise<UserPrefs>;
418
511
 
@@ -455,7 +548,11 @@ declare function createAdminNotification(payload: Payload, data: {
455
548
  recipient?: number | string;
456
549
  }, collectionSlug?: string): Promise<void>;
457
550
 
458
- type WebhookEvent = 'ticket_created' | 'ticket_resolved' | 'ticket_replied' | 'sla_breached';
551
+ /**
552
+ * Outbound webhook events. Must stay in sync with the `events` options of the
553
+ * webhook-endpoints collection.
554
+ */
555
+ type WebhookEvent = 'ticket_created' | 'ticket_resolved' | 'ticket_replied' | 'ticket_assigned' | 'sla_breached';
459
556
  /**
460
557
  * Dispatch outbound webhooks for a given event.
461
558
  * Fetches all active webhook endpoints matching the event,
@@ -467,7 +564,7 @@ type WebhookEvent = 'ticket_created' | 'ticket_resolved' | 'ticket_replied' | 's
467
564
  * @param payload - Payload instance
468
565
  * @param slugs - Collection slugs for dynamic collection references
469
566
  */
470
- declare function dispatchWebhook(data: Record<string, unknown>, event: WebhookEvent, payload: BasePayload, slugs: CollectionSlugs): void;
567
+ declare function dispatchWebhook(data: Record<string, unknown>, event: WebhookEvent, payload: BasePayload, slugs: CollectionSlugs): Promise<void>;
471
568
 
472
569
  interface TicketSynthesisResult {
473
570
  summary: string;
@@ -578,4 +675,4 @@ declare function createTicketStatusesCollection(slugs: CollectionSlugs): Collect
578
675
  */
579
676
  declare function createTicketCollaboratorsCollection(slugs: CollectionSlugs): CollectionConfig;
580
677
 
581
- export { type AIProviderConfig, type ActivityEntryData, type CannedResponseData, type ClientData, type CollectionSlugs, DEFAULT_FEATURES, DEFAULT_INBOUND_EMAIL_LIMITS, DEFAULT_SETTINGS, DEFAULT_SLUGS, DEFAULT_USER_PREFS, type EmailConfig, type InboundEmailInput, type InboundEmailLimits, type InboundEmailValidationError, MemoryRateLimitStore, type MessageData, PayloadRateLimitStore, type RateLimitEntry, type RateLimitStore, RateLimiter, type SatisfactionSurveyData, type SupportFeatures, type SupportPluginConfig, type SupportSettings, type TicketData, type TicketSynthesisResult, type TimeEntryData, type UserPrefs, calculateBusinessHoursDeadline, createAdminNotification, createAssignSlaDeadlines, createAuthLogsCollection, createCannedResponsesCollection, createChatMessagesCollection, createCheckSlaOnReply, createCheckSlaOnResolve, createEmailLogsCollection, createKnowledgeBaseCollection, createLoginEndpoint, createMacrosCollection, createOAuthGoogleEndpoint, createPendingEmailsCollection, createSatisfactionSurveysCollection, createSlaPoliciesCollection, createSupportClientsCollection, createTicketActivityLogCollection, createTicketCollaboratorsCollection, createTicketMessagesCollection, createTicketStatusEmail, createTicketStatusesCollection, createTicketsCollection, createTimeEntriesCollection, createTrackOpenEndpoint, createWebhookEndpointsCollection, dispatchWebhook, generateTicketSynthesis, readSupportSettings, readUserPrefs, resolveSlugs, supportPlugin, validateInboundEmailPayload, verifySecret };
678
+ export { type AIProviderConfig, type ActivityEntryData, type CannedResponseData, type ClientData, type CollectionSlugs, DEFAULT_FEATURES, DEFAULT_INBOUND_EMAIL_LIMITS, DEFAULT_SETTINGS, DEFAULT_SLUGS, DEFAULT_TICKETING_FEATURES, DEFAULT_USER_PREFS, type EmailConfig, type InboundEmailInput, type InboundEmailLimits, type InboundEmailValidationError, MemoryRateLimitStore, type MessageData, PayloadRateLimitStore, type RateLimitEntry, type RateLimitStore, RateLimiter, type SatisfactionSurveyData, type SupportFeatures, type SupportPluginConfig, type SupportSettings, type SupportSettingsState, type TicketData, type TicketSynthesisResult, type TicketingFeatures, type TimeEntryData, type UserPrefs, calculateBusinessHoursDeadline, createAdminNotification, createAssignSlaDeadlines, createAuthLogsCollection, createCannedResponsesCollection, createChatMessagesCollection, createCheckSlaOnReply, createCheckSlaOnResolve, createEmailLogsCollection, createKnowledgeBaseCollection, createLoginEndpoint, createMacrosCollection, createOAuthGoogleEndpoint, createPendingEmailsCollection, createSatisfactionSurveysCollection, createSlaPoliciesCollection, createSupportClientsCollection, createTicketActivityLogCollection, createTicketCollaboratorsCollection, createTicketMessagesCollection, createTicketStatusEmail, createTicketStatusesCollection, createTicketsCollection, createTimeEntriesCollection, createTrackOpenEndpoint, createWebhookEndpointsCollection, dispatchWebhook, generateTicketSynthesis, normalizeFeatures, projectAutoClose, readSupportSettings, readSupportSettingsState, readUserPrefs, resolveSlugs, stripProjectedFeatures, supportPlugin, validateInboundEmailPayload, verifySecret };
package/dist/index.d.ts CHANGED
@@ -381,6 +381,87 @@ declare const DEFAULT_SLUGS: CollectionSlugs;
381
381
  */
382
382
  declare function resolveSlugs(overrides?: Partial<CollectionSlugs>): CollectionSlugs;
383
383
 
384
+ /**
385
+ * Ticketing feature flags — single source of truth (client + server).
386
+ *
387
+ * Flags are stored SERVER-side, in the `support-settings` row of
388
+ * `payload-preferences` (see `readSettings.ts` and `endpoints/settings.ts`).
389
+ * A flag toggled on one machine therefore applies to every browser and to
390
+ * server-side code (hooks, cron endpoints) alike.
391
+ *
392
+ * `localStorage` is still used, but demoted to a plain CACHE: it lets admin
393
+ * views paint synchronously on first render and keeps them usable when the
394
+ * settings endpoint is unreachable. It is never authoritative.
395
+ *
396
+ * Two flags are *projections* of settings that already lived server-side long
397
+ * before this module, and are deliberately NOT stored twice:
398
+ * - `autoClose` ← `settings.autoClose.enabled`
399
+ * - `autoCloseDays` ← `settings.autoClose.daysBeforeClose`
400
+ * The `autoClose` block stays authoritative; the flags are recomputed on read
401
+ * and dropped on write. See `projectAutoClose` / `stripProjectedFeatures`.
402
+ */
403
+ /**
404
+ * Feature flags for the ticketing module.
405
+ * Each feature can be enabled/disabled by the admin.
406
+ * When disabled, the corresponding UI section is hidden entirely.
407
+ */
408
+ interface TicketingFeatures {
409
+ /** Time tracking: timer, manual entries, billing */
410
+ timeTracking: boolean;
411
+ /** AI features: sentiment, synthesis, suggestion, rewrite */
412
+ ai: boolean;
413
+ /** Satisfaction surveys: CSAT rating after resolution */
414
+ satisfaction: boolean;
415
+ /** Live chat integration: chat → ticket conversion */
416
+ chat: boolean;
417
+ /** Email tracking: pixel tracking, open/sent status per message */
418
+ emailTracking: boolean;
419
+ /** Canned responses: quick reply templates */
420
+ canned: boolean;
421
+ /** Ticket merge: combine two tickets into one */
422
+ merge: boolean;
423
+ /** Snooze: temporarily hide a ticket */
424
+ snooze: boolean;
425
+ /** External messages: add messages received outside the system */
426
+ externalMessages: boolean;
427
+ /** Client history: past tickets, projects, notes sidebar */
428
+ clientHistory: boolean;
429
+ /** Activity log: audit trail of actions on the ticket */
430
+ activityLog: boolean;
431
+ /** Split ticket: extract a message into a new ticket */
432
+ splitTicket: boolean;
433
+ /** Scheduled replies: send a message at a future date */
434
+ scheduledReplies: boolean;
435
+ /** Auto-close: automatically resolve inactive tickets (projection of settings.autoClose.enabled) */
436
+ autoClose: boolean;
437
+ /** Auto-close delay in days (projection of settings.autoClose.daysBeforeClose) */
438
+ autoCloseDays: number;
439
+ /** Round-robin: distribute new tickets evenly among agents */
440
+ roundRobin: boolean;
441
+ }
442
+ /** Default features — all enabled except round-robin */
443
+ declare const DEFAULT_TICKETING_FEATURES: TicketingFeatures;
444
+ /** Flags derived from another settings block — never persisted inside `features`. */
445
+ declare const PROJECTED_FEATURE_KEYS: readonly ["autoClose", "autoCloseDays"];
446
+ /**
447
+ * Coerce arbitrary input (stale localStorage, hand-edited preference row, older
448
+ * plugin version) into a complete, well-typed feature set. Unknown keys are
449
+ * dropped and wrongly-typed values fall back to their default.
450
+ */
451
+ declare function normalizeFeatures(raw: unknown): TicketingFeatures;
452
+ /** Shape of the `autoClose` settings block the two projected flags mirror. */
453
+ interface AutoCloseProjectionSource {
454
+ enabled?: boolean;
455
+ daysBeforeClose?: number;
456
+ }
457
+ /** Recompute the projected flags from the authoritative `autoClose` block. */
458
+ declare function projectAutoClose(features: TicketingFeatures, autoClose: AutoCloseProjectionSource | undefined): TicketingFeatures;
459
+ /**
460
+ * Drop the projected flags before persisting, so `features` and the `autoClose`
461
+ * block can never disagree.
462
+ */
463
+ declare function stripProjectedFeatures(features: TicketingFeatures): Omit<TicketingFeatures, (typeof PROJECTED_FEATURE_KEYS)[number]>;
464
+
384
465
  interface SupportSettings {
385
466
  email: {
386
467
  fromAddress: string;
@@ -406,6 +487,8 @@ interface SupportSettings {
406
487
  daysBeforeClose: number;
407
488
  reminderDaysBefore: number;
408
489
  };
490
+ /** Ticketing feature flags — server-authoritative since 2.1 (used to be per-browser localStorage). */
491
+ features: TicketingFeatures;
409
492
  }
410
493
  interface UserPrefs {
411
494
  locale: 'fr' | 'en';
@@ -413,6 +496,16 @@ interface UserPrefs {
413
496
  }
414
497
  declare const DEFAULT_SETTINGS: SupportSettings;
415
498
  declare const DEFAULT_USER_PREFS: UserPrefs;
499
+ interface SupportSettingsState {
500
+ settings: SupportSettings;
501
+ /**
502
+ * False when the preference row carries no `features` object yet — a
503
+ * pre-2.1 install, or a fresh one. Clients use it to decide whether their
504
+ * legacy `localStorage` flags should seed the server.
505
+ */
506
+ featuresConfigured: boolean;
507
+ }
508
+ declare function readSupportSettingsState(payload: Payload): Promise<SupportSettingsState>;
416
509
  declare function readSupportSettings(payload: Payload): Promise<SupportSettings>;
417
510
  declare function readUserPrefs(payload: Payload, userId: string | number): Promise<UserPrefs>;
418
511
 
@@ -455,7 +548,11 @@ declare function createAdminNotification(payload: Payload, data: {
455
548
  recipient?: number | string;
456
549
  }, collectionSlug?: string): Promise<void>;
457
550
 
458
- type WebhookEvent = 'ticket_created' | 'ticket_resolved' | 'ticket_replied' | 'sla_breached';
551
+ /**
552
+ * Outbound webhook events. Must stay in sync with the `events` options of the
553
+ * webhook-endpoints collection.
554
+ */
555
+ type WebhookEvent = 'ticket_created' | 'ticket_resolved' | 'ticket_replied' | 'ticket_assigned' | 'sla_breached';
459
556
  /**
460
557
  * Dispatch outbound webhooks for a given event.
461
558
  * Fetches all active webhook endpoints matching the event,
@@ -467,7 +564,7 @@ type WebhookEvent = 'ticket_created' | 'ticket_resolved' | 'ticket_replied' | 's
467
564
  * @param payload - Payload instance
468
565
  * @param slugs - Collection slugs for dynamic collection references
469
566
  */
470
- declare function dispatchWebhook(data: Record<string, unknown>, event: WebhookEvent, payload: BasePayload, slugs: CollectionSlugs): void;
567
+ declare function dispatchWebhook(data: Record<string, unknown>, event: WebhookEvent, payload: BasePayload, slugs: CollectionSlugs): Promise<void>;
471
568
 
472
569
  interface TicketSynthesisResult {
473
570
  summary: string;
@@ -578,4 +675,4 @@ declare function createTicketStatusesCollection(slugs: CollectionSlugs): Collect
578
675
  */
579
676
  declare function createTicketCollaboratorsCollection(slugs: CollectionSlugs): CollectionConfig;
580
677
 
581
- export { type AIProviderConfig, type ActivityEntryData, type CannedResponseData, type ClientData, type CollectionSlugs, DEFAULT_FEATURES, DEFAULT_INBOUND_EMAIL_LIMITS, DEFAULT_SETTINGS, DEFAULT_SLUGS, DEFAULT_USER_PREFS, type EmailConfig, type InboundEmailInput, type InboundEmailLimits, type InboundEmailValidationError, MemoryRateLimitStore, type MessageData, PayloadRateLimitStore, type RateLimitEntry, type RateLimitStore, RateLimiter, type SatisfactionSurveyData, type SupportFeatures, type SupportPluginConfig, type SupportSettings, type TicketData, type TicketSynthesisResult, type TimeEntryData, type UserPrefs, calculateBusinessHoursDeadline, createAdminNotification, createAssignSlaDeadlines, createAuthLogsCollection, createCannedResponsesCollection, createChatMessagesCollection, createCheckSlaOnReply, createCheckSlaOnResolve, createEmailLogsCollection, createKnowledgeBaseCollection, createLoginEndpoint, createMacrosCollection, createOAuthGoogleEndpoint, createPendingEmailsCollection, createSatisfactionSurveysCollection, createSlaPoliciesCollection, createSupportClientsCollection, createTicketActivityLogCollection, createTicketCollaboratorsCollection, createTicketMessagesCollection, createTicketStatusEmail, createTicketStatusesCollection, createTicketsCollection, createTimeEntriesCollection, createTrackOpenEndpoint, createWebhookEndpointsCollection, dispatchWebhook, generateTicketSynthesis, readSupportSettings, readUserPrefs, resolveSlugs, supportPlugin, validateInboundEmailPayload, verifySecret };
678
+ export { type AIProviderConfig, type ActivityEntryData, type CannedResponseData, type ClientData, type CollectionSlugs, DEFAULT_FEATURES, DEFAULT_INBOUND_EMAIL_LIMITS, DEFAULT_SETTINGS, DEFAULT_SLUGS, DEFAULT_TICKETING_FEATURES, DEFAULT_USER_PREFS, type EmailConfig, type InboundEmailInput, type InboundEmailLimits, type InboundEmailValidationError, MemoryRateLimitStore, type MessageData, PayloadRateLimitStore, type RateLimitEntry, type RateLimitStore, RateLimiter, type SatisfactionSurveyData, type SupportFeatures, type SupportPluginConfig, type SupportSettings, type SupportSettingsState, type TicketData, type TicketSynthesisResult, type TicketingFeatures, type TimeEntryData, type UserPrefs, calculateBusinessHoursDeadline, createAdminNotification, createAssignSlaDeadlines, createAuthLogsCollection, createCannedResponsesCollection, createChatMessagesCollection, createCheckSlaOnReply, createCheckSlaOnResolve, createEmailLogsCollection, createKnowledgeBaseCollection, createLoginEndpoint, createMacrosCollection, createOAuthGoogleEndpoint, createPendingEmailsCollection, createSatisfactionSurveysCollection, createSlaPoliciesCollection, createSupportClientsCollection, createTicketActivityLogCollection, createTicketCollaboratorsCollection, createTicketMessagesCollection, createTicketStatusEmail, createTicketStatusesCollection, createTicketsCollection, createTimeEntriesCollection, createTrackOpenEndpoint, createWebhookEndpointsCollection, dispatchWebhook, generateTicketSynthesis, normalizeFeatures, projectAutoClose, readSupportSettings, readSupportSettingsState, readUserPrefs, resolveSlugs, stripProjectedFeatures, supportPlugin, validateInboundEmailPayload, verifySecret };