Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
5.3 KiB
05 — Ticket detail enrichment (tags, categories, activity, auto flags)
Agent: 5/10 · Series: support-auto
Migration: apps/api/sql/schema/031_support_ticket_detail.sql
Contract: 02-contract.md §§2, 4.4, 6–7
Goal
Enrich support tickets for “more detailed support” without breaking existing create/list/get contracts:
| Capability | Storage / API |
|---|---|
| Tags | support_tickets.tags TEXT[] — create + staff PATCH (set_tags) |
| Better categories | support_categories taxonomy; seeds expand beyond billing|bug|account|other |
| Related resource refs | related_product_id → processed_products (tenant-checked), related_sku |
| Customer context snapshot | customer_context JSONB — server-filled on create; staff GET full; customer GET redacted |
| Disable auto-reply | auto_reply_disabled — staff PATCH; auto-set on human reply / customer follow-up after auto |
| Match / AI metadata | auto_reply_status, auto_reply_meta, auto_reply_* message columns |
| Activity timeline | support_ticket_activity — auto / AI / human events on staff GET |
Migration coordination (agents 3 / 4)
One additive series — do not fork ticket columns.
| File | Owner | Contents |
|---|---|---|
031_support_ticket_detail.sql |
agent 5 | Ticket rich fields, message auto_* columns, support_categories, support_ticket_activity, notification kind auto_reply |
032_* (KB / templates / jobs) |
agent 3 | support_kb_articles, support_reply_templates, matcher tables/jobs — do not re-ALTER ticket/message columns from 031 |
| AI fallback | agent 4 | Reuse RecordAutoReplyOutcome, message auto_source='ai', statuses ai_draft / ai_sent / failed / handed_off |
Shared helpers for agents 3–4:
support.RecordAutoReplyOutcome(ctx, ticketID, status, disabled, messageID, meta, activityKind)- Message columns:
is_auto_reply,auto_source∈kb|template|ai,auto_confidence,auto_ref_type,auto_ref_id - Ticket:
auto_reply_status∈none|matched|ai_draft|ai_sent|skipped|failed|handed_off
API changes (additive)
Customer create — POST /api/support/tickets
Existing: subject, category, priority, body.
Additive optional:
{
"tags": ["woo", "export"],
"related_product_id": "uuid",
"related_sku": "SKU-123"
}
related_product_id must belong to the caller’s company_id or the API returns invalid related_product_id.
List — customer + staff
Returns (in addition to prior fields): tags, related_product_id, related_sku, auto_reply_disabled, auto_reply_status, resolved_by_user_id.
Does not embed full customer_context, auto_reply_meta, or activity (detail-only).
GET customer — GET /api/support/tickets/{id}
Detail fields + messages (with is_auto_reply / auto_source when present).
customer_context redacts signals and user_email.
auto_reply_meta and activity omitted.
GET staff — GET /api/admin/support/tickets/{id}
Full snapshot + auto_reply_meta + activity[] timeline + messages including internal notes and auto metadata.
Staff PATCH — PATCH /api/admin/support/tickets/{id}
Additive fields on AdminUpdateInput:
| Field | Notes |
|---|---|
category |
Active taxonomy slug |
tags + set_tags: true |
Replace tag set (omit set_tags to leave unchanged) |
related_product_id / clear_related_product |
Tenant-scoped |
related_sku |
Optional string |
auto_reply_disabled |
Staff kill-switch for auto pipeline |
Activity timeline kinds
created, customer_message, agent_message, system_message, auto_reply, ai_draft, ai_sent, ai_failed, handed_off, claimed, released, status_changed, auto_disabled, auto_enabled, note
Behavior hooks
- Create — writes
customer_context, activitycreated; leavesauto_reply_status=nonefor agent 3 matcher. - Customer reply after matched/ai_sent — sets
auto_reply_disabled=true,auto_reply_status=handed_off. - Staff public reply — sets
auto_reply_disabled=true. - Staff toggles
auto_reply_disabled— activityauto_disabled/auto_enabled.
Create / Reply* still must not call LLM completers directly (agent 4 owns TryAutoReplyLLM).
Tests
| Test | File |
|---|---|
| Tag / SKU / category validation | ticket_detail_test.go |
| Context redaction | ticket_detail_test.go |
| Create rejects bad tags (ClientError) | ticket_detail_test.go |
| Existing CRUD auth / claim / CSAT | unchanged; pre-031 column fallbacks keep them green until goose up |
Verify locally
# from apps/api
goose -dir sql/schema postgres "$DATABASE_URL" up
go test ./internal/support/ -count=1
ASSUMPTIONS
- ASSUMPTION: Agent 3 lands KB in
032_*without duplicating 031 ticket ALTERs. (Confirmed:032_support_kb_auto_reply.sqlreferences 031.) - ASSUMPTION:
plans.nameis stored ascustomer_context.plan_slug(plans have no slug column). - ASSUMPTION: List payloads stay lean; UI agents read detail GET for timeline / context.
- NOTE for agent 10: two files share version
033_*(033_support_auto_ai_config.sqland033_support_auto_security_perf.sql) — rename one before goose up.