Internal
Internal-only tooling. Currently limited to the Internal Chat workspace — a Slack-style channels + DMs surface for staff collaboration.
Scope
This namespace is for features that are meaningful only to staff and have no external-facing variant. Today it hosts chat; future developer/admin utilities (debug consoles, data exports, tooling) would live here.
Pages
src/pages/internal/Chat.tsx— mounted at/internal/chat.
Route (src/App.tsx:197):
<Route path="/internal/chat"
element={<ProtectedRoute requiredPermissions={['chat.view']}>
<ChatPage />
</ProtectedRoute>} />
Internal Chat
Slack-like layout (see Chat.tsx:293):
- Left rail — search, channel list, DM list, and two CTAs: New channel and New DM.
- Main pane — message list + composer.
- Thread panel —
ThreadPaneldrawer for replies (opens on right).
Capabilities:
| Capability | Component / Service |
|---|---|
| Public / private channels | ChannelList, createChannel() (services/chatService.ts) |
| Direct messages | DMList, createDMWithUser() |
| Realtime delivery | Supabase Realtime via subscribeToMessages() |
| Presence | createPresenceChannel() shows "N online" pill |
| Reactions | toggleReaction() |
| Threaded replies | parentMessageId on sendMessage() |
| Soft delete / edit | softDeleteMessage(), updateMessage() |
| Read receipts | upsertReadState() |
| Mentions + sounds | playMentionSound, playMessageSound, playDMSound (src/lib/notificationSound.ts) |
| Attachments | ChatAttachmentInput → Supabase Storage |
Migration dependency
If the chat tables are missing (supabase/migrations/20260122100000_chat.sql not applied), the page shows an inline error instead of loading:
Chat tables are missing. Apply migration supabase/migrations/20260122100000_chat.sql. See
Chat.tsx:117.
Audience
All staff roles with chat.view. The matrix grants chat.view to every internal staff role (super-admins, managers, execs). Portal roles (AGENT, CUSTOMER) do not get it.
chat.view history
Referenced by /internal/chat since day one, but originally unseeded. Drift #1 in docs/PERMISSIONS.md §8 notes that it was backfilled by supabase/migrations/20260416030000_seed_chat_and_dashboard_view.sql.
Permissions
| Action | Permission | Enforcement |
|---|---|---|
View /internal/chat |
chat.view |
Route guard |
| Create channel | chat.view |
No finer gate today; any staff member with chat access can create channels |
| Delete channel | chat.view + ownership (server RLS) |
|
| Send / edit / delete own messages | chat.view + author check |
Server RLS enforces authorId = auth.uid() for edits/deletes |
| Send DM | chat.view |
DM participant check enforced server-side |
API / service surface
Chat does not go through src/lib/api.ts — it talks to Supabase directly via src/services/chatService.ts. Underlying tables live in the ChatChannel, ChatChannelMember, ChatDM, ChatDMMember, ChatMessage, ChatReaction, ChatReadState models (Prisma schema).
Related
- Dashboard →
docs/features/dashboard.md(chat notifications feed can also appear as push notifications). - Communications (customer-facing broadcasts) →
docs/features/communications.md.