Outbound (already existed one-way: ticket create -> Gitea issue) now
also mirrors status changes: closing/reopening a ticket in the admin
UI closes/reopens the linked Gitea issue, and replies posted from
Epicure (by the ticket owner or an admin) post as a comment on the
issue. Captures and stores the Gitea issue number at creation time
to address these follow-up calls without re-parsing the issue URL.
Inbound: new webhook receiver at /api/webhooks/gitea, verified via
HMAC-SHA256 signature (X-Gitea-Signature) with a configurable
GITEA_WEBHOOK_SECRET site setting, deduped by delivery id the same
way the existing Stripe receiver dedupes events. Handles "issues"
(closed/reopened -> ticket status) and "issue_comment" (created ->
appends to the ticket's comment thread), skipping comments Epicura
already posted itself (matched by Gitea comment id) to avoid loops.
New support_ticket_comments table backs a lightweight conversation
thread on both the user-facing support page and the admin support
manager, each comment tagged by author (user/admin/gitea).
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Two related bugs in the Gitea issue body:
1. Attachments were always plain bullet links (`- url`), even for images —
so they never rendered as a preview in the Gitea issue, just a clickable
URL. Image content-types now use markdown image embed (``).
2. The admin "Create Gitea issue" retry action built its own body from
scratch (`ticket.description` only) and never queried attachments at
all — a retry always lost them, regardless of point 1's fix.
Extracted buildGiteaIssueBody() to lib/gitea.ts so both the initial
ticket-creation path and the retry path share one body-building
implementation instead of two independent (and inevitably diverging) ones.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Users can now report bugs, suggestions, or questions from a new /support
page. Each submission sends a confirmation email and, when GITEA_URL/
GITEA_TOKEN/GITEA_REPO are configured in admin Settings, opens a labeled
issue on that repo automatically (best-effort — failure doesn't block the
ticket). Admins get a Support section to triage status and retry failed
Gitea issue creation.
New support_tickets table, gitea.ts client, site-settings entries for the
three new secrets, and OpenAPI docs for the two user-facing endpoints.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>