Org layer and per-user persona injected into every chat system prompt
Chris-o-O added a multi-tenant organization model and a per-user persona that gets prepended to every chat and project-chat system prompt. The persona carries user role, practice areas, jurisdictions, bar number, a personal custom instruction field, and a firm-level custom instruction from the org -- making the assistant context-aware of who it's talking to.
Three new tables land in migration 002: organizations (slug, jurisdictions, practice areas, custom_instructions, language), organization_members (role: admin|member), and organization_invites (email-based, 7-day expiry). Six columns are added to user_profiles: org_id, user_role, practice_areas, user_custom_instructions, bar_number, and a defensive re-add of openrouter_api_key.
The persona logic sits in backend/src/lib/persona.ts. fetchPersonaContext joins the profile and org; buildPersonaSystemPrompt formats the result. Both routes/chat.ts and routes/projectChat.ts prepend it to every system prompt. The fetch happens on every chat request with no caching.
On the API side, routes/organizations.ts (444 lines) covers full CRUD, member management, and invite flows. Frontend gets a new account/company page and a "My Profile" section on the General account page.
A few things to verify before adopting. RLS policies are SELECT-only -- the backend uses the service-role key for all writes, so write isolation relies entirely on your backend auth, not Postgres RLS. The org slug uniqueness helper uses Math.random() for the suffix with no collision loop. Member listing fetches user_profiles per member (N+1). The openrouter_api_key column appears in both migration 001 and 002 with if not exists guards, which signals the two features were developed independently without coordinating migration numbering.
Spotted something wrong? Or know the PR text has fresher detail than the writeup above?