Support Tickets
The built-in help desk, privacy guards, and internal notes.
Job-Easy has a native support ticket system allowing users to converse with admins without leaving the platform.
The Feature Flag
The entire ticket system is governed by a single feature flag: SystemSettings.ticketSystemEnabled (off by default). This flag is enforced in server/guards.ts, which every route calls first. Hiding the sidebar entry and 404-ing the pages is just visual tidiness; the backend guard is the true control.
Privacy Invariants
Query-Level Ownership
A user must only ever see their own tickets. To guarantee this, user-facing queries take a userId and place it directly into the Postgres WHERE clause. The system deliberately avoids the "fetch-then-compare" anti-pattern, ensuring that a missing authorization check cannot accidentally leak another account's correspondence.
Internal Notes
Admins can leave internal: true notes on a user's ticket.
Query-level isolation
getUserTicket vs getAdminTicket). The user query explicitly filters out internal notes (internal: false) at the database level, meaning the note is physically absent from the returned payload. No downstream serialization mistake can expose it.Workflow
- Reopening: If a user replies to a resolved ticket, the ticket is instantly reopened. Requiring a new ticket for a follow-up discards the history of the problem, and users will naturally reply to the last message they see regardless.
- Transactional Counters: Denormalized counters (like
messageCount,unreadForAdmin, andlastMessageAt) are written only by specific service functions inside a database transaction. A message written without its counter bump would cause the sidebar badge to disagree with the thread.