> ## Documentation Index
> Fetch the complete documentation index at: https://docs.encoreos.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Tenant White-Labeling & Theming — Integration

> Feature ID: PF-95 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

**Feature ID:** PF-95\
**Status:** ✅ Complete (Phase 1–3; Phase 4 email branding deferred)\
**Spec:** [PF-95-tenant-white-labeling-theming.md](../../../specs/pf/specs/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), optional `pf_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)

| Point                                    | Type                | Document / Spec                                                                              |
| ---------------------------------------- | ------------------- | -------------------------------------------------------------------------------------------- |
| PF-01 (Organizations)                    | Data                | `pf_organizations`; `subdomain`, `subdomain_verified`, `prefer_subdomain_redirect`           |
| PF-74 (Org URL Routing)                  | Platform internal   | Implements **Canonical redirect matrix** (R1–R5) on primary host; path org routing unchanged |
| PF-77 (Tenant Domain Management)         | Platform / external | Vercel host + SSL; custom apex domain out of scope for PF-95                                 |
| PF-81 (Multi-Tenant Host & URL Strategy) | Reference           | Strategy umbrella; normative redirect table lives in PF-95 spec                              |
| PF-86 (Email Signatures)                 | Platform Layer      | Theme color tokens for HTML notification templates (Phase 4)                                 |
| PF-77 / Vercel                           | External infra      | Subdomain SSL and hostname configuration                                                     |

***

## Platform Layer / Event / API Contracts

* **Platform layer (planned):** `@/platform/theming` — `TenantThemeProvider`, `useTenantTheme`, `useTenantThemeForLogin` (or equivalent) calling **RPCs below** for pre-auth, shared types aligned with `pf_tenant_themes` rows.
* **Pre-auth (database):** Call **`pf_public_login_branding_by_subdomain(subdomain_label)`** when the request host is a tenant subdomain; call **`pf_public_login_branding_by_slug(slug)`** when resolving branding from PF-74 path slug (e.g. login with org context). **Do not** expose anonymous `SELECT` on `pf_tenant_themes`. Functions return a **fixed JSON projection** (login-safe fields only); see spec Data Model.
* **Authenticated:** Standard Supabase CRUD on `pf_tenant_themes` with RLS; org subdomain flags updated via existing org update patterns and `pf.subdomain.manage`.
* **Event contracts:** None planned for MVP.
* **Single active theme:** Partial unique index `(organization_id) WHERE is_active` + `BEFORE` trigger 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`.

| Rule | Request                                          | Action                                                                                                            |
| ---- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------- |
| R1   | Primary app host + `/o/{slug}/…`                 | If org for `slug` meets eligibility → **308** to `https://{subdomain}.{apex}/o/{slug}/…` (preserve path + query). |
| R2   | Tenant subdomain host + `/o/{slug}/…`            | No redirect.                                                                                                      |
| R3   | Primary host, path without `/o/:slug`            | No PF-95 redirect.                                                                                                |
| R4   | Unknown subdomain host                           | No PF-95 redirect (platform default).                                                                             |
| R5   | Wrong subdomain host for resolved org (optional) | **308** to canonical tenant host (recommended; PF-74 may defer with implementation log).                          |

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 via `pf_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_path` pinned inside functions.
* **Redirects:** Gated on `subdomain_verified` to avoid redirect loops to hosts without valid TLS.

***

## Related Docs

* [CROSS\_CORE\_INTEGRATIONS.md](./CROSS_CORE_INTEGRATIONS.md)
* [PF-74 Integration](./organization-url-routing-integration.md) — implements redirect matrix
* [PF-81 Integration](./multi-tenant-host-url-strategy-integration.md)
* [PF-77 Integration](./tenant-domain-management-integration.md)
* [PF-86 Integration](./platform-email-signature-service-integration.md)
* [PF-95 Spec](../../../specs/pf/specs/PF-95-tenant-white-labeling-theming.md)
