Drop one-shot tmp/axe scripts and agent i18n scratch so the Gitea tree is deployable.
2.6 KiB
2.6 KiB
13 — Support ticket ratings / CSAT
Owner: agent 13
Depends on: agent 12 schema (030_support_desk.sql → support_csat_ratings)
Status: implemented (API + tests)
Goal
Customers rate resolved or closed tickets once (score 1–5 + optional comment). Platform admins see aggregate CSAT (no PII).
Schema (agent 12)
Table support_csat_ratings:
| Column | Notes |
|---|---|
ticket_id |
UNIQUE — one rating per ticket |
company_id, user_id |
owner + tenant |
score |
SMALLINT 1–5 |
comment |
optional, max 2000 runes (truncated) |
created_at |
UTC |
Ticket columns csat_token_hash / csat_invite_sent_at exist for optional public token flow (not wired in this agent).
Rules
- Only
created_by_user_idmay rate (others →404). - Status must be
resolvedorclosedelse400(ticket not eligible for rating). - Duplicate insert →
409(already rated). - Logs:
ticket_id+scoreonly — never comment, email, or names.
APIs
| Method | Path | Auth | Response |
|---|---|---|---|
POST |
/api/support/tickets/{id}/csat |
session + company | 201 SupportCsat |
GET |
/api/support/tickets/{id} |
customer | additive csat / csat_eligible |
GET |
/api/admin/support/tickets/{id} |
support desk | includes csat when present |
GET |
/api/admin/support/csat?from=&to= |
platform admin | aggregate |
Customer submit body
{ "score": 4, "comment": "optional" }
Admin aggregate
{
"total": 12,
"average": 4.25,
"distribution": { "1": 0, "2": 1, "3": 2, "4": 4, "5": 5 },
"from": null,
"to": null
}
from / to are optional RFC3339 bounds on created_at (to exclusive).
Code map
| Piece | Path |
|---|---|
| Service | apps/api/internal/support/ratings.go |
| Types | CSATInput, CSATRating, CSATAggregate in types.go |
| Handlers | apps/api/internal/httpapi/support_csat_handlers.go |
| Routes | customer POST csat; admin GET /api/admin/support/csat |
| Unit tests | ratings_test.go, support_csat_auth_test.go |
| Integration | ratings_integration_test.go (needs DATABASE_URL + goose) |
Verification
cd apps/api
go test ./internal/support/ -count=1 -run 'CSAT|NormalizeCSAT|ClientErrorCSAT'
go test ./internal/httpapi/ -count=1 -run 'SupportCSAT|SupportTicketCRUDAuth'
With DB migrated:
go test ./internal/support/ -count=1 -run TestSubmitCSATOwnershipAndOnce
Out of scope (this agent)
- Public token CSAT (
POST /api/public/support/csat) - User/staff UI panels (agents 14–15)
- Email CSAT invite stubs