@consilioweb/payload-support 0.16.0 β†’ 1.1.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 (199) hide show
  1. package/README.md +357 -435
  2. package/dist/components/TicketConversation/RewriteDropdown.cjs +98 -0
  3. package/dist/components/TicketConversation/RewriteDropdown.js +93 -0
  4. package/dist/components/TicketConversation/SkeletonText.cjs +21 -0
  5. package/dist/components/TicketConversation/SkeletonText.js +20 -0
  6. package/dist/components/TicketConversation/constants.cjs +27 -0
  7. package/dist/components/TicketConversation/constants.js +26 -1
  8. package/dist/components/TicketConversation/hooks/useDocumentIdFromUrl.cjs +20 -0
  9. package/dist/components/TicketConversation/hooks/useDocumentIdFromUrl.js +19 -0
  10. package/dist/components/TicketConversation/index.cjs +10 -147
  11. package/dist/components/TicketConversation/index.js +4 -141
  12. package/dist/index.cjs +1763 -677
  13. package/dist/index.d.cts +4 -0
  14. package/dist/index.d.ts +4 -0
  15. package/dist/index.js +1760 -677
  16. package/dist/views/BillingView/client.cjs +40 -54
  17. package/dist/views/BillingView/client.js +40 -54
  18. package/dist/views/ChatView/client.cjs +4 -3
  19. package/dist/views/ChatView/client.js +4 -3
  20. package/dist/views/CrmView/client.cjs +7 -7
  21. package/dist/views/CrmView/client.js +7 -7
  22. package/dist/views/EmailTrackingView/client.cjs +6 -5
  23. package/dist/views/EmailTrackingView/client.js +6 -5
  24. package/dist/views/ImportConversationView/client.cjs +4 -4
  25. package/dist/views/ImportConversationView/client.js +4 -4
  26. package/dist/views/LogsView/client.cjs +3 -2
  27. package/dist/views/LogsView/client.js +3 -2
  28. package/dist/views/NewTicketView/client.cjs +1 -1
  29. package/dist/views/NewTicketView/client.js +1 -1
  30. package/dist/views/PendingEmailsView/client.cjs +7 -6
  31. package/dist/views/PendingEmailsView/client.js +7 -6
  32. package/dist/views/SupportDashboardView/client.cjs +19 -22
  33. package/dist/views/SupportDashboardView/client.js +19 -22
  34. package/dist/views/TicketDetailView/NextActionItem.cjs +40 -0
  35. package/dist/views/TicketDetailView/NextActionItem.js +34 -0
  36. package/dist/views/TicketDetailView/RewriteDropdown.cjs +80 -0
  37. package/dist/views/TicketDetailView/RewriteDropdown.js +78 -0
  38. package/dist/views/TicketDetailView/client.cjs +59 -190
  39. package/dist/views/TicketDetailView/client.js +52 -183
  40. package/dist/views/TicketDetailView/constants.cjs +20 -0
  41. package/dist/views/TicketDetailView/constants.js +16 -0
  42. package/dist/views/TicketDetailView/helpers.cjs +23 -0
  43. package/dist/views/TicketDetailView/helpers.js +20 -0
  44. package/dist/views/TicketDetailView/types.cjs +2 -0
  45. package/dist/views/TicketDetailView/types.js +1 -0
  46. package/dist/views/TicketInboxView/client.cjs +14 -10
  47. package/dist/views/TicketInboxView/client.js +14 -10
  48. package/dist/views/TicketingSettingsView/client.cjs +101 -96
  49. package/dist/views/TicketingSettingsView/client.js +92 -88
  50. package/dist/views/TimeDashboardView/client.cjs +2 -2
  51. package/dist/views/TimeDashboardView/client.js +2 -2
  52. package/dist/views/shared/StatusPill.cjs +23 -12
  53. package/dist/views/shared/StatusPill.js +23 -12
  54. package/dist/views/shared/dateLocale.cjs +5 -0
  55. package/dist/views/shared/dateLocale.js +3 -0
  56. package/package.json +28 -15
  57. package/src/__tests__/generateTrackingToken.test.ts +53 -0
  58. package/src/__tests__/integration/ai-agent.test.ts +46 -0
  59. package/src/__tests__/integration/auth.test.ts +43 -0
  60. package/src/__tests__/integration/automation-rules.test.ts +68 -0
  61. package/src/__tests__/integration/buildTestPayload.ts +52 -0
  62. package/src/__tests__/integration/channels.test.ts +52 -0
  63. package/src/__tests__/integration/core-behaviors.test.ts +58 -0
  64. package/src/__tests__/integration/dashboard-volume.test.ts +31 -0
  65. package/src/__tests__/integration/digest.test.ts +48 -0
  66. package/src/__tests__/integration/invoice-pdf.test.ts +30 -0
  67. package/src/__tests__/integration/isolation.test.ts +81 -0
  68. package/src/__tests__/integration/mentions-invoice.test.ts +50 -0
  69. package/src/__tests__/integration/nps.test.ts +37 -0
  70. package/src/__tests__/integration/per-team-sla.test.ts +44 -0
  71. package/src/__tests__/integration/push.test.ts +75 -0
  72. package/src/__tests__/integration/sanitization.test.ts +35 -0
  73. package/src/__tests__/integration/sla-pause.test.ts +39 -0
  74. package/src/__tests__/integration/smoke.test.ts +26 -0
  75. package/src/__tests__/integration/snooze.test.ts +68 -0
  76. package/src/__tests__/integration/teams.test.ts +38 -0
  77. package/src/__tests__/rateLimiter.test.ts +89 -0
  78. package/src/__tests__/sanitizeHtml.test.ts +165 -0
  79. package/src/__tests__/sla.test.ts +258 -0
  80. package/src/collections/AutomationRules.ts +66 -0
  81. package/src/collections/NotificationQueue.ts +30 -0
  82. package/src/collections/PushSubscription.ts +28 -0
  83. package/src/collections/SatisfactionSurveys.ts +11 -2
  84. package/src/collections/SlaPolicies.ts +10 -0
  85. package/src/collections/SupportClients.ts +58 -1
  86. package/src/collections/SupportTeam.ts +27 -0
  87. package/src/collections/TicketActivityLog.ts +9 -4
  88. package/src/collections/TicketMessages.ts +140 -31
  89. package/src/collections/Tickets.ts +31 -73
  90. package/src/collections/index.ts +4 -0
  91. package/src/components/TicketConversation/RewriteDropdown.tsx +86 -0
  92. package/src/components/TicketConversation/SkeletonText.tsx +23 -0
  93. package/src/components/TicketConversation/constants.ts +29 -0
  94. package/src/components/TicketConversation/hooks/useDocumentIdFromUrl.ts +21 -0
  95. package/src/components/TicketConversation/index.tsx +4 -152
  96. package/src/endpoints/admin-chat-stream.ts +3 -4
  97. package/src/endpoints/admin-chat.ts +11 -20
  98. package/src/endpoints/admin-stats.ts +77 -35
  99. package/src/endpoints/ai-agent.ts +36 -0
  100. package/src/endpoints/apply-macro.ts +8 -14
  101. package/src/endpoints/auth-2fa.ts +12 -12
  102. package/src/endpoints/auto-close.ts +6 -10
  103. package/src/endpoints/billing.ts +17 -4
  104. package/src/endpoints/bulk-action.ts +7 -12
  105. package/src/endpoints/channels.ts +89 -0
  106. package/src/endpoints/chat-stream.ts +3 -4
  107. package/src/endpoints/chat.ts +7 -12
  108. package/src/endpoints/chatbot.ts +2 -2
  109. package/src/endpoints/client-intelligence.ts +4 -4
  110. package/src/endpoints/delete-account.ts +9 -16
  111. package/src/endpoints/email-stats.ts +2 -2
  112. package/src/endpoints/escalate.ts +2 -2
  113. package/src/endpoints/export-csv.ts +2 -2
  114. package/src/endpoints/export-data.ts +5 -8
  115. package/src/endpoints/import-conversation.ts +6 -10
  116. package/src/endpoints/index.ts +22 -1
  117. package/src/endpoints/invite-collaborator.ts +30 -15
  118. package/src/endpoints/invoice.ts +127 -0
  119. package/src/endpoints/kb-search.ts +2 -2
  120. package/src/endpoints/login.ts +12 -4
  121. package/src/endpoints/merge-clients.ts +14 -19
  122. package/src/endpoints/merge-tickets.ts +11 -18
  123. package/src/endpoints/oauth-google.ts +86 -39
  124. package/src/endpoints/pending-emails-process.ts +15 -25
  125. package/src/endpoints/process-digests.ts +93 -0
  126. package/src/endpoints/process-scheduled.ts +6 -10
  127. package/src/endpoints/process-snooze.ts +78 -0
  128. package/src/endpoints/purge-logs.ts +2 -2
  129. package/src/endpoints/push.ts +49 -0
  130. package/src/endpoints/resend-notification.ts +3 -4
  131. package/src/endpoints/round-robin-config.ts +3 -4
  132. package/src/endpoints/satisfaction.ts +21 -14
  133. package/src/endpoints/search.ts +5 -8
  134. package/src/endpoints/seed-kb.ts +3 -4
  135. package/src/endpoints/send-reminder.ts +6 -9
  136. package/src/endpoints/settings.ts +5 -2
  137. package/src/endpoints/signature.ts +3 -4
  138. package/src/endpoints/sla-check.ts +2 -2
  139. package/src/endpoints/split-ticket.ts +7 -12
  140. package/src/endpoints/statuses.ts +2 -2
  141. package/src/endpoints/ticket-feedback.ts +4 -6
  142. package/src/endpoints/ticket-synthesis.ts +2 -2
  143. package/src/endpoints/track-open.ts +16 -28
  144. package/src/endpoints/transfer-ticket.ts +21 -9
  145. package/src/endpoints/user-prefs.ts +3 -4
  146. package/src/hooks/automationRules.ts +84 -0
  147. package/src/hooks/checkSLA.ts +63 -17
  148. package/src/plugin.ts +8 -0
  149. package/src/portal/LiveChat.tsx +2 -63
  150. package/src/portal/auth/tickets/detail/CloseTicketButton.tsx +10 -0
  151. package/src/portal/auth/tickets/detail/MarkSolutionButton.tsx +14 -2
  152. package/src/portal/auth/tickets/detail/MessageActions.tsx +37 -18
  153. package/src/portal/auth/tickets/detail/ReopenTicketButton.tsx +10 -0
  154. package/src/portal/auth/tickets/detail/TransferAndInviteActions.tsx +3 -2
  155. package/src/portal/auth/tickets/detail/page.tsx +2 -2
  156. package/src/portal/helpers.ts +46 -0
  157. package/src/portal/login/page.tsx +3 -8
  158. package/src/portal/types.ts +15 -0
  159. package/src/types/lucide-react.d.ts +34 -0
  160. package/src/types/payload-config.d.ts +10 -0
  161. package/src/utils/adminNotification.ts +2 -2
  162. package/src/utils/aiAgent.ts +147 -0
  163. package/src/utils/auth.ts +5 -4
  164. package/src/utils/channels.ts +36 -0
  165. package/src/utils/db.ts +73 -0
  166. package/src/utils/emailTemplate.ts +8 -1
  167. package/src/utils/fireWebhooks.ts +4 -6
  168. package/src/utils/generateTicketSynthesis.ts +7 -12
  169. package/src/utils/invoicePdf.ts +88 -0
  170. package/src/utils/notificationQueue.ts +36 -0
  171. package/src/utils/push.ts +63 -0
  172. package/src/utils/readSettings.ts +22 -6
  173. package/src/utils/sanitizeHtml.ts +57 -0
  174. package/src/utils/slugs.ts +8 -0
  175. package/src/utils/teamAccess.ts +27 -0
  176. package/src/utils/ticketAccess.ts +53 -0
  177. package/src/utils/webhookDispatcher.ts +4 -6
  178. package/src/views/BillingView/client.tsx +49 -37
  179. package/src/views/ChatView/client.tsx +4 -3
  180. package/src/views/CrmView/client.tsx +7 -7
  181. package/src/views/EmailTrackingView/client.tsx +7 -6
  182. package/src/views/ImportConversationView/client.tsx +4 -4
  183. package/src/views/LogsView/client.tsx +3 -2
  184. package/src/views/NewTicketView/client.tsx +1 -1
  185. package/src/views/PendingEmailsView/client.tsx +7 -6
  186. package/src/views/SupportDashboardView/client.tsx +21 -21
  187. package/src/views/TicketDetailView/NextActionItem.tsx +30 -0
  188. package/src/views/TicketDetailView/RewriteDropdown.tsx +63 -0
  189. package/src/views/TicketDetailView/client.tsx +54 -179
  190. package/src/views/TicketDetailView/constants.ts +23 -0
  191. package/src/views/TicketDetailView/helpers.ts +17 -0
  192. package/src/views/TicketDetailView/types.ts +10 -0
  193. package/src/views/TicketInboxView/client.tsx +16 -10
  194. package/src/views/TicketingSettingsView/client.tsx +90 -87
  195. package/src/views/TimeDashboardView/client.tsx +2 -2
  196. package/src/views/shared/StatusPill.tsx +24 -12
  197. package/src/views/shared/dateLocale.ts +5 -0
  198. package/src/views/shared/locales/en.json +708 -0
  199. package/src/views/shared/locales/fr.json +708 -0
package/README.md CHANGED
@@ -1,525 +1,447 @@
1
- <!-- Header Banner -->
1
+ <div align="center" style="background: linear-gradient(135deg, #1f8a5b 0%, #16a34a 50%, #0d9488 100%); padding: 50px 40px; border-radius: 12px; color: white; margin-bottom: 40px;">
2
+ <h1 style="margin: 0 0 15px 0; font-size: 42px; font-weight: 700; letter-spacing: -0.5px;">payload-support</h1>
3
+ <p style="margin: 0 auto; font-size: 18px; opacity: 0.95; max-width: 640px; line-height: 1.6;">A complete, self-hosted support &amp; ticketing system for Payload CMS 3 + Next.js β€” tickets, SLA, AI assists and an autonomous AI agent, live chat, a full client portal, time tracking &amp; invoicing, and a visual automation-rules engine. No third-party support SaaS required.</p>
4
+ </div>
5
+
2
6
  <div align="center">
3
7
 
4
- <a href="https://git.io/typing-svg">
5
- <img src="https://readme-typing-svg.demolab.com?font=Fira+Code&weight=700&size=32&duration=3000&pause=1000&color=3B82F6&center=true&vCenter=true&width=700&lines=%40consilioweb%2Fpayload-support;Professional+Ticketing+for+Payload+CMS;AI+%7C+SLA+%7C+Time+Tracking+%7C+Live+Chat;15+Collections+%7C+34+API+Routes;Open-Source+%7C+MIT+License" alt="Typing SVG" />
6
- </a>
8
+ [![npm version](https://img.shields.io/npm/v/@consilioweb/payload-support?color=1f8a5b&label=npm)](https://www.npmjs.com/package/@consilioweb/payload-support)
9
+ [![MIT License](https://img.shields.io/badge/license-MIT-1f8a5b)](LICENSE)
10
+ [![Node.js](https://img.shields.io/badge/node-18+-1f8a5b)](https://nodejs.org)
11
+ [![Payload](https://img.shields.io/badge/payload-3.x-1f8a5b)](https://payloadcms.com)
12
+ [![Tests](https://img.shields.io/badge/tests-102%20passing-1f8a5b)](src/__tests__)
13
+ [![TypeScript](https://img.shields.io/badge/typescript-strict-1f8a5b)](https://www.typescriptlang.org)
7
14
 
8
- <br><br>
15
+ </div>
9
16
 
10
- <!-- Badges -->
11
- <img src="https://img.shields.io/badge/version-0.2.0-blue?style=for-the-badge" alt="version">
12
- <img src="https://img.shields.io/badge/Payload%20CMS-3.x-0F172A?style=for-the-badge&logo=data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iMjQiIGhlaWdodD0iMjQiIHZpZXdCb3g9IjAgMCAyNCAyNCIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj48cGF0aCBkPSJNMTIgMkw0IDdWMTdMMTIgMjJMMjAgMTdWN0wxMiAyWiIgc3Ryb2tlPSJ3aGl0ZSIgc3Ryb2tlLXdpZHRoPSIyIiBzdHJva2UtbGluZWNhcD0icm91bmQiIHN0cm9rZS1saW5lam9pbj0icm91bmQiLz48L3N2Zz4=&logoColor=white" alt="Payload CMS 3">
13
- <img src="https://img.shields.io/badge/AI-Anthropic%20%7C%20OpenAI%20%7C%20Ollama-10B981?style=for-the-badge" alt="AI">
14
- <img src="https://img.shields.io/badge/i18n-FR%20%7C%20EN-F59E0B?style=for-the-badge&logo=translate&logoColor=white" alt="i18n FR | EN">
15
- <a href="https://github.com/pOwn3d/payload-support/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-7C3AED?style=for-the-badge" alt="MIT License"></a>
16
- <img src="https://img.shields.io/badge/TypeScript-5.x-3178C6?style=for-the-badge&logo=typescript&logoColor=white" alt="TypeScript">
17
+ <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" width="100%" alt="" />
17
18
 
18
- </div>
19
+ ## πŸ“‘ Table of Contents
19
20
 
20
- <p align="center">
21
- <a href="https://buymeacoffee.com/pown3d">
22
- <img src="https://img.shields.io/badge/Buy%20me%20a%20coffee-β˜•-FFDD00?style=for-the-badge&logo=buy-me-a-coffee&logoColor=black" alt="Buy me a coffee" />
23
- </a>
24
- </p>
25
-
26
- <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" alt="line">
27
-
28
- > [!IMPORTANT]
29
- > ## ⚠️ Next.js 16 + Turbopack β€” Known Issue
30
- >
31
- > If you're using **Next.js 16** with Turbopack (default bundler), you may encounter a `createContext is not a function` error during `next build`. This is a **known Payload CMS issue** ([#15429](https://github.com/payloadcms/payload/issues/15429), [#14330](https://github.com/payloadcms/payload/discussions/14330)) β€” not specific to this plugin.
32
- >
33
- > **Workaround** β€” Add this to your admin page (`src/app/(payload)/admin/[[...segments]]/page.tsx`):
34
- > ```ts
35
- > export const dynamic = 'force-dynamic'
36
- > ```
37
- >
38
- > And ensure all `@consilioweb/*` packages are in `transpilePackages` in your `next.config.ts`:
39
- > ```ts
40
- > transpilePackages: ['@consilioweb/payload-seo-analyzer', '@consilioweb/payload-admin-nav', /* ...other @consilioweb packages */],
41
- > ```
42
- >
43
- > βœ… **Next.js 15** works without any workaround.
44
-
45
- ## About
46
-
47
- > **@consilioweb/payload-support** β€” A complete, production-ready support & ticketing system for Payload CMS 3. Comparable to Freshdesk, HelpScout, and Crisp β€” but free, open-source, and fully integrated into Payload's admin panel.
21
+ - [Features](#-features)
22
+ - [Quick Start](#-quick-start)
23
+ - [Installation](#-installation)
24
+ - [Usage](#-usage)
25
+ - [API Reference](#-api-reference)
26
+ - [Configuration](#-configuration)
27
+ - [Performance](#-performance)
28
+ - [Examples](#-examples)
29
+ - [FAQ](#-faq)
30
+ - [Troubleshooting](#-troubleshooting)
31
+ - [Security](#-security)
32
+ - [Contributing](#-contributing)
33
+ - [Changelog](#-changelog)
34
+ - [Roadmap](#-roadmap)
35
+ - [Support](#-support)
36
+ - [License](#-license)
37
+
38
+ <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" width="100%" alt="" />
39
+
40
+ ## ✨ Features
48
41
 
49
42
  <table>
50
- <tr>
51
- <td align="center" width="20%">
52
- <b>Ticketing</b><br>
53
- <sub>Auto-increment, SLA, priorities, categories</sub>
54
- </td>
55
- <td align="center" width="20%">
56
- <b>AI-Powered</b><br>
57
- <sub>Sentiment, synthesis, suggestions, rewrite</sub>
58
- </td>
59
- <td align="center" width="20%">
60
- <b>Time Tracking</b><br>
61
- <sub>Timer, entries, billing dashboard</sub>
62
- </td>
63
- <td align="center" width="20%">
64
- <b>Live Chat</b><br>
65
- <sub>Real-time, chat-to-ticket conversion</sub>
66
- </td>
67
- <td align="center" width="20%">
68
- <b>Modular</b><br>
69
- <sub>25+ feature flags, enable what you need</sub>
70
- </td>
71
- </tr>
72
- </table>
43
+ <tr>
44
+ <td width="50%">
73
45
 
74
- <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" alt="line">
75
-
76
- ## Features
77
-
78
- ### Core Ticketing
79
- - Auto-increment ticket numbers (TK-0001, TK-0002...)
80
- - Statuses, priorities, categories, tags
81
- - Multi-agent assignment with round-robin distribution
82
- - Ticket merge, split, snooze
83
- - Scheduled replies
84
- - Bulk actions on multiple tickets
85
- - Command palette (⌘K) for instant search
86
-
87
- ### AI Integration
88
- - **Sentiment analysis** β€” detect client mood from messages
89
- - **AI summary** β€” generate conversation synthesis
90
- - **Smart reply** β€” suggest contextual responses
91
- - **Rewrite** β€” rephrase messages professionally
92
- - Multi-provider: Anthropic Claude, OpenAI, Ollama, custom endpoint
93
- - AI chatbot for first-line self-service
94
-
95
- ### SLA & Compliance
96
- - Response & resolution time targets per priority
97
- - Business hours support
98
- - SLA breach alerts on dashboard
99
- - Webhook dispatch on `sla_breached` events
100
-
101
- ### Time Tracking & Billing
102
- - Built-in timer with pause/resume
103
- - Manual time entries per ticket
104
- - Time dashboard with analytics
105
- - Billing/invoicing foundation
106
- - Facturable toggle per ticket
107
-
108
- ### Live Chat
109
- - Real-time chat sessions via **Server-Sent Events (SSE)** (v0.2.0)
110
- - Automatic **SSE to polling fallback** when EventSource unavailable (v0.2.0)
111
- - Typing indicators
112
- - Chat-to-ticket conversion
113
- - Agent presence/collision detection
114
-
115
- ### Email Integration
116
- - Inbound email β†’ ticket/message (via webhook)
117
- - Pending email queue with client matching
118
- - Email pixel tracking (opens)
119
- - Per-agent email signatures
120
- - Email log viewer with purge
121
-
122
- ### Client Management (CRM)
123
- - Client profiles with history
124
- - Impersonation (view as client)
125
- - Client merge
126
- - Satisfaction surveys (CSAT 1-5)
127
- - Knowledge base / FAQ
128
- - Client portal (separate auth)
129
-
130
- ### Automation
131
- - Auto-close inactive tickets
132
- - Canned responses with template variables
133
- - Macros (multi-action shortcuts)
134
- - Webhooks (HMAC-SHA256 signed) with dispatch on ticket events (v0.2.0)
135
- - **Scheduled replies** processing endpoint (v0.2.0)
136
- - Activity log (full audit trail)
137
-
138
- ### Security (v0.2.0)
139
- - **XSS prevention** β€” escapeHtml on all email template dynamic fields
140
- - **2FA codes** hashed with HMAC-SHA256 before storage
141
- - **Tracking pixels** signed with HMAC
142
- - **OAuth Google** β€” `allowedEmailDomains` option for domain restriction
143
- - **Rate limiting** β€” unified RateLimiter class on all public endpoints
144
- - **Collection injection protection** β€” validates collection parameters against whitelist
145
- - **Password generation** β€” uses crypto.randomBytes (not Math.random)
146
-
147
- ### Internationalization
148
- - Full FR/EN support
149
- - Locale toggle in settings
150
- - Extensible translation system
151
-
152
- <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" alt="line">
153
-
154
- ## Architecture
155
-
156
- ### Collections (15)
157
-
158
- | Collection | Description |
159
- |------------|-------------|
160
- | `tickets` | Core ticket with auto-increment, SLA, activity hooks |
161
- | `ticket-messages` | Conversation messages with author type, attachments |
162
- | `support-clients` | Client auth collection (email/password) |
163
- | `time-entries` | Time tracking per ticket |
164
- | `canned-responses` | Quick reply templates with variables |
165
- | `ticket-activity-log` | Immutable audit trail |
166
- | `satisfaction-surveys` | CSAT ratings (1-5) |
167
- | `knowledge-base` | FAQ articles with rich text |
168
- | `chat-messages` | Live chat sessions |
169
- | `pending-emails` | Inbound email queue |
170
- | `email-logs` | Email delivery audit |
171
- | `auth-logs` | Authentication audit |
172
- | `webhook-endpoints` | Outbound webhook config |
173
- | `sla-policies` | SLA rules per priority |
174
- | `macros` | Multi-action shortcuts |
175
- | `ticket-statuses` | Custom configurable statuses |
176
-
177
- ### API Endpoints (34)
178
-
179
- | Category | Endpoints |
180
- |----------|-----------|
181
- | **Tickets** | search, bulk-action, merge-tickets, split-ticket, export-csv, export-data |
182
- | **AI** | ai (sentiment/synthesis/suggest/rewrite), chatbot |
183
- | **Chat** | chat, admin-chat, typing, presence |
184
- | **Email** | pending-emails/process, resend-notification, track-open, email-stats |
185
- | **Config** | settings, signature, round-robin-config, statuses, sla-check, auto-close |
186
- | **Auth** | login, 2fa, oauth/google, delete-account |
187
- | **SSE** | client-stream, admin-stream (v0.2.0) |
188
- | **Scheduled** | process-scheduled (v0.2.0) |
189
- | **Misc** | apply-macro, purge-logs, seed-kb, admin-stats, billing, import-conversation, merge-clients, satisfaction |
190
-
191
- ### Admin Views (12)
192
-
193
- | View | Path | Description |
194
- |------|------|-------------|
195
- | Inbox | `/support/inbox` | Superhuman-style ticket list with keyboard nav |
196
- | Dashboard | `/support/dashboard` | KPIs, SLA metrics, active tickets |
197
- | Ticket Detail | `/support/ticket?id=X` | Full conversation with sidebar panels |
198
- | New Ticket | `/support/new-ticket` | Create ticket with client search |
199
- | Settings | `/support/settings` | Feature flags, AI, SLA, auto-close config |
200
- | CRM | `/support/crm` | Client list and profiles |
201
- | Chat | `/support/chat` | Live chat sessions |
202
- | Pending Emails | `/support/emails` | Inbound email queue |
203
- | Email Tracking | `/support/tracking` | Open/delivery tracking |
204
- | Time Dashboard | `/support/time` | Time entries analytics |
205
- | Logs | `/support/logs` | Email & auth audit logs |
206
- | Billing | `/support/billing` | Invoice management |
207
-
208
- ### Client Portal (30 files)
209
-
210
- Full-featured client-facing support portal with its own auth system:
211
-
212
- | Page | Description |
213
- |------|-------------|
214
- | Login / Register | Email + password auth, Google OAuth |
215
- | Forgot / Reset password | Email-based password recovery |
216
- | Dashboard | Ticket stats, recent activity, quick actions |
217
- | Ticket List | Filterable, sortable ticket list |
218
- | Ticket Detail | Conversation thread, reply form, file attachments, satisfaction survey |
219
- | New Ticket | Category selection, priority, file upload |
220
- | FAQ | Knowledge base with search |
221
- | Profile | Edit name, company, email, password, notification prefs, 2FA, delete account |
222
- | Chat Widget | Real-time live chat with agent |
223
- | Chatbot | AI-powered self-service from knowledge base |
224
-
225
- ### Email Template System
226
-
227
- Configurable, responsive HTML email templates:
46
+ **🎫 Complete ticketing**
228
47
 
229
- ```ts
230
- import { createEmailTemplateFactory } from '@consilioweb/payload-support'
231
-
232
- const emails = createEmailTemplateFactory({
233
- brandName: 'My Company',
234
- brandColor: '#2563eb',
235
- logoUrl: 'https://example.com/logo.png',
236
- supportEmail: 'support@example.com',
237
- websiteUrl: 'https://example.com',
238
- })
48
+ Statuses, priorities, categories, tags, merge/split, snooze, scheduled replies, internal notes, an immutable activity log and a keyboard-driven Superhuman-style inbox.
239
49
 
240
- // Use pre-configured functions
241
- const html = emails.wrapper('Welcome', [
242
- emails.paragraph('Hello <strong>John</strong>,'),
243
- emails.button('Open Dashboard', 'https://example.com/dashboard'),
244
- ].join(''))
245
- ```
50
+ </td>
51
+ <td width="50%">
246
52
 
247
- Available functions: `emailWrapper`, `emailButton`, `emailParagraph`, `emailQuote`, `emailInfoRow`, `emailRichContent`, `emailTrackingPixel`, `escapeHtml`
53
+ **⏱️ SLA & automation**
248
54
 
249
- <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" alt="line">
55
+ SLA policies (business hours + pause-on-hold), escalation, macros, round-robin, and a **visual automation-rules engine** (conditions β†’ actions).
250
56
 
251
- ## Installation
57
+ </td>
58
+ </tr>
59
+ <tr>
60
+ <td width="50%">
252
61
 
253
- ```bash
254
- pnpm add @consilioweb/payload-support
255
- ```
62
+ **πŸ€– Built-in AI**
256
63
 
257
- Or with npm/yarn:
64
+ Sentiment, reply suggestions, multi-style rewriting, cached synthesis, a KB chatbot, and an **autonomous AI agent** that answers or escalates. Anthropic, OpenAI or self-hosted Ollama.
258
65
 
259
- ```bash
260
- npm install @consilioweb/payload-support
261
- yarn add @consilioweb/payload-support
262
- ```
66
+ </td>
67
+ <td width="50%">
68
+
69
+ **πŸ’¬ Omnichannel & portal**
70
+
71
+ Inbound/outbound email, live chat (SSE), widget, a full **client portal** (auth, 2FA, Google OAuth), knowledge base and deflection.
263
72
 
264
- ### Peer Dependencies
73
+ </td>
74
+ </tr>
75
+ <tr>
76
+ <td width="50%">
265
77
 
266
- | Package | Version | Required |
267
- |---------|---------|----------|
268
- | `payload` | `^3.0.0` | **Yes** |
269
- | `@payloadcms/next` | `^3.0.0` | Optional (admin views) |
270
- | `@payloadcms/ui` | `^3.0.0` | Optional (admin UI) |
271
- | `next` | `^14.0.0 \|\| ^15.0.0 \|\| ^16.0.0` | Optional (admin UI) |
272
- | `react` | `^18.0.0 \|\| ^19.0.0` | Optional (admin UI) |
78
+ **πŸ’Ά Time tracking & billing**
273
79
 
274
- <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" alt="line">
80
+ Timer, manual entries, time dashboard, per-project pre-billing and a **print-ready invoice** (HTML β†’ PDF).
275
81
 
276
- ## Quick Start
82
+ </td>
83
+ <td width="50%">
84
+
85
+ **πŸ“Š Reporting & privacy**
86
+
87
+ Real-time dashboard, **CSAT + NPS**, email tracking, HMAC-signed webhooks, notification digests, CSV exports. 100% self-hostable.
88
+
89
+ </td>
90
+ </tr>
91
+ </table>
92
+
93
+ <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" width="100%" alt="" />
94
+
95
+ ## πŸš€ Quick Start
277
96
 
278
97
  ```ts
98
+ // payload.config.ts
279
99
  import { buildConfig } from 'payload'
280
100
  import { supportPlugin } from '@consilioweb/payload-support'
281
101
 
282
102
  export default buildConfig({
283
- // ... your existing config
284
103
  plugins: [
285
104
  supportPlugin({
286
- // All features enabled by default β€” disable what you don't need
287
- features: {
288
- chat: false, // disable live chat
289
- billing: false, // disable billing
290
- roundRobin: true, // enable round-robin (off by default)
291
- },
292
-
293
- // AI provider (optional)
294
- ai: {
295
- provider: 'anthropic',
296
- model: 'claude-haiku-4-5-20251001',
297
- },
298
-
299
- // Locale
105
+ features: { ai: true, sla: true, timeTracking: true, chat: true },
106
+ ai: { provider: 'anthropic', model: 'claude-haiku-4-5-20251001' },
300
107
  locale: 'fr',
301
-
302
- // Email
303
- email: {
304
- fromAddress: 'support@example.com',
305
- fromName: 'Support Team',
306
- },
307
108
  }),
308
109
  ],
309
110
  })
310
111
  ```
311
112
 
312
- ### Next.js Configuration
113
+ ```bash
114
+ pnpm payload generate:importmap
115
+ pnpm dev
116
+ ```
313
117
 
314
- Add the plugin to `transpilePackages` in your `next.config.mjs` so Next.js can resolve the view components:
118
+ Open `/admin/support/inbox` for the agent inbox, or `/support` for the client portal. The plugin injects collections, API endpoints and admin views automatically β€” no external SaaS.
315
119
 
316
- ```js
317
- // next.config.mjs
318
- import { withPayload } from '@payloadcms/next/withPayload'
120
+ <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" width="100%" alt="" />
319
121
 
320
- /** @type {import('next').NextConfig} */
321
- const nextConfig = {
322
- transpilePackages: ['@consilioweb/payload-support'],
323
- }
122
+ ## πŸ“¦ Installation
324
123
 
325
- export default withPayload(nextConfig)
124
+ ### npm
125
+ ```bash
126
+ npm install @consilioweb/payload-support
326
127
  ```
327
128
 
328
- Then regenerate the import map:
129
+ ### yarn
130
+ ```bash
131
+ yarn add @consilioweb/payload-support
132
+ ```
329
133
 
134
+ ### pnpm
330
135
  ```bash
331
- pnpm generate:importmap
136
+ pnpm add @consilioweb/payload-support
332
137
  ```
333
138
 
334
- <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" alt="line">
139
+ **Peer dependencies:** `payload@^3`, `react@^18 || ^19`, `react-dom@^18 || ^19`, `next@^14 || ^15 || ^16`. `lucide-react` and the `@payloadcms/*` packages are optional depending on the features you enable. After adding admin components, run `pnpm payload generate:importmap`.
335
140
 
336
- ## Configuration
141
+ <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" width="100%" alt="" />
337
142
 
338
- ### `SupportPluginConfig`
143
+ ## πŸ’» Usage
144
+
145
+ ### Basic
339
146
 
340
147
  ```ts
341
- supportPlugin({
342
- features: {}, // Feature flags (see below)
343
- ai: { provider, apiKey, model }, // AI provider config
344
- email: { fromAddress, fromName, replyTo },
345
- locale: 'fr', // 'fr' | 'en'
346
- navGroup: 'Support', // Sidebar group label
347
- basePath: '/support', // Admin view base path
348
- userCollectionSlug: 'users', // Agent collection slug
349
- collectionSlugs: { // Override any collection slug
350
- tickets: 'my-tickets',
351
- ticketMessages: 'my-messages',
352
- // ...
353
- },
354
-
355
- // v0.2.0 β€” Webhook dispatch
356
- webhooks: {
357
- url: 'https://hooks.slack.com/services/...',
358
- secret: process.env.WEBHOOK_SECRET,
359
- events: ['ticket.created', 'ticket.resolved', 'ticket.assigned', 'ticket.replied'],
360
- },
361
-
362
- // v0.2.0 β€” OAuth restrictions
363
- allowedEmailDomains: ['mycompany.com', 'partner.com'],
364
- })
148
+ // All features are on by default β€” turn off what you don't need:
149
+ supportPlugin({ features: { chat: false, pendingEmails: false }, locale: 'en' })
365
150
  ```
366
151
 
367
- ### Feature Flags (25+)
368
-
369
- All features are **enabled by default** except `roundRobin` and `customStatuses`.
370
-
371
- | Flag | Default | Description |
372
- |------|---------|-------------|
373
- | `timeTracking` | `true` | Timer, manual entries, billing |
374
- | `ai` | `true` | Sentiment, synthesis, suggestion, rewrite |
375
- | `satisfaction` | `true` | CSAT surveys after resolution |
376
- | `chat` | `true` | Live chat sessions |
377
- | `emailTracking` | `true` | Pixel tracking, open status |
378
- | `canned` | `true` | Quick reply templates |
379
- | `merge` | `true` | Merge two tickets |
380
- | `snooze` | `true` | Temporarily hide ticket |
381
- | `externalMessages` | `true` | Add external messages |
382
- | `clientHistory` | `true` | Past tickets sidebar |
383
- | `activityLog` | `true` | Audit trail |
384
- | `splitTicket` | `true` | Extract message to new ticket |
385
- | `scheduledReplies` | `true` | Future message sending |
386
- | `autoClose` | `true` | Close inactive tickets |
387
- | `autoCloseDays` | `7` | Days before auto-close |
388
- | `roundRobin` | `false` | Distribute tickets to agents |
389
- | `sla` | `true` | SLA policies & alerts |
390
- | `webhooks` | `true` | Outbound HTTP hooks |
391
- | `macros` | `true` | Multi-action shortcuts |
392
- | `customStatuses` | `false` | Configurable ticket statuses |
393
- | `collisionDetection` | `true` | Multi-agent collision warning |
394
- | `signatures` | `true` | Per-agent email signatures |
395
- | `chatbot` | `true` | AI self-service chatbot |
396
- | `bulkActions` | `true` | Bulk ticket operations |
397
- | `commandPalette` | `true` | ⌘K search |
398
- | `knowledgeBase` | `true` | FAQ / knowledge base |
399
- | `pendingEmails` | `true` | Inbound email queue |
400
- | `authLogs` | `true` | Authentication audit logs (v0.2.0) |
401
-
402
- <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" alt="line">
403
-
404
- ## AI Providers
405
-
406
- ### Anthropic (Claude)
152
+ ### Advanced
407
153
 
408
154
  ```ts
409
155
  supportPlugin({
410
- ai: {
411
- provider: 'anthropic',
412
- apiKey: process.env.ANTHROPIC_API_KEY,
413
- model: 'claude-haiku-4-5-20251001', // fast & affordable
414
- },
156
+ features: { ai: true, sla: true, roundRobin: true, webhooks: true, snooze: true },
157
+ ai: { provider: 'ollama', model: 'qwen2.5', baseUrl: process.env.OLLAMA_API_URL },
158
+ email: { fromName: 'Support ACME', fromAddress: 'support@acme.com', replyTo: 'support@acme.com' },
159
+ allowedEmailDomains: ['acme.com'], // restrict OAuth auto-registration
160
+ collectionSlugs: { tickets: 'support-tickets' }, // slug overrides
161
+ navGroup: 'Support',
162
+ basePath: '/support',
415
163
  })
416
164
  ```
417
165
 
418
- ### OpenAI
166
+ ### Run the AI agent on a ticket
419
167
 
420
168
  ```ts
421
- supportPlugin({
422
- ai: {
423
- provider: 'openai',
424
- apiKey: process.env.OPENAI_API_KEY,
425
- model: 'gpt-4o-mini',
426
- },
169
+ await fetch('/api/support/ai-agent', {
170
+ method: 'POST',
171
+ headers: { 'Content-Type': 'application/json' },
172
+ body: JSON.stringify({ ticketId, confidenceThreshold: 0.7 }),
427
173
  })
428
174
  ```
429
175
 
430
- ### Ollama (self-hosted)
176
+ <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" width="100%" alt="" />
431
177
 
432
- ```ts
433
- supportPlugin({
434
- ai: {
435
- provider: 'ollama',
436
- baseUrl: 'https://ollama.example.com',
437
- model: 'qwen2.5:32b',
438
- },
439
- })
178
+ ## πŸ”Œ API Reference
179
+
180
+ ### `supportPlugin(config)`
181
+
182
+ The Payload plugin. Adds collections, admin views, editor components and API endpoints.
183
+
184
+ ```typescript
185
+ supportPlugin(config?: SupportPluginConfig): Plugin
186
+ ```
187
+
188
+ ### Exports
189
+
190
+ ```typescript
191
+ import { supportPlugin, generateTicketSynthesis, dispatchWebhook } from '@consilioweb/payload-support'
192
+ import type { SupportPluginConfig, SupportFeatures } from '@consilioweb/payload-support'
440
193
  ```
441
194
 
442
- <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" alt="line">
195
+ ### Key HTTP endpoints (under `/api/support`)
443
196
 
444
- ## Package Exports
197
+ | Method | Path | Purpose |
198
+ |---|---|---|
199
+ | `POST` | `/ai` | Sentiment, reply suggestion, rewrite, synthesis (admin). |
200
+ | `POST` | `/ai-agent` | **Autonomous AI agent** β€” answers from the KB or escalates. |
201
+ | `POST` | `/login`, `/2fa`, `/oauth/google` | Client portal auth (password, 2FA, OAuth). |
202
+ | `GET` | `/admin-stats` | Dashboard KPIs (real volume series, CSAT, NPS). |
203
+ | `GET` | `/billing`, `/billing/invoice` | Pre-billing + print-ready invoice. |
204
+ | `POST` | `/process-snooze`, `/process-digests`, `/process-scheduled`, `/auto-close` | Cron jobs (guarded by `x-cron-secret`). |
445
205
 
446
- ```ts
447
- // Server β€” plugin, types, collections
448
- import { supportPlugin, DEFAULT_FEATURES } from '@consilioweb/payload-support'
449
- import type {
450
- SupportPluginConfig,
451
- SupportFeatures,
452
- AIProviderConfig,
453
- TicketData,
454
- MessageData,
455
- } from '@consilioweb/payload-support'
456
-
457
- // Client β€” React components for Payload admin
458
- import { /* components */ } from '@consilioweb/payload-support/client'
459
-
460
- // Views β€” server components wrapped in DefaultTemplate
461
- import { /* views */ } from '@consilioweb/payload-support/views'
206
+ <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" width="100%" alt="" />
207
+
208
+ ## βš™οΈ Configuration
209
+
210
+ | Option | Type | Default | Description |
211
+ |--------|------|---------|-------------|
212
+ | `features` | `SupportFeatures` | all `true` | Toggle each feature on/off. |
213
+ | `ai` | `AIProviderConfig` | `anthropic` | AI provider: `anthropic` \| `openai` \| `ollama` \| `custom`. |
214
+ | `email` | `EmailConfig` | β€” | `fromName`, `fromAddress`, `replyTo`. |
215
+ | `locale` | `'fr' \| 'en'` | `'fr'` | Admin/portal language. |
216
+ | `basePath` | `string` | `'/support'` | Admin views prefix. |
217
+ | `userCollectionSlug` | `string` | `'users'` | Agents collection. |
218
+ | `allowedEmailDomains` | `string[]` | β€” | Domains allowed for OAuth auto-registration. |
219
+ | `collectionSlugs` | `object` | β€” | Collection slug overrides. |
220
+ | `skipCollections` / `skipViews` / `skipEndpoints` | `boolean` | `false` | Skip injecting that part. |
221
+
222
+ ### Environment variables
223
+
224
+ | Env var | Required | Description |
225
+ |---------|----------|-------------|
226
+ | `PAYLOAD_SECRET` | βœ… | Payload secret (also signs 2FA & tracking). |
227
+ | `NEXT_PUBLIC_SERVER_URL` | βœ… | Public URL (email/portal links). |
228
+ | `CRON_SECRET` | for crons | `x-cron-secret` header for the cron endpoints. |
229
+ | `ANTHROPIC_API_KEY` / `OLLAMA_API_URL` | if AI | AI provider keys/URL. |
230
+ | `GOOGLE_OAUTH_CLIENT_ID` / `_SECRET` | if OAuth | Portal Google sign-in. |
231
+ | `VAPID_PUBLIC_KEY` / `VAPID_PRIVATE_KEY` | if push | Web Push keys (`npx web-push generate-vapid-keys`). |
232
+ | `VAPID_SUBJECT` | optional | Push contact (`mailto:` or URL), defaults to `mailto:support@example.com`. |
233
+ | `SUPPORT_TEAM_SCOPING` | optional | `1` to scope agents to their team's tickets. |
234
+ | `SUPPORT_EMAIL` / `SUPPORT_REPLY_TO` | optional | From/reply-to addresses. |
235
+
236
+ <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" width="100%" alt="" />
237
+
238
+ ## ⚑ Performance
239
+
240
+ Engineered to stay fast under load (no fabricated benchmarks β€” figures depend on your volume and host):
241
+
242
+ | Concern | Approach |
243
+ |---------|----------|
244
+ | Settings reads | In-process cache (TTL + invalidation) β€” avoids ~8 redundant DB reads per ticket mutation. |
245
+ | List queries | SQLite indexes on filtered fields β€” inbox/dashboard/SLA in `O(index)` instead of full scans. |
246
+ | Email sends | Fire-and-forget β€” the response no longer waits on the SMTP round-trip (βˆ’200-500 ms). |
247
+ | Stats & billing | Paginated aggregation + bounded `select` β€” never loads all tickets in memory. |
248
+ | AI synthesis | Cached per ticket β€” no LLM recompute on every view. |
249
+
250
+ <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" width="100%" alt="" />
251
+
252
+ ## πŸ“š Examples
253
+
254
+ ### Automation rule (no code)
255
+
256
+ Create a **Automation Rules** entry: `event = ticket_created`, condition `category = bug`, action `set_priority = urgent`. New "bug" tickets become "urgent" automatically.
257
+
258
+ ### Wire the cron jobs
259
+
260
+ ```bash
261
+ # Hourly: auto-close, snooze wake-up, scheduled replies
262
+ curl -X POST https://your-app/api/support/auto-close -H "x-cron-secret: $CRON_SECRET"
263
+ curl -X POST https://your-app/api/support/process-snooze -H "x-cron-secret: $CRON_SECRET"
264
+ # Daily / weekly: notification digests
265
+ curl -X POST https://your-app/api/support/process-digests -H "x-cron-secret: $CRON_SECRET" -d '{"frequency":"daily"}'
462
266
  ```
463
267
 
464
- <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" alt="line">
268
+ <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" width="100%" alt="" />
465
269
 
466
- ## Roadmap
270
+ ## ❓ FAQ
467
271
 
468
- - Custom ticket statuses β€” dynamic workflow states instead of hardcoded open/waiting/resolved
469
- - Snooze tickets β€” hide from inbox until a specified date
470
- - Billing & invoicing β€” time-based billing, invoice PDF generation
471
- - Knowledge base search β€” client portal FAQ with full-text search
472
- - Email inbound processing β€” parse email replies into ticket messages
473
- - Real-time typing indicators via SSE
474
- - Canned responses / macros UI β€” quick reply templates in admin
475
- - Dashboard analytics β€” charts, trends, response times, SLA compliance
476
- - Multi-language client portal β€” full i18n beyond FR/EN
477
- - File attachments on ticket messages
478
- - Ticket tags & custom fields
272
+ <details>
273
+ <summary><b>Which databases are supported?</b></summary>
479
274
 
480
- <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" alt="line">
275
+ Built and tested on **SQLite** (`@payloadcms/db-sqlite`) with a sequential seed and `busyTimeout`. It works with any Payload adapter, but indexes and queries were validated on SQLite.
481
276
 
482
- ## Requirements
277
+ </details>
483
278
 
484
- - **Node.js** >= 18
485
- - **Payload CMS** 3.x
486
- - **React** 18.x or 19.x
487
- - **Database**: Any Payload-supported adapter (SQLite, PostgreSQL, MongoDB)
279
+ <details>
280
+ <summary><b>What Node / Payload versions are supported?</b></summary>
488
281
 
489
- <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" alt="line">
282
+ Node.js 18+, Payload 3.x, React 18 or 19.
490
283
 
491
- ## β˜• Support
284
+ </details>
492
285
 
493
- If this plugin saves you time, consider buying me a coffee!
286
+ <details>
287
+ <summary><b>Is there TypeScript support?</b></summary>
494
288
 
495
- <a href="https://buymeacoffee.com/pown3d">
496
- <img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" width="217" />
497
- </a>
289
+ Yes β€” strict TypeScript, with business types exported (`SupportPluginConfig`, `SupportFeatures`, …).
498
290
 
499
- ## License
291
+ </details>
500
292
 
501
- [MIT](LICENSE)
293
+ <details>
294
+ <summary><b>Do I need an external AI service?</b></summary>
502
295
 
503
- <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" alt="line">
296
+ No. AI features are optional and you can run **self-hosted Ollama** to depend on no cloud (sovereignty/GDPR). Anthropic and OpenAI are also supported.
504
297
 
505
- <div align="center">
298
+ </details>
506
299
 
507
- ### Author
300
+ <details>
301
+ <summary><b>How do I migrate the schema in production?</b></summary>
508
302
 
509
- **Made with passion by [ConsilioWEB](https://consilioweb.fr)**
303
+ In standalone mode the schema isn't auto-migrated: generate/push the schema (new fields and collections) before deploying. See [Troubleshooting](#-troubleshooting).
510
304
 
511
- <a href="https://www.linkedin.com/in/christophe-lopez/">
512
- <img src="https://img.shields.io/badge/LinkedIn-0077B5?style=for-the-badge&logo=linkedin&logoColor=white" alt="LinkedIn">
513
- </a>
514
- <a href="https://github.com/pOwn3d">
515
- <img src="https://img.shields.io/badge/GitHub-100000?style=for-the-badge&logo=github&logoColor=white" alt="GitHub">
516
- </a>
517
- <a href="https://consilioweb.fr">
518
- <img src="https://img.shields.io/badge/Website-consilioweb.fr-3B82F6?style=for-the-badge&logo=google-chrome&logoColor=white" alt="Website">
305
+ </details>
306
+
307
+ <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" width="100%" alt="" />
308
+
309
+ ## πŸ”§ Troubleshooting
310
+
311
+ ### `useServerFunctions must be used within ServerFunctionsProvider`
312
+
313
+ Use Payload **3.75+** for all `@payloadcms/*` packages (aligned versions).
314
+
315
+ ### `SQLITE_BUSY` / database is locked during seed
316
+
317
+ Make the seed **sequential** (no `Promise.all` on inserts) and add `busyTimeout: 10000` to the SQLite adapter.
318
+
319
+ ### Admin views don't load
320
+
321
+ Regenerate the import map after adding components: `pnpm payload generate:importmap`. In a plugin/headless context, use `skipViews: true` if you don't mount the admin UI.
322
+
323
+ ### New fields/collections missing in production
324
+
325
+ Standalone doesn't run migrations: push the schema for `googleId`, `twoFactorVerifiedAt`, `slaPausedAt`, `nps`, `mentions`, and the `notification-queue` / `automation-rules` collections.
326
+
327
+ <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" width="100%" alt="" />
328
+
329
+ ## πŸ” Security
330
+
331
+ Security is a first-class concern β€” several guardrails are validated by integration tests.
332
+
333
+ - **Cross-client isolation** β€” a client can never read another's tickets/messages (filtered by owned tickets).
334
+ - **2FA** enforced server-side (`beforeLogin`); **OAuth** verifies the Google email.
335
+ - **Sanitization** of message HTML server-side (stored-XSS protection).
336
+ - **HMAC-signed** webhooks, signed tracking pixel, fail-closed secrets.
337
+
338
+ ### Reporting Security Issues
339
+
340
+ Please email **contact@consilioweb.fr** instead of opening a public issue.
341
+
342
+ ### Best Practices
343
+
344
+ - βœ… Set a strong `PAYLOAD_SECRET` (never a default value)
345
+ - βœ… Set `CRON_SECRET` to protect the cron endpoints
346
+ - βœ… Restrict read access to the `media` collection to the ticket owner
347
+ - βœ… Put the app behind a trusted proxy (`x-forwarded-for` header)
348
+ - βœ… Keep the plugin up-to-date
349
+
350
+ <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" width="100%" alt="" />
351
+
352
+ ## 🀝 Contributing
353
+
354
+ Contributions are very welcome!
355
+
356
+ 1. **Fork** the repository
357
+ 2. **Create** a feature branch (`git checkout -b feature/AmazingFeature`)
358
+ 3. **Commit** your changes (`git commit -m 'feat: add AmazingFeature'`)
359
+ 4. **Push** the branch (`git push origin feature/AmazingFeature`)
360
+ 5. **Open** a Pull Request
361
+
362
+ Run the checks before submitting:
363
+
364
+ ```bash
365
+ npm run typecheck && npm test && npm run build
366
+ ```
367
+
368
+ <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" width="100%" alt="" />
369
+
370
+ ## πŸ“ Changelog
371
+
372
+ See [CHANGELOG.md](CHANGELOG.md) for the full history.
373
+
374
+ ### [1.1.0] β€” 2026-06-25
375
+
376
+ - 🎯 **Per-team SLA policies & dashboards** (team policy overrides the default, `?teamId=` scoping).
377
+ - πŸ”” **Native push / browser notifications** (Web Push / VAPID, agent pushed on new client messages).
378
+ - 🎭 **End-to-end UI test harness** (browser-driven admin via Playwright, `pnpm test:e2e`).
379
+ - βœ… 109 integration tests (up from 102).
380
+
381
+ ### [1.0.0] β€” 2026-06-25
382
+
383
+ - ✨ Complete ticketing, SLA (+ pause-on-hold), automation & **visual rules engine**.
384
+ - πŸ€– AI (sentiment, suggestion, synthesis, chatbot) + **autonomous AI agent**.
385
+ - πŸ’¬ Live chat, client portal (2FA, OAuth), knowledge base.
386
+ - πŸ’Ά Time tracking, pre-billing & print-ready invoice.
387
+ - πŸ“Š CSAT + NPS, real volume series, digests, webhooks.
388
+ - πŸ” Security hardening (cross-client isolation, anti-XSS, server-side 2FA).
389
+ - βœ… Integration test harness (Payload + in-memory SQLite), 102 tests.
390
+
391
+ <details>
392
+ <summary><b>Previous versions (0.x)</b></summary>
393
+
394
+ - **0.16.0** β€” Manual client reminder + auto-close after 24h
395
+ - **0.15.0** β€” Next 16 compatibility + accumulated features
396
+ - **0.9.0 β†’ 0.9.13** β€” Enriched views (Client Intelligence, Billing), bundled RichTextEditor, code blocks in emails, inline message editing, enriched pre-billing, per-ticket cached AI synthesis, multi-style rewriting
397
+ - **0.6.0 β†’ 0.6.4** β€” Split build (`bundle:false`) for Next.js RSC compatibility + barrel exports
398
+ - **0.5.0** β€” Full i18n across the 13 admin views
399
+ - **0.4.0** β€” Per-user preferences (locale, signature) vs global settings
400
+ - **0.3.0** β€” Feature parity with ConsilioWEB + `skipCollections` / `skipViews` / `skipEndpoints`
401
+ - **0.2.0** β€” 2026-04-08 β€” Security overhaul, SSE live chat, webhooks, SLA, scheduled replies, client portal
402
+ - **0.1.0** β€” 2026-04-08 β€” Initial scaffold: `supportPlugin()`, 15 collections, feature flags, AI provider abstraction
403
+
404
+ </details>
405
+
406
+ <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" width="100%" alt="" />
407
+
408
+ ## πŸ—ΊοΈ Roadmap
409
+
410
+ - [x] Ticketing, SLA, time tracking & billing
411
+ - [x] AI assists + autonomous AI agent
412
+ - [x] Live chat, client portal, knowledge base
413
+ - [x] Visual automation-rules engine
414
+ - [x] Native binary PDF invoice (alongside the print-ready HTML)
415
+ - [x] Full admin i18n (all views)
416
+ - [x] Social channels (WhatsApp, Messenger)
417
+ - [x] Multi-team / workspaces mode
418
+ - [x] Per-team SLA policies & dashboards
419
+ - [x] Native push / browser notifications
420
+ - [x] End-to-end UI test harness (browser-driven admin)
421
+
422
+ <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" width="100%" alt="" />
423
+
424
+ ## β˜• Support
425
+
426
+ If this plugin saves you time, consider buying me a coffee!
427
+
428
+ <a href="https://buymeacoffee.com/pown3d">
429
+ <img src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" alt="Buy Me A Coffee" width="217" />
519
430
  </a>
520
431
 
521
- <br><br>
432
+ <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" width="100%" alt="" />
433
+
434
+ ## πŸ“„ License
435
+
436
+ Licensed under the **MIT License**. See the [LICENSE](LICENSE) file for details.
522
437
 
523
- <img src="https://capsule-render.vercel.app/api?type=waving&color=gradient&customColorList=6,11,20&height=100&section=footer" width="100%"/>
438
+ <img src="https://raw.githubusercontent.com/andreasbm/readme/master/assets/lines/rainbow.png" width="100%" alt="" />
524
439
 
440
+ <div align="center" style="padding: 40px 0; color: #666; border-top: 1px solid #e0e0e0; margin-top: 50px;">
441
+ <p style="margin: 10px 0;">Built and maintained by <a href="https://consilioweb.fr" style="color: #1f8a5b; text-decoration: none;">ConsilioWEB</a></p>
442
+ <p style="margin: 10px 0; font-size: 13px;">
443
+ <a href="https://github.com/pOwn3d/payload-support#readme" style="color: #1f8a5b; text-decoration: none; margin: 0 15px;">Documentation</a>
444
+ <a href="https://github.com/pOwn3d/payload-support/issues" style="color: #1f8a5b; text-decoration: none; margin: 0 15px;">Issues</a>
445
+ <a href="https://www.npmjs.com/package/@consilioweb/payload-support" style="color: #1f8a5b; text-decoration: none; margin: 0 15px;">npm</a>
446
+ </p>
525
447
  </div>