Multi-Org Membership with Isolated Organization Switching
Allow user to be a member of several orgs, including Operator. At any given moment user acts on behalf of the currently selected org, no permissions mix or leak. User can switch between orgs by clicking on his icon and selecting a switch icon next to the org. Same model as in Stripe and other multitenant systems
Subtasks
- [business_analysis] Multi-Org Membership with Isolated Organization Switching Requirements settled for multi-org membership with session-wide org switching from the avatar menu. Strict isolation: Operator powers apply only while acting as Operator. Includes invite+accept, self-created orgs (pending approval), deep-link interstitial and MFA step-up. 17 ACs; security gate applies.
- [architecture] Multi-Org Membership with Isolated Organization Switching Per-org admin_users rows + new identities table; switch re-mints cookie under target org's full sign-in policy; X-Jaah-Org stale-tab guard. 9 children: identity, security records, switch, invites, self-create, web switcher, deep-link, notif labels, isolation suite.
- [plan] Multi-Org Membership with Isolated Organization Switching Split by the architecture's 9 boundaries into 9 coders across 4 phases: identity → MFA/self-create/notif labels → switch+invites → web switcher/deep-link/isolation suite. One migration per wave. All are security-gated.
- Identity table and membership sign-in foundation Built the identities table (rev 0360, 1:1 backfill), person-field hybrids, the email census, two-epoch sessions and pick_membership on all 4 doors, plus /me memberships. Full gate green; review findings fixed; merged via #4500 with operator approval. Deferred: rev-2 contraction, trusted devices→identity (C2).
- Re-key MFA and security records MFA, recovery codes, trusted devices, resets and legal acceptances keyed on identity (rev 0361, additive), with the review's cascade bug fixed. Full gate green, operator approved, PR #4505 merged. Deferred: rev-2 drop of user_id/org_id.
- Self-create organization for signed-in users Built POST /api/orgs/self-create: pending org + new non-superadmin Owner membership via create_signup identity path, 1-pending cap (409). Full gate green; operator-approved; merged #4503. Deferred: verified-email requirement (M1), reject cooldown.
- Label every notification with its org Every notification (Slack, email, inbox) now names its org; org_label moved to app/org_names.py. AC12 and inbox tests added. Full gate green; merged #4504 with operator approval. Deferred: web bell render, settled-card header, webhook escaping.
- Org switch endpoint and stale-tab guard Built POST /api/auth/switch (target-org policy, iat kept) and the X-Jaah-Org/?org= stale-tab 409 guard; SSE closes on session_switched. Full gate green; security fixes in; operator approved; merged #4506. Deferred: MFA enrol on switch.
- Invite existing users into orgs Built org invitations: existing email → pending invite + email; accept/decline routes; operator plane 403; /me pending_invitations; rev 0362. Full gate green; operator approved; merged #4510. Deferred: revoke/expiry, per-recipient limit, email outcome.
- Org switcher in console account menu Org switcher in account menu (rail, collapsed, phone) + stale-tab guard (X-Jaah-Org, broadcast, reload dialog), invites, create org. Full gate green, visual check good; operator-approved; merged #4513. Deferred: Google inline re-auth.
- Deep-link interstitial for other-org items Built GET /api/auth/locate + the "This belongs to B — Switch to B" interstitial on 6 detail pages; AC13 e2e + census pass; full gate green; security gate approved; merged #4514. Deferred: Google-MFA return-to, per-identity rate bucket.
- Cross-org isolation and operator-plane tests Added a test-only cross-org isolation suite (18 tests, AC2/3/4/11, registry-driven sweeps); no leak found. Full gate green; operator approved; merged #4512. Deferred: WebSocket routes, unlisted stream entities, unseeded-param detail routes.
- [finish] Multi-Org Membership with Isolated Organization Switching All 9 coders merged; ask met (multi-org incl. Operator, isolated active org, account-menu switcher; no flags, switcher deployed to dev). Filed follow-up 5105: unenrolled person can't switch into an MFA-required org. Dev browser check not possible from this node.
- Org switch: let a person with no authenticator enrol Org switch now answers door 'enrol' (pending cookie → existing enrol flow) for a person with no authenticator; switcher + deep-link gate open the enrol page. Full gate green, operator approved security gate, PR #4517 merged.
Artifacts
Activity
- Created
- Runner started
- Ready
- Ready
- Ready
- Runner started
- Awaiting response
- Awaiting response
- Awaiting response
- Awaiting response
- Awaiting response
- Runner resumed
- Awaiting response
- Awaiting response
- Awaiting response
- Awaiting response
- Awaiting response
- Runner resumed
- Runner ended (done)
- Runner started
- Awaiting response
- Awaiting response
- Awaiting response
- Awaiting response
- Runner resumed
- Runner ended (done)
- Runner started
- Draft
- Draft
- Draft
- Draft
- Draft
- Draft
- Draft
- Draft
- Draft
- Draft
- Ready
- Ready
- Ready
- Ready
- Ready
- Ready
- Ready
- Ready
- Ready
- Ready
- Runner ended (done)
- Runner started
- Awaiting response
- Awaiting response
- Runner resumed
- Runner ended (done)
- Runner started
- Runner started
- Runner started
- Awaiting response
- Awaiting response
- Awaiting response
- Awaiting response
- Awaiting response
- Awaiting response
- Runner resumed
- Awaiting response
- Runner resumed
- Runner resumed
- Runner ended (done)
- Runner ended (done)
- Runner ended (done)
- Runner started
- Runner started
- Awaiting response
- Awaiting response
- Awaiting response
- Awaiting response
- Runner resumed
- Awaiting response
- Runner resumed
- Runner ended (done)
- Runner ended (done)
- Runner started
- Runner started
- Runner started
- Awaiting response
- Awaiting response
- Awaiting response
- Awaiting response
- Runner resumed
- Awaiting response
- Awaiting response
- Runner resumed
- Runner resumed
- Runner ended (done)
- Runner ended (done)
- Runner ended (done)
- Runner started
- Ready
- Runner ended (done)
- Runner started
- Awaiting response
- Awaiting response
- Runner resumed
- Runner ended (done)
- Runner ended (done)