Status: ✅ Complete (Phase 1–3; Phase 4 email branding deferred)
Spec: PF-95-tenant-white-labeling-theming.md (v1.2.0) Last Updated: 2026-03-25
Overview
PF-95 adds per-tenant visual theming (CSS custom properties), optionalpf_organizations.subdomain, subdomain_verified, prefer_subdomain_redirect, and coordination with email branding. It extends the platform foundation without introducing cross-core imports. Consumers use @/platform/theming (planned) for theme resolution and CSS variable injection.
Integration Points (from Spec)
Platform Layer / Event / API Contracts
- Platform layer (planned):
@/platform/theming—TenantThemeProvider,useTenantTheme,useTenantThemeForLogin(or equivalent) calling RPCs below for pre-auth, shared types aligned withpf_tenant_themesrows. - Pre-auth (database): Call
pf_public_login_branding_by_subdomain(subdomain_label)when the request host is a tenant subdomain; callpf_public_login_branding_by_slug(slug)when resolving branding from PF-74 path slug (e.g. login with org context). Do not expose anonymousSELECTonpf_tenant_themes. Functions return a fixed JSON projection (login-safe fields only); see spec Data Model. - Authenticated: Standard Supabase CRUD on
pf_tenant_themeswith RLS; org subdomain flags updated via existing org update patterns andpf.subdomain.manage. - Event contracts: None planned for MVP.
- Single active theme: Partial unique index
(organization_id) WHERE is_active+BEFOREtrigger to deactivate sibling rows (spec DDL).
Canonical redirect matrix (normative summary)
Eligibility:subdomain IS NOT NULL and subdomain_verified = true and prefer_subdomain_redirect = true.
Full text and notes (308 vs 302, loop prevention, PF-77 boundary) are in the spec section Canonical redirect matrix (PF-74 / PF-81). PF-74 owns implementation (middleware, edge, or client bootstrap — PF-74 choice).
Security & Tenancy
- All theme rows scoped by
organization_id; RLS viapf_has_org_access(SECURITY DEFINER helper; no inline role-assignment queries in policies). - Permission keys (PF-30):
pf.theme.view,pf.theme.manage,pf.subdomain.manage— constants + seeds with feature UI. - No arbitrary CSS/HTML injection; colors validated to safe formats; assets via approved upload paths.
- Pre-auth: Only
pf_public_login_branding_*RPCs; fixed column allowlist;search_pathpinned inside functions. - Redirects: Gated on
subdomain_verifiedto avoid redirect loops to hosts without valid TLS.
Related Docs
- CROSS_CORE_INTEGRATIONS.md
- PF-74 Integration — implements redirect matrix
- PF-81 Integration
- PF-77 Integration
- PF-86 Integration
- PF-95 Spec