Skip to content

Offer organization creation in the self-host switcher to root owners - #84

Merged
shuv1337 merged 5 commits into
v2from
feat/selfhost-multi-org-ui
Nov 9, 2026
Merged

shuv1337 merged 5 commits into
v2from
feat/selfhost-multi-org-ui

Conversation

@shuv1337

@shuv1337 shuv1337 commented Nov 5, 2026

Copy link
Copy Markdown
Owner

Why

Self-host is getting real multi-organization support with owner-only creation. The dashboard's organization switcher should offer "Create organization" to exactly the people the server lets create, the root organization's owners, and switching should show each organization its own data. Stacked on #83. This is the top of the stack, so its selection below covers every layer.

What changed

  • GET /api/auth/self-host/capabilities (session only) returns { createOrganization } from the same ownsRoot check the create endpoint applies. Bearer callers and anonymous callers get 401.
  • organizationCreationAtom (browser only) reads it. The self-host org layout passes allowCreateOrganization as true only on a successful true, and it stays false while loading, after a failure and during server rendering. The action sits inside the closed switcher menu, so nothing shifts when it appears.
  • The entry page keeps allowCreate={false}: on self-host, someone with no organization cannot hold a session.

Verification

bun run check: exit 0.

self-host-organization-switcher.spec.ts (new), passed:

  • The owner's capabilities answer is true. The owner creates "Second team" from the switcher and lands on /org/second-team/apps, which lists none of the root's apps. Switching back shows the root's app.
  • The admin's answer is false. The admin's switcher lists one organization and no create action.

Negative check: forcing the action on makes the scenario fail on the admin ([1, 1] instead of [1, 0]).

Whole stack, run on this branch: 31/31 selected self-host scenarios passed. That covers every new or changed spec, the invitation, onboarding and password login scenarios, and the dashboard read-count and batch scenarios, which could see the new read. The fork CI security scenarios: 5/5 passed.

self-host-organization-switcher.spec.ts
self-host-organization-creation.spec.ts
self-host-many-organizations.spec.ts
self-host-sso.spec.ts
resource-isolation.spec.ts
groups.spec.ts
pat-mcp.spec.ts
dashboard-batch-isolation.spec.ts
invitation-redemption.spec.ts
invitation-roles.spec.ts
invitation-reaccept.spec.ts
invitation-security.spec.ts
invitation-dialog.spec.ts
self-host-onboarding.spec.ts
hosted.spec.ts
dashboard-request-volume.spec.ts
dashboard-read-batches.spec.ts
query-refresh.spec.ts

shuv1337 and others added 4 commits November 5, 2026 15:30
A self-host database refused every sign-in, invitation and SSO login once it
held a second organization, because each path required exactly one. Sessions
now need a membership in any organization, an invitation admits into its own
organization, and SSO signs in only people who already belong to one: it no
longer adds a verified, approved address to the instance's organization.

Setup records the organization it creates as the instance's root in a new
selfHostRoot table. The private_self_host_migrations step 1_root_organization
records an existing install's root when it has exactly one organization and
leaves it unset otherwise. Organization creation remains disabled.

Co-authored-by: Cursor <cursoragent@cursor.com>
Better Auth's create endpoint now asks whether the signed-in user owns the
root organization that setup recorded. Admins, members, people outside the
root, owners of other organizations, anonymous callers and bearer keys are
refused, and an install with no root record refuses everyone. The creator
becomes the new organization's owner.

Co-authored-by: Cursor <cursoragent@cursor.com>
Self-host can now hold several organizations, so the scenarios proving that
apps, accounts, connections, groups, grants, dashboard batches and PAT MCP
calls stay inside their organization run there too. Self-host cannot remove
organizations, so those scenarios remove theirs only on Cloud; each self-host
scenario's server is discarded. The batch scenario's own organization is
created by the root owner, who invites the member as an administrator.

Co-authored-by: Cursor <cursoragent@cursor.com>
A signed-in user's GET /api/auth/self-host/capabilities answers whether they
may create organizations, from the same root-owner check the create endpoint
applies. The self-host switcher shows Create organization only when it says
so; the server still refuses everyone else.

Co-authored-by: Cursor <cursoragent@cursor.com>
@shuv1337
shuv1337 changed the base branch from feat/selfhost-multi-org-isolation to v2 November 9, 2026 04:38
@shuv1337
shuv1337 merged commit 0956ab2 into v2 Nov 9, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant