Repository navigation
Conversation
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Self-host is getting real multi-organization support where only owners of the root organization, the one setup created, may create organizations. This PR turns creation on with that rule enforced by the server. Stacked on #81, which must ship and be verified in production first: an older server locks everyone out once a second organization exists.
What changed
allowUserToCreateOrganizationasksselfHostRoot().ownsRoot(user.id): theselfHostRootrecord must exist and the user's membership in that organization must have roleowner. No record, or any other role, is a refusal.init, because the library calls this option with only the user.ctx.requestwith no session is401), and API keys haveenableSessionForAPIKeys: false, so bearer keys and OAuth tokens cannot create.creatorRoledefault).Decision recorded from Lauren (relayed): root-organization owners only, not owners of any organization; an install with several organizations and no root record fails closed.
Verification
bun run check: exit 0.self-host-organization-creation.spec.ts(new), 3/3 passed on self-host:200) and is the only member, with roleowner. Refused: admin403, member403, someone invited only into the new organization403, that person after being made owner of the new organization403, anonymous401, the owner's API key as a bearer401. The denied attempts created nothing.setup: true. Setup gives200, thensetup: falseand a second setup403. Two creations follow, setup is still403, and the root record is the setup organization. After a restart setup is still403and the owner creates a fourth.403, still after a restart.Negative check: with the rule weakened to "owner of any organization", the authority scenario fails at line 135 (
expected 200 to be 403, the owner of a non-root organization).#81's scenarios and
invitation-rolesrerun on this branch: 5/5 passed.The fork CI runs only for pull requests into
v2, so it runs here once #81 merges and this is retargeted.