Design Rationale — Identity
Non-obvious design choices for the identity module — the WHY behind each decision.
Identity (locked 2026-06-09)
Identity owns authorization; Supabase Auth owns authentication
Decision: identity schema owns roles, permissions, assignments, site access, SSO config, and support grants. Password storage, session tokens, and OAuth flows are Supabase Auth's responsibility — no such tables exist in Vrida schemas.
Why: Rebuilding authentication is unnecessary and risky. Supabase Auth is battle-tested; Vrida adds the authorization model on top.
Guard: No password or session tables will ever appear in identity or any other Vrida schema. If an auth concern arises that looks like it needs a Vrida table, check whether Supabase's JWT claims or metadata can carry it first.
Security policy config lives in identity, not admin
Decision: password_policy, sso_provider, session_config, and ip_whitelist tables live in identity. The admin module is the UI surface; it writes these via IdentityService — it does not own the tables.
Why: Auth config belongs with auth ownership. Co-locating config with the service that enforces it means one team owns the full security surface.
Guard: Do not create admin.password_policy or similar. Admin reads and updates identity config through IdentityService; the tables stay in identity.
Support access via time-boxed grants, not permanent admin flags
Decision: Vrida staff access to tenant data is expressed through support_access_grant rows with explicit granted_until timestamps — not a permanent is_vrida_staff flag on identity_user.
Why: Principle of least privilege. Every support session is auditable, time-bounded, and revocable. A permanent flag creates an ever-present elevated-access pathway.