Skip to content

fix(authz): support scoped project visibility - #14429

Merged
erichare merged 4 commits into
release-1.12.0from
fix/project-owner-labels
Aug 6, 2026
Merged

fix(authz): support scoped project visibility#14429
erichare merged 4 commits into
release-1.12.0from
fix/project-owner-labels

Conversation

@erichare

@erichare erichare commented Aug 5, 2026

Copy link
Copy Markdown
Member

Summary

  • Return project owner metadata from the project-list endpoint and qualify foreign project labels in the UI while preserving canonical names for mutations.
  • Add a compact, project-backed visibility scope for logical workspaces whose stored workspace_id is null, with SQL/in-memory parity and reserved-project exclusions.
  • Require provider-specific visible deployment evidence before relaxing deployment-provider account lookup, preserving UUID privacy.

Validation

  • 135 passed, 1 skipped across project, authorization visibility/guard, and deployment prefilter/route regressions.
  • 19 passed across the four focused frontend suites.
  • Ruff, Biome, pre-commit, detect-secrets, and git diff --check pass.

Summary by CodeRabbit

  • New Features
    • Project listings now show owner information and identify projects you own.
    • Project names are clearer when viewing projects owned by others, including duplicate names.
    • Project selection now prioritizes your own matching project.
  • Bug Fixes
    • Project renaming now targets the correct project and is restricted to projects you can edit.
    • Improved visibility handling for workspace and project resources.
    • Unauthorized shared deployment access is masked to prevent revealing whether a provider exists.
  • Tests
    • Expanded coverage for project ownership, visibility, naming, and authorization scenarios.

@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: eb57e764-cfec-49ee-840d-8f95e8c580b1

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

Walkthrough

The change adds scoped visibility rules and provider authorization checks. Project listings now include ownership metadata. Frontend project labels, default selection, and rename behavior use project IDs, owner-qualified names, and write permissions.

Changes

Visibility and project ownership

Layer / File(s) Summary
Visibility scope rules
src/lfx/..., src/backend/base/langflow/services/authorization/listing.py, src/backend/tests/unit/services/authorization/*
Visibility scopes now support unassigned workspaces and excluded workspace projects. SQL and in-memory checks apply matching rules.
Provider deployment authorization
src/backend/base/langflow/api/v1/deployments.py, src/backend/base/langflow/services/database/models/deployment/crud.py, src/backend/tests/unit/api/v1/test_deployment_route_handlers.py, src/backend/tests/unit/services/database/test_deployment_crud_authz_prefilter.py
Shared provider lookup requires a visible deployment. Unauthorized shared-provider access returns 404.
Owner-qualified project listings
src/backend/base/langflow/api/v1/projects.py, src/backend/base/langflow/services/database/models/folder/model.py, src/backend/tests/unit/api/v1/test_projects.py, .secrets.baseline
Project responses now include owner_username and is_owner. The secrets baseline records the shifted test line and new timestamp.
Project display and default selection
src/frontend/src/pages/MainPage/entities/index.tsx, src/frontend/src/utils/project-display-name.ts, src/frontend/src/controllers/API/queries/folders/use-get-folders.ts, src/frontend/src/pages/MainPage/pages/homePage/*, src/frontend/src/utils/__tests__/*
Frontend project types and utilities select owned defaults and format foreign project names with owner metadata.
Sidebar identity and rename permissions
src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/*, src/frontend/src/components/core/appHeaderComponent/components/FlowMenu/*
Sidebar state, keys, labels, and edit controls use project IDs. Rename actions require write permission. Tests cover duplicate names and foreign projects.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant deployments.py
  participant has_visible_deployment_for_provider
  participant DeploymentDatabase
  Client->>deployments.py: request deployment listing
  deployments.py->>has_visible_deployment_for_provider: verify provider visibility
  has_visible_deployment_for_provider->>DeploymentDatabase: apply provider and visibility scope
  DeploymentDatabase-->>has_visible_deployment_for_provider: visibility result
  has_visible_deployment_for_provider-->>deployments.py: visible or not visible
  deployments.py->>DeploymentDatabase: resolve provider and authorize READ
  DeploymentDatabase-->>deployments.py: deployments or authorization failure
  deployments.py-->>Client: deployment list or 404
Loading

Suggested labels: bug

Suggested reviewers: hzarashid, viktoravelino

🚥 Pre-merge checks | ✅ 5 | ❌ 4

❌ Failed checks (4 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.37% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Test Quality And Coverage ⚠️ Warning Coverage is broad, but SelectOptions and InputEditFolderName are not directly tested, and project-list tests cover success only; the sidebar test mocks InputEditFolderName. Add focused Jest tests for SelectOptions labels/IDs and InputEditFolderName ID-based editing, plus an error-response test for GET /api/v1/projects/.
Test File Naming And Structure ⚠️ Warning Backend tests use pytest, but all changed frontend tests use Jest/@testing-library; FlowMenu.spec.tsx also violates the required *.test.ts(x) naming and no changed test uses Playwright. Rename FlowMenu.spec.tsx to a *.test.tsx file and convert or relocate the changed frontend coverage to Playwright tests under the frontend Playwright test tree.
Excessive Mock Usage Warning ⚠️ Warning The new HomePage test uses 21 module mocks for two tests and replaces internal Header, MCP, store, query, and child components; the sidebar test also replaces InputEditFolderName. Reduce mocks to external boundaries, keep real Header and rename components, and add an integration-level test for project display and rename behavior.
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Test Coverage For New Implementations ✅ Passed The PR adds focused backend route, database, SQL/in-memory authorization, and project-list tests, plus frontend utility and component tests for labels, ownership, permissions, and ID-based renaming.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the pull request's primary change: support for scoped project visibility and authorization.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/project-owner-labels

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.

@github-actions github-actions Bot added the bug Something isn't working label Aug 5, 2026
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Migration Validation Passed

All migrations follow the Expand-Contract pattern correctly.

@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

✅ Test Coverage Advisor

No source changes detected without accompanying tests. Thanks for keeping coverage up! 🎉

Advisory check only — never blocks merge.

@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Aug 5, 2026
@codecov

codecov Bot commented Aug 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.91983% with 31 lines in your changes missing coverage. Please review.
✅ Project coverage is 63.40%. Comparing base (83b26b2) to head (00de8a3).
⚠️ Report is 4 commits behind head on release-1.12.0.

Files with missing lines Patch % Lines
...omponent/components/sideBarFolderButtons/index.tsx 91.83% 8 Missing ⚠️
src/frontend/src/pages/MainPage/entities/index.tsx 0.00% 8 Missing ⚠️
...olderButtons/components/input-edit-folder-name.tsx 42.85% 4 Missing ⚠️
...sideBarFolderButtons/components/select-options.tsx 40.00% 3 Missing ⚠️
...controllers/API/queries/folders/use-get-folders.ts 66.66% 2 Missing ⚠️
src/frontend/src/types/zustand/folders/index.ts 0.00% 2 Missing ⚠️
src/backend/base/langflow/api/v1/deployments.py 87.50% 1 Missing ⚠️
src/backend/base/langflow/api/v1/flows.py 50.00% 1 Missing ⚠️
src/backend/base/langflow/initial_setup/setup.py 50.00% 1 Missing ⚠️
src/lfx/src/lfx/services/authorization/base.py 75.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@                Coverage Diff                 @@
##           release-1.12.0   #14429      +/-   ##
==================================================
+ Coverage           61.95%   63.40%   +1.44%     
==================================================
  Files                2417     2391      -26     
  Lines              242524   243318     +794     
  Branches            36184    37370    +1186     
==================================================
+ Hits               150251   154268    +4017     
+ Misses              90354    87125    -3229     
- Partials             1919     1925       +6     
Flag Coverage Δ
backend 70.80% <95.00%> (+0.69%) ⬆️
frontend 61.90% <84.39%> (+2.04%) ⬆️
lfx 61.10% <75.00%> (+0.02%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Files with missing lines Coverage Δ
src/backend/base/langflow/api/v1/projects.py 45.82% <100.00%> (+4.73%) ⬆️
...end/base/langflow/services/authorization/guards.py 93.29% <ø> (ø)
...nd/base/langflow/services/authorization/listing.py 99.09% <100.00%> (+0.19%) ⬆️
...ngflow/services/database/models/deployment/crud.py 72.59% <100.00%> (+1.80%) ⬆️
.../langflow/services/database/models/folder/model.py 100.00% <100.00%> (ø)
...backend/base/langflow/services/database/service.py 73.09% <ø> (+4.06%) ⬆️
...e/appHeaderComponent/components/FlowMenu/index.tsx 94.71% <100.00%> (+0.44%) ⬆️
...ontend/src/pages/MainPage/pages/homePage/index.tsx 82.46% <100.00%> (+30.73%) ⬆️
src/frontend/src/utils/project-display-name.ts 100.00% <100.00%> (ø)
src/backend/base/langflow/api/v1/deployments.py 82.75% <87.50%> (+<0.01%) ⬆️
... and 9 more

... and 580 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@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: 3

🧹 Nitpick comments (2)
src/backend/tests/unit/api/v1/test_deployment_route_handlers.py (1)

875-882: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Use the configured async test mode.

Remove these explicit async runner markers. asyncio_mode = "auto" already runs these async def tests. If the AnyIO marker is required for a distinct backend policy, document that policy and configure it explicitly.

  • src/backend/tests/unit/api/v1/test_deployment_route_handlers.py#L875-L882: Remove @pytest.mark.asyncio.
  • src/backend/tests/unit/api/v1/test_deployment_route_handlers.py#L915-L920: Remove @pytest.mark.asyncio.
  • src/backend/tests/unit/api/v1/test_deployment_route_handlers.py#L953-L961: Remove @pytest.mark.asyncio.
  • src/backend/tests/unit/services/authorization/test_visibility_scope_prefilter.py#L150-L151: Remove @pytest.mark.anyio unless the test requires a documented alternate backend.
  • src/backend/tests/unit/services/database/test_deployment_crud_authz_prefilter.py#L200-L201: Remove @pytest.mark.asyncio.

Based on learnings: pytest-asyncio uses asyncio_mode = 'auto'; tests should avoid unnecessary async markers.

🤖 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/backend/tests/unit/api/v1/test_deployment_route_handlers.py` around lines
875 - 882, Remove the unnecessary async test markers under configured automatic
async mode: delete `@pytest.mark.asyncio` from the three tests in
src/backend/tests/unit/api/v1/test_deployment_route_handlers.py at lines
875-882, 915-920, and 953-961; delete `@pytest.mark.anyio` from the test in
src/backend/tests/unit/services/authorization/test_visibility_scope_prefilter.py
at lines 150-151 unless it explicitly requires a documented alternate backend;
and delete `@pytest.mark.asyncio` from the test in
src/backend/tests/unit/services/database/test_deployment_crud_authz_prefilter.py
at lines 200-201. Preserve the async test bodies and configure/document an
alternate backend only if required.

Source: Learnings

src/frontend/src/pages/MainPage/pages/homePage/__tests__/project-owner-label.test.tsx (1)

37-97: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Add an integration-level owner-label test.

This setup mocks the header and MCP tab that the assertions inspect. The test verifies values passed to mocks, not the rendered owner-label behavior. Keep focused unit tests, but add a provider-backed test that renders the real project-name consumers.

As per coding guidelines, frontend tests must avoid excessive mocks and verify meaningful behavior.

🤖 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/frontend/src/pages/MainPage/pages/homePage/__tests__/project-owner-label.test.tsx`
around lines 37 - 97, Add an integration-level test that renders the real
project-name consumers instead of mocked Header and CustomMcpServerTab
components, while retaining focused unit tests as appropriate. Use the necessary
providers and realistic folder/ownership data to verify the rendered owner label
behavior, and remove or bypass only the mocks that prevent observing it.

Source: Coding guidelines

🤖 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 `@src/backend/tests/unit/api/v1/test_projects.py`:
- Around line 159-192: Extend
test_read_projects_qualifies_visible_same_named_projects_by_owner with a visible
project whose user_id is None, include it in the mocked project results, and
assert the returned project has owner_username set to None and is_owner set to
False while preserving the existing owner qualification assertions.

In
`@src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/index.tsx`:
- Line 456: Make both project test IDs unique by appending item.id: update the
sidebar-nav test ID in
src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/index.tsx
lines 456-456 and the more-options-button test ID in
src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/select-options.tsx
lines 60-62, preserving the existing item.name values.

In `@src/frontend/src/utils/__tests__/project-display-name.test.ts`:
- Around line 43-73: Add an empty-input edge-case test to the
getDefaultProjectId test suite, passing an empty project list and the default
project name, and assert that it returns an empty string to cover folder-store
initialization when no projects are visible.

---

Nitpick comments:
In `@src/backend/tests/unit/api/v1/test_deployment_route_handlers.py`:
- Around line 875-882: Remove the unnecessary async test markers under
configured automatic async mode: delete `@pytest.mark.asyncio` from the three
tests in src/backend/tests/unit/api/v1/test_deployment_route_handlers.py at
lines 875-882, 915-920, and 953-961; delete `@pytest.mark.anyio` from the test in
src/backend/tests/unit/services/authorization/test_visibility_scope_prefilter.py
at lines 150-151 unless it explicitly requires a documented alternate backend;
and delete `@pytest.mark.asyncio` from the test in
src/backend/tests/unit/services/database/test_deployment_crud_authz_prefilter.py
at lines 200-201. Preserve the async test bodies and configure/document an
alternate backend only if required.

In
`@src/frontend/src/pages/MainPage/pages/homePage/__tests__/project-owner-label.test.tsx`:
- Around line 37-97: Add an integration-level test that renders the real
project-name consumers instead of mocked Header and CustomMcpServerTab
components, while retaining focused unit tests as appropriate. Use the necessary
providers and realistic folder/ownership data to verify the rendered owner label
behavior, and remove or bypass only the mocks that prevent observing it.
🪄 Autofix

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 Plus

Run ID: d4871e2b-6054-44c9-8bca-2bc352527acf

📥 Commits

Reviewing files that changed from the base of the PR and between 259369e and ac42109.

📒 Files selected for processing (24)
  • .secrets.baseline
  • src/backend/base/langflow/api/v1/deployments.py
  • src/backend/base/langflow/api/v1/projects.py
  • src/backend/base/langflow/services/authorization/listing.py
  • src/backend/base/langflow/services/database/models/deployment/crud.py
  • src/backend/base/langflow/services/database/models/folder/model.py
  • src/backend/tests/unit/api/v1/test_deployment_route_handlers.py
  • src/backend/tests/unit/api/v1/test_projects.py
  • src/backend/tests/unit/services/authorization/test_guards.py
  • src/backend/tests/unit/services/authorization/test_visibility_scope_prefilter.py
  • src/backend/tests/unit/services/database/test_deployment_crud_authz_prefilter.py
  • src/frontend/src/components/core/appHeaderComponent/components/FlowMenu/__tests__/FlowMenu.spec.tsx
  • src/frontend/src/components/core/appHeaderComponent/components/FlowMenu/index.tsx
  • src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/__tests__/project-create-error.test.tsx
  • src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/input-edit-folder-name.tsx
  • src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/components/select-options.tsx
  • src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/index.tsx
  • src/frontend/src/controllers/API/queries/folders/use-get-folders.ts
  • src/frontend/src/pages/MainPage/entities/index.tsx
  • src/frontend/src/pages/MainPage/pages/homePage/__tests__/project-owner-label.test.tsx
  • src/frontend/src/pages/MainPage/pages/homePage/index.tsx
  • src/frontend/src/utils/__tests__/project-display-name.test.ts
  • src/frontend/src/utils/project-display-name.ts
  • src/lfx/src/lfx/services/authorization/base.py

Comment thread src/backend/tests/unit/api/v1/test_projects.py
Comment thread src/frontend/src/utils/__tests__/project-display-name.test.ts
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Aug 5, 2026
@erichare
erichare requested a review from keval718 August 5, 2026 20:12
@github-actions

github-actions Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Frontend Unit Test Coverage Report

Coverage Summary

Lines Statements Branches Functions
Coverage: 50%
50.28% (72468/144123) 70.19% (10158/14471) 46.99% (1666/3545)

Unit Test Results

Tests Skipped Failures Errors Time
5550 0 💤 0 ❌ 0 🔥 18m 42s ⏱️

@keval718 keval718 left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The security narrowing (deployment provider gate) and the rename-by-id fix are correct and well tested. Two things block: a Postgres-only 500 in the exact path this PR exists to enable, and ~6 Playwright specs silently broken by the testid change.


Blocking

1. literal(None) IS NULL will 500 on Postgres — in the primary new code path

src/backend/base/langflow/api/v1/projects.py:384 passes workspace_expression=literal(project.workspace_id). The new unassigned-workspace branch at src/backend/base/langflow/services/authorization/listing.py:187 then calls resolved_workspace.is_(None) on that bind param. Compiled against the asyncpg dialect:

workspace_id=None    ->  $1 IS NULL          # no cast
workspace_id=<uuid>  ->  $1::UUID IS NULL    # cast inferred from the value

Postgres rejects an untyped parameter in an IS NULL predicate: 42P18 could not determine data type of parameter $1. The pre-existing resolved_workspace.in_(visibility.workspace_ids) survives because PG infers the type from the IN list — IS NULL has nothing to infer from.

Failure scenario: a plugin returns include_unassigned_workspace=True, a user opens a shared project whose workspace_id is NULL with ?page=1&size=12, and GET /api/v1/projects/{id} 500s. Every backend test here runs on SQLite, where ? IS NULL is legal — so CI stays green.

Suggested fix, short-circuiting in Python instead of emitting a bind param:

workspace_expression=sa.null() if project.workspace_id is None else literal(project.workspace_id),

or have restrict_to_owned_or_visible_scope take a workspace_is_null: bool | None and emit true()/false(). Worth a Postgres-marked regression test — SQLite parity tests structurally cannot catch this class of bug.

2. Project sidebar testid change breaks Playwright suites, none updated

src/frontend/src/components/core/folderSidebarComponent/components/sideBarFolderButtons/index.tsx:456 (sidebar-nav-${name} -> sidebar-nav-${name}-${id}) and .../components/select-options.tsx:60 (more-options-button_${name} -> ..._${name}_${id}). Playwright's getByTestId is an exact match, so these break:

  • src/frontend/tests/core/features/folders.spec.ts:56,83,98,111,171,187,192,199
  • src/frontend/tests/core/features/folder-deletion-integrity.spec.ts (27 refs)
  • src/frontend/tests/extended/features/mcp-server-starter-projects.spec.ts:65,88,92
  • src/frontend/tests/extended/regression/general-bugs-move-flow-from-folder.spec.ts:51,59,71,83
  • src/frontend/tests/utils/clean-old-folders.ts:18 — shared helper, fans out further

Separately: the id suffix alone achieves uniqueness. Keeping the raw, unslugified item.name (sidebar-nav-Starter Project-<uuid>) makes selectors doubly brittle and is inconsistent with more-options-button, which does run convertTestName. Prefer data-testid={sidebar-nav-${item.id}} and have e2e resolve name -> id, or at minimum slugify.


Should fix

3. Null-owner projects render a raw UUID to OSS users

src/frontend/src/utils/project-display-name.ts:12${name} — ${owner_username ?? id ?? "unknown owner"}. read_projects deliberately surfaces user_id IS NULL projects on the OSS path (projects.py:257), and the new test asserts owner_username=None, is_owner=False for exactly those rows. On a default OSS install with a legacy null-owner folder the sidebar renders My Projects — 3f2a19c8-...: a UUID leaked into the UI, and a project nobody owns mislabelled as foreign.

if (project.is_owner !== false || !project.owner_username) return project.name;
return t("project.ownedBy", { name: project.name, owner: project.owner_username });

That also removes the unreachable "unknown owner" literal.

4. Owner qualifier is untranslated

Same file — the separator and the whole format are hardcoded English/typography, while adjacent code uses t("folder.optionsFor", { name }). AGENTS.md conventions want user-facing copy behind i18n; a translation key also lets RTL locales and CJK punctuation render correctly.

5. is_owner handled inconsistently across the two new helpers

getProjectDisplayName treats is_owner !== false as owned, so undefined is safe. getDefaultProjectId (project-display-name.ts:21) uses truthy project.is_owner, so undefined skips both find calls and falls through to projects[0]. The old code matched on name === defaultFolderName with no ownership dependency.

Failure scenario: any client hitting a backend that doesn't emit is_owner (version skew, /customization overrides) silently loses default-project selection by name. Add the name match as a final fallback before projects[0], or normalize is_owner once at the query boundary.

6. getDefaultProjectId returns "" where the old code returned undefined

use-get-folders.ts:26 now always stores a string. src/frontend/src/pages/MainPage/pages/deploymentsPage/components/deployment-stepper-modal.tsx:76 reads currentFlowProjectId ?? folderId ?? myCollectionId ?? undefined — with "" the ?? undefined guard no longer fires and an empty project_id can reach the API. Returning undefined and leaving the existing ?? "" call sites to cope keeps the old contract.


Confirmed good

  • No OSS widening. include_unassigned_workspace and excluded_workspace_project_ids default to false/empty, OSS visible_scope_prefilter still returns None, and read_projects keeps its owner-scoped query. The has_cross_user_access addition only fires on the new flag. Matches the AGENTS.md rule that enabling LANGFLOW_AUTHZ_ENABLED without a plugin cannot widen visibility.
  • Deployment provider gate strictly narrows. deployments.py:793-830 now requires provider-specific visible evidence via has_visible_deployment_for_provider before the unscoped lookup, then masks the subsequent 403 with deny_to_404 — consistent with the 11 other deny_to_404 sites in the same file. The evidence query reuses _scope_to_owner_or_allowed, so it cannot drift from the page/count predicate. Good catch on the existence oracle.
  • SQL / in-memory parity between restrict_to_owned_or_visible_scope and resource_visible_in_scope is correct for both the exclusion gate and the unassigned branch, and test_workspace_scope_sql_matches_in_memory_for_project_nulls_and_exclusions exercises it against a real session rather than string-matching SQL.
  • Rename targeting by id is the right fix, and project-create-error.test.tsx:222 proves both halves — foreign project not editable, own project renames with folderId: "own-id".
  • Frontend test claim verified. I ran the four suites locally: 19 passed, 4 suites, matching the PR description.

Nitpicks

  • projects.py:290FolderListRead(**FolderRead.model_validate(...).model_dump(), ...) validates twice. FolderListRead.model_validate(project, from_attributes=True) with the two extras assigned afterwards is cheaper and won't silently break if FolderRead ever gains a colliding field name.
  • sideBarFolderButtons/index.tsx:66ProjectRenamePermission duplicates the can(id, "write") computation select-options.tsx:34 already does. A shared useProjectCanWrite(id) hook would keep the two from drifting.
  • sideBarFolderButtons/index.tsx:496 — the onClick={(e) => e.stopPropagation()} on the SelectOptions wrapper was dropped without mention in the PR body. It looks safe (no ancestor click handler), but it's an unexplained behavior change riding along in an authz PR.
  • Agreed with CodeRabbit on dropping the redundant @pytest.mark.asyncio / @pytest.mark.anyio markers given asyncio_mode = "auto". Disagreed on its request for a provider-backed integration test in project-owner-label.test.tsx — the unit coverage in project-display-name.test.ts plus the sidebar integration test is proportionate.
  • PR body has no Fixes #N reference; AGENTS.md asks for the issue link.

@erichare

erichare commented Aug 5, 2026

Copy link
Copy Markdown
Member Author

Thanks @keval718 — addressed in 954642f. The null-workspace prefilter now emits SQL NULL with an asyncpg compilation regression; project row/options selectors are UUID-only and the affected specs/helpers resolve names to IDs; and owner labels/default selection now handle i18n, null owners, version skew, and undefined. I also removed the redundant async markers and double Folder validation. Focused backend, Jest, and affected Playwright scenarios are green.

@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Aug 5, 2026
@erichare
erichare requested a review from keval718 August 5, 2026 21:00
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Aug 5, 2026
@erichare

erichare commented Aug 5, 2026

Copy link
Copy Markdown
Member Author

Thanks @keval718 — the upgrade/scoping follow-up is pushed. Existing Global Viewer/Developer/Admin assignments now reconcile to the documented flow permissions; roleless users remain owner/direct-share only; Default workspace covers only null-workspace projects; and ownerless Starter Project flows/deployments stay excluded from automatic scope access while exact shares remain additive. The exact-pin Enterprise suite is green (654 passed, 9 skipped).

@github-actions github-actions Bot added the lgtm This PR has been approved by a maintainer label Aug 6, 2026
@erichare
erichare merged commit 23f91d8 into release-1.12.0 Aug 6, 2026
182 checks passed
@erichare
erichare deleted the fix/project-owner-labels branch August 6, 2026 00:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working lgtm This PR has been approved by a maintainer

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants