Milestone 11: SLA and business hours
Purpose: Admins configure SLA policies and business hours; tickets show SLA status; breach and near-breach trigger notifications.
Exit state: SLA CRUD (policy + business hours); SLA status on ticket (on track / due soon / breached); SLA cron for notifications.
Spec reference: §2.4 SLA, Business hours, §4.8 SLA checks, §5.10 SlaPolicy, §5.21 BusinessHours, §6.10 settings/sla, §10.7 SLA lifecycle.
Prerequisites: M10 (Billing). Notifications (M08) for breach emails.
11.1 SLA policies and business hours
Tasks
-
SLA policies CRUD
- tRPC: list, create, update, delete. sla_policies: tenant_id, inbox_id (nullable = all inboxes), name, first_response_hours, resolution_hours, business_hours_only. Section 5.10.
- Settings → SLA: list policies (name, targets, inbox assignment); "New policy" form (name, first response hours, resolution hours, inbox or "All inboxes", business hours only toggle). Edit/delete with confirm. Section 6.10.
-
Business hours
- business_hours table: tenant_id, timezone, monday_start/end through sunday_start/end (time or null = closed). One row per tenant. Section 5.21. Default when missing: e.g. Mon–Fri 09:00–17:00 Europe/Berlin (Section 5.21). tRPC get/upsert for tenant.
- Settings → SLA: Business hours section — timezone select, per-day rows with "Open" toggle and start/end time pickers. Section 6.10.
-
Assign policy to ticket
- When creating ticket (from email or manual): assign sla_policy_id from inbox (policy for that inbox_id or tenant-wide null inbox_id). Optional: allow manual override in ticket edit. Section 5.5.
Acceptance criteria
| Criterion | Status |
|---|---|
| Admin can create and edit SLA policies and business hours; policies can be per-inbox or global. | Pending |
| New tickets get policy from inbox or default; business hours default when no row. | Pending |
11.2 SLA status computation
Tasks
-
First response target
- Policy first_response_hours; ticket first_response_at null → deadline = created_at + first_response_hours (in business hours if business_hours_only). Elapsed = now - created_at (business-hours count only if policy.business_hours_only). Status: breached if elapsed > target and first_response_at null; due_soon if within 20% of target; on_track else.
-
Resolution target
- Policy resolution_hours; ticket resolved_at null → deadline = created_at + resolution_hours (business hours). Elapsed same. Status: breached if elapsed > target and resolved_at null; due_soon; on_track. When status = waiting, pause SLA clock (do not count waiting time toward target). Section 2.4.
-
Helper
- Function:
computeSlaStatus(ticket, policy, businessHours)→ returns{ firstResponse: 'on_track'|'due_soon'|'breached', resolution: same }. Use in API and cron.
- Function:
-
Display on ticket
- Ticket sidebar or header: show SLA status (e.g. "First response: on track", "Resolution: due in 2h" or "Breached"). Section 6.5.
Acceptance criteria
| Criterion | Status |
|---|---|
| SLA status correct for business-hours and calendar-hours policies; waiting status pauses clock. | Pending |
| Ticket detail shows current SLA status; updates when ticket or time changes. | Pending |
| SLA status and breach state on ticket reflected in real time when cron or status changes (SSE: ticket.updated triggers refetch; Section 4.11). | Pending |
11.3 SLA cron and notifications
Tasks
-
Cron (periodic)
- Inngest cron: e.g. every 15 min. Query tickets with sla_policy_id not null, status not in (resolved, closed). For each, compute SLA status; if first_response or resolution = breached (or due_soon per product), create notification for assignee and tenant admins (type sla_breach or sla_due_soon); send email if preference allows. Section 4.8, 2.10.
- Idempotent: do not spam; e.g. one notification per ticket per breach event (store last_notified_at or event id).
-
Templates
- sla-breach email (already in M08): ticket_number, ticket_subject, sla_type, breached_at, ticket_url. Section 2.10b.
Acceptance criteria
| Criterion | Status |
|---|---|
| Cron runs; breached (and optionally due_soon) tickets trigger in-app and email notifications. | Pending |
| No duplicate notifications for same breach; assignee and admins notified. | Pending |
Milestone 11 sign-off
| Criterion | Status |
|---|---|
| All tasks in 11.1–11.3 complete. | Pending |
| All acceptance criteria met. | Pending |
| SLA and business hours configurable; ticket shows status; breach notifications work. | Pending |
| E2E: SLA config and ticket status/breach UI (see INDEX — Testing strategy). | Pending |
| Ready for M12 (Search). | Pending |