Skip to content

feat: add connectors permissions for Saas#1782

Merged
Wallgau merged 11 commits into
mainfrom
feat/rbac-connector-access-v2
Jun 9, 2026
Merged

feat: add connectors permissions for Saas#1782
Wallgau merged 11 commits into
mainfrom
feat/rbac-connector-access-v2

Conversation

@Wallgau

@Wallgau Wallgau commented Jun 5, 2026

Copy link
Copy Markdown
Collaborator

Introduce admin Connectors Permission settings (cloud-only) backed by workspace_config, enforce availability on connector APIs and OAuth init, and sync the new connectors:manage:access permission at startup without an Alembic migration. OSS/dev OSS brand bypasses policy; add dev role toggle and brand-aware proxy headers for local RBAC testing.

Screen.Recording.2026-06-05.at.5.13.10.PM.mov

Summary by CodeRabbit

  • New Features

    • Added developer role-switching capability for local testing environments (when dev mode is enabled)
    • Added connector access management tab in Settings to configure workspace connector availability
    • Enhanced role-based permission system for granular connector access control
  • Documentation

    • Updated configuration guide with new development-mode settings for role toggle and connector policy enforcement

Introduce admin Connectors Permission settings (cloud-only) backed by
workspace_config, enforce availability on connector APIs and OAuth init,
and sync the new connectors:manage:access permission at startup without
an Alembic migration. OSS/dev OSS brand bypasses policy; add dev role
toggle and brand-aware proxy headers for local RBAC testing.
@github-actions github-actions Bot added frontend 🟨 Issues related to the UI/UX backend 🔷 Issues related to backend services (OpenSearch, Langflow, APIs) tests enhancement 🔵 New feature or request labels Jun 5, 2026
@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

This PR integrates workspace connector-access policy enforcement and dev-role switching across backend and frontend. It adds environment toggles and cloud-context determination, enforces workspace connector availability via database policy checks in API handlers, provides admin UI to manage connector access per workspace, and enables developers to switch roles locally for testing. Frontend contexts and permission evaluation were refactored to support SaaS policy gating.

Changes

Connector policy, settings access, and dev-role controls

Layer / File(s) Summary
Policy flags and RBAC catalog foundation
.env.example, src/config/settings.py, src/db/seed.py, src/db/migrations_runtime.py, tests/unit/db/migrations/test_rbac_catalog_sync.py, tests/unit/services/test_rbac_service.py
Dev-only toggles OPENRAG_DEV_ROLE_TOGGLE and OPENRAG_DEV_CONNECTOR_POLICY are added; is_cloud_context() combines IBM auth, SaaS mode, and the connector policy toggle; RBAC catalog sync runs per-boot with connectors:manage:access permission; startup migration validates idempotent sync behavior and permission grant to admin.
Connector-access policy service
src/services/connector_access_service.py
Service loads/persists workspace connector access map, provides governable type list, validates type membership, enforces cloud-context-only policy, and filters connector metadata by enabled state.
Backend API endpoint enforcement
src/api/auth.py, src/api/connectors.py, src/app/routes/internal.py
All connector operations and auth_init now accept session dependency; request-time policy checks return 403 JSON when connector type is blocked; connector-type lists for sync operations are filtered by policy; routes /connectors/user-access GET/PUT for access management.
Connector-access enforcement tests
tests/unit/api/test_auth_init_connector_access.py, tests/unit/api/test_connectors_connector_access.py, tests/unit/services/test_connector_access_service.py
Unit tests validate service persistence/filtering, policy gating by run-mode/auth flags, and endpoint 403 short-circuit behavior when connector types are disabled.
Dev-role switching service and API
src/services/dev_role_toggle.py, src/api/users.py, src/dependencies.py, tests/unit/services/test_dev_role_toggle.py
Service swaps user built-in role membership; /me/dev-role endpoint returns updated roles and permissions; /me response adds cloud_context field; JWT role sync is bypassed when dev-role toggle is enabled; test coverage validates role replacement semantics.
Frontend brand and policy core
frontend/lib/brand.ts
New module exports Brand type, cloud classification, SaaS policy context helper, connector visibility rules, and RBAC settings tab gating predicates.
Auth and brand context updates
frontend/contexts/auth-context.tsx, frontend/contexts/brand-context.tsx, frontend/hooks/use-permissions.ts
Auth context adds cloudContext and permissionsResolved fields; brand context uses centralized helpers to compute effective brand; permission checks delegate to RBAC-aware hasRbacPermission; new useSettingsTabAccess hook builds settings access context from auth/brand state.
Connector query keys and mutations
frontend/app/api/queries/useGetConnectorsQuery.ts, frontend/app/api/mutations/useConnectConnectorMutation.ts, frontend/app/api/mutations/useDisconnectConnectorMutation.ts
Connector query key now includes cloud brand; workspace-policy filtering uses stored access map; mutations standardized to use shared snapshot/restore/update helpers; user-access query/mutation added for connector management API.
Settings tabs and connector-access UI
frontend/app/settings/[tab]/page.tsx, frontend/app/settings/_components/settings-nav.tsx, frontend/app/settings/_components/connector-access-section.tsx, frontend/app/settings/_components/connector-cards.tsx
New connector-access settings tab added; authorization switches to shared RBAC predicates; ConnectorAccessSection implements draft state, save flow, loading/error/retry; connector cards rendering aligns with SaaS policy context.
Dev-role toggle UI
frontend/components/dev-role-toggle.tsx, frontend/components/header.tsx
New DevRoleToggle component posts to /api/users/me/dev-role, refreshes permissions, invalidates connector caches, and triggers router refresh; header conditionally renders it under dev theme.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~65 minutes

Possibly related PRs

  • langflow-ai/openrag#1579: Both PRs touch the connector "browse connection files" flow: the referenced PR wires an internal route to connectors.browse_connection_files, while this PR updates the handler to enforce workspace connector access policy.
  • langflow-ai/openrag#1631: Both PRs modify frontend settings tab RBAC gating—the referenced PR removes role UI, while this PR adds the connector-access tab and updates permission-context gating logic.

Suggested reviewers

  • lucaseduoli
  • edwinjosechittilappilly
  • phact
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 41.46% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add connectors permissions for Saas' directly describes the main change: introducing connector permissions functionality for the SaaS deployment mode. It is specific, concise, and accurately reflects the changeset's primary objective.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/rbac-connector-access-v2

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.

@github-actions github-actions Bot removed the enhancement 🔵 New feature or request label Jun 5, 2026
@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 5, 2026
Comment thread src/api/auth.py Fixed
@Wallgau Wallgau changed the title feat: add SaaS workspace connector permissions with RBAC gates feat: add connectors permissions for Saas Jun 5, 2026
@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 5, 2026
@Wallgau Wallgau changed the title feat: add connectors permissions for Saas feat: add connectors permissions for Saas Jun 5, 2026
@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 5, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

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

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

1-26: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix import ordering and unused import to unblock Ruff/mypy CI.

Current import layout triggers E402, and typing.Optional is unused (F401). This is currently failing pipeline checks.

Suggested fix
-from typing import Optional
-
-from fastapi import Depends, HTTPException, Request
-from fastapi.responses import JSONResponse
-
-from utils.logging_config import get_logger
-from utils.telemetry import Category, MessageId, TelemetryClient
-from utils.version_utils import OPENRAG_VERSION
-
-logger = get_logger(__name__)
-
-from pydantic import BaseModel
-from sqlalchemy.ext.asyncio import AsyncSession
-
-from dependencies import (
+from fastapi import Depends, HTTPException, Request
+from fastapi.responses import JSONResponse
+from pydantic import BaseModel
+from sqlalchemy.ext.asyncio import AsyncSession
+
+from dependencies import (
     get_auth_service,
     get_current_user,
     get_db_session,
     get_optional_user,
 )
 from services.connector_access_service import (
     CONNECTOR_TYPES,
     is_connector_access_policy_enforced,
     is_connector_allowed_for_request,
 )
 from session_manager import User
+from utils.logging_config import get_logger
+from utils.telemetry import Category, MessageId, TelemetryClient
+from utils.version_utils import OPENRAG_VERSION
+
+logger = get_logger(__name__)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/api/auth.py` around lines 1 - 26, Reorder and clean up imports in auth
module to satisfy linters: remove the unused typing.Optional import and reorder
imports so standard library imports come first, then third-party (fastapi,
pydantic, sqlalchemy), then local project imports; ensure symbols referenced
like get_logger, OPENRAG_VERSION, BaseModel, AsyncSession, get_auth_service,
get_current_user, get_db_session, get_optional_user, CONNECTOR_TYPES,
is_connector_access_policy_enforced, is_connector_allowed_for_request, and User
remain correctly imported after the reorder to avoid E402/F401 errors.
🧹 Nitpick comments (3)
frontend/components/dev-role-toggle.tsx (1)

63-68: 💤 Low value

Consider parallelizing independent invalidations.

The invalidateQueries calls (lines 64 and 66) are independent and could run concurrently. While the current sequential approach is safe, wrapping them in Promise.all would improve perceived responsiveness.

⚡ Proposed refactor
 onSuccess: async (data) => {
   await refreshPermissions();
-  await queryClient.invalidateQueries({ queryKey: ["connectors"] });
-  await queryClient.invalidateQueries({
-    queryKey: ["connector-user-access"],
-  });
+  await Promise.all([
+    queryClient.invalidateQueries({ queryKey: ["connectors"] }),
+    queryClient.invalidateQueries({ queryKey: ["connector-user-access"] }),
+  ]);
   router.refresh();
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/components/dev-role-toggle.tsx` around lines 63 - 68, The two
independent calls to queryClient.invalidateQueries for queryKey ["connectors"]
and ["connector-user-access"] should run in parallel to reduce latency: replace
the sequential awaits with a single await
Promise.all([queryClient.invalidateQueries({ queryKey: ["connectors"] }),
queryClient.invalidateQueries({ queryKey: ["connector-user-access"] })]) while
keeping refreshPermissions awaited before and router.refresh() after,
referencing refreshPermissions, queryClient.invalidateQueries and router.refresh
to locate the changes.
src/api/users.py (1)

129-167: ⚡ Quick win

Add an explicit response model for POST /users/me/dev-role.

This endpoint returns structured JSON but doesn’t declare response_model, so schema drift won’t be caught and docs are less reliable.

Suggested refactor
+class DevRoleResponse(BaseModel):
+    roles: list[str]
+    role: str
+    permissions: list[str]
+
-@router.post("/me/dev-role")
+@router.post("/me/dev-role", response_model=DevRoleResponse)
 async def set_my_dev_role(
@@
-    return JSONResponse(
-        {
-            "roles": roles,
-            "role": body.role,
-            "permissions": sorted(perms),
-        }
-    )
+    return DevRoleResponse(
+        roles=roles,
+        role=body.role,
+        permissions=sorted(perms),
+    )

As per coding guidelines, src/api/**/*.py routes should verify response model typing.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/api/users.py` around lines 129 - 167, The endpoint set_my_dev_role should
declare an explicit Pydantic response model to keep OpenAPI/docs and schema
validation correct: create a response model (e.g., DevRoleResponse) with fields
roles: List[str], role: str, permissions: List[str] and add
response_model=DevRoleResponse to the `@router.post` decorator on set_my_dev_role;
ensure the handler returns a dict or model instance that matches that schema
(adjust the JSONResponse usage or return the model directly) and add any
necessary imports for the new DevRoleResponse type.
tests/unit/services/test_dev_role_toggle.py (1)

55-56: ⚡ Quick win

Include the "user" switch case in the parameterized test.

The feature supports switching to any built-in role; adding "user" closes the remaining branch in the happy-path matrix.

Suggested refactor
-@pytest.mark.parametrize("target", ["admin", "developer", "viewer"])
+@pytest.mark.parametrize("target", ["admin", "developer", "user", "viewer"])
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/services/test_dev_role_toggle.py` around lines 55 - 56, Update the
parameterized test decorator for test_switch_to_any_builtin_role to include the
"user" role so the test covers all built-in roles; modify the
`@pytest.mark.parametrize`("target", ["admin", "developer", "viewer"]) declaration
in test_switch_to_any_builtin_role to also contain "user" to exercise that
branch of the happy-path matrix.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/lib/fetch-server.ts`:
- Around line 15-23: The fetch currently always sends "X-OpenRAG-Brand" using
resolveBrand, causing a default header even when no brand cookie exists; change
this so you read the raw brand cookie via cookieStore.get(BRAND_COOKIE) and only
add the "X-OpenRAG-Brand" header when that cookie value is present (do not call
resolveBrand to supply a fallback), updating the headers building in the fetch
call to conditionally include the header based on the cookie existence.

In `@src/api/connectors.py`:
- Around line 33-49: The connector access policy is only enforced in some
handlers and can be bypassed via other connector routes; ensure all
connector-related endpoints call the central check _connector_access_denied (or
use a middleware/decorator that invokes it) before performing any connector
action. Update the token, browse, disconnect, preview and any other connector
route handlers to call await _connector_access_denied(request, session, user,
connector_type) and return its JSONResponse if non-None, or implement a
request-level middleware that uses is_connector_access_policy_enforced and
is_connector_allowed_for_request to reject disallowed connector_type values with
a 403; keep the existing error message format and status code when rejecting.

In `@src/services/connector_access_service.py`:
- Around line 51-59: Currently src/services/connector_access_service.py reads
IBM_AUTH_ENABLED directly via os.getenv and assigns it to ibm_auth; move this
env read into config/settings.py as a typed setting (e.g., IBM_AUTH_ENABLED:
bool or is_connector_access_policy_enforced: bool) and then replace the
os.getenv usage by importing and using that setting (referencing the ibm_auth
variable and the config setting) so connector_access_service consumes the
centralized, typed config instead of reading os.environ itself.

In `@src/services/dev_role_toggle.py`:
- Around line 49-50: rbac.invalidate is being called before the caller's write
transaction commits, allowing a race that can repopulate stale permissions; move
the invalidation to run only after the DB commit completes. Either register an
on_commit/post_commit callback from within role_repo.assign_role (or return a
token and have the caller call rbac.invalidate after commit) or use your DB
session's after_commit hook to call rbac.invalidate(db_user_id) (target.id can
remain for logging) so invalidation happens post-commit and not inside the
pre-commit window.

---

Outside diff comments:
In `@src/api/auth.py`:
- Around line 1-26: Reorder and clean up imports in auth module to satisfy
linters: remove the unused typing.Optional import and reorder imports so
standard library imports come first, then third-party (fastapi, pydantic,
sqlalchemy), then local project imports; ensure symbols referenced like
get_logger, OPENRAG_VERSION, BaseModel, AsyncSession, get_auth_service,
get_current_user, get_db_session, get_optional_user, CONNECTOR_TYPES,
is_connector_access_policy_enforced, is_connector_allowed_for_request, and User
remain correctly imported after the reorder to avoid E402/F401 errors.

---

Nitpick comments:
In `@frontend/components/dev-role-toggle.tsx`:
- Around line 63-68: The two independent calls to queryClient.invalidateQueries
for queryKey ["connectors"] and ["connector-user-access"] should run in parallel
to reduce latency: replace the sequential awaits with a single await
Promise.all([queryClient.invalidateQueries({ queryKey: ["connectors"] }),
queryClient.invalidateQueries({ queryKey: ["connector-user-access"] })]) while
keeping refreshPermissions awaited before and router.refresh() after,
referencing refreshPermissions, queryClient.invalidateQueries and router.refresh
to locate the changes.

In `@src/api/users.py`:
- Around line 129-167: The endpoint set_my_dev_role should declare an explicit
Pydantic response model to keep OpenAPI/docs and schema validation correct:
create a response model (e.g., DevRoleResponse) with fields roles: List[str],
role: str, permissions: List[str] and add response_model=DevRoleResponse to the
`@router.post` decorator on set_my_dev_role; ensure the handler returns a dict or
model instance that matches that schema (adjust the JSONResponse usage or return
the model directly) and add any necessary imports for the new DevRoleResponse
type.

In `@tests/unit/services/test_dev_role_toggle.py`:
- Around line 55-56: Update the parameterized test decorator for
test_switch_to_any_builtin_role to include the "user" role so the test covers
all built-in roles; modify the `@pytest.mark.parametrize`("target", ["admin",
"developer", "viewer"]) declaration in test_switch_to_any_builtin_role to also
contain "user" to exercise that branch of the happy-path matrix.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ea8e8b32-ff61-4d87-ac27-f4da2bc9bec1

📥 Commits

Reviewing files that changed from the base of the PR and between 6004ef2 and 128faa8.

📒 Files selected for processing (30)
  • .env.example
  • frontend/app/api/[...path]/route.ts
  • frontend/app/api/mutations/useUpdateConnectorAccessMutation.ts
  • frontend/app/api/queries/useGetConnectorAccessQuery.ts
  • frontend/app/api/queries/useGetConnectorsQuery.ts
  • frontend/app/settings/[tab]/page.tsx
  • frontend/app/settings/_components/connector-access-section.tsx
  • frontend/app/settings/_components/settings-nav.tsx
  • frontend/components/dev-role-toggle.tsx
  • frontend/components/header.tsx
  • frontend/contexts/auth-context.tsx
  • frontend/contexts/brand-context.tsx
  • frontend/lib/brand.ts
  • frontend/lib/fetch-server.ts
  • frontend/lib/settings-tab-access.ts
  • src/api/auth.py
  • src/api/connectors.py
  • src/api/users.py
  • src/app/routes/internal.py
  • src/config/settings.py
  • src/db/migrations_runtime.py
  • src/db/seed.py
  • src/dependencies.py
  • src/services/connector_access_service.py
  • src/services/dev_role_toggle.py
  • tests/unit/api/test_auth_init_connector_access.py
  • tests/unit/db/migrations/test_rbac_catalog_sync.py
  • tests/unit/services/test_connector_access_service.py
  • tests/unit/services/test_dev_role_toggle.py
  • tests/unit/services/test_rbac_service.py

Comment thread frontend/lib/fetch-server.ts Outdated
Comment thread src/api/connectors.py
Comment thread src/services/connector_access_service.py Outdated
Comment thread src/services/dev_role_toggle.py Outdated
@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 5, 2026
Comment thread frontend/app/api/[...path]/route.ts Outdated
Comment on lines +103 to +107
const brand = request.cookies.get(BRAND_COOKIE)?.value;
if (brand === "oss" || brand === "ibm") {
headers.set("X-OpenRAG-Brand", brand);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

why are we setting a new cookie for this?

Comment thread src/api/connectors.py Outdated
# Connector type not found or validation not needed
pass

if denied := await _connector_access_denied(request, session, connector_type):

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This check is happening after the handle_webhook_validation it should be before

@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 9, 2026
Add admin Connectors Permission (workspace_config-backed) with RBAC
connectors:manage:access, enforce policy on connector APIs and OAuth init,
and keep the permission list independent of the live connectors tab.
Consolidate frontend connector-access hooks into useGetConnectorsQuery and
settings tab helpers into brand.ts. Fix Connectors Permission tab redirects
(RSC dev-brand default, wait for permissionsResolved). Let explicitly
enabled connectors override deployment visibility filters; add
OPENRAG_DEV_CONNECTOR_POLICY for local OSS dev backend enforcement Snapshot and restore all cached connector query keys in connect/disconnect
mutations so optimistic updates stay correct when policy context changes
mid-mutation (brand toggle, permissions resolving).
@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 9, 2026
@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 9, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 2

Caution

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

⚠️ Outside diff range comments (1)
frontend/app/settings/_components/connector-cards.tsx (1)

33-36: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Don't collapse fetch failures into the SaaS "not authorized" empty state.

queryConnectors defaults to [], so when useGetConnectorsQuery errors this branch still renders “No connectors available or authorized…”. A transient /api/connectors failure will look like a policy denial instead of a load error.

💡 Minimal fix
-  const { data: queryConnectors = [], isLoading: connectorsLoading } =
+  const {
+    data: queryConnectors = [],
+    isLoading: connectorsLoading,
+    isError: connectorsError,
+  } =
     useGetConnectorsQuery({
       enabled: isAuthenticated || isNoAuthMode,
     });
@@
-  if (!connectorsLoading && connectors.length === 0) {
+  if (!connectorsLoading && !connectorsError && connectors.length === 0) {
     if (isSaasPolicy) {
       return (
         <p className="text-sm text-muted-foreground">
           No connectors available or authorized for your organization.
         </p>
       );
     }

Also applies to: 82-89

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@frontend/app/settings/_components/connector-cards.tsx` around lines 33 - 36,
The component collapses fetch failures into the "not authorized" empty state
because data is defaulted to []; remove the default assignment from the
useGetConnectorsQuery destructure (do not set data: queryConnectors = []) and
instead use the hook's isError/error flags to distinguish failure from an empty
list: when useGetConnectorsQuery reports isError (or error) show a load-error
UI/message, when !connectorsLoading and data is an empty array show the "no
connectors or authorized" message; apply the same change to the other occurrence
that uses useGetConnectorsQuery (the block around where queryConnectors is read
again).
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@frontend/app/settings/_components/settings-nav.tsx`:
- Around line 57-68: The redirect effect (useEffect) currently only reacts to
tabIsVisible and fallbackTab so navigating between two hidden tabs can leave the
effect stale; include the routed-tab identifier in the dependency array (the
variable that represents the current route tab — e.g., the routed tab value or
route.query.tab / currentTab) so the effect reruns when the user navigates to a
different routed tab; update the dependency list that includes isLoading,
permissionsResolved, tabIsVisible, fallbackTab, visibleTabKey, router to also
include the routed-tab variable (or replace visibleTabKey with the actual
routed-tab variable if visibleTabKey isn't the routed value) so
router.replace(`/settings/${fallbackTab}`) fires correctly.

In `@tests/unit/api/test_connectors_connector_access.py`:
- Around line 45-54: The test fixtures _FakeRequest and _FakeWebhookRequest
currently define mutable dicts as class attributes (headers, query_params) which
can be shared across tests; change them to per-instance attributes by adding
__init__ constructors that assign fresh dicts to self.headers and
self.query_params (and keep method as an instance attribute for
_FakeWebhookRequest if needed) so each test gets its own independent dicts and
mutations cannot leak between tests.

---

Outside diff comments:
In `@frontend/app/settings/_components/connector-cards.tsx`:
- Around line 33-36: The component collapses fetch failures into the "not
authorized" empty state because data is defaulted to []; remove the default
assignment from the useGetConnectorsQuery destructure (do not set data:
queryConnectors = []) and instead use the hook's isError/error flags to
distinguish failure from an empty list: when useGetConnectorsQuery reports
isError (or error) show a load-error UI/message, when !connectorsLoading and
data is an empty array show the "no connectors or authorized" message; apply the
same change to the other occurrence that uses useGetConnectorsQuery (the block
around where queryConnectors is read again).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 54675c31-3697-4a56-b4b7-50e405c5a6e1

📥 Commits

Reviewing files that changed from the base of the PR and between 10a7d41 and 93cb6e8.

📒 Files selected for processing (26)
  • .env.example
  • frontend/app/api/mutations/useConnectConnectorMutation.ts
  • frontend/app/api/mutations/useDisconnectConnectorMutation.ts
  • frontend/app/api/queries/useGetConnectorsQuery.ts
  • frontend/app/settings/[tab]/page.tsx
  • frontend/app/settings/_components/connector-access-section.tsx
  • frontend/app/settings/_components/connector-card.tsx
  • frontend/app/settings/_components/connector-cards.tsx
  • frontend/app/settings/_components/settings-nav.tsx
  • frontend/components/dev-role-toggle.tsx
  • frontend/contexts/auth-context.tsx
  • frontend/contexts/brand-context.tsx
  • frontend/hooks/use-permissions.ts
  • frontend/lib/brand.ts
  • src/api/auth.py
  • src/api/connectors.py
  • src/api/users.py
  • src/app/routes/internal.py
  • src/config/settings.py
  • src/dependencies.py
  • src/services/connector_access_service.py
  • src/services/dev_role_toggle.py
  • tests/unit/api/test_auth_init_connector_access.py
  • tests/unit/api/test_connectors_connector_access.py
  • tests/unit/services/test_connector_access_service.py
  • tests/unit/services/test_dev_role_toggle.py
💤 Files with no reviewable changes (3)
  • src/dependencies.py
  • src/services/dev_role_toggle.py
  • tests/unit/services/test_dev_role_toggle.py
✅ Files skipped from review due to trivial changes (1)
  • frontend/app/settings/_components/connector-card.tsx
🚧 Files skipped from review as they are similar to previous changes (6)
  • tests/unit/api/test_auth_init_connector_access.py
  • src/app/routes/internal.py
  • src/api/auth.py
  • src/api/users.py
  • frontend/components/dev-role-toggle.tsx
  • src/api/connectors.py

Comment thread frontend/app/settings/_components/settings-nav.tsx
Comment thread tests/unit/api/test_connectors_connector_access.py
@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 9, 2026
@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 9, 2026
Comment thread .env.example Outdated
Comment on lines +365 to +373
# Local/dev only: enables POST /users/me/dev-role and the header role toggle
# (pair with NEXT_PUBLIC_IBM_THEME_DEV=true). Never enable in production.
# OPENRAG_DEV_ROLE_TOGGLE=true

# Local OSS dev: enforce workspace connector policy on the backend (pair with
# NEXT_PUBLIC_IBM_THEME_DEV=true). Without this, the UI filters connectors but
# connect/OAuth routes ignore Connectors Permission until run mode is saas.
# OPENRAG_DEV_CONNECTOR_POLICY=true

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Let's avoid putting mentions of dev only envs in the env.example especially for anything IBM specific

@github-actions github-actions Bot added the lgtm label Jun 9, 2026
@github-actions github-actions Bot added enhancement 🔵 New feature or request and removed enhancement 🔵 New feature or request labels Jun 9, 2026
@Wallgau Wallgau merged commit 499a2c5 into main Jun 9, 2026
19 checks passed
@github-actions github-actions Bot deleted the feat/rbac-connector-access-v2 branch June 9, 2026 18:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

backend 🔷 Issues related to backend services (OpenSearch, Langflow, APIs) enhancement 🔵 New feature or request frontend 🟨 Issues related to the UI/UX lgtm tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants