Skip to content

[fix] Resolve broken oss invites from non-default projects#4461

Open
junaway wants to merge 3 commits into
mainfrom
fix/broken-invitations-in-oss
Open

[fix] Resolve broken oss invites from non-default projects#4461
junaway wants to merge 3 commits into
mainfrom
fix/broken-invitations-in-oss

Conversation

@junaway
Copy link
Copy Markdown
Contributor

@junaway junaway commented May 27, 2026

Resolves this issue.

Copilot AI review requested due to automatic review settings May 27, 2026 12:26
@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label May 27, 2026
@vercel
Copy link
Copy Markdown

vercel Bot commented May 27, 2026

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

Project Deployment Actions Updated (UTC)
agenta-documentation Ready Ready Preview, Comment May 27, 2026 12:28pm

Request Review

@dosubot dosubot Bot added the bug Something isn't working label May 27, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 27, 2026

Review Change Stack

📝 Walkthrough

Summary by CodeRabbit

  • New Features

    • Organization invitations now operate at the organization level, improving invitation management workflow.
  • Bug Fixes

    • Improved error handling for organization invitations when a default project is not configured.
  • Chores

    • Version bumped to 0.100.4 across all packages and manifests.

Walkthrough

This pull request refactors organization-level invitation handling to operate independently of project context, adding organization-scoped database queries and validators, and updating router endpoints and service logic to use these new organization-level lookups. Additionally, it bumps the version to 0.100.4 across all packages and manifests.

Changes

Organization-scoped invitation refactor

Layer / File(s) Summary
Organization-scoped invitation data access
api/oss/src/services/db_manager.py
New functions get_project_invitation_by_organization_and_email and get_project_invitation_by_organization_token_and_email query invitations by organization/email across projects; check_if_user_invitation_exists and user-assignment logic updated to use organization-based lookups instead of project-specific filtering.
Organization-scoped invitation validation
api/oss/src/services/organization_service.py
New functions check_existing_organization_invitation and check_valid_organization_invitation validate invitations at organization level; invite_user_to_organization and resend_user_organization_invite accept optional organization_id parameter to switch to organization-scoped logic; accept_organization_invitation validates using organization-scoped helper instead of resolving default projects.
Router endpoints resolve default project and invoke updated service
api/oss/src/routers/organization_router.py
invite_user_to_organization and resend_user_invitation_to_organization now look up organization default project, return 400 if missing, and pass resolved project_id to updated service calls instead of using request.state.project_id.

Version bump across monorepo

Layer / File(s) Summary
Version updates in package manifests and Helm chart
api/pyproject.toml, clients/python/pyproject.toml, hosting/kubernetes/helm/Chart.yaml, sdks/python/pyproject.toml, services/pyproject.toml, web/ee/package.json, web/oss/package.json, web/package.json, web/packages/agenta-api-client/package.json
All version fields updated from 0.100.3 to 0.100.4 across API, client, SDK, service, and web packages, plus Helm chart version and appVersion.

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically describes the main change: fixing broken OSS user invitations when projects are non-default.
Description check ✅ Passed The description references a specific GitHub issue, which is related to the changeset about fixing broken invitations.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% 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.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/broken-invitations-in-oss

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.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR addresses OSS organization invitation handling so invites can be accepted regardless of the project active when they were created, alongside a patch version bump to 0.100.4.

Changes:

  • Adds organization-wide invitation lookup/validation paths for OSS invite flows.
  • Updates OSS invite/resend routes to use the organization’s default project when creating links.
  • Bumps package, Python project, lockfile, and Helm chart versions.

Reviewed changes

Copilot reviewed 12 out of 16 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
api/oss/src/services/organization_service.py Adds organization-scoped invitation checks and acceptance logic.
api/oss/src/services/db_manager.py Adds organization-scoped invitation queries and updates signup assignment lookup.
api/oss/src/routers/organization_router.py Routes OSS invite/resend through the organization default project.
api/pyproject.toml Bumps API package version.
api/uv.lock Updates locked API/service-related package versions.
clients/python/pyproject.toml Bumps Python client version.
clients/python/uv.lock Updates locked Python client version.
hosting/kubernetes/helm/Chart.yaml Bumps Helm chart and app version.
sdks/python/pyproject.toml Bumps Python SDK version.
sdks/python/uv.lock Updates locked SDK/client versions.
services/pyproject.toml Bumps services package version.
services/uv.lock Updates locked services/SDK/client versions.
web/package.json Bumps web workspace version.
web/ee/package.json Bumps EE web package version.
web/oss/package.json Bumps OSS web package version.
web/packages/agenta-api-client/package.json Bumps generated API client package version.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +467 to 472
select(InvitationDB)
.join(ProjectDB, InvitationDB.project_id == ProjectDB.id)
.where(
InvitationDB.email == email,
ProjectDB.organization_id == uuid.UUID(organization_id),
)
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3


ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3523b83d-1847-4322-be7d-ebecfdb9b6d3

📥 Commits

Reviewing files that changed from the base of the PR and between fec4391 and ee558c6.

⛔ Files ignored due to path filters (4)
  • api/uv.lock is excluded by !**/*.lock
  • clients/python/uv.lock is excluded by !**/*.lock
  • sdks/python/uv.lock is excluded by !**/*.lock
  • services/uv.lock is excluded by !**/*.lock
📒 Files selected for processing (12)
  • api/oss/src/routers/organization_router.py
  • api/oss/src/services/db_manager.py
  • api/oss/src/services/organization_service.py
  • api/pyproject.toml
  • clients/python/pyproject.toml
  • hosting/kubernetes/helm/Chart.yaml
  • sdks/python/pyproject.toml
  • services/pyproject.toml
  • web/ee/package.json
  • web/oss/package.json
  • web/package.json
  • web/packages/agenta-api-client/package.json

Comment on lines +276 to +278
project_db = await db_manager.get_default_project_by_organization_id(
organization_id=organization_id
)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion | 🟠 Major | ⚡ Quick win

Keep router-to-service boundary; move default-project lookup into service layer.

The router now directly depends on db_manager for default-project resolution. Please shift this lookup into organization_service and keep the router calling service-only entrypoints.

As per coding guidelines: "Dependency direction for API layers must be: Router -> Service -> DAO Interface -> DAO Implementation -> DB."

Also applies to: 351-353

Comment on lines +1371 to +1374
async def get_project_invitation_by_organization_and_email(
organization_id: str,
email: str,
) -> InvitationDB:
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Return type should be optional for nullable invitation lookups.

Both helpers can return None (.first()), but the signatures declare InvitationDB. This weakens type contracts and can mislead callers.

Suggested fix
-async def get_project_invitation_by_organization_and_email(
+async def get_project_invitation_by_organization_and_email(
     organization_id: str,
     email: str,
-) -> InvitationDB:
+) -> Optional[InvitationDB]:
-async def get_project_invitation_by_organization_token_and_email(
+async def get_project_invitation_by_organization_token_and_email(
     organization_id: str,
     token: str,
     email: str,
-) -> InvitationDB:
+) -> Optional[InvitationDB]:

As per coding guidelines: "Use Optional[DTO] for missing entities, List[DTO] for collections."

Also applies to: 1563-1567

Comment on lines +109 to +114
if invitation is not None and invitation.expiration_date > datetime.now(
timezone.utc
):
return invitation

return None
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Reject already-used invitations during org-scoped validation.

check_valid_organization_invitation treats a used invitation as valid if it has not expired. This makes invitation acceptance replayable until expiry.

Suggested fix
-    if invitation is not None and invitation.expiration_date > datetime.now(
+    if (
+        invitation is not None
+        and not invitation.used
+        and invitation.expiration_date > datetime.now(
         timezone.utc
-    ):
+    )):
         return invitation

@github-actions
Copy link
Copy Markdown
Contributor

Railway Preview Environment

Preview URL https://gateway-production-9146.up.railway.app/w
Image tag pr-4461-26b9a79
Status Failed
Railway logs Open logs
Logs View workflow run
Updated at 2026-05-27T12:35:27.082Z

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working size:L This PR changes 100-499 lines, ignoring generated files.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Self-hosted OSS invitations depend on active project and fail unless created from the default project

3 participants