Skip to content

fix(rbac): add permission checks in api and use owner id for provider sync - #14104

Merged
erichare merged 5 commits into
release-1.12.0from
fix/deployment-rbac
Jul 23, 2026
Merged

fix(rbac): add permission checks in api and use owner id for provider sync#14104
erichare merged 5 commits into
release-1.12.0from
fix/deployment-rbac

Conversation

@HzaRashid

@HzaRashid HzaRashid commented Jul 15, 2026

Copy link
Copy Markdown
Collaborator
  • add pre-flight permission checks in the api for the acting user
  • pass the owner id to the synchronization logic so that provider sync can succeed for readers (actors) that do not necessarily own the deployment resources or have the necessary write or delete permissions needed for synchronization
  • pass both the owner id and actor id to the crud layer to perform any resource pre-filtering enforced by the auth layer

Summary by CodeRabbit

  • New Features
    • Added batched flow deployment permission checks with improved audit coverage.
    • Deployment listings now consistently respect ownership and visibility rules.
  • Bug Fixes
    • Improved deployment creation, updates, deletion, and rollback authorization.
    • Fixed cross-owner deployment synchronization and attachment counting.
    • Strengthened deletion handling when database results are uncertain.
  • Tests
    • Expanded coverage for authorization, ownership scoping, synchronization, filtering, and deletion edge cases.

@coderabbitai

coderabbitai Bot commented Jul 15, 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: 87931946-0707-4b9f-af70-73e974179033

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

Deployment authorization now resolves flow ownership in batches, deployment listing and reconciliation carry a separate provider-owner scope, and deployment mutations authorize before provider access. Deletion paths handle owner scoping, rollback retries, and unconfirmed database row counts explicitly.

Changes

Deployment ownership and authorization

Layer / File(s) Summary
Batch flow authorization and visibility prefilters
src/backend/base/langflow/services/authorization/*, src/backend/base/langflow/api/v1/mappers/deployments/helpers.py
Adds batched flow deploy enforcement, owner-override-aware visible-ID prefilters, UUID de-duplication, and public exports with corresponding authorization tests.
Owner-resolved deployment synchronization
src/backend/base/langflow/api/v1/mappers/deployments/sync.py, src/backend/base/langflow/api/v1/flows.py, src/backend/base/langflow/api/v1/projects.py, src/backend/tests/unit/api/v1/test_deployment_guard_retry.py
Resolves flow owners before deployment synchronization and updates flow/project retry call sites and retry tests.
Owner-scoped deployment listing and reconciliation
src/backend/base/langflow/api/v1/mappers/deployments/helpers.py, src/backend/base/langflow/services/database/models/deployment/crud.py, src/backend/tests/unit/api/v1/test_deployment_sync.py, src/backend/tests/unit/services/database/*
Threads row_owner_id through listing, counting, provider resource lookup, attachment reconciliation, pagination, and authorization filtering.
Pre-mutation authorization and strict deletion
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
Moves flow deploy checks before provider operations, scopes rollback and local cleanup by deployment owner, and propagates unconfirmed delete row counts for strict 404/500 handling.

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

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant DeploymentRoute
  participant FlowDeployGuard
  participant DeploymentCRUD
  participant Provider
  Client->>DeploymentRoute: create or update deployment
  DeploymentRoute->>FlowDeployGuard: authorize flow-version deployment
  FlowDeployGuard-->>DeploymentRoute: allow or deny
  DeploymentRoute->>DeploymentCRUD: resolve owner-scoped deployment data
  DeploymentRoute->>Provider: mutate provider resource
  Provider-->>DeploymentRoute: provider result
Loading

Possibly related PRs

Suggested reviewers: erichare

🚥 Pre-merge checks | ✅ 8 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 57.84% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (8 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: added API permission checks and owner-scoped provider synchronization.
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 New/updated tests cover the authz guards, deployment sync, CRUD delete sentinels, and route handlers; filenames follow backend test conventions.
Test Quality And Coverage ✅ Passed Comprehensive pytest/anyio coverage hits new auth, sync, CRUD, and route success/error paths; assertions validate owner scoping, rowcount sentinel, and rollback behavior.
Test File Naming And Structure ✅ Passed PASS: All changed test files are named test_*.py, use pytest-style classes/functions, and include clear setup plus positive/negative edge-case coverage.
Excessive Mock Usage Warning ✅ Passed Mocks are used mainly at API/authorization boundaries; CRUD and SQL prefilter tests use real DB/SQLAlchemy behavior, so mocking isn’t excessive.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/deployment-rbac

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.

@HzaRashid HzaRashid changed the title fix(rbac): properly separate owner id from actor id for preflight checks and crud fix(rbac): add permissions checks in api and use owner id for provider sync Jul 15, 2026
@github-actions github-actions Bot added the bug Something isn't working label Jul 15, 2026
@HzaRashid HzaRashid changed the title fix(rbac): add permissions checks in api and use owner id for provider sync fix(rbac): add permission checks in api and use owner id for provider sync Jul 15, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Migration Validation Passed

All migrations follow the Expand-Contract pattern correctly.

@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 15, 2026
@erichare
erichare self-requested a review July 15, 2026 22:31
…cess gaps

- Pass row_owner_id through list/count/sync so credentials and attachments stay
  in the provider-account owner namespace while user_id remains the listing actor
- Use deployment_row.user_id for shared delete cleanup; confirmed zero rows → 404;
  unconfirmed DELETE rowcount → 500
- Keep shared update rollback in the deployment owner namespace
- Add apply_owned_or_visible_prefilter so scoped API keys with a concrete
  visible-id set do not auto-include owned deployments (owner override still
  unions via restrict_to_owned_or_visible)
- Document None vs [] at the deployment list prefilter call site
- Enforce flow:deploy before provider mutation on create, update (added
  versions), and snapshot replacement via ensure_flows_permission
- Authorize deployment:create before existing-resource provider get/create
- Add route, CRUD, listing, and guard coverage for the above
Guard-retry was syncing with the actor user_id, so shared deleters/movers
could not reconcile the owner's deployments. Resolve owners from the flow
rows and sync per owner instead.
@HzaRashid
HzaRashid force-pushed the fix/deployment-rbac branch from 5d7a842 to f90b1fe Compare July 20, 2026 22:29
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 20, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 20, 2026
@erichare
erichare changed the base branch from release-1.11.0 to release-1.12.0 July 23, 2026 15:03
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 23, 2026
@erichare
erichare marked this pull request as ready for review July 23, 2026 15:07
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 23, 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: 3

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

2759-2817: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider a real DB fixture for flow_ids_for_version_ids tests instead of mocking db.exec.

These new tests mock db.exec/result.all() directly rather than exercising the real select(FlowVersion.flow_id)... query against a DB session, unlike sibling authorization-prefilter tests added in this same PR (e.g. test_deployment_crud_authz_prefilter.py) which use a real async_session fixture with actual Flow/FlowVersion rows. A real-session variant would catch query-shape regressions (e.g. wrong column, wrong filter) that a mocked .all() return value cannot.

Based on path instructions: "Warn when backend pytest files rely on excessive mocks that obscure what is actually being tested, replace mocks with real objects or test doubles when mocks become excessive, and prefer integration tests when unit tests are overly mocked."

🤖 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_sync.py` around lines 2759 -
2817, Replace the mocked db.exec/result.all setup in TestFlowIdsForVersionIds
with a real async_session fixture and persisted Flow/FlowVersion rows. Exercise
flow_ids_for_version_ids against the actual query, preserving coverage for empty
input, partial matches raising HTTP 404, and deduplication when multiple
versions share a flow.

Source: Path instructions

🤖 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/base/langflow/services/authorization/guards.py`:
- Around line 522-558: Validate that the results returned by batch_enforce match
len(flow_ids) before calling _audit_flow_decision_batch or zip(...,
strict=True). On a mismatch, follow the existing fail-closed behavior: audit a
deny decision with the relevant domain and error details, then raise the
documented 403 HTTPException instead of allowing ValueError to escape.

In `@src/backend/base/langflow/services/database/models/deployment/crud.py`:
- Line 627: Update the sync delete path and its widened batch helpers around
delete_deployments_by_ids() to explicitly handle UNCONFIRMED_DELETE_ROWCOUNT.
Ensure non-strict callers propagate the sentinel, log the undetermined outcome,
or return the established structured result instead of treating the deletion as
completed; preserve existing behavior for confirmed rowcounts.

In
`@src/backend/tests/unit/services/database/test_deployment_crud_authz_prefilter.py`:
- Around line 106-109: Remove the redundant pytest.mark.asyncio decorator from
test_list_deployments_page_allowed_ids_skips_owner_when_override_disabled in
src/backend/tests/unit/services/database/test_deployment_crud_authz_prefilter.py
and test_delete_by_id_negative_rowcount_returns_unconfirmed in
src/backend/base/langflow/tests/services/database/models/deployment/test_crud.py;
leave both async test functions unchanged because asyncio_mode = 'auto' detects
them automatically.

---

Nitpick comments:
In `@src/backend/tests/unit/api/v1/test_deployment_sync.py`:
- Around line 2759-2817: Replace the mocked db.exec/result.all setup in
TestFlowIdsForVersionIds with a real async_session fixture and persisted
Flow/FlowVersion rows. Exercise flow_ids_for_version_ids against the actual
query, preserving coverage for empty input, partial matches raising HTTP 404,
and deduplication when multiple versions share a flow.
🪄 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 Plus

Run ID: 6471a6a3-16eb-4aca-ad32-e0083fbb2b04

📥 Commits

Reviewing files that changed from the base of the PR and between 77964d4 and 4c25c22.

📒 Files selected for processing (22)
  • src/backend/base/langflow/api/v1/deployments.py
  • src/backend/base/langflow/api/v1/flows.py
  • src/backend/base/langflow/api/v1/mappers/deployments/helpers.py
  • src/backend/base/langflow/api/v1/mappers/deployments/sync.py
  • src/backend/base/langflow/api/v1/projects.py
  • src/backend/base/langflow/services/authorization/__init__.py
  • src/backend/base/langflow/services/authorization/guards.py
  • src/backend/base/langflow/services/authorization/listing.py
  • src/backend/base/langflow/services/authorization/utils.py
  • src/backend/base/langflow/services/database/models/deployment/crud.py
  • src/backend/base/langflow/tests/services/database/models/deployment/test_crud.py
  • src/backend/base/langflow/tests/services/database/models/deployment/test_in_memory.py
  • src/backend/base/langflow/tests/services/database/models/flow_version/test_in_memory.py
  • src/backend/tests/unit/api/v1/test_deployment_guard_retry.py
  • src/backend/tests/unit/api/v1/test_deployment_route_handlers.py
  • src/backend/tests/unit/api/v1/test_deployment_sync.py
  • src/backend/tests/unit/api/v1/test_deployments_telemetry.py
  • src/backend/tests/unit/services/authorization/test_guards.py
  • src/backend/tests/unit/services/authorization/test_visible_id_prefilter.py
  • src/backend/tests/unit/services/database/test_deployment_crud_authz_prefilter.py
  • src/backend/tests/unit/services/database/test_deployment_crud_filters.py
  • src/backend/tests/unit/services/database/test_deployment_crud_project_filter.py
💤 Files with no reviewable changes (1)
  • src/backend/base/langflow/api/v1/projects.py

Comment thread src/backend/base/langflow/services/authorization/guards.py
Comment thread src/backend/tests/unit/services/database/test_deployment_crud_authz_prefilter.py Outdated
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 23, 2026
@erichare

Copy link
Copy Markdown
Member

Addressed the remaining CodeRabbit review-summary nitpick in e074f82: TestFlowIdsForVersionIds now uses a real AsyncSession with persisted User, Flow, and FlowVersion rows for empty-input, partial-match/404, and shared-flow deduplication coverage.

Also addressed all three inline findings and resolved their threads:

  • fail closed with an audited 403 when batch_enforce returns the wrong result count;
  • explicitly warn when a stale deployment batch delete has an unconfirmed rowcount;
  • remove the two redundant pytest.mark.asyncio decorators.

Additionally fixed the external-access ceiling ordering so flow:deploy remains admin-only when AUTHZ_ENABLED is false. Merge conflicts with release-1.12.0 are resolved. Validation: Ruff clean; 172 affected backend tests passed.

@github-actions

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.

@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 85.24590% with 18 lines in your changes missing coverage. Please review.
✅ Project coverage is 61.21%. Comparing base (597d05f) to head (1cea166).
⚠️ Report is 34 commits behind head on release-1.12.0.

Files with missing lines Patch % Lines
...end/base/langflow/services/authorization/guards.py 81.08% 7 Missing ⚠️
...ngflow/services/database/models/deployment/crud.py 61.11% 7 Missing ⚠️
src/backend/base/langflow/api/v1/deployments.py 90.90% 2 Missing ⚠️
src/backend/base/langflow/api/v1/projects.py 66.66% 2 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@                Coverage Diff                 @@
##           release-1.12.0   #14104      +/-   ##
==================================================
- Coverage           61.47%   61.21%   -0.27%     
==================================================
  Files                2339     2345       +6     
  Lines              237145   238012     +867     
  Branches            35410    35527     +117     
==================================================
- Hits               145787   145690      -97     
- Misses              89561    90512     +951     
- Partials             1797     1810      +13     
Flag Coverage Δ
backend 67.21% <85.24%> (-1.75%) ⬇️
frontend 59.76% <ø> (+0.01%) ⬆️
lfx 60.37% <ø> (+0.16%) ⬆️

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/flows.py 47.44% <100.00%> (-8.64%) ⬇️
...ase/langflow/api/v1/mappers/deployments/helpers.py 67.87% <100.00%> (-1.94%) ⬇️
...d/base/langflow/api/v1/mappers/deployments/sync.py 88.12% <100.00%> (-7.27%) ⬇️
...nd/base/langflow/services/authorization/listing.py 98.90% <100.00%> (+1.37%) ⬆️
...kend/base/langflow/services/authorization/utils.py 92.30% <ø> (ø)
src/backend/base/langflow/api/v1/deployments.py 77.09% <90.90%> (-4.30%) ⬇️
src/backend/base/langflow/api/v1/projects.py 35.71% <66.66%> (+1.56%) ⬆️
...end/base/langflow/services/authorization/guards.py 90.00% <81.08%> (-5.94%) ⬇️
...ngflow/services/database/models/deployment/crud.py 70.29% <61.11%> (+0.79%) ⬆️

... and 183 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.

@github-actions

github-actions Bot commented Jul 23, 2026

Copy link
Copy Markdown
Contributor

Frontend Unit Test Coverage Report

Coverage Summary

Lines Statements Branches Functions
Coverage: 47%
47.01% (67374/143289) 70.15% (9504/13547) 45.58% (1554/3409)

Unit Test Results

Tests Skipped Failures Errors Time
5375 0 💤 0 ❌ 0 🔥 19m 36s ⏱️

@erichare erichare left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Pushed some small fixes and rebased. LGTM!

@github-actions github-actions Bot added the lgtm This PR has been approved by a maintainer label Jul 23, 2026
@erichare
erichare enabled auto-merge July 23, 2026 16:09
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 23, 2026
@erichare
erichare added this pull request to the merge queue Jul 23, 2026
@erichare
erichare removed this pull request from the merge queue due to the queue being cleared Jul 23, 2026
@erichare
erichare merged commit 9d6346e into release-1.12.0 Jul 23, 2026
232 of 234 checks passed
@erichare
erichare deleted the fix/deployment-rbac branch July 23, 2026 17:58
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