Identity and sessions
Users sign in with Google Identity Services. The app exchanges the Google ID token with the backend, which creates or links the user and returns a short-lived API token.
The backend also rotates an HttpOnly refresh cookie through /api/auth/refresh and revokes it through /api/auth/session/revoke. The browser app sends credentials with API calls so refresh can work when the origin is trusted.
Tenant scoping
Most API routes require an active membership in the requested workspace. Organization, inbox, member, ticket, tag, draft, and saved-reply data is filtered by organization id.
Workspace isolation
A user can belong to multiple workspaces, but the active workspace id controls which tickets, inboxes, members, tags, and replies the app reads or changes.
Provider secrets
- Customer Resend API keys are stored per workspace provider connection.
- Webhook signing secrets are stored per provider connection.
- Secrets are protected by the backend before being persisted.
- The public app receives status booleans such as
hasApiKeyandhasWebhookSecret, not the secret values.
Email safety
- Webhook verification
- Inbound Resend webhooks must match the saved signing secret before ReTicketDesk processes the message.
- Idempotency
- Webhook events and message ids are checked so retries do not create duplicate messages.
- HTML display
- Inbound HTML is sanitized in the app before rendering, with scripts, iframes, inline handlers, and unsafe URLs removed.
- Attachments
- Attachment metadata is tracked. Binary attachment storage and downloads are not part of the current UI.
Audit trail
The backend writes audit events for membership changes, ticket updates, notes, drafts, tags, saved replies, and reply lifecycle events. Export and admin browsing are planned, but not exposed in the current app UI.