01Department isolation without row-level security
Problem
Departments must never see each other's tickets, but Prisma connects to Postgres as a single database role. RLS would have meant threading per-request session variables through every query and debugging policy failures that surface as empty result sets.
Approach
Scope is enforced in one place on the server: a guard that resolves the caller's memberships and turns them into a Prisma where clause every ticket query is built on. Server components and route handlers both go through it, so there is no path to a ticket that skips the check — and a denied request fails loudly instead of returning nothing.
02Roles that differ per team
Problem
The same person can lead one team and be staff on another. A single role column on the user could not express that, and admin, manager, lead and staff each unlock different actions.
Approach
Role lives on the membership, not the user. Permission checks ask "what is this user on this ticket's team", which keeps cross-team work possible without granting anyone more than they hold.
03Status that reflects shipped code
Problem
Manually dragged statuses drift from reality: tickets sat in review long after merge, or jumped to done before anything shipped.
Approach
A GitHub webhook links pull requests to tickets and moves status forward only — opened moves to review, merged moves to done — and never backwards. Deliveries are verified by signature and processed idempotently, so a retried webhook cannot double-apply a transition.
04Live boards without a polling storm
Problem
Several people work the same board at once. Polling every open tab would hammer the database and still feel stale.
Approach
Supabase Realtime broadcasts a small change event; each client invalidates just the affected TanStack Query keys and refetches through the same scoped API. Realtime never carries ticket data itself, so it can never leak across departments.