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¶
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-loadedSupportPage) - Sidebar: "Support" item with
LifeBuoyicon 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 tokenSupportTicketError- Custom error class with HTTPstatusChatbotIssuePayload/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.aihttp://localhost:3002http://localhost:5173http://localhost:5174
Deployment¶
The function is deployed via GitHub Actions (.github/workflows/deploy-linear-ticket-fn.yml):
- Trigger: Push to
mainordeveloptouchingbackend/functions/linear-ticket/**, or manualworkflow_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 |