Skip to content

fix: enforce locked flows in backend - #14192

Merged
erichare merged 6 commits into
release-1.11.0from
fix/enforce-locked-flow-backend
Jul 21, 2026
Merged

fix: enforce locked flows in backend#14192
erichare merged 6 commits into
release-1.11.0from
fix/enforce-locked-flow-backend

Conversation

@erichare

@erichare erichare commented Jul 21, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • reject PATCH, PUT, and import/upsert mutations to locked flows with HTTP 423
  • allow an existing locked flow to be unlocked only when no other effective field changes are included
  • enforce the same lock in MCP mutation paths that persist directly through the assistant and component-field helpers
  • re-check the lock immediately before long-running assistant edits are persisted

Root cause

The locked flag was persisted, but flow update helpers never consulted it. Most MCP editing tools inherit that gap because they update flows through PATCH /api/v1/flows/{id}; the agentic MCP component-field and assistant paths could also bypass the REST endpoint and write directly to the database.

User impact

Locked flows are now read-only across backend API and MCP editing surfaces. Clients receive 423 Locked with guidance to unlock the flow before changing it. The existing UI unlock workflow remains compatible because full-payload requests are accepted when locked=false is the only effective change.

Validation

  • uv run pytest src/backend/tests/unit/api/v1/test_flows.py src/backend/tests/unit/api/v1/test_flows_helpers.py src/backend/tests/unit/agentic/utils/test_flow_component.py src/backend/tests/unit/agentic/mcp/test_run_assistant_tool.py -q (83 passed)
  • focused API regression including combined unlock-and-edit rejection (passed)
  • Ruff lint and format checks on all changed Python files
  • pre-commit hooks, including secret detection (passed)

Summary by CodeRabbit

  • New Features

    • Locked flows are now protected from edits across assistant runs, component updates, and flow API updates.
    • Locked flows can only be modified by explicitly unlocking them first.
    • API attempts to update locked flows now return a clear 423 Locked response.
  • Bug Fixes

    • Prevented concurrent lock changes from being bypassed during flow updates.
    • Ensured locked-flow updates are not persisted.

@coderabbitai

coderabbitai Bot commented Jul 21, 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

Run ID: 32105978-e438-4514-af99-d9149e2ae191

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

Changes

Flow locking

Layer / File(s) Summary
Flow lock guard contracts
src/backend/base/langflow/services/database/models/flow/guards.py
Adds shared locked-flow errors and guards that reject mutations while allowing an unlock-only update.
API update enforcement
src/backend/base/langflow/api/v1/flows_helpers.py, src/backend/tests/unit/api/v1/test_flows.py
PUT and PATCH updates map locked-flow violations to HTTP 423 and test rejection, unlocking, and subsequent updates.
Agentic and component mutation checks
src/backend/base/langflow/agentic/..., src/backend/tests/unit/agentic/...
Assistant execution and component updates validate lock state before model execution and persistence, including fresh database-row checks. Tests verify blocked execution and skipped commits.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant flows_helpers
  participant ensure_flow_update_allowed
  Client->>flows_helpers: PUT or PATCH flow update
  flows_helpers->>ensure_flow_update_allowed: validate flow and update data
  ensure_flow_update_allowed-->>flows_helpers: LockedFlowError for blocked mutation
  flows_helpers-->>Client: HTTP 423 LOCKED
Loading

Suggested labels: fix-index

Suggested reviewers: keval718


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Test Coverage For New Implementations ❌ Error Tests cover API PATCH/PUT, MCP lock rejection, and component DB lock, but not the new assistant refresh-before-commit race or upload/upsert lock path. Add tests for a lock acquired during assistant streaming (assert no commit/save) and for locked upload/upsert requests returning 423.
Test Quality And Coverage ⚠️ Warning Core behaviors are covered, but the new post-refresh assistant lock race and locked import/upload mutation path lack direct tests. Add a test that flips flow.locked during assistant execution and asserts no commit/save, plus a locked upload/import regression test.
✅ Passed checks (7 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: enforcing locked-flow restrictions across backend paths.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 File Naming And Structure ✅ Passed All changed backend test files use test_*.py names, pytest async tests, fixtures/classes, and descriptive positive/negative coverage including lock/error cases.
Excessive Mock Usage Warning ✅ Passed Mocks are limited to isolating DB/streaming/filesystem deps; the new API regression uses real client calls, and the unit tests still read clearly.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/enforce-locked-flow-backend

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 Jul 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Migration Validation Passed

All migrations follow the Expand-Contract pattern correctly.

@erichare
erichare requested a review from keval718 July 21, 2026 18:52
@erichare
erichare marked this pull request as ready for review July 21, 2026 18:52
@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.

@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 21, 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

🧹 Nitpick comments (1)
src/backend/tests/unit/agentic/mcp/test_run_assistant_tool.py (1)

162-162: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove redundant @pytest.mark.asyncio decorators.

  • src/backend/tests/unit/agentic/mcp/test_run_assistant_tool.py#L162-L162: remove the marker.
  • src/backend/tests/unit/agentic/utils/test_flow_component.py#L289-L289: remove the marker.

Based on learnings, pytest-asyncio uses asyncio_mode = auto, so async tests are auto-detected and should not use this marker.

🤖 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/agentic/mcp/test_run_assistant_tool.py` at line 162,
Remove the redundant `@pytest.mark.asyncio` decorator from the async test at
src/backend/tests/unit/agentic/mcp/test_run_assistant_tool.py lines 162-162 and
from the corresponding async test at
src/backend/tests/unit/agentic/utils/test_flow_component.py lines 289-289; rely
on pytest-asyncio’s asyncio_mode = auto without changing test behavior.

Source: Learnings

🤖 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/agentic/utils/assistant_runner.py`:
- Around line 213-217: Make flow mutation writes atomic with the lock state:
update the persistence logic around assistant_runner.py lines 213-217,
flow_component.py lines 281-284, and both flows_helpers.py sites at lines
506-507 and 555-556 to condition writes on locked=false at write time, using a
conditional update or row lock rather than relying on refresh/get followed by
flush/commit. Preserve unlock-only updates by allowing writes that set
locked=false even when the flow is currently locked.

In `@src/backend/tests/unit/agentic/mcp/test_run_assistant_tool.py`:
- Around line 178-191: Extend the tests around run_assistant_and_persist with a
changed-stream scenario where session.refresh() updates flow.locked to True
during assistant execution. Assert that the locked-flow path raises
LockedFlowError and that session.commit() and _save_flow_to_fs() are not called,
while preserving the existing pre-execution lock assertions.

---

Nitpick comments:
In `@src/backend/tests/unit/agentic/mcp/test_run_assistant_tool.py`:
- Line 162: Remove the redundant `@pytest.mark.asyncio` decorator from the async
test at src/backend/tests/unit/agentic/mcp/test_run_assistant_tool.py lines
162-162 and from the corresponding async test at
src/backend/tests/unit/agentic/utils/test_flow_component.py lines 289-289; rely
on pytest-asyncio’s asyncio_mode = auto without changing test behavior.
🪄 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: 574d78fc-235f-47b9-8b51-2e9251c3c0a4

📥 Commits

Reviewing files that changed from the base of the PR and between 82a79aa and a84eb77.

📒 Files selected for processing (7)
  • src/backend/base/langflow/agentic/utils/assistant_runner.py
  • src/backend/base/langflow/agentic/utils/flow_component.py
  • src/backend/base/langflow/api/v1/flows_helpers.py
  • src/backend/base/langflow/services/database/models/flow/guards.py
  • src/backend/tests/unit/agentic/mcp/test_run_assistant_tool.py
  • src/backend/tests/unit/agentic/utils/test_flow_component.py
  • src/backend/tests/unit/api/v1/test_flows.py

Comment thread src/backend/base/langflow/agentic/utils/assistant_runner.py
Comment thread src/backend/tests/unit/agentic/mcp/test_run_assistant_tool.py
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 21, 2026
@codecov

codecov Bot commented Jul 21, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.39130% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 61.14%. Comparing base (76d6792) to head (4a05462).
⚠️ Report is 2 commits behind head on release-1.11.0.

Files with missing lines Patch % Lines
src/frontend/src/hooks/flows/use-save-flow.ts 89.28% 6 Missing ⚠️
src/backend/base/langflow/api/v1/flows_helpers.py 90.00% 1 Missing ⚠️
Additional details and impacted files

Impacted file tree graph

@@                Coverage Diff                 @@
##           release-1.11.0   #14192      +/-   ##
==================================================
- Coverage           61.21%   61.14%   -0.07%     
==================================================
  Files                2440     2387      -53     
  Lines              238935   237299    -1636     
  Branches            34065    33535     -530     
==================================================
- Hits               146270   145105    -1165     
+ Misses              90909    90436     -473     
- Partials             1756     1758       +2     
Flag Coverage Δ
backend 68.69% <97.22%> (-0.07%) ⬇️
frontend 59.40% <89.28%> (-0.12%) ⬇️
lfx 59.91% <ø> (+0.02%) ⬆️

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

Files with missing lines Coverage Δ
...nd/base/langflow/agentic/utils/assistant_runner.py 93.65% <100.00%> (+0.31%) ⬆️
...kend/base/langflow/agentic/utils/flow_component.py 81.73% <100.00%> (+3.36%) ⬆️
...e/langflow/services/database/models/flow/guards.py 100.00% <100.00%> (ø)
src/backend/base/langflow/api/v1/flows_helpers.py 63.17% <90.00%> (-8.74%) ⬇️
src/frontend/src/hooks/flows/use-save-flow.ts 86.04% <89.28%> (+5.76%) ⬆️

... and 171 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 21, 2026

Copy link
Copy Markdown
Contributor

Frontend Unit Test Coverage Report

Coverage Summary

Lines Statements Branches Functions
Coverage: 47%
47.01% (66886/142274) 70.04% (9385/13399) 45.36% (1532/3377)

Unit Test Results

Tests Skipped Failures Errors Time
5348 0 💤 0 ❌ 0 🔥 20m 6s ⏱️

@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 21, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 21, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 21, 2026
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 21, 2026
@erichare
erichare merged commit 2fc8066 into release-1.11.0 Jul 21, 2026
130 checks passed
@erichare
erichare deleted the fix/enforce-locked-flow-backend branch July 21, 2026 23:35
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant