Tenant ownership is the organizing principle.
Clientana stores identity-linked workspace state in Postgres, keeps large media in R2, and uses explicit relationships plus row-level security to prevent one workspace from seeing another.
Domain map
Workspace identity
- tenants
- tenant_members
- workspace_invites
- workspace_join_requests
- workspace_owner_transfers
- workspace_security_settings
Plans and licensing
- subscriptions
- billing_events
- appsumo_deals
- appsumo_licenses
- complimentary_plan_grants
Recording workspace
- recordings
- video_folders
- video_comments
- video_views
- recording_versions
- recording_processing_jobs
Rooms and events
- meeting_rooms
- meeting_participants
- meeting_events
- scheduled_meetings
Domains and shares
- domains
- domain_verifications
- recordings share fields
- translation_entries
- share access and visibility settings
SSO and SCIM
- workspace_identity_providers
- workspace_sso_domains
- workspace_scim_tokens
- workspace_scim_users
Support and administration
- support_tickets
- support_ticket_messages
- platform_admin_notes
- platform_feature_flags
- platform_tenant_overrides
Security and reliability
- audit_logs
- security_events
- worker_failures
- worker_heartbeats
- platform_incidents
- security_event_reviews
Core relationships
Supabase Auth user
An authenticated user can belong to more than one workspace.
tenant_members
The join table assigns owner, admin, or member role inside a tenant.
tenants
The active tenant scopes subscription, videos, meetings, domains, settings, and enterprise identity.
recordings
Screen recordings, saved meetings, and uploads converge on one tenant-owned asset model.
Unified recording asset
recordings is the center of the durable video product. Important categories of fields include:
- Ownership: tenant, original user, source type, folder, deletion state.
- Media: original R2 key, content type, size, duration, processed playback and derivative metadata.
- Workspace metadata: title, description, transcript, search text, chapters, summary, action items, decisions, translations.
- Sharing: share ID/token state, expiry, public/password access, password hash, comments, download visibility, CTA, branding, transcript and translation visibility.
- Engagement: view and comment counters, viewer notifications, analytics inputs.
- Editing: timeline settings, clips, active version, thumbnail and export state.
Separate tables hold many-to-one or event-like concerns: folders, comments, views, versions, and processing jobs. Media bytes remain in R2 rather than Postgres.
Meeting persistence
meeting_roomsstores durable room identity, tenant ownership when present, hashed host authority, plan limits, expiry/status, and SFU metadata.meeting_participantsrecords request, admission, denial, join, and leave history.meeting_eventsstores durable chat, captions, caption-control, and other meeting events with indexes for recent room hydration.scheduled_meetingsstores upcoming meeting details and reusable meeting configuration.- Closing an entitled transcript can queue a resumable meeting summary, whose final artifact can be attached to the saved recording/workspace experience.
Row-level security model
Tables in the exposed public schema enable RLS. Policies follow the domain instead of applying one generic rule everywhere:
- Tenant-scoped reads require an active membership in the row’s tenant.
- Admin-only settings and membership changes require owner/admin role.
- User-authored comments allow the author or tenant admins to update within explicit policy rules.
- Owner-only platform administration tables are locked from direct client access and used through guarded server routes.
- Server-only operational tables use explicit deny policies for browser roles where appropriate.
- Update access requires both visibility of the existing row and validation of the resulting row; ownership columns cannot be reassigned through a permissive update.
Migration ownership
Canonical migrations live in migrations/supabase/ and are applied in numeric order by scripts/migrate.js. The supabase/migrations/ directory contains CLI-linked project history for selected later changes; engineering work must avoid creating two competing migration histories for the same change.
When changing schema:
- Create the migration with the Supabase CLI rather than inventing a filename.
- Review RLS, grants, indexes, foreign keys, view security, and function execution privileges.
- Run repository security and migration checks.
- Verify the behavior with the role and tenant context that will actually call it.
- Update this map when the domain or ownership model changes.