Skip to content

Service Ticketing Demo

Ordered runbook for showcasing Floh service ticketing: catalog submit, My Tickets, agent assignment, comments, status/SLA, queues, and (optionally) email intake.

For a five-card IT support portal walkthrough (self-service + approval + ticketed cards) seeded via pnpm seed:support-portal, see Support Portal Demo.

Read Service Ticketing for architecture and story inventory. This page is the live checklist.

Start the stack

pnpm dev:all https starts infra + migrations, then the full HTTPS stack (API :7070, console BFF :7074, admin SPA :7072, portal BFF :7071, portal SPA :7073, form-builder :7080). Do not start pnpm dev:portal in a second terminal — those ports are already bound.

pnpm dev:all https
Port App Started by
7070 API (+ /api/docs) dev:all https
7071 Portal BFF dev:all https
7072 Admin web dev:all https
7073 Portal SPA dev:all https
7074 Console BFF dev:all https
7080 Form-builder dev:all https

pnpm dev:all with no argument prompts from the HTTPS picker (dev:https, dev:mux, …). Use pnpm dev:all:http for the HTTP picker. pnpm dev:all portal:https is valid but starts only the portal side.

Accounts

  • Requester — any authenticated portal user (catalog submit + own tickets)
  • Agent — user with ticket:manage (Tickets hub, queues, SLA, assign/status/comments/snooze). Prefer a second user so assignment is visible.

One-time config (before the live demo)

  1. Admin → Tickets → Ticket Queues → create e.g. IT Support
  2. Admin → Tickets → SLA Policies → create or attach a policy to that queue (response/resolution hours per priority)
  3. Admin → Workflows → open a catalog-published workflow → Catalog Publishing → Ticket Queue → select IT Support → save (needs ticket:manage to load queues)
  4. Confirm the workflow is published to the Request Catalog (or use draft preview if you hold workflow:publish)

Demo script

1. Catalog submit → ticket created (LSA-9061)

Where: Portal https://localhost:7073/requests/catalog

  1. Sign in as requester
  2. Open Request Catalog (topbar)
  3. Pick a catalog item whose workflow has a Create ticket step (and optionally a Ticket Queue)
  4. Fill the form (optional: ticketTitle, ticketDescription, ticketRequestType) → Submit Request
  5. Confirm the banner: Your request was submitted as ticket #N (link when you are the requester). Without Create ticket, expect “Your request was submitted.”
  6. When ticketed, click the link → lands on /tickets/N

What to say: Ticket creation is opt-in via the create_ticket step. When present, one DB transaction creates the run and service_ticket. Form variables map title/description/request type. On-behalf-of sets requester_id to the target user. The portal does not expose raw POST /api/tickets.

2. Portal My Tickets (LSA-9063)

Where: /tickets and /tickets/:ticketNumber

  1. Topbar My Tickets
  2. Walk tabs: Open, Pending Your Response, Resolved, All
  3. Open #N — Details, Description, Conversation
  4. Post a Reply (public comment only)

What to say: The list is force-scoped to requester_id. The BFF whitelist blocks agent mutations (assign, status, internal notes) from the portal. Open tab uses statusIn=open,in_progress,on_hold.

3. Agent inbox — assign, status, priority, queue

Where: Admin https://localhost:7072/tickets (sidebar Tickets, needs ticket:manage)

  1. Find ticket #N (filters: Status / Priority / Queue / Assignee)
  2. Open detail or use list Update for a quick status/priority/queue change
  3. On detail Assignment card: set Assignee to the agent, change Status (e.g. open → in_progress or pending_customer), adjust Priority / Queue if useful
  4. Save, then refresh portal as requester to show the same ticket number with updated fields

What to say: Agents work in admin; requesters work in portal. Same display ticket number in both UIs.

4. Comments — public vs internal

Where: Admin ticket detail → Comments

  1. Add a public comment (visible on portal Conversation)
  2. Check Internal note → add another (tag Internal)
  3. Switch to portal as requester → only the public reply appears

What to say: Internal notes never leave the agent surface. The email channel also never emails internal notes. A public requester reply on pending_customer returns the ticket to open.

5. SLA visibility + snooze

Where: Admin ticket detail; portal list SLA column

  1. Show SLA due / countdown fields on admin (and portal list if present)
  2. Snooze SLA → pick a future time → confirm
  3. Mention breach notifications (LSA-9067) if SMTP is configured; otherwise note they are environment-dependent

6. Queues and SLA policy admin

Where: /tickets/queues, /tickets/sla-policies

Brief walkthrough of creating a queue and editing policy hours so the audience sees the config that drives assignment defaults and SLA clocks.

7. Optional — email channel (LSA-9066)

Where: Admin → Connectors → email-ticketing; webhook against the API

If a connector is configured:

  1. Show fields: inboxAddress, webhookSecret, adminNotifyEmail
  2. POST /api/email-ticketing/inbound/:connectorId with HMAC signature — see Email Ticketing connector
  3. Ticket appears with source=email; agent public comments would trigger outbound mail with a full gateway

If no connector is set up, skip and point at the connector doc.

8. Out of scope for this demo

Call these out so expectations stay clear:

  • Ticket reporting / charts (LSA-9068) — planned, not shipped
  • Portal “create ticket” button / BFF POST /api/tickets — intentionally omitted; catalog is the create path
  • Phase 1 triage (LSA-9052) — owned elsewhere; not required for this walkthrough

Quick reference checklist

  • [ ] Terminal A: pnpm dev:all https (7070, 7072)
  • [ ] Terminal B: pnpm dev:portal:https (7071, 7073)
  • [ ] Queue + SLA policy created
  • [ ] Catalog workflow has Ticket Queue bound
  • [ ] Requester + agent accounts ready
  • [ ] Catalog submit → #N banner → My Tickets
  • [ ] Agent assign / status / public + internal comment
  • [ ] SLA snooze (optional)
  • [ ] Email webhook (optional)