Skip to content

feat(api): Sweep remaining single-org assumptions in OSS#4675

Open
jp-agenta wants to merge 5 commits into
feat/oss-org-creationfrom
feat/oss-singleton-sweep
Open

feat(api): Sweep remaining single-org assumptions in OSS#4675
jp-agenta wants to merge 5 commits into
feat/oss-org-creationfrom
feat/oss-singleton-sweep

Conversation

@jp-agenta

@jp-agenta jp-agenta commented Jun 12, 2026

Copy link
Copy Markdown
Member

Context

After the org-creation PR (#4673), OSS can have multiple organizations, but several code paths still assume exactly one: bare-API-key auth resolves "the" workspace by picking the oldest row, organization/workspace listings return everything in the database instead of the user's memberships, the admin API refuses to delete the legacy oss-default org, and the web sidebar keeps the org switcher disabled outside EE. Sequencing step 4 of the convergence plan.

Changes

API:

  • get_default_workspace_id(user_id) (workspace owned by the user, falling back to their oldest membership) moves from db_manager_ee to OSS db_manager; the is_ee() fork in the auth middleware's bare-key path collapses to one call. The OSS-only get_default_workspace_id_oss() (oldest workspace in the whole DB) and get_oss_organization() are deleted.
  • GET /organizations/ (OSS branch) now lists the requesting user's organizations via the membership join, with each org's workspaces attached, instead of all orgs plus the first workspace in the database. GET /organizations/{id} scopes its workspace and invitation lookups to the requested org rather than request.state.project_id. GET /workspaces/ returns the user's workspaces instead of all of them.
  • Admin API: the oss-default singleton guards are gone (the legacy org is a normal org now; deleting it follows EE semantics), and admin_create_organization always inserts a new row instead of collapsing onto the singleton slug in OSS.

Web (ListOfOrgs.tsx): organization selection is enabled in OSS, the "New organization" item and the owner submenu (transfer/rename/delete) are no longer EE-gated, and the label shows the selected organization's name instead of the hard-coded "Agenta". The Organization settings tab stays EE-gated (its content is domain verification and SSO, which remain EE features).

Tests / notes

  • ruff format and ruff check pass; the edited component passes prettier and introduces no tsc errors.
  • The get_default_workspace_id unit tests move to oss/tests/pytest/unit/services/test_db_manager.py (the function moved OSS-ward, so patching db_manager_ee's engine no longer reached it). The admin org create/delete round-trip returns to the OSS acceptance suite now that the singleton delete guard is gone.
  • Playwright auth bootstrap unified: OSS no longer does the owner-signup + invite + re-login dance; both editions sign up a fresh user directly. AGENTA_TEST_OSS_OWNER_EMAIL remains as an optional fixed-account login for persistent CI deployments.
  • Admin membership delete/swap endpoints stay EE-gated; they were not part of the singleton sweep and can be ungated separately if OSS needs them.
  • Stacked on feat(api): Add OSS org-creation path and EE-shaped signup flow #4673.

What to QA

  • OSS with two orgs (create one via the sidebar): the org switcher lists both, switching works, and each org's sidebar shows only its own workspaces and members.
  • Authenticate with a bare API key (no project/workspace query params): requests resolve to the key owner's workspace, not the deployment's oldest workspace.
  • As org owner, rename / transfer / delete an org from the sidebar submenu in OSS.
  • Regression: a user invited into someone else's org sees that org in the switcher alongside their own.

🤖 Generated with Claude Code

@vercel

vercel Bot commented Jun 12, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview, Comment Jun 14, 2026 6:39pm

Request Review

@coderabbitai

coderabbitai Bot commented Jun 12, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9ca80d2f-cd12-4d17-898b-988f0a33440e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(api): Sweep remaining single-org assumptions in OSS' clearly and accurately summarizes the main objective—removing remaining single-organization assumptions from the OSS edition.
Docstring Coverage ✅ Passed Docstring coverage is 90.91% which is sufficient. The required threshold is 60.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Description check ✅ Passed The PR description clearly relates to the changeset, detailing removal of single-org assumptions and refactoring workspace/organization resolution across API and web components.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/oss-singleton-sweep

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Jun 12, 2026
@dosubot dosubot Bot added Backend enhancement New feature or request Frontend labels Jun 12, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (3)
api/oss/src/middlewares/auth.py (1)

626-691: ⚠️ Potential issue | 🔴 Critical | ⚡ Quick win

Enforce explicit-scope membership checks in OSS too.

The project_member_exists / workspace_member_exists gate still only runs under is_ee(). After removing OSS singleton assumptions, any authenticated OSS user can pass another organization's project_id or workspace_id in the query string and this middleware will mint a scoped secret token without proving membership in that resource.

api/oss/src/routers/organization_router.py (1)

76-110: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Populate workspaces_by_org before serializing the EE response.

This branch initializes workspaces_by_org = {} and never fills it, so every EE organization now returns workspaces: []. Any client code that relies on Organization.workspaces to keep org/workspace selection in sync loses that relationship.

api/oss/src/routers/workspace_router.py (1)

164-168: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Use the route's workspace_id for OSS removals.

The OSS branch ignores the path parameter and forwards request.state.project_id to db_manager.remove_user_from_workspace(). After this PR, callers can target a different workspace than their ambient auth scope, so /workspaces/{workspace_id}/users/ can remove memberships/invitations from the wrong workspace context.


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: fda5621b-f8ce-4759-949b-2ed3c92035e4

📥 Commits

Reviewing files that changed from the base of the PR and between 0c8a441 and ab96500.

📒 Files selected for processing (7)
  • api/ee/src/services/db_manager_ee.py
  • api/oss/src/core/accounts/service.py
  • api/oss/src/middlewares/auth.py
  • api/oss/src/routers/organization_router.py
  • api/oss/src/routers/workspace_router.py
  • api/oss/src/services/db_manager.py
  • web/oss/src/components/Sidebar/components/ListOfOrgs.tsx
💤 Files with no reviewable changes (1)
  • api/oss/src/core/accounts/service.py

Comment thread api/oss/src/routers/organization_router.py
Comment thread api/oss/src/services/db_manager.py
Comment thread web/oss/src/components/Sidebar/components/ListOfOrgs.tsx Outdated
@github-actions

github-actions Bot commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Railway Preview Environment

Preview URL https://gateway-production-6bf6.up.railway.app/w
Image tag pr-4675-8fae8fc
Status Failed
Railway logs Open logs
Logs View workflow run
Updated at 2026-06-14T18:46:07.991Z

@junaway junaway force-pushed the feat/oss-singleton-sweep branch from ab96500 to 96c348b Compare June 12, 2026 13:50
@junaway junaway force-pushed the feat/oss-org-creation branch from 042bffd to c4da60a Compare June 12, 2026 15:39
@junaway junaway force-pushed the feat/oss-singleton-sweep branch from b6d4a7d to dcb998f Compare June 12, 2026 15:40
@junaway junaway force-pushed the feat/oss-org-creation branch from c4da60a to 8492cc4 Compare June 12, 2026 17:59
@junaway junaway force-pushed the feat/oss-singleton-sweep branch from dcb998f to 91d979d Compare June 12, 2026 18:00
@junaway junaway force-pushed the feat/oss-org-creation branch from 58a009f to 8492cc4 Compare June 14, 2026 13:03
@junaway junaway force-pushed the feat/oss-singleton-sweep branch from 4356253 to 91d979d Compare June 14, 2026 13:03
@junaway junaway force-pushed the feat/oss-org-creation branch from 8492cc4 to 83c2f59 Compare June 14, 2026 13:24
@junaway junaway force-pushed the feat/oss-singleton-sweep branch from 91d979d to 13535b9 Compare June 14, 2026 13:25
@junaway junaway force-pushed the feat/oss-org-creation branch from 83c2f59 to bc9a071 Compare June 14, 2026 17:13
@junaway junaway force-pushed the feat/oss-singleton-sweep branch from 8b4094e to 1a31273 Compare June 14, 2026 17:13
@junaway junaway force-pushed the feat/oss-singleton-sweep branch from 1a31273 to 7a49b6e Compare June 14, 2026 18:01
jp-agenta and others added 4 commits June 14, 2026 20:07
Default workspace resolution becomes membership-based in both editions
(get_default_workspace_id moves OSS-ward; the OSS oldest-workspace fallback
and get_oss_organization are gone). Organization and workspace listings are
scoped to the requesting user's memberships. The admin singleton org/workspace
delete guards and the admin_create_organization ON CONFLICT branch are
removed. Web: org switcher, New Organization, and owner submenu are enabled
in OSS.
…d-trip

The workspace-resolution unit tests move to the OSS suite (the function moved
OSS-ward; patching db_manager_ee's engine no longer reaches it). The admin
org create/delete round-trip returns to the OSS acceptance suite now that the
singleton slug-collapse and delete guard are gone.
OSS no longer needs the owner-signup + invite + re-login dance: any user can
sign up directly and gets their own organization, same as EE. global-setup
drops the license fork and inviteOssUser; AGENTA_TEST_OSS_OWNER_EMAIL stays
as an optional fixed-account login for persistent CI deployments.
The api-key auth path sets request.state.user_id to the user's DB id
(api_key.created_by_id), but get_user only matched UserDB.id when is_ee().
In OSS the new user-facing POST /organizations/ resolved the api-key user
via get_user and 404'd. Apply the id fallback in both editions, guarded so
a non-UUID SuperTokens uid still matches on uid only.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Backend enhancement New feature or request Frontend size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant