Skip to content

Support Tickets

The support ticket system lets backoffice users report issues directly to the engineering team via Linear. It supports two issue types: chatbot issues (flagged from a specific conversation) and general issues (free-form).

Architecture

sequenceDiagram participant User as Backoffice User participant UI as SupportPage participant Supa as Supabase Auth participant Fn as Cloud Function<br/>(GCP) participant Linear as Linear API User->>UI: Fill & submit form UI->>Supa: getSession() Supa-->>UI: access_token UI->>Fn: POST /create-ticket<br/>Bearer token + payload Fn->>Supa: Validate token Supa-->>Fn: User info Fn->>Linear: GraphQL mutation Linear-->>Fn: Issue ID, identifier, URL Fn-->>UI: LinearIssueResponse UI-->>User: Toast with Linear link

Issue Types

Chatbot Issue

Reported from the conversation timeline panel via the Report issue button. The URL carries domainId and sessionId as query parameters so the form can load the conversation context.

Field Source
domain_id URL param / selected domain
session_id URL param
conversation_link Auto-built from domain + session
selected_message_content User picks an assistant message
issue_subtype accurate_but_not_ok or not_accurate
expected_answer Free-text
reporter_name / reporter_email Pre-filled from auth context

Other Issue

A free-form report for anything not tied to a specific conversation.

Field Source
title User input (max 200 chars)
description Free-text
reporter_name / reporter_email Pre-filled from auth context

Frontend

Route & Navigation

  • Route: /support (lazy-loaded SupportPage)
  • Sidebar: "Support" item with LifeBuoy icon in bottom nav
  • Timeline panel: "Report issue" button navigates to /support?domainId=X&sessionId=Y

Components

Component Path Purpose
SupportPage pages/SupportPage.tsx Issue type tabs, form orchestration, submission + toast
ChatbotIssueForm components/support/ChatbotIssueForm.tsx Conversation-aware form with message selector
OtherIssueForm components/support/OtherIssueForm.tsx Simple title + description form
MessageSelector components/support/MessageSelector.tsx Scrollable list of assistant messages to select

Service Layer

services/supportTicket.ts exports:

  • createSupportTicket(payload) - POSTs to the cloud function with a Supabase bearer token
  • SupportTicketError - Custom error class with HTTP status
  • ChatbotIssuePayload / OtherIssuePayload - TypeScript interfaces matching the backend models

Backend — Cloud Function

Location: backend/functions/linear-ticket/

A standalone GCP Cloud Function (Python 3.12, functions-framework) that receives ticket payloads, validates auth, and creates Linear issues.

Files

File Purpose
main.py HTTP entry point, CORS, request routing
models.py Pydantic v2 models with discriminated union (issue_type)
auth.py Supabase bearer token validation
linear_client.py Linear GraphQL client (httpx, async)

Request / Response

POST /create-ticket
Authorization: Bearer <supabase_access_token>
Content-Type: application/json

{
  "payload": { ... ChatbotIssuePayload | OtherIssuePayload }
}

Response:

{
  "success": true,
  "issue_id": "abc-123",
  "issue_identifier": "IX-100",
  "issue_url": "https://linear.app/inboundx/issue/IX-100",
  "error": null
}

CORS

Allowed origins:

  • https://backoffice.userose.ai
  • http://localhost:3002
  • http://localhost:5173
  • http://localhost:5174

Deployment

The function is deployed via GitHub Actions (.github/workflows/deploy-linear-ticket-fn.yml):

  • Trigger: Push to main or develop touching backend/functions/linear-ticket/**, or manual workflow_dispatch
  • Region: europe-west9
  • Runtime: Python 3.12
  • Entry point: create_support_ticket

Environment Variables

Variable Where Purpose
VITE_SUPPORT_FUNCTION_URL Frontend .env Cloud function URL
LINEAR_API_KEY GCP Secret Manager Linear API authentication
SUPABASE_URL GCP Secret Manager Token validation endpoint
SUPABASE_ANON_KEY GCP Secret Manager Supabase anon key

Testing

# Frontend tests
cd frontend && npx vitest run client-backoffice/src/services/supportTicket.test.ts

# Backend tests
cd backend/functions/linear-ticket && python -m pytest tests/