Supabase data space
Supabase stores private Workspace and tenant module data: bookings, rental requests, Pages media, audience contacts, logs, user access and module settings. Treat it as the operational database for private portal state.
Server-side boundary
The service role key must never reach the browser. Public pages use only safe content selected by the server. Tenant DNS rendering must resolve the tenant first and then expose only public fields for that tenant.
Use the browser client only for flows that are safe with anon/authenticated keys. Use server routes for privileged operations.
Typical data groups
| Data group | Examples | Public exposure |
|---|---|---|
| Workspace access | users, roles, invites | Never public |
| Tenant settings | DNS route, enabled modules, theme, public flags | Only safe public fields |
| Pages | published pages, media, redirects | Published content only |
| Booking | services, requests, status, customer actions | Public form and limited status |
| Rent | items, requests, approvals | Public listing and limited status |
| Audience | contacts, tags, unsubscribed state | Never expose contact list |
| Logs | module actions, errors, credit events | Workspace/staff only |
Required checks
Before a tenant portal goes live:
- Confirm the tenant workspace record exists.
- Confirm the DNS host maps to the correct tenant.
- Confirm RLS/server boundaries prevent cross-tenant reads.
- Confirm public routes do not return private tables.
- Confirm logs are written for integration failures.
- Confirm customer action links are scoped and cannot update another tenant.
Module storage
Booking, Rent, Pages, Audience, Store and Calendar need structured storage. If a module is not configured, the UI should explain what the owner needs to do instead of showing a partial failure.
Recommended module setup state:
status: "not_configured" | "ready" | "error"
missing: ["supabase", "resend", "stripe"]
message: "Connect Resend before sending booking confirmations."
Logs
Workspace logs help track module actions, customer actions and integration errors. Logs do not replace a formal audit policy, but they provide operational visibility.
Log useful events:
- DNS route resolution failure.
- Email send failure.
- Stripe webhook mismatch.
- Credit reserve/capture/refund.
- Customer cancellation action.
- Module setup changed.
Do not log service role keys, API keys, full card data or sensitive payloads.
tenant-exec-sql.txt
The tenant-exec-sql.txt helper creates a controlled SQL execution function for service-role-only maintenance operations. It must not be available to public, anon or authenticated browser users.
create or replace function public.exec_sql(query text)
returns void
language plpgsql
security definer
as $$
begin
execute query;
end;
$$;
<br>
revoke all on function public.exec_sql(text) from public;
revoke all on function public.exec_sql(text) from anon;
revoke all on function public.exec_sql(text) from authenticated;
<br>
grant execute on function public.exec_sql(text) to service_role;
Use it only from trusted server-side maintenance code. Prefer explicit migrations for normal schema changes. If this helper exists, document who may call it and why.
FAQ
Can public pages query Supabase directly?
Only for explicitly public data with safe keys and strict policies. Most tenant rendering should go through server code so the host can be resolved and data can be filtered.
What happens when Supabase is not configured?
Modules that require private state should show a setup message in Workspace. Tenant public pages should hide or disable the affected module.
Where are media files stored?
Pages media can live in Supabase storage or another approved storage layer, but public rendering should use safe public URLs or signed server-generated access where needed.