@consilioweb/payload-support 4.0.0 → 6.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 (159) hide show
  1. package/README.md +272 -35
  2. package/dist/components/RichTextEditor/index.js +1 -1
  3. package/dist/components/TicketConversation/RewriteDropdown.js +1 -1
  4. package/dist/components/TicketConversation/components/AISummaryPanel.js +3 -0
  5. package/dist/components/TicketConversation/components/ActionPanels.js +13 -8
  6. package/dist/components/TicketConversation/components/ClientHistory.js +1 -0
  7. package/dist/components/TicketConversation/components/CodeBlock.js +1 -0
  8. package/dist/components/TicketConversation/components/CodeBlockInserter.js +1 -1
  9. package/dist/components/TicketConversation/components/QuickActions.js +10 -8
  10. package/dist/components/TicketConversation/components/TicketHeader.js +2 -0
  11. package/dist/components/TicketConversation/components/TimeTrackingPanel.js +15 -9
  12. package/dist/components/TicketConversation/index.d.ts +10 -0
  13. package/dist/components/TicketConversation/index.js +25 -7
  14. package/dist/index.cjs +421 -73
  15. package/dist/index.d.cts +127 -38
  16. package/dist/index.d.ts +127 -38
  17. package/dist/index.js +415 -72
  18. package/dist/styles/BillingView.module.scss +11 -11
  19. package/dist/styles/ChatView.module.scss +7 -7
  20. package/dist/styles/CommandPalette.module.scss +1 -1
  21. package/dist/styles/CrmView.module.scss +9 -9
  22. package/dist/styles/EmailTracking.module.scss +6 -6
  23. package/dist/styles/ImportConversation.module.scss +5 -5
  24. package/dist/styles/Logs.module.scss +5 -5
  25. package/dist/styles/NewTicket.module.scss +2 -2
  26. package/dist/styles/PendingEmails.module.scss +13 -13
  27. package/dist/styles/SupportDashboard.module.scss +24 -8
  28. package/dist/styles/TicketDetail.module.scss +20 -20
  29. package/dist/styles/TicketInbox.module.scss +6 -6
  30. package/dist/styles/TicketingSettings.module.scss +10 -10
  31. package/dist/styles/TimeDashboard.module.scss +6 -6
  32. package/dist/styles/_tokens.scss +3 -1
  33. package/dist/utils/db.d.ts +34 -0
  34. package/dist/utils/readSettings.d.ts +90 -0
  35. package/dist/views/BillingView/client.js +15 -8
  36. package/dist/views/BillingView/index.js +4 -4
  37. package/dist/views/ChatView/client.js +2 -0
  38. package/dist/views/ChatView/index.js +4 -4
  39. package/dist/views/CrmView/client.js +2 -0
  40. package/dist/views/CrmView/index.js +4 -4
  41. package/dist/views/EmailTrackingView/client.js +23 -11
  42. package/dist/views/EmailTrackingView/index.js +4 -4
  43. package/dist/views/ImportConversationView/client.js +1 -0
  44. package/dist/views/ImportConversationView/index.js +4 -4
  45. package/dist/views/LogsView/client.js +1 -1
  46. package/dist/views/LogsView/index.js +4 -2
  47. package/dist/views/NewTicketView/client.js +20 -13
  48. package/dist/views/NewTicketView/index.js +4 -2
  49. package/dist/views/PendingEmailsView/client.js +9 -3
  50. package/dist/views/PendingEmailsView/index.js +4 -4
  51. package/dist/views/SupportDashboardView/client.js +17 -19
  52. package/dist/views/SupportDashboardView/index.js +4 -4
  53. package/dist/views/TicketDetailView/client.js +23 -11
  54. package/dist/views/TicketDetailView/index.js +4 -4
  55. package/dist/views/TicketInboxView/client.js +52 -26
  56. package/dist/views/TicketInboxView/index.js +4 -2
  57. package/dist/views/TicketingSettingsView/TicketingSettings.module.scss +7 -7
  58. package/dist/views/TicketingSettingsView/client.js +44 -26
  59. package/dist/views/TicketingSettingsView/index.js +4 -4
  60. package/dist/views/TimeDashboardView/client.js +10 -7
  61. package/dist/views/TimeDashboardView/index.js +4 -4
  62. package/dist/views/shared/ErrorBoundary.d.ts +36 -1
  63. package/dist/views/shared/ErrorBoundary.js +59 -28
  64. package/dist/views/shared/adminTokens.d.ts +15 -5
  65. package/dist/views/shared/adminTokens.js +23 -7
  66. package/dist/views/shared/icons.d.ts +49 -0
  67. package/dist/views/shared/icons.js +92 -0
  68. package/dist/views/shared/locales/en.json +15 -1
  69. package/dist/views/shared/locales/fr.json +15 -1
  70. package/dist/views/shared/viewAccess.d.ts +29 -0
  71. package/dist/views/shared/viewAccess.js +24 -0
  72. package/package.json +31 -21
  73. package/scripts/uninstall-data.mjs +178 -0
  74. package/scripts/uninstall.mjs +184 -0
  75. package/src/collections/Tickets.ts +7 -0
  76. package/src/collections/TimeEntries.ts +11 -3
  77. package/src/components/RichTextEditor/index.tsx +1 -1
  78. package/src/components/TicketConversation/RewriteDropdown.tsx +1 -1
  79. package/src/components/TicketConversation/components/AISummaryPanel.tsx +3 -0
  80. package/src/components/TicketConversation/components/ActionPanels.tsx +13 -8
  81. package/src/components/TicketConversation/components/ClientHistory.tsx +1 -0
  82. package/src/components/TicketConversation/components/CodeBlock.tsx +1 -0
  83. package/src/components/TicketConversation/components/CodeBlockInserter.tsx +1 -1
  84. package/src/components/TicketConversation/components/QuickActions.tsx +10 -8
  85. package/src/components/TicketConversation/components/TicketHeader.tsx +2 -0
  86. package/src/components/TicketConversation/components/TimeTrackingPanel.tsx +17 -9
  87. package/src/components/TicketConversation/index.tsx +41 -7
  88. package/src/endpoints/auth-2fa.ts +53 -8
  89. package/src/endpoints/capabilities.ts +2 -4
  90. package/src/endpoints/chatbot.ts +2 -2
  91. package/src/endpoints/delete-account.ts +191 -47
  92. package/src/endpoints/export-data.ts +104 -4
  93. package/src/endpoints/import-conversation.ts +2 -2
  94. package/src/endpoints/login.ts +13 -3
  95. package/src/endpoints/purge-logs.ts +6 -15
  96. package/src/endpoints/push.ts +14 -1
  97. package/src/endpoints/statuses.ts +17 -0
  98. package/src/index.ts +2 -0
  99. package/src/plugin.ts +51 -1
  100. package/src/portal/LiveChat.tsx +1 -1
  101. package/src/portal/auth/profile/page.tsx +3 -2
  102. package/src/portal/icons.tsx +91 -0
  103. package/src/portal/login/page.tsx +14 -4
  104. package/src/styles/BillingView.module.scss +11 -11
  105. package/src/styles/ChatView.module.scss +7 -7
  106. package/src/styles/CommandPalette.module.scss +1 -1
  107. package/src/styles/CrmView.module.scss +9 -9
  108. package/src/styles/EmailTracking.module.scss +6 -6
  109. package/src/styles/ImportConversation.module.scss +5 -5
  110. package/src/styles/Logs.module.scss +5 -5
  111. package/src/styles/NewTicket.module.scss +2 -2
  112. package/src/styles/PendingEmails.module.scss +13 -13
  113. package/src/styles/SupportDashboard.module.scss +24 -8
  114. package/src/styles/TicketDetail.module.scss +20 -20
  115. package/src/styles/TicketInbox.module.scss +6 -6
  116. package/src/styles/TicketingSettings.module.scss +10 -10
  117. package/src/styles/TimeDashboard.module.scss +6 -6
  118. package/src/styles/_tokens.scss +3 -1
  119. package/src/types.ts +20 -0
  120. package/src/utils/push.ts +22 -0
  121. package/src/utils/rateLimiter.ts +98 -0
  122. package/src/utils/retention.ts +111 -0
  123. package/src/utils/slugs.ts +15 -0
  124. package/src/utils/twoFactorChallenge.ts +6 -1
  125. package/src/utils/urlSafety.ts +36 -1
  126. package/src/views/BillingView/client.tsx +17 -8
  127. package/src/views/BillingView/index.tsx +4 -4
  128. package/src/views/ChatView/client.tsx +2 -0
  129. package/src/views/ChatView/index.tsx +4 -4
  130. package/src/views/CrmView/client.tsx +2 -0
  131. package/src/views/CrmView/index.tsx +4 -4
  132. package/src/views/EmailTrackingView/client.tsx +18 -7
  133. package/src/views/EmailTrackingView/index.tsx +4 -4
  134. package/src/views/ImportConversationView/client.tsx +1 -0
  135. package/src/views/ImportConversationView/index.tsx +4 -4
  136. package/src/views/LogsView/client.tsx +1 -1
  137. package/src/views/LogsView/index.tsx +4 -2
  138. package/src/views/NewTicketView/client.tsx +22 -13
  139. package/src/views/NewTicketView/index.tsx +4 -2
  140. package/src/views/PendingEmailsView/client.tsx +9 -3
  141. package/src/views/PendingEmailsView/index.tsx +4 -4
  142. package/src/views/SupportDashboardView/client.tsx +11 -5
  143. package/src/views/SupportDashboardView/index.tsx +4 -4
  144. package/src/views/TicketDetailView/client.tsx +25 -11
  145. package/src/views/TicketDetailView/index.tsx +4 -4
  146. package/src/views/TicketInboxView/client.tsx +47 -7
  147. package/src/views/TicketInboxView/index.tsx +4 -2
  148. package/src/views/TicketingSettingsView/TicketingSettings.module.scss +7 -7
  149. package/src/views/TicketingSettingsView/client.tsx +201 -144
  150. package/src/views/TicketingSettingsView/index.tsx +4 -4
  151. package/src/views/TimeDashboardView/client.tsx +10 -7
  152. package/src/views/TimeDashboardView/index.tsx +4 -4
  153. package/src/views/shared/ErrorBoundary.tsx +95 -31
  154. package/src/views/shared/adminTokens.ts +28 -11
  155. package/src/views/shared/icons.tsx +146 -0
  156. package/src/views/shared/locales/en.json +15 -1
  157. package/src/views/shared/locales/fr.json +15 -1
  158. package/src/views/shared/viewAccess.ts +73 -0
  159. package/src/types/lucide-react.d.ts +0 -42
package/dist/index.d.cts CHANGED
@@ -11,9 +11,29 @@ interface RateLimitStore {
11
11
  /**
12
12
  * Process-local fallback store. Applications running more than one process
13
13
  * should provide a persistent RateLimitStore through the plugin options.
14
+ *
15
+ * BOUNDED, because the keys come from anonymous HTTP traffic: `/support/login`
16
+ * and `/support/chatbot` key their limiter on the client IP, and the IP is read
17
+ * from `x-forwarded-for`. A caller rotating that header wrote one PERMANENT
18
+ * entry per value into a map that had no ceiling, no expiry sweep and no
19
+ * eviction — only `reset()` ever removed anything, and the login path never
20
+ * calls it. Worse, every fresh key opened a fresh window, so the limiter did
21
+ * not even slow down the flood that was exhausting it.
22
+ *
23
+ * Two independent bounds, the same pair `endpoints/typing.ts` already applies
24
+ * to its own module-level map: `clientIpRateKey` caps the SIZE of a key, the
25
+ * ceiling below caps their NUMBER.
14
26
  */
15
27
  declare class MemoryRateLimitStore implements RateLimitStore {
28
+ private readonly maxKeys;
16
29
  private readonly entries;
30
+ constructor(maxKeys?: number);
31
+ /** Distinct keys currently held. Exposed so the ceiling can be asserted. */
32
+ get size(): number;
33
+ /** Reclaims every window that has already closed. */
34
+ private sweepExpired;
35
+ /** Soonest-closing window first, so the ceiling drops the least useful entry. */
36
+ private evictOldest;
17
37
  increment(key: string, windowMs: number): Promise<RateLimitEntry>;
18
38
  reset(key: string): Promise<void>;
19
39
  }
@@ -45,6 +65,94 @@ declare class RateLimiter {
45
65
  reset(key: string, context?: unknown): Promise<void>;
46
66
  }
47
67
 
68
+ /**
69
+ * Default collection slugs used by the support plugin.
70
+ * All slugs can be overridden via SupportPluginConfig.collectionSlugs.
71
+ */
72
+ interface CollectionSlugs {
73
+ tickets: string;
74
+ ticketMessages: string;
75
+ supportClients: string;
76
+ timeEntries: string;
77
+ cannedResponses: string;
78
+ ticketActivityLog: string;
79
+ satisfactionSurveys: string;
80
+ knowledgeBase: string;
81
+ chatMessages: string;
82
+ pendingEmails: string;
83
+ emailLogs: string;
84
+ authLogs: string;
85
+ webhookEndpoints: string;
86
+ slaPolicies: string;
87
+ macros: string;
88
+ ticketStatuses: string;
89
+ ticketFeedback: string;
90
+ notificationQueue: string;
91
+ automationRules: string;
92
+ supportTeams: string;
93
+ pushSubscriptions: string;
94
+ rateLimits: string;
95
+ counters: string;
96
+ users: string;
97
+ media: string;
98
+ }
99
+ declare const DEFAULT_SLUGS: CollectionSlugs;
100
+ /**
101
+ * Resolve collection slugs merging user overrides with defaults.
102
+ */
103
+ declare function resolveSlugs(overrides?: Partial<CollectionSlugs>): CollectionSlugs;
104
+
105
+ /**
106
+ * How long the two journals are kept, in days.
107
+ *
108
+ * Defaults follow the CNIL guidance the README documents: six months would be
109
+ * the floor for connection logs, a year is the ceiling usually accepted, and
110
+ * these two values sit inside that range while staying long enough to
111
+ * investigate an intrusion. Set a value to 0 to disable the automatic purge of
112
+ * that journal — never to mean "delete everything", which is what `days=0`
113
+ * means on the manual endpoint.
114
+ */
115
+ interface RetentionConfig {
116
+ /** Retention of `auth-logs` in days. `0` disables the scheduled purge. */
117
+ authLogsDays?: number;
118
+ /** Retention of `email-logs` in days. `0` disables the scheduled purge. */
119
+ emailLogsDays?: number;
120
+ /**
121
+ * Cron for the scheduled purge. Payload's cron takes an optional leading
122
+ * seconds field. Default: every day at 03:30.
123
+ */
124
+ cron?: string;
125
+ /** Queue the scheduled job is pushed to. Default: `default`. */
126
+ queue?: string;
127
+ }
128
+ declare const DEFAULT_RETENTION: {
129
+ readonly authLogsDays: 180;
130
+ readonly emailLogsDays: 365;
131
+ readonly cron: "0 30 3 * * *";
132
+ readonly queue: "default";
133
+ };
134
+ declare const PURGE_LOGS_TASK_SLUG = "support-purge-logs";
135
+ /** Journals the purge is allowed to touch, keyed by their public name. */
136
+ declare function purgeableCollections(slugs: CollectionSlugs): Record<string, string>;
137
+ /**
138
+ * Delete rows of `slug` created more than `days` days ago.
139
+ *
140
+ * `days <= 0` means "everything" and is only reachable from the manual
141
+ * admin-only endpoint. The scheduled task refuses it: a misconfigured cron
142
+ * that wipes the whole security journal every night is a far worse outcome
143
+ * than a journal that grows.
144
+ */
145
+ declare function purgeOlderThan(payload: Payload, slug: string, days: number, req?: PayloadRequest): Promise<number>;
146
+ interface ScheduledPurgeResult {
147
+ purged: Record<string, number>;
148
+ skipped: string[];
149
+ }
150
+ /**
151
+ * The scheduled half of the purge. Never accepts `days <= 0`, and silently
152
+ * skips a journal whose collection is not registered (its feature flag is off).
153
+ */
154
+ declare function runScheduledPurge(payload: Payload, slugs: CollectionSlugs, retention: RetentionConfig | false | undefined, req?: PayloadRequest): Promise<ScheduledPurgeResult>;
155
+
48
156
  interface InboundEmailLimits {
49
157
  maxRequestBytes: number;
50
158
  maxAttachmentBytes: number;
@@ -208,6 +316,24 @@ interface SupportPluginConfig {
208
316
  email?: EmailConfig;
209
317
  /** Shared rate-limit storage. Defaults to process-local memory. */
210
318
  rateLimitStore?: RateLimitStore | 'payload';
319
+ /**
320
+ * Automatic retention of the two journals the plugin writes.
321
+ *
322
+ * The plugin registers a daily Payload Jobs task that deletes rows older
323
+ * than the configured number of days. Set a value to 0 to keep that journal
324
+ * forever (the manual `DELETE /api/support/purge-logs` endpoint stays
325
+ * available either way).
326
+ *
327
+ * Defaults: auth-logs 180 days, email-logs 365 days, cron `0 30 3 * * *`.
328
+ *
329
+ * `false` registers no task at all. That is the ONLY value that changes the
330
+ * schema footprint: registering a task turns Payload's job queue on, which
331
+ * adds the `payload-jobs` collection and the `payload-jobs-stats` global to
332
+ * an app that had no jobs — two tables you would have to migrate. Pass
333
+ * `false` if you would rather purge from your own cron, calling
334
+ * `DELETE /api/support/purge-logs`.
335
+ */
336
+ retention?: RetentionConfig | false;
211
337
  /** Sequential ticket number formatting. */
212
338
  ticketNumber?: {
213
339
  prefix?: string;
@@ -356,43 +482,6 @@ declare const DEFAULT_FEATURES: Required<SupportFeatures>;
356
482
  */
357
483
  declare function supportPlugin(config?: SupportPluginConfig): Plugin;
358
484
 
359
- /**
360
- * Default collection slugs used by the support plugin.
361
- * All slugs can be overridden via SupportPluginConfig.collectionSlugs.
362
- */
363
- interface CollectionSlugs {
364
- tickets: string;
365
- ticketMessages: string;
366
- supportClients: string;
367
- timeEntries: string;
368
- cannedResponses: string;
369
- ticketActivityLog: string;
370
- satisfactionSurveys: string;
371
- knowledgeBase: string;
372
- chatMessages: string;
373
- pendingEmails: string;
374
- emailLogs: string;
375
- authLogs: string;
376
- webhookEndpoints: string;
377
- slaPolicies: string;
378
- macros: string;
379
- ticketStatuses: string;
380
- ticketFeedback: string;
381
- notificationQueue: string;
382
- automationRules: string;
383
- supportTeams: string;
384
- pushSubscriptions: string;
385
- rateLimits: string;
386
- counters: string;
387
- users: string;
388
- media: string;
389
- }
390
- declare const DEFAULT_SLUGS: CollectionSlugs;
391
- /**
392
- * Resolve collection slugs merging user overrides with defaults.
393
- */
394
- declare function resolveSlugs(overrides?: Partial<CollectionSlugs>): CollectionSlugs;
395
-
396
485
  /**
397
486
  * Ticketing feature flags — single source of truth (client + server).
398
487
  *
@@ -690,4 +779,4 @@ declare function createTicketStatusesCollection(slugs: CollectionSlugs): Collect
690
779
  */
691
780
  declare function createTicketCollaboratorsCollection(slugs: CollectionSlugs): CollectionConfig;
692
781
 
693
- 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 };
782
+ export { type AIProviderConfig, type ActivityEntryData, type CannedResponseData, type ClientData, type CollectionSlugs, DEFAULT_FEATURES, DEFAULT_INBOUND_EMAIL_LIMITS, DEFAULT_RETENTION, DEFAULT_SETTINGS, DEFAULT_SLUGS, DEFAULT_TICKETING_FEATURES, DEFAULT_USER_PREFS, type EmailConfig, type InboundEmailInput, type InboundEmailLimits, type InboundEmailValidationError, MemoryRateLimitStore, type MessageData, PURGE_LOGS_TASK_SLUG, PayloadRateLimitStore, type RateLimitEntry, type RateLimitStore, RateLimiter, type RetentionConfig, type SatisfactionSurveyData, type ScheduledPurgeResult, 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, purgeOlderThan, purgeableCollections, readSupportSettings, readSupportSettingsState, readUserPrefs, resolveSlugs, runScheduledPurge, stripProjectedFeatures, supportPlugin, validateInboundEmailPayload, verifySecret };
package/dist/index.d.ts CHANGED
@@ -11,9 +11,29 @@ interface RateLimitStore {
11
11
  /**
12
12
  * Process-local fallback store. Applications running more than one process
13
13
  * should provide a persistent RateLimitStore through the plugin options.
14
+ *
15
+ * BOUNDED, because the keys come from anonymous HTTP traffic: `/support/login`
16
+ * and `/support/chatbot` key their limiter on the client IP, and the IP is read
17
+ * from `x-forwarded-for`. A caller rotating that header wrote one PERMANENT
18
+ * entry per value into a map that had no ceiling, no expiry sweep and no
19
+ * eviction — only `reset()` ever removed anything, and the login path never
20
+ * calls it. Worse, every fresh key opened a fresh window, so the limiter did
21
+ * not even slow down the flood that was exhausting it.
22
+ *
23
+ * Two independent bounds, the same pair `endpoints/typing.ts` already applies
24
+ * to its own module-level map: `clientIpRateKey` caps the SIZE of a key, the
25
+ * ceiling below caps their NUMBER.
14
26
  */
15
27
  declare class MemoryRateLimitStore implements RateLimitStore {
28
+ private readonly maxKeys;
16
29
  private readonly entries;
30
+ constructor(maxKeys?: number);
31
+ /** Distinct keys currently held. Exposed so the ceiling can be asserted. */
32
+ get size(): number;
33
+ /** Reclaims every window that has already closed. */
34
+ private sweepExpired;
35
+ /** Soonest-closing window first, so the ceiling drops the least useful entry. */
36
+ private evictOldest;
17
37
  increment(key: string, windowMs: number): Promise<RateLimitEntry>;
18
38
  reset(key: string): Promise<void>;
19
39
  }
@@ -45,6 +65,94 @@ declare class RateLimiter {
45
65
  reset(key: string, context?: unknown): Promise<void>;
46
66
  }
47
67
 
68
+ /**
69
+ * Default collection slugs used by the support plugin.
70
+ * All slugs can be overridden via SupportPluginConfig.collectionSlugs.
71
+ */
72
+ interface CollectionSlugs {
73
+ tickets: string;
74
+ ticketMessages: string;
75
+ supportClients: string;
76
+ timeEntries: string;
77
+ cannedResponses: string;
78
+ ticketActivityLog: string;
79
+ satisfactionSurveys: string;
80
+ knowledgeBase: string;
81
+ chatMessages: string;
82
+ pendingEmails: string;
83
+ emailLogs: string;
84
+ authLogs: string;
85
+ webhookEndpoints: string;
86
+ slaPolicies: string;
87
+ macros: string;
88
+ ticketStatuses: string;
89
+ ticketFeedback: string;
90
+ notificationQueue: string;
91
+ automationRules: string;
92
+ supportTeams: string;
93
+ pushSubscriptions: string;
94
+ rateLimits: string;
95
+ counters: string;
96
+ users: string;
97
+ media: string;
98
+ }
99
+ declare const DEFAULT_SLUGS: CollectionSlugs;
100
+ /**
101
+ * Resolve collection slugs merging user overrides with defaults.
102
+ */
103
+ declare function resolveSlugs(overrides?: Partial<CollectionSlugs>): CollectionSlugs;
104
+
105
+ /**
106
+ * How long the two journals are kept, in days.
107
+ *
108
+ * Defaults follow the CNIL guidance the README documents: six months would be
109
+ * the floor for connection logs, a year is the ceiling usually accepted, and
110
+ * these two values sit inside that range while staying long enough to
111
+ * investigate an intrusion. Set a value to 0 to disable the automatic purge of
112
+ * that journal — never to mean "delete everything", which is what `days=0`
113
+ * means on the manual endpoint.
114
+ */
115
+ interface RetentionConfig {
116
+ /** Retention of `auth-logs` in days. `0` disables the scheduled purge. */
117
+ authLogsDays?: number;
118
+ /** Retention of `email-logs` in days. `0` disables the scheduled purge. */
119
+ emailLogsDays?: number;
120
+ /**
121
+ * Cron for the scheduled purge. Payload's cron takes an optional leading
122
+ * seconds field. Default: every day at 03:30.
123
+ */
124
+ cron?: string;
125
+ /** Queue the scheduled job is pushed to. Default: `default`. */
126
+ queue?: string;
127
+ }
128
+ declare const DEFAULT_RETENTION: {
129
+ readonly authLogsDays: 180;
130
+ readonly emailLogsDays: 365;
131
+ readonly cron: "0 30 3 * * *";
132
+ readonly queue: "default";
133
+ };
134
+ declare const PURGE_LOGS_TASK_SLUG = "support-purge-logs";
135
+ /** Journals the purge is allowed to touch, keyed by their public name. */
136
+ declare function purgeableCollections(slugs: CollectionSlugs): Record<string, string>;
137
+ /**
138
+ * Delete rows of `slug` created more than `days` days ago.
139
+ *
140
+ * `days <= 0` means "everything" and is only reachable from the manual
141
+ * admin-only endpoint. The scheduled task refuses it: a misconfigured cron
142
+ * that wipes the whole security journal every night is a far worse outcome
143
+ * than a journal that grows.
144
+ */
145
+ declare function purgeOlderThan(payload: Payload, slug: string, days: number, req?: PayloadRequest): Promise<number>;
146
+ interface ScheduledPurgeResult {
147
+ purged: Record<string, number>;
148
+ skipped: string[];
149
+ }
150
+ /**
151
+ * The scheduled half of the purge. Never accepts `days <= 0`, and silently
152
+ * skips a journal whose collection is not registered (its feature flag is off).
153
+ */
154
+ declare function runScheduledPurge(payload: Payload, slugs: CollectionSlugs, retention: RetentionConfig | false | undefined, req?: PayloadRequest): Promise<ScheduledPurgeResult>;
155
+
48
156
  interface InboundEmailLimits {
49
157
  maxRequestBytes: number;
50
158
  maxAttachmentBytes: number;
@@ -208,6 +316,24 @@ interface SupportPluginConfig {
208
316
  email?: EmailConfig;
209
317
  /** Shared rate-limit storage. Defaults to process-local memory. */
210
318
  rateLimitStore?: RateLimitStore | 'payload';
319
+ /**
320
+ * Automatic retention of the two journals the plugin writes.
321
+ *
322
+ * The plugin registers a daily Payload Jobs task that deletes rows older
323
+ * than the configured number of days. Set a value to 0 to keep that journal
324
+ * forever (the manual `DELETE /api/support/purge-logs` endpoint stays
325
+ * available either way).
326
+ *
327
+ * Defaults: auth-logs 180 days, email-logs 365 days, cron `0 30 3 * * *`.
328
+ *
329
+ * `false` registers no task at all. That is the ONLY value that changes the
330
+ * schema footprint: registering a task turns Payload's job queue on, which
331
+ * adds the `payload-jobs` collection and the `payload-jobs-stats` global to
332
+ * an app that had no jobs — two tables you would have to migrate. Pass
333
+ * `false` if you would rather purge from your own cron, calling
334
+ * `DELETE /api/support/purge-logs`.
335
+ */
336
+ retention?: RetentionConfig | false;
211
337
  /** Sequential ticket number formatting. */
212
338
  ticketNumber?: {
213
339
  prefix?: string;
@@ -356,43 +482,6 @@ declare const DEFAULT_FEATURES: Required<SupportFeatures>;
356
482
  */
357
483
  declare function supportPlugin(config?: SupportPluginConfig): Plugin;
358
484
 
359
- /**
360
- * Default collection slugs used by the support plugin.
361
- * All slugs can be overridden via SupportPluginConfig.collectionSlugs.
362
- */
363
- interface CollectionSlugs {
364
- tickets: string;
365
- ticketMessages: string;
366
- supportClients: string;
367
- timeEntries: string;
368
- cannedResponses: string;
369
- ticketActivityLog: string;
370
- satisfactionSurveys: string;
371
- knowledgeBase: string;
372
- chatMessages: string;
373
- pendingEmails: string;
374
- emailLogs: string;
375
- authLogs: string;
376
- webhookEndpoints: string;
377
- slaPolicies: string;
378
- macros: string;
379
- ticketStatuses: string;
380
- ticketFeedback: string;
381
- notificationQueue: string;
382
- automationRules: string;
383
- supportTeams: string;
384
- pushSubscriptions: string;
385
- rateLimits: string;
386
- counters: string;
387
- users: string;
388
- media: string;
389
- }
390
- declare const DEFAULT_SLUGS: CollectionSlugs;
391
- /**
392
- * Resolve collection slugs merging user overrides with defaults.
393
- */
394
- declare function resolveSlugs(overrides?: Partial<CollectionSlugs>): CollectionSlugs;
395
-
396
485
  /**
397
486
  * Ticketing feature flags — single source of truth (client + server).
398
487
  *
@@ -690,4 +779,4 @@ declare function createTicketStatusesCollection(slugs: CollectionSlugs): Collect
690
779
  */
691
780
  declare function createTicketCollaboratorsCollection(slugs: CollectionSlugs): CollectionConfig;
692
781
 
693
- 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 };
782
+ export { type AIProviderConfig, type ActivityEntryData, type CannedResponseData, type ClientData, type CollectionSlugs, DEFAULT_FEATURES, DEFAULT_INBOUND_EMAIL_LIMITS, DEFAULT_RETENTION, DEFAULT_SETTINGS, DEFAULT_SLUGS, DEFAULT_TICKETING_FEATURES, DEFAULT_USER_PREFS, type EmailConfig, type InboundEmailInput, type InboundEmailLimits, type InboundEmailValidationError, MemoryRateLimitStore, type MessageData, PURGE_LOGS_TASK_SLUG, PayloadRateLimitStore, type RateLimitEntry, type RateLimitStore, RateLimiter, type RetentionConfig, type SatisfactionSurveyData, type ScheduledPurgeResult, 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, purgeOlderThan, purgeableCollections, readSupportSettings, readSupportSettingsState, readUserPrefs, resolveSlugs, runScheduledPurge, stripProjectedFeatures, supportPlugin, validateInboundEmailPayload, verifySecret };