OpenHands / OpenHands/enterprise
Allow superadmin to seed a new org via a normal (invitation-based) flow, without user-provisioning
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 4
- Forks
- 2
- Avg merge
- 1d 22h
- Merged PRs (30d)
- 101
Description
Summary
Provide a way for an instance-level superadmin to seed a newly-created organization with an initial owner/admin through a normal, invitation-based flow — without requiring the privileged POST /api/organizations/provision-user endpoint.
Background
Two recently merged PRs established the super-admin org-management model:
- OpenHands/OpenHands#14864 — adds
POST /api/organizations/provision-user(gated byUSER_PROVISIONING_ENABLED). - OpenHands/OpenHands#14937 — adds instance-level super roles. A
superadmin(user.role_id->adminrole row) holdsSUPER_ROLE_PERMISSIONS = {CREATE_ORGANIZATION, PROVISION_USER}.POST /api/organizationsnow creates the org withadd_creator_as_owner=False, so the creating superadmin is not a member of the org it just created.
Problem
After a superadmin creates an organization, there is currently no non-privileged path to add the first user to it. Tracing every caller of OrgMemberStore.add_user_to_org:
- Provisioning (
server/routes/user_provisioning.py) — only mounted whenUSER_PROVISIONING_ENABLEDis on. It mints the user, sets a server-side non-temporary password, and returns a per-user API key. This is a specialized OEM flow, not appropriate as the only seeding mechanism. - Invitation accept (
server/services/org_invitation_service.py) — requires a pending invitation. Creating an invitation needsPermission.INVITE_USER_TO_ORGANIZATION, which is held only by org-scopedowner/admin(existing members). A superadmin is neither granted invite inSUPER_ROLE_PERMISSIONSnor a member of the freshly-created org, so it cannot create an invite. A brand-new org has zero members, so there is no one to bootstrap from. - Default-org auto-add (
storage/default_org_service.py) — only targets the single globally-configured default org bootstrap; cannot target an arbitrary superadmin-created org.
Net result: if USER_PROVISIONING_ENABLED is off, a superadmin can create organizations but they are empty shells that can never be populated. The org-creation capability is effectively inert without the OEM provisioning endpoint.
Proposed solution
Allow a superadmin to seed an org through the existing invitation subsystem (normal auth: invitee logs in via Keycloak/SSO, sets their own password, accepts — no server-side credential or API-key minting). Options, roughly in order of preference:
- Grant superadmin the ability to invite into any org. Extend
require_permission(Permission.INVITE_USER_TO_ORGANIZATION)handling so a super-role satisfies it for any target org (the super-role permission check already falls back after org-scoped checks). This lets a superadmin send a normal invite to the org they created. - Optionally seed on create. Let
POST /api/organizationsaccept an initial-owner email and emit an invitation (or add-on-first-login) for that user asowner, without the superadmin itself becoming a member. - Some combination — e.g. superadmin can invite the first owner, after which the normal org-scoped owner/admin invitation flow takes over.
Whatever the approach, the goal is a seeding path that does not depend on the credential-minting provision-user endpoint, so the superadmin org-creation feature is usable on installs where OEM provisioning is intentionally disabled.
Acceptance criteria
- A
superadmincan, immediately after creating an org, cause an initialowner/adminto join that org via the standard invitation flow (self-service auth; no server-set password, no minted API key). - Works with
USER_PROVISIONING_ENABLED=false. - The superadmin does not need to become a member of the org to do this.
- Existing org-scoped permission boundaries for non-super users are unchanged.
Related
- OpenHands/OpenHands#14864
- OpenHands/OpenHands#14937
- OpenHands-Cloud PR wiring the OEM provisioning toggle for Replicated installs: OpenHands/OpenHands-Cloud#914
This issue was filed by an AI agent (OpenHands) on behalf of the user.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by tracing permission handling around POST /api/organizations and the invitation flow, then read server/routes/user_provisioning.py, server/services/org_invitation_service.py, and storage/default_org_service.py. Compare how super-role and org-scoped permissions are checked. Done means a newly created org can receive its first owner or admin through the normal invitation flow with provisioning disabled, while non-super-user boundaries remain unchanged.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- api, authorization, backend
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 45/100