Multi-tenant persona layer adds org management and firm-level system-prompt injection
Chris-o-O repositions Mike from a single-user tool into something deployable at a law firm: organizations, member roles, and a persona block that injects org context into every system prompt. The `en`/`fr` language flag and `bar_number` field hint at a Canadian/bilingual market.
Migration 002_personas.sql adds organizations, organization_members, and organization_invites tables, then extends user_profiles with org_id, user_role, practice_areas, user_custom_instructions, and bar_number. RLS is enabled on all three new tables; service-role backend traffic bypasses it. The /organizations/* REST module (444 lines) covers the full org lifecycle: create, join, edit, invite, member management. A /user/persona GET/PATCH endpoint handles individual profile updates.
The most portable piece is persona.ts, roughly 100 lines. It assembles a USER & ORGANISATION CONTEXT: block from org name, jurisdictions, practice areas, language, user role, firm-level instructions, then user-level instructions - and chat.ts and projectChat.ts inject it into every request. This block is provider-agnostic and small enough to lift independently of the org tables if your fork only needs per-user context.
Several things to audit before adopting. Invites are keyed by email with no requirement that the invitee verifies ownership before accepting membership. bar_number is plaintext, no format validation. Most significant: user_custom_instructions is injected verbatim into the system prompt, so anyone with profile-edit access can change how the assistant behaves for themselves. An org admin can do the same to the whole firm via custom_instructions. That prompt-injection surface is worth a hard look before firm deployment. Migration 002 also redundantly re-adds openrouter_api_key - already present from migration 001, but safe because it uses if not exists.
The PR is large (~1,420 lines, including two 444-line files) and ships without tests.
Spotted something wrong? Or know the PR text has fresher detail than the writeup above?