Chat is implemented in two hosts:Documentation Index
Fetch the complete documentation index at: https://docs.tuturuuu.com/llms.txt
Use this file to discover all available pages before exploring further.
apps/webowns protected APIs, workspace authorization, storage signing, and private Supabase RPC execution.apps/chatis the standalone satellite UI athttps://chat.tuturuuu.com, with local Portless originhttps://chat.tuturuuu.localhostand direct fallbackhttp://localhost:7821.
@tuturuuu/ui/chat/chat-workspace
and call the same @tuturuuu/internal-api chat client. Do not add direct
browser Supabase reads, client-local raw fetch('/api/...'), or host-specific
chat business logic.
API Ownership
apps/chat forwards /api/v1/* and /api/ai/* to apps/web. The standalone
app authenticates through the cross-app session target chat; apps/web
accepts that target only on the chat API surface and still performs normal
request-scoped user validation before protected work.
Chat routes must follow this order:
- Authenticate the request user or app-session user.
- Normalize workspace aliases such as
personal. - Verify workspace membership and the required chat permission.
- Call private-schema RPCs through a service-role admin client with
.schema('private').rpc(...). - Return only JSON DTOs that are safe for participants of the conversation.
Private Schema Contract
Durable chat data lives in private tables only:private.chat_conversationsprivate.chat_conversation_membersprivate.chat_messagesprivate.chat_message_attachmentsprivate.chat_message_reactionsprivate.chat_conversation_ai_settingsprivate.chat_audit_events
public,
anon, and authenticated; grants execution only to service_role; and keeps
RLS enabled with no permissive direct-access policies. Browser clients must
recover durable state by refetching the apps/web API, never by reading private
or legacy public chat tables directly.
RPCs enforce participant access, workspace membership, direct-chat uniqueness,
attachment path ownership, message ownership, reaction limits, search scoping,
read state, and audit metadata. When adding behavior, extend the private RPC
surface first and keep the web route as a thin auth/validation wrapper.
Attachments
Chat attachments use the existing workspace storage provider rather than a separate chat bucket. The upload flow is:- Client requests
/api/v1/workspaces/:wsId/chat/conversations/:conversationId/attachments/upload-url. apps/webverifies the participant throughprivate.chat_prepare_attachment.apps/webcreates a Drive-backed signed upload payload under:wsId/chats/:conversationId/*.- The client uploads to the signed URL and sends the returned attachment draft with the message.
private.chat_send_messagefinalizes records and links attachments to the message.
private.chat_get_attachment
first, then issues a short-lived storage read URL only after the caller is
confirmed as a participant.
Permissions
The chat permission set is:view_chat: read conversations where the actor is a participant.create_chat: create direct messages, groups, channels, and AI chats.manage_chat: manage chat membership, state, and AI settings.moderate_chat: moderate messages and reactions.
view_chat and create_chat. The dashboard navigation
should hide or disable Chat when view_chat is missing.
AI Conversations
AI conversations are normal private chat conversations withai_enabled = true plus private AI settings. Existing AI audit or billing
tables can remain for provider usage tracking, but human chat access must not
depend on public AI chat tables. Persist generated assistant messages through
private chat RPCs so conversation history, read state, attachments, and audit
events remain in one protected chat domain.