18174 Commits

Author SHA1 Message Date
49d091ef17 fix(a11y): resolve WCAG 2.1 Level A and AA violations on settings general page 2026-06-24 14:38:37 -04:00
6f7c1f88ec fix(a11y): add accessible names to icon-only buttons, fix placeholder (#13666)
* fix(a11y): add accessible names to icon-only buttons, fix placeholder contrast, and enforce touch target size on /flows

* [autofix.ci] apply automated fixes

* fix issues

* [autofix.ci] apply automated fixes

* fix(a11y): fix aria-allowed-attr, invalid sidebar list structure, and session filter label mismatch on flow editor (#13668)

* fix(a11y): fix aria-allowed-attr, invalid sidebar list structure, and session filter label mismatch on flow editor

* [autofix.ci] apply automated fixes

* improve translations

* remove app-header-a11y

---------

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com>

* label get-started close button and fix dark-mode placeholder contrast

* remove testing change

* improve the lint of the testcase

---------

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Viktor Avelino <64113566+viktoravelino@users.noreply.github.com>
Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com>
2026-06-24 11:25:31 -04:00
5ea9fe6b55 Merge branch 'release-1.11.0' into feat/a11y 2026-06-23 10:04:17 -04:00
6fae209f7e fix(a11y): add accessible names and hide decorative icons in LangflowCounts (#13731)
* fix(a11y): add accessible names and hide decorative icons in LangflowCounts

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@mac.war.can.ibm.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-06-22 18:55:30 -04:00
d36083e17d a11y: improve auth accessibility coverage (#13724)
* fix: improve auth accessibility coverage

* fix(a11y): restore delete trigger tab focus

* test(dialog): cover nested description
2026-06-22 09:32:15 -04:00
c368aded0e fix(a11y): restore focus-visible indicators (#13664)
* fix(a11y): restore focus-visible indicators

* [autofix.ci] apply automated fixes

---------

Co-authored-by: Olayinka Adelakun <olayinkaadelakun@Olayinkas-MacBook-Pro.local>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Viktor Avelino <64113566+viktoravelino@users.noreply.github.com>
2026-06-22 09:28:17 -04:00
2b7b113049 fix: warn on empty value and decrypt failure in get_all variable listing (#13741)
Co-authored-by: Janardan S Kavia <janardanskavia@Janardans-MacBook-Pro.local>
2026-06-19 17:30:49 +00:00
2ff192129a docs: add lfx-nextplaid bundle (#13679) 2026-06-19 17:11:25 +00:00
59e03266c7 feat(lfx): verified-JWT identity forwarding for lfx serve (#13632)
* feat(lfx): verified-JWT identity forwarding for lfx serve

Add an optional per-user identity layer to `lfx serve` so the edge gateway's
authenticated caller is threaded into flow execution as `user_id`. Identity
must arrive as a cryptographically verifiable JWT by default; plain gateway
headers are accepted only under an explicit, weaker trust mode.

- serve_identity.py: IdentityConfig (off / jwt / header modes, env round-trip)
  and IdentityVerifier (pyjwt) with algorithms pinned to RS256/ES256 (rejects
  alg:none and HMAC alg-confusion before any crypto), exact iss, aud
  containment, exp/nbf with skew, and a per-process TTL'd JWKS cache with
  startup prefetch, rate-limited refresh, and keep-cache-on-fetch-failure. The
  raw token never reaches a log line or error body.
- Wiring: /flows/{id}/run and /stream gain an identity dependency that
  sub-depends on verify_api_key, so identity only annotates requests that
  already cleared the serve-key floor. execute_graph_with_capture threads the
  resolved user_id through run + stream paths and graph.user_id.
- CLI options propagated to uvicorn workers via LFX_SERVE_IDENTITY_* (each
  worker keeps its own JWKS cache).
- Startup notices (failed JWKS prefetch, header-mode trust warning) are emitted
  on a guaranteed stderr console as well as the logger, since the structlog
  logger is not reliably surfaced on the serve stdout path under uvicorn.

Tests use a locally generated RSA keypair and an in-memory fake JWKS (no
network) covering off-mode regression, identity threading, the reject matrix,
rate-limited refresh, warm-cache resilience, prefetch recovery, header mode,
the serve-key floor, multi-worker env round-trip, and token-never-logged.

* [autofix.ci] apply automated fixes

* fix(lfx): require HTTPS for JWKS/issuer and fail closed on malformed JWKS

Security: plaintext http:// JWKS/issuer URLs are MITM-able — an attacker who
tampers with the response serves their own JWKS and forges tokens with the
expected iss/aud. Require https:// by default for the JWKS URL and the
issuer-derived OIDC discovery URL (and the discovered jwks_uri), with an
explicit --identity-jwt-allow-insecure-http / LFX_SERVE_IDENTITY_ALLOW_INSECURE_HTTP
escape hatch for local/dev. Non-http(s) schemes remain refused.

Availability: malformed external JSON (a JWKS or OIDC discovery doc that is a
JSON array rather than an object, or a non-string jwks_uri) raised an uncaught
AttributeError out of prefetch/request handling — aborting startup or 500ing a
request instead of failing closed. Guard the shapes and raise IdentityConfigError
so they funnel into the existing fail-closed (401) path.

Also adds ES256 unit coverage (the second accepted algorithm was only exercised
manually before).

Tests: +14 (HTTPS policy + escape hatch, malformed-shape fail-closed, ES256).

* fix(lfx): resolve identity OptionInfo leak and ANSI-fragile help assertion

serve_command declared the identity params as typer.Option(...). Direct
(non-CLI) callers that omit them got the raw OptionInfo as the value, so
IdentityConfig(mode=<OptionInfo>) raised on every serve. Convert them to
plain defaults (the CLI options live on serve_command_wrapper), completing
the pattern already applied to identity_jwt_allow_insecure_http.

Also strip ANSI before the serve --help substring assertion: rich colorizes
each hyphen-segment of an option name, so '--identity-mode' is never a literal
substring when color is forced (as in CI).

Additionally reject whitespace-only identity claims, not just empty/None, and
cover it with a parametrized test.

* Fix jwks fetch to use httpx client, avoiding redirects

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
2026-06-19 15:24:53 +00:00
c49a8db88a Merge branch 'release-1.11.0' into feat/a11y 2026-06-19 10:02:31 -04:00
2b8f7f90a0 fix: Raise on an undecryptable secret at the variable-resolution (#13681)
fix: Raise on an undecryptable secret at the variable-resolution boundary

Co-authored-by: Janardan S Kavia <janardanskavia@Janardans-MacBook-Pro.local>
2026-06-18 17:22:50 +00:00
d82723ecc8 Merge branch 'release-1.11.0' into feat/a11y 2026-06-18 11:07:36 -04:00
b033bfa22b feat(auth): external trusted JWT auth + JIT user mapping + access ceiling (#13293)
* feat(auth): external trusted JWT auth + JIT user mapping

Adds the OSS half of trusted external identity support:

- New EXTERNAL_AUTH_* AuthSettings (off by default) covering provider
  key, token transport (header/cookie), JWKS or trusted-decode, claim
  mapping, and a pluggable EXTERNAL_AUTH_IDENTITY_RESOLVER import path.
- New services/auth/external.py with JWT/JWKS validation, identity
  resolver protocol, and token extraction helpers.
- AuthService.get_or_create_user_from_claims +
  extract_user_info_from_claims implement the existing BaseAuthService
  JIT hook through SSOUserProfile - no new tables.
- _authenticate_with_token falls back to external resolution when the
  native JWT path fails, so Authorization-header callers transparently
  upgrade to external auth.
- Token extractors in services/auth/utils.py consult the configured
  external header/cookie after the native JWT path on session,
  WebSocket, SSE, and optional-user dependencies.
- /api/v1/session catches AuthenticationError so external-credential
  failures resolve to authenticated=False rather than 500.

Tests: 14 unit tests for external.py (JWT decode, claim mapping,
custom resolver) plus 3 integration tests in test_login.py exercising
the session endpoint JIT path (header + cookie + expired-token).

Co-Authored-By: phact <estevezsebastian@gmail.com>
Co-Authored-By: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com>
Based-On: langflow-ai/langflow#13280

* Update src/backend/base/langflow/services/auth/external.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix(auth): refetch JWKS once on unknown kid to survive IdP key rotation

Without this, a token signed by a newly rotated IdP key is rejected for
up to JWKS_CACHE_TTL_SECONDS (5 min) because the cached JWKS predates
the key. On a kid miss we now refetch the JWKS once, rate-limited to
one forced refresh per 30s per URL so attacker-supplied kids cannot
hammer the IdP's JWKS endpoint.

Adds JWKS-path tests (signature verification, rotation refetch,
rate-limited refresh) that were previously uncovered.

* feat(auth): add external access ceiling for trusted auth (#13637)

* feat(auth): add external access ceiling

* fix(auth): tolerate minimal external access settings

* fix(auth): address external-auth review (require JWKS audience, untangle authz/auth)

Resolves Gabriel's PR review feedback on #13293:

- Require EXTERNAL_AUTH_AUDIENCE on the JWKS verification path. Previously a
  JWKS-only config verified signature + exp but left aud/iss unbound, so a token
  the same IdP minted for a *different* relying party was accepted. decode now
  fails closed (before any network fetch) with an actionable message and binds
  aud; iss stays verified-when-set. Adds wrong-aud / missing-aud tests.

- Move the request-scoped action ceiling out of auth/external.py into a new
  authorization/access_ceiling.py so the authorization package no longer imports
  the auth layer (the only such import). Guards consult the authz-owned
  primitive; the auth layer only derives the ceiling and installs it. external.py
  re-exports the names for callers that derive/inspect the ceiling.

- _unique_external_username reuses _external_username_fallback instead of
  re-implementing the provider-digest formula.

- Read the non-optional EXTERNAL_AUTH_* settings as plain attributes (drop
  getattr(..., default), which re-hardcoded Field defaults) in service.py and
  api_key/crud.py.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* feat(authz): pass API key context to authorization (#13639)

* chore: bump version to 1.10.1

* fix(lfx): restamp component index version after 1.10.1 fork bump (#13575)

Companion to the release-1.11.0 fix (#13574). The 1.10.1 fork bump left component_index.json's version at 1.10.0; _read_component_index fails closed on the exact-version mismatch, so the bundled registry loads as None and the upgrade-gate LFX tests fail on this branch's CI.

Surgical restamp: version -> 1.10.1, sha256 recomputed with the build script's exact hashing/serialization. Entries unchanged; 2-line diff. The three affected tests pass locally.

* fix(ci): rebalance backend test splits with measured durations + raise unit-test step timeout (1.10.1) (#13585)

fix(ci): rebalance backend test splits with measured durations + raise unit-test step timeout

Unit Tests - Python 3.12 - Group 3 has been failing at 98-99% on the
nightly: the job hits the nick-fields/retry 40-minute per-attempt timeout
and pytest is SIGTERM'd mid-test, so it looks like one flaky last test
when it is actually a deterministic timeout (and the internal retry plus
run-level retries can never succeed).

Root cause is twofold:

1. .test_durations was last regenerated ~May 2025 and covered only 2,219
   of ~9,500 current unit tests, so pytest-split weighted 77% of the
   suite at the 0.73s average. The expensive client-fixture tests
   (test_webhook.py, test_login.py - each pays a full create_app +
   lifespan boot per test, 60-120s late in a CI run) clustered into
   group 3's tail, making it ~8-10 minutes slower than its siblings
   (33:15 on 3.13, >40min on 3.12 which is additionally slowed by
   astrapy disabling SSL connection reuse on Python 3.12.0-11).
   The weekly store_pytest_durations workflow that should refresh the
   file has been dying at the 6-hour GitHub job limit every week (serial
   full-suite run no longer fits), so the file silently froze.

   This regenerates the file from real per-test wall-clock measured in
   the passing Python 3.13 nightly jobs (run 27246228762 attempt 1, all
   5 groups, parsed from the -vv xdist logs: per-worker start-to-start
   deltas). 9,508 tests now have measured durations; old entries are
   kept where no new measurement exists. Simulated least_duration
   split goes from one outlier group to 5 even groups (~24.6 min each)
   with the >50s tests spread 1-2 per group instead of 7 in one.

2. timeout_minutes 40 -> 50 gives headroom for matrix-cell variance
   (3.12 runs ~20% slower than 3.13) so a slightly slow cell degrades
   gracefully instead of burning 2x40min and failing the whole run.

Follow-ups (not in this PR): fix store_pytest_durations to run with
xdist or split groups so it fits the 6h limit; investigate the in-worker
degradation that makes client-fixture boots cost 8-12s early in a run
but 60-120s after ~30 minutes.

* fix(test): raise spawn-child join timeout in test_multi_process_visibility (1.10.1) (#13590)

fix(test): raise spawn-child join timeout in test_multi_process_visibility

The test spawns a child via multiprocessing spawn context, which
cold-imports the full langflow package (plus coverage's multiprocessing
hooks in CI) before appending a single event. The 10s join timeout is
routinely exceeded on a loaded CI runner sharing 4 vCPUs with a second
xdist worker: in nightly run 27253229568 (Unit Tests - Python 3.12 -
Group 5) the test failed all 12 executions (5 reruns x 2 step attempts),
each rerun exactly 10s apart - the join deadline, not a product bug.

Raise the liveness bound to 60s (join returns immediately when the
child exits, so the passing case is unaffected) and kill the child on
timeout so a hung spawn can't leak into later tests.

* fix(ci): anchor langflow-base version extraction in nightly docker build (1.10.1) (#13593)

fix(ci): anchor langflow-base version extraction in nightly docker build

The first nightly on the 1.11 workspace (tag v1.11.0.dev0, run
27253229568) failed in Build Nightly Base Package within seconds:
'Base version format is incorrect'. The extraction (uv tree, grep
langflow-base unanchored, awk field 3, first line) broke because uv
tree now prints the langflow-base workspace-root line
('langflow-base v1.11.0.dev0', two fields) before any dependency line
('langflow-base[complete] v1.11.0.dev0' under the langflow root, three
fields), so the first match yields an empty field 3 and the format
check exits 1. uv tree's stderr is discarded, which made the real
cause invisible in CI.

Anchor to the root line and take field 2 instead - the exact pattern
the langflow (main package) extraction in this same file already uses,
which is why the main-package builds passed on the same tag. Verified
both extractions print 1.11.0.dev0 against a local checkout of
v1.11.0.dev0.

* fix(test): gate models.dev background refresh out of tests (1.10.1) (#13598)

fix(test): gate models.dev background refresh out of tests

Integration tests failed twice in nightly run 27260425158 with pyleak
EventLoopBlockError - first Integration Tests 3.14, then 3.12 on the
rerun, each time in a different test. The blocking stack points at
refresh_models_dev_periodically: every app boot unconditionally starts
a lifespan task that immediately fetches https://models.dev/api.json,
so the request lands mid-test in whatever test happens to be running.
Under pyleak's asyncio debug instrumentation the fetch blocked the loop
0.797s against a 0.2s threshold. Whichever test draws the short straw
flakes - which is why it looked transient and moved between versions.

Add a LANGFLOW_MODELS_DEV_REFRESH env gate (default unchanged: enabled)
and disable it session-wide in the backend test conftest. Tests fall
back to the bundled static model lists, which is also deterministic.

Verified: with the gate set, app boot makes zero models.dev requests;
the previously failing integration test passes.

* fix(ci): allow pre-releases when pinning the nightly in migration validation (1.10.1) (#13601)

fix(ci): allow pre-releases when pinning the nightly in migration validation

Migration Test: pip/venv (stable -> nightly) failed deterministically on
nightly run 27260425158 (twice, including a rerun):

  hint: langflow-base was requested with a pre-release marker (e.g.,
  langflow-base==1.11.0.dev1), but pre-releases weren't enabled
  (try: --prerelease=allow)

This is the first nightly publishing as a canonical .devN pre-release
of the langflow distribution (nightly -> stable bundle cutover). The
'latest' branch of the upgrade step already passes --prerelease=allow,
but the pinned-version branches do not. uv implicitly allows the
pre-release for the directly requested ==X.Y.Z.devN pin, yet langflow's
metadata pins langflow-base==X.Y.Z.devN transitively, and uv rejects
transitive pre-releases unless they are enabled - so the install fails
after the stable uninstall, sinking the migration test.

Add --prerelease=allow to both pinned-version install lines.

* fix(ci): scope nightly migration-test pre-releases to the langflow stack (1.10.1) (#13605)

fix(ci): scope nightly migration-test pre-releases to the langflow stack

The previous fix (#13599) added a global --prerelease=allow, which let
UNRELATED dependencies resolve to alphas: on nightly run 27274206250
the stable->nightly upgrade pulled pydantic 2.14.0a1 + pydantic-yaml
1.6.1a1, and the pydantic alpha breaks langchain-core at import time
(RunnablePassthrough pydantic ValidationError), failing the nightly
boot right after a successful install. Clean installs were fine - only
this upgrade path resolved the alpha combo.

Scope pre-release eligibility to the langflow lockstep stack instead:
uv accepts a pre-release when the package's own requirement carries a
pre-release marker, but not via transitive pins, and the nightly chain
is langflow -> langflow-base -> lfx -> langflow-sdk with exact ==devN
pins. Request each directly; langflow-sdk versions independently
(0.2.0.devN), so an explicit .dev0 floor marks it eligible while lfx's
exact pin selects the version. The 'latest' branch gets the same
treatment via .dev0 floors on all four.

Verified by dry-run against PyPI: langflow/langflow-base/lfx at
1.11.0.dev2 + langflow-sdk 0.2.0.dev2 resolve with pydantic staying at
stable 2.13.4.

* fix(ci): create GitHub releases on the dispatched v-prefixed tag (1.10.1) (#13609)

fix(ci): create GitHub releases on the dispatched v-prefixed tag

The create_release job passed the bare version (v stripped) as the
release tag with no commit target, so when that tag did not exist
GitHub minted a new lightweight tag at the default-branch HEAD -- the
wrong commit, still carrying the previous version (main only adopts a
release's version via the post-release back-merge). Every release since
1.8.2 shipped a stray bare tag (1.8.2, 1.8.3, 1.9.0-1.9.6, 1.10.0)
pointing at a previous-version commit, and the GitHub release had to be
manually re-pointed to the real vX.Y.Z tag after each release.

- create_release now attaches the release to inputs.release_tag for
  stable releases; pre-releases keep their computed tag (e.g.
  1.10.0rc1) but it is minted at the release commit via 'commit:'.
- release-lfx.yml pins the minted lfx-v* tag to github.sha instead of
  the default branch.

The validate-tag-format guard (#12847) only blocks at dispatch time;
create_release was re-creating the very duplicates it guards against.

* fix(ci): resolve validate-version output in release-lfx changelog link (1.10.1) (#13611)

fix(ci): resolve validate-version output in release-lfx changelog link

The create-release job references
needs.validate-version.outputs.current_version in its generated release
notes (the Full Changelog compare link), but validate-version was not in
the job's needs array, so the expression evaluated empty and the link
rendered as compare/v...lfx-vX.Y.Z (broken base).

Add validate-version to the create-release needs. This adds no real
serialization: create-release already waits on release-lfx, which
transitively requires validate-version via run-tests, and the job's
always() if-condition is unaffected.

Flagged by actionlint: property "validate-version" is not defined in
object type {build-docker, release-lfx}.

* feat(auth): external trusted JWT auth + JIT user mapping

Adds the OSS half of trusted external identity support:

- New EXTERNAL_AUTH_* AuthSettings (off by default) covering provider
  key, token transport (header/cookie), JWKS or trusted-decode, claim
  mapping, and a pluggable EXTERNAL_AUTH_IDENTITY_RESOLVER import path.
- New services/auth/external.py with JWT/JWKS validation, identity
  resolver protocol, and token extraction helpers.
- AuthService.get_or_create_user_from_claims +
  extract_user_info_from_claims implement the existing BaseAuthService
  JIT hook through SSOUserProfile - no new tables.
- _authenticate_with_token falls back to external resolution when the
  native JWT path fails, so Authorization-header callers transparently
  upgrade to external auth.
- Token extractors in services/auth/utils.py consult the configured
  external header/cookie after the native JWT path on session,
  WebSocket, SSE, and optional-user dependencies.
- /api/v1/session catches AuthenticationError so external-credential
  failures resolve to authenticated=False rather than 500.

Tests: 14 unit tests for external.py (JWT decode, claim mapping,
custom resolver) plus 3 integration tests in test_login.py exercising
the session endpoint JIT path (header + cookie + expired-token).

Co-Authored-By: phact <estevezsebastian@gmail.com>
Co-Authored-By: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com>
Based-On: langflow-ai/langflow#13280

* Update src/backend/base/langflow/services/auth/external.py

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>

* fix(auth): refetch JWKS once on unknown kid to survive IdP key rotation

Without this, a token signed by a newly rotated IdP key is rejected for
up to JWKS_CACHE_TTL_SECONDS (5 min) because the cached JWKS predates
the key. On a kid miss we now refetch the JWKS once, rate-limited to
one forced refresh per 30s per URL so attacker-supplied kids cannot
hammer the IdP's JWKS endpoint.

Adds JWKS-path tests (signature verification, rotation refetch,
rate-limited refresh) that were previously uncovered.

* fix(components): follow HTTP redirects in URL component with per-hop SSRF revalidation (#13572)

* fix(components): follow HTTP redirects in URL component with per-hop SSRF revalidation

The URL component sent every request with follow_redirects=False, so any
site whose entered URL 301s to its canonical address (http->https or
www/non-www normalization) returned the redirect stub - e.g. a bare
"301 Moved Permanently / nginx" page - as the scraped content, or failed
outright when the redirect response had an empty body.

Redirects are now followed via a new advanced "Follow Redirects" input
(default on). When SSRF protection is enabled, hops are followed manually
and each Location target is re-validated with the same blocked-IP denylist
and DNS pinning as the initial request before any connection is made,
mirroring the API Request component; cross-host hops drop sensitive
headers and chains are capped at 20 redirects.

* fix(components): compare full origin when keeping credentials across redirects, crawl from post-redirect base

Addresses CodeRabbit review:
- _headers_for_redirect now keeps Authorization/Proxy-Authorization/Cookie
  only for same-origin hops (scheme, host, port) or a direct http->https
  upgrade on default ports, exactly the cases where httpx keeps the
  Authorization header. Applied to both the URL and API Request
  components (the helper was copied from the latter).
- _crawl_recursive resolves relative links and the prevent_outside check
  against the final post-redirect URL, and marks it visited, so depth>1
  crawls work on sites that 301 to their canonical address.

* chore: regenerate component index and starter projects for release-1.10.1 base

The autofix.ci jobs uploaded but never pushed the regeneration after the
rebase, leaving the 4 URL-component templates with a stale field_order
(missing follow_redirects) and the index without the new code hashes.
Generated with the same commands CI uses: LFX_DEV=1 make
build_component_index + scripts/ci/update_starter_projects.py.
Pokedex Agent / Structured Data Analysis Agent pick up the API Request
component's new code_hash from the origin-comparison fix.

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>

* fix(ci): make release Biome lint green — NUL-delimit file list + clear pre-existing lint errors (#13550)

The Lint Frontend job runs against `main` as the base. In a release
(workflow_dispatch) run it diffs the entire release branch (~915 files) and
re-lints nearly the whole frontend, exposing two issues that per-PR linting
never hits together:

1. xargs split starter-project spec paths containing spaces (e.g.
   "News Aggregator.spec.ts" -> "News" + "Aggregator.spec.ts"), producing
   `internalError/io: No such file or directory`. NUL-delimit the file list
   so spaces are preserved. (supersedes #13381)

2. The whole-branch diff surfaced 30 pre-existing Biome errors: 22
   noExplicitAny + 8 organizeImports. Resolved with real types where safe
   (freezeObject generic, ColDef defaults, messagesSorter field shape,
   VertexBuildTypeAPI, Record<string,string>, DragEvent<HTMLElement>,
   unknown for narrowed values) and justified biome-ignore for genuinely
   loose cases (polymorphic display values, test global stubs, captured
   unexported StreamCallbacks). Imports auto-sorted via biome.

Verified locally: biome check on the full release-vs-main file set is now 0
errors (was 30); tsc unchanged at its 303-error baseline (no new type errors).

* fix: limit public flow endpoint from displaying private flow streams (#13602)

* fix: limit public flow endpoint from displaying private flow streams

* fix: Address coderabbit reviews

---------

Co-authored-by: Janardan S Kavia <janardanskavia@Janardans-MacBook-Pro.local>

* fix: enforce the FileSystemTool credential deny-list (#13625)

* enforce the FileSystemTool credential deny-list

* security checks gh review

* [autofix.ci] apply automated fixes

* feat(authz): pass API key context to authorization

* refactor(authz): address review feedback on API-key auth context

- Add AuthCredentialContext.from_api_key_result() and use it at all six
  API-key projection sites (service.py x5, mcp_projects.py) so the caveat
  fields stay in sync and no site can silently drop one.
- authz_me builds the enforce context from the public
  current_auth_context_for_authz() helper instead of reaching into the
  private guards._auth_context.
- Clear request-local credential context at the top of verify_project_auth
  to match the service.py entrypoints, so the composer-token fast path can
  never inherit stale context.

---------

Co-authored-by: phact <estevezsebastian@gmail.com>
Co-authored-by: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Janardan Singh Kavia <janardankavia@ibm.com>
Co-authored-by: Janardan S Kavia <janardanskavia@Janardans-MacBook-Pro.local>
Co-authored-by: Cristhian Zanforlin Lousa <cristhian.lousa@gmail.com>

* [autofix.ci] apply automated fixes

* fix(auth): close access-ceiling bypasses and harden external JWT auth

Address review findings on the external trusted-auth + access-ceiling work:

- Enforce the access ceiling on execution/mutation paths that bypassed the
  ensure_*_permission chokepoint: MCP project tool-call (flow execute),
  flow version snapshot/activate/delete, v1 file upload/delete, and memory
  base CRUD/ingest.
- Move the external-user API-key block into the shared authenticate_api_key
  chokepoint so /run, v2 workflow, OpenAI-compat, WebSocket, webhook and MCP
  key auth all enforce it (was only on the JWT-fallback path).
- Require exp on both the JWKS and trusted-decode paths; reject non-https
  JWKS URLs (loopback http allowed for dev).
- Normalize EXTERNAL_AUTH_PROVIDER at the config boundary so the API-key floor
  cannot be silently disabled by an empty/whitespace value.
- Make a configured EXTERNAL_AUTH_ACCESS_CLAIM_MAPPING authoritative: an
  unmapped claim value falls to the default level instead of self-elevating
  via the built-in alias table.
- Stop nulling a stored SSOUserProfile.email when a later token omits email.
- Keep the external credential usable as a fallback when a stale/invalid
  native token is present (WebSocket, SSE, optional-user paths).
- Add delete to the editor access level (deploy stays admin-only).

Adds regression tests across auth, authz guards, api-key crud, and the newly
guarded routes.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(mcp): give handle_call_tool flow stub the attrs ensure_flow_permission reads

The access-ceiling hardening added an ensure_flow_permission(EXECUTE) guard to
handle_call_tool that reads flow.user_id and flow.workspace_id, but the
_invoke_handle_call_tool flow stub only carried id/name/folder_id, raising
AttributeError. Set user_id to match the current user so the owner-override
path is exercised, and add workspace_id.

* fix(auth): close remaining ceiling gaps + external-cookie/filesystem/job-queue hardening

Synthesizes the external review (P1-P3) with the multi-agent re-review findings.

External auth:
- P1: regular HTTP (get_current_user) and /api/v1/session now extract the
  external credential separately and pass it as a fallback, so a stale/invalid
  native cookie can no longer shadow a valid external credential (previously only
  WS/SSE/optional paths did this).
- P2: clear the request-local external access ceiling at every auth entrypoint
  (api-key, raw access-token, webhook, ws api-key, MCP), not just
  authenticate_with_credentials, so a stale ceiling can never carry into a
  non-external path.
- Make a configured access-claim mapping authoritative even when it parses empty
  (all-invalid entries no longer re-enable alias self-elevation).
- A blocked external user's API key no longer increments usage counters.

Access-ceiling coverage (routes that previously escaped the deny-only cap):
- custom_component / custom_component_update (code instantiation) now enforce the
  ceiling directly (viewer denied; editor/admin/native users unchanged).
- Deprecated /upload/{flow_id}, update_project_mcp_settings, and the models.py
  default/enabled-model variable routes now call the appropriate guard.
- Memory-base guards resolve the base first and pass kb_id + real owner so plugin
  enforce runs for non-owners and audit rows carry the kb id.

Bundled hardening:
- P2: filesystem deny-list now denies a protected credential directory requested
  by basename (.ssh/.aws/.git) and as a glob entry, not just as a parent dir.
- P3: public-job marker write failures on the Redis backend now fail the build
  (503) instead of returning an un-shareable job id that 404s on other workers.

Adds regression tests across auth, authz route guards, api-key crud, external
auth, filesystem deny-list, memory bases, and the redis job queue.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* [autofix.ci] apply automated fixes

---------

Co-authored-by: phact <estevezsebastian@gmail.com>
Co-authored-by: Lucas Oliveira <62335616+lucaseduoli@users.noreply.github.com>
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Janardan Singh Kavia <janardankavia@ibm.com>
Co-authored-by: Janardan S Kavia <janardanskavia@Janardans-MacBook-Pro.local>
Co-authored-by: Cristhian Zanforlin Lousa <cristhian.lousa@gmail.com>
2026-06-17 22:58:43 +00:00
5992048bd9 Merge branch 'release-1.11.0' into feat/a11y 2026-06-17 10:55:40 -04:00
e5d42e54fc feat: upgrade Firecrawl to v2 SDK and extract into the lfx-firecrawl extension bundle (#13495)
* Upgrade Firecrawl components to firecrawl-py v2 + add Search component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Upgrade Firecrawl components to firecrawl-py v2 + add Search component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Upgrade Firecrawl components to firecrawl-py v2 + add Search component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Upgrade Firecrawl components to firecrawl-py v2 + add Search component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Upgrade Firecrawl components to firecrawl-py v2 + add Search component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Upgrade Firecrawl components to firecrawl-py v2 + add Search component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* Upgrade Firecrawl components to firecrawl-py v2 + add Search component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: add Firecrawl Search API to the bundle page

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [autofix.ci] apply automated fixes

* fix(firecrawl): D205 docstring + defensive .get('data') in crawl

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* fix(firecrawl): D205 docstring in scrape

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* perf(firecrawl): use list.extend in map (PERF401)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test: add unit tests for Firecrawl v2 components

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [autofix.ci] apply automated fixes

* test: align Firecrawl component tests with lfx _attributes pattern

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [autofix.ci] apply automated fixes

* refactor(firecrawl): remove deprecated extract endpoint component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(firecrawl): remove deprecated extract endpoint component

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test: drop extract component test (extract endpoint removed)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* docs: remove Firecrawl Extract API section (deprecated)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* [autofix.ci] apply automated fixes

* fix(firecrawl): map Search component to Firecrawl icon, drop Extract

The frontend icon map in styleUtils.ts still referenced the removed
FirecrawlExtractApi and lacked the new FirecrawlSearchApi, so the Search
node would not render the Firecrawl logo.

* chore: regenerate component index for Firecrawl v2 (Search added, Extract removed)

* refactor(firecrawl): extract components into the lfx-firecrawl extension bundle

Port the firecrawl provider out of lfx.components into a standalone
Extension Bundle at src/bundles/firecrawl (distribution: lfx-firecrawl),
following src/bundles/PORTING.md:

- Move the v2-SDK components (Scrape, Crawl, Map, Search) to
  src/bundles/firecrawl/src/lfx_firecrawl/components/firecrawl/ and
  remove the in-tree provider + its lfx.components registration.
- Own the firecrawl-py>=4,<5 pin in the bundle; drop it from
  langflow-base.
- Wire the workspace (root pyproject deps/sources/members) and uv.lock.
- Append migration-table entries (bare name, both import paths, pre-a
  slot) for the four classes; FirecrawlExtractApi gets no entries since
  the v2 SDK removed the extract endpoint and the component was dropped.
- Regenerate the component index (firecrawl category removed) and
  locales/en.json (54 firecrawl keys move out of core).
- Bundle-local unit tests + test_pilot_firecrawl_upgrade integration
  test; update Dockerfile bundle enumeration comments.

* fix(lfx): repair migration table entry fused during release-1.11.0 merge

The release-1.11.0 back-merge collided the FirecrawlSearchApi legacy_slot
entry with the NextPlaidVectorStoreComponent bare_class_name entry, mashing
both into a single object with duplicate 'target' keys, populating two of
{bare_class_name, import_path, legacy_slot}. That fails the MigrationTable
validator (entries.51) and broke the lfx loader tests.

Split it into the two intended entries so each populates exactly one
key-field. Restores the FirecrawlSearchApi and NextPlaidVectorStoreComponent
quads (60 entries total, +16 vs base). Append-only and bare-name guards pass.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>
2026-06-17 12:55:01 +00:00
97c5598ee3 fix(authz): schedule periodic audit-log retention cleanup (#13546)
* fix(authz): schedule periodic audit-log retention cleanup

clean_authz_audit_log() was only invoked once, at startup inside
initialize_services(). A long-running instance never pruned authz_audit_log
again after boot, so the table grew unbounded between restarts even though the
retention helper was already implemented and unit-tested.

Wire the same helper to a recurring background worker:

- New AuditLogCleanupWorker (services/task/audit_cleanup.py), modelled on the
  sibling temp_flow_cleanup.CleanupWorker: a stop-event-driven asyncio task that
  prunes on a fixed interval in its own session_scope(). Best-effort -- the
  helper logs-and-swallows DB errors and an outer guard keeps the loop alive, so
  it never blocks the event loop or request path.
- Gated: the worker only schedules when AUTHZ_AUDIT_ENABLED is True and
  AUTHZ_AUDIT_RETENTION_DAYS > 0; otherwise start() is a no-op. Retention=0
  stays a no-op end to end.
- Sleep-first loop: the unconditional startup sweep still prunes at boot, so the
  first scheduled pass waits one interval to avoid a redundant immediate delete.
  The startup sweep is left unchanged.
- New AUTHZ_AUDIT_CLEANUP_INTERVAL setting (default 86400 = daily, floor 300s).
- Started/stopped from the application lifespan, both best-effort.

Tests (test_audit_cleanup_worker.py) show cleanup runs repeatedly on the
recurring schedule (not just at startup), is a no-op when retention or auditing
is disabled, survives sweep failures, and -- end to end against a real SQLite
engine -- prunes a row inserted after startup while leaving in-window rows.

Closes the audit-retention-scheduling gap (C) for OSS RBAC on release-1.10.0.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* refactor(authz): read AUTHZ_AUDIT_CLEANUP_INTERVAL directly

The cleanup worker resolved the sweep interval via getattr-with-default
plus a TypeError/ValueError guard, mirroring the field default in a
module constant. Pydantic already guarantees the field is present and
>= 300, so those fallbacks were unreachable and the constant was a
second source of truth that could drift.

Read the setting directly; keep DEFAULT_CLEANUP_INTERVAL_SECONDS only as
the pre-start() placeholder for unstarted workers. Drop the matching
missing/garbage-fallback test assertion.

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 21:18:54 +00:00
5d1c36c8b1 test(authz): RBAC enforcement + share-lifecycle integration tests via a test-double enforcer (#13549)
* test(authz): RBAC enforcement + share-lifecycle integration tests via a test-double enforcer

No automated test exercised end-to-end authorization enforcement. The OSS
authorization service is a pass-through (enforce() always returns True,
supports_cross_user_fetch() is False), so allow/deny semantics could not be
asserted against it — only guard-wiring unit tests existed.

Add a lightweight, OSS-only test-double enforcer plus integration tests that
drive the real flow routes over HTTP under a genuine allow/deny signal — no EE
Casbin package required.

- _policy_double.py: PolicyTestAuthorizationService derives allow/deny from the
  seeded authz_role / authz_role_assignment / authz_share rows and sets
  SUPPORTS_CROSS_USER_FETCH=True. install_policy_authz() swaps it onto the
  service manager (str-enum keys make ServiceType interchangeable) and flips
  AUTHZ_ENABLED=true / AUTHZ_SUPERUSER_BYPASS=false, restoring both on exit, so
  every get_authorization_service() call site (guards, fetch, listing, helpers)
  sees it for the duration of a test. Ships seed helpers (roles/assignments/
  shares) so tests stay declarative.

- test_rbac_enforcement_integration.py:
  * Role matrix (Phase 1.11) on flow routes, with flows owned by a separate user
    so the guards' owner-override does not mask the role decision:
      - viewer: read + execute (build) allowed; write/delete -> 404; create -> 403
      - developer: write + create allowed; delete -> 404
      - admin: full, including delete
  * Share lifecycle (Phase 3.13): Alice shares a flow with Bob ->
    Bob GET/PATCH/build succeed; without the share every fetch route -> 404
    (UUID-privacy mask). A read-level share grants GET but 404s PATCH, proving
    permission_level (not mere share presence) is enforced.
  * Domain resolution: a workspace-scoped grant authorizes a flow in that
    workspace but 404s a flow in another — trips if _resolve_authz_domain
    regresses.

In each test a cross-user GET -> 200 (only possible with enforcement on +
share-aware fetch) is the linchpin proving the paired deny is real enforcement,
not an owner-scoped fetch miss; removing a guard flips a 404 to 200/200.

Closes the enforcement integration-test gap (D) for OSS RBAC on release-1.10.0.
Per the ticket's triage note, the reusable test-double also stands alone if the
team prefers the deny-path matrix to live in EE.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

* test(authz): harden policy double per review — strict scoped grants, deterministic seeding, read-share build denial

- _assignment_covers: a scoped assignment missing domain_id no longer
  widens to global coverage; only domain_type='global' is global
- assign_role: fail fast (ValueError) on non-global assignments without
  a domain_id so malformed grants can't hide domain-resolution bugs
- seed_system_roles: overwrite preexisting viewer/developer/admin rows
  so the asserted policy matrix is always SYSTEM_ROLE_PERMISSIONS
- read-only share test: also assert build/execute is denied (404), not
  just PATCH

---------

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-16 13:35:05 -07:00
40d7814739 feat: New Bundle support for Multi-vector NextPLAID vector store (#13553)
* nextplaid integrate

* doc ids fix

* multivec fixes

* type check

* refactor: ship NextPlaid as the lfx-nextplaid extension bundle

Convert the in-tree NextPlaid vector store and its companion vLLM
multivector embeddings into a standalone `lfx-nextplaid` Extension Bundle,
following src/bundles/PORTING.md (cf. lfx-arxiv, lfx-ibm). The whole
feature now ships as an additive bundle with no core modifications.

- Move both components into src/bundles/nextplaid (components/nextplaid),
  dropping src/lfx/.../components/nextplaid and reverting the core vllm
  __init__ multivector additions.
- Bundle declares its own runtime deps (langchain-plaid, pillow) and ships
  extension.json + the langflow.extensions entry point.
- Add migration_table entries mapping the legacy class names / import
  paths to ext:nextplaid:*@official; wire the workspace (root pyproject,
  uv.lock).
- Add the pilot upgrade integration test and bundle-local unit tests.
- Declare explicit outputs on NextPlaidVectorStoreComponent so the
  extension validator can resolve its output methods.

* fix: address CodeRabbit review on NextPlaid bundle

- nextplaid: derive stable text IDs from source/page+content (not content
  alone) and fingerprint raw PIL images by bytes (not batch position) so
  ingests upsert instead of colliding/overwriting unrelated vectors
- vllm impl: validate the /pooling response envelope before nested indexing,
  raising a clear RuntimeError on malformed text/image responses
- icon: use the isDark boolean prop contract instead of the isdark string
- test: gate the distribution check on package presence (PackageNotFoundError)
  so genuine import failures surface instead of being skipped

---------

Co-authored-by: Meet <meet@dhcp-9-127-22-227.c4p-in.ibm.com>
Co-authored-by: Eric Hare <ericrhare@gmail.com>
2026-06-16 16:00:26 +00:00
caad567248 Merge branch 'release-1.11.0' into feat/a11y 2026-06-15 23:56:51 -04:00
0007f2032d feat: Add a11y regression scan suite (#13663)
* test: add component a11y unit tests (jest-axe)

Cover 14 components in two waves. 16 tests fail by design - each
encodes a known gap from a11y-action-plan (phases 0-3) and flips to
a regression lock once the component fix lands. 23 tests pass as
regression locks for already-correct semantics.

* ci: split a11y unit tests into separate workflow

Main jest CI excludes *.a11y.test.* so known-gap failures don't
block PRs; new a11y-unit-tests.yml runs them as informational check.

* fix(a11y): resolve component gaps flagged by a11y unit tests

Fixes all 16 failing jest-axe gap tests:
- TableHead defaults scope=col
- alert display area gets aria-live region
- app header becomes <header> landmark; bell button labeled
- icon wrapper decorative by default (aria-hidden), ariaLabel opt-in
- Input drops wrapping <label> (name pollution) and hides placeholder span
- password toggle back in tab order with aria-label/aria-pressed
- CheckBoxDiv exposes checkbox role + state
- accordion trigger renders native Radix button
- dialogs focus container on open instead of suppressing autofocus
- full-screen modal exposes dialog role/aria-modal/ariaLabel
- flow list card focusable with keyboard activation

Also wraps test focus calls in act() and mocks the icon loader so
the a11y suite runs without React warnings.

* fix: skip Puppeteer Chrome download in remaining Dockerfiles

frontend and base images still ran bare npm install; puppeteer (via
accessibility-checker, test-only) tried to fetch Chrome and broke the
Docker image build in CI.

* test: extend a11y unit test coverage (jest-axe)

Adds axe + semantics tests for untested primitives (button, alert,
textarea, radio-group, dropdown-menu, tooltip, popover) and two
known-gap tests that fail by design until fixes land:
- copyFieldAreaComponent copy action is a bare div onClick (plan 2.4)
- DialogContentWithouFixed renders an empty fragment (plan 1.6)

* fix: make webhook copy field a real button (a11y)

Copy action was a bare div onClick - no role, name, or keyboard
support (a11y-action-plan 2.4). Drops the no-longer-needed
DialogContentWithouFixed known-gap test.

* feat: update a11y unit tests and improve accessibility semantics in components

* feat: enable pull request trigger for a11y scan workflow

* test: add a11y regression scan suite

* test: make a11y scans non-blocking

* test: discover a11y scan specs

* ci: group a11y workflow checks
2026-06-15 23:49:21 -04:00
72f86c96eb ci: gate backend tests by Python changes (#13614)
* ci: gate backend tests by Python changes

* fix(ci): update test conditions to include docs-only path filter

* Update .github/workflows/ci.yml

Co-authored-by: Adam-Aghili <149833988+Adam-Aghili@users.noreply.github.com>

---------

Co-authored-by: Adam-Aghili <149833988+Adam-Aghili@users.noreply.github.com>
2026-06-15 18:35:30 +00:00
287ca4c1e7 Merge branch 'release-1.11.0' into feat/a11y 2026-06-15 14:35:14 -04:00
3c1b2cdba6 test: add component a11y unit tests (jest-axe) (#13613)
* test: add component a11y unit tests (jest-axe)

Cover 14 components in two waves. 16 tests fail by design - each
encodes a known gap from a11y-action-plan (phases 0-3) and flips to
a regression lock once the component fix lands. 23 tests pass as
regression locks for already-correct semantics.

* ci: split a11y unit tests into separate workflow

Main jest CI excludes *.a11y.test.* so known-gap failures don't
block PRs; new a11y-unit-tests.yml runs them as informational check.

* fix(a11y): resolve component gaps flagged by a11y unit tests

Fixes all 16 failing jest-axe gap tests:
- TableHead defaults scope=col
- alert display area gets aria-live region
- app header becomes <header> landmark; bell button labeled
- icon wrapper decorative by default (aria-hidden), ariaLabel opt-in
- Input drops wrapping <label> (name pollution) and hides placeholder span
- password toggle back in tab order with aria-label/aria-pressed
- CheckBoxDiv exposes checkbox role + state
- accordion trigger renders native Radix button
- dialogs focus container on open instead of suppressing autofocus
- full-screen modal exposes dialog role/aria-modal/ariaLabel
- flow list card focusable with keyboard activation

Also wraps test focus calls in act() and mocks the icon loader so
the a11y suite runs without React warnings.

* fix: skip Puppeteer Chrome download in remaining Dockerfiles

frontend and base images still ran bare npm install; puppeteer (via
accessibility-checker, test-only) tried to fetch Chrome and broke the
Docker image build in CI.

* test: extend a11y unit test coverage (jest-axe)

Adds axe + semantics tests for untested primitives (button, alert,
textarea, radio-group, dropdown-menu, tooltip, popover) and two
known-gap tests that fail by design until fixes land:
- copyFieldAreaComponent copy action is a bare div onClick (plan 2.4)
- DialogContentWithouFixed renders an empty fragment (plan 1.6)

* fix: make webhook copy field a real button (a11y)

Copy action was a bare div onClick - no role, name, or keyboard
support (a11y-action-plan 2.4). Drops the no-longer-needed
DialogContentWithouFixed known-gap test.

* feat: update a11y unit tests and improve accessibility semantics in components

* feat: enable pull request trigger for a11y scan workflow
2026-06-15 14:34:42 -04:00
bb930e2ffe docs: build docker from source (#13041)
* docs-add-build-from-source-and-refresh

* peer review

* peer-review

* peer-review

* peer-review
2026-06-15 17:16:28 +00:00
ca29afab5c fix(frontend): restore Inspection Panel access to hidden advanced fields (1.11.0) (#13626)
fix(frontend): restore Inspection Panel access to hidden advanced fields

Fields that were both advanced=True and listed in HIDDEN_FIELDS became
unreachable from the Inspection Panel: hidden from the node body (advanced)
and removed from the panel (HIDDEN_FIELDS), leaving no edit path. This
affected every HIDDEN_FIELDS entry, originally reported for Chat Input/Output
Store Messages (should_store_message).

Keep HIDDEN_FIELDS out of the default advanced view (the #12473 declutter
intent) but stop filtering them out of edit-fields mode, so users can surface
and edit them via the visibility toggle. Also drop the stale Agent verbose
entry (removed from the component via drop = {verbose}) while keeping the
still-live format_instructions and output_schema hidden. i18n the two
remaining hardcoded panel strings.

Fixes #13595
2026-06-15 16:51:46 +00:00
de06b9176a fix(frontend): duplicate tooltip + raw i18n key on collapsed sidebar nav (1.11.0) (#13652)
fix(frontend): remove duplicate tooltip and raw i18n key on collapsed sidebar nav

The floating canvas control nav (shown when the sidebar is collapsed)
rendered two tooltips per icon: a native `title` attribute on
ControlButton plus the styled ShadTooltip. On top of that,
MemoizedComponents passed the raw i18n key (`item.tooltip`) as the
tooltip text instead of running it through `t()`, so the ShadTooltip
exposed strings like `sidebar.nav.bundles` while the native title showed
the bare id (`bundles`).

- CanvasControlButton: drop the native `title` (the duplicate tooltip);
  keep accessibility via `aria-label`. The ShadTooltip is the single
  visual tooltip. This also removes the redundant native tooltip from the
  zoom/fit/lock control buttons.
- MemoizedComponents: translate the nav tooltip with `t(item.tooltip)`.

Adds an isolated CanvasControlButton regression test asserting no native
`title` and that the label is surfaced via aria-label + ShadTooltip.
2026-06-15 14:44:37 +00:00
9dbde72246 Merge branch 'release-1.11.0' into feat/a11y 2026-06-15 09:44:19 -04:00
02319696dc feat: add docs feedback components (#13627)
* add-docs-page-feedback-component

* make-buttons-same-size
2026-06-12 18:03:54 +00:00
3e3a24e353 fix: fail fast when Redis job queue backend is unreachable (#13456)
* fix: fail fast when Redis job queue backend is unreachable

When LANGFLOW_JOB_QUEUE_TYPE=redis is set but Redis is not reachable,
Langflow booted normally and then raised a raw redis ConnectionError as
a 500 on the first flow execution, with no clear cause.

Probe Redis at startup (bounded retry) and abort boot with an actionable
error when it stays unreachable, mirroring the existing external-cache
connectivity check. Translate a later Redis outage on the build and
ownership paths into a clean HTTP 503 via a typed
JobQueueBackendUnavailableError instead of a raw stack trace.

* [autofix.ci] apply automated fixes

* [autofix.ci] apply automated fixes (attempt 2/3)

* chore: auto-bake note keys and regenerate backend locales/en.json [skip ci]

* [autofix.ci] apply automated fixes

* fix: address review - probe redis pre-start, redact credentials, cancel orphaned build

- is_connected() now probes with a temporary client when the service has
  not started yet: the startup fail-fast in initialize_services() runs
  before the per-worker start() creates the client, so it previously
  rejected every redis boot, healthy or not
- connection_target redacts URL userinfo so credentials never reach
  server logs or the HTTP 503 detail
- build_flow cancels the just-started build (best-effort) when owner
  registration fails, instead of leaving an unreachable build running
- register_job_owner only records the local owner after the Redis write
  succeeds, so a failed write cannot leave same-worker ownership checks
  passing while other workers see the job as unowned

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-06-12 17:13:55 +00:00
538bcf3845 feat: docs page copy-as-markdown keyboard shortcut (#13628)
* add-copy-page-keyboard-shortcut

* peer-review
2026-06-12 16:58:50 +00:00
415323ec6d docs: migrate code blocks to native Prism and restyle API reference pages (#13299)
* docs: migrate code blocks from CodeSnippet to native Prism

Replace the custom CodeSnippet component (@code-hike/lighter) with
Docusaurus's native @theme/CodeBlock across all MDX files (current and
versioned docs). Add bash to additionalLanguages and swizzle
prism-include-languages.js to add custom token highlighting for shell
commands and flags. Remove @code-hike/mdx dependency.

* docs: improve inline code styling

Darken inline code background, increase horizontal padding to 0.4em,
fix vertical alignment, and remove border in light mode.

* docs: address PR review — fix code slice regression and CSS/regex polish

- Inline RecursiveCharacterTextSplitter inputs and methods as literal
  code blocks in concepts-components.mdx (current + 1.8.0 + 1.9.0),
  restoring the focused slices lost when migrating from CodeSnippet
- Scope bash-plain Prism regex to unambiguous CLI subcommands only,
  removing generic bash builtins (run, add, get, set, start, stop, etc.)
- Merge duplicate .theme-code-block CSS rules into a single declaration

* fix(docs): prevent horizontal scroll on API docs pages

The Redoc two-column layout (sidebar 300px + api-content 1300px)
totals 1600px, expanding .main-wrapper beyond narrower viewports
because it has overflow:visible. Clips at .main-wrapper using the
html.plugin-redoc class that Docusaurus adds on API pages only.

* fix(docs): API docs sidebar and layout fixes

- Disable Redoc built-in search (disableSearch: true)
- Pin sidebar top to navbar height (top: 60px) so it never hides behind navbar
- Remove hardcoded #111 background from dark mode sidebar

* fix(docs): render markdown correctly in API docs descriptions

The _clean_descriptions function was converting newlines to <br> tags,
mixing HTML with Markdown. CommonMark stops parsing Markdown headings
(###) inside HTML blocks, causing them to appear as literal text in Redoc.

Replace the <br> conversion with a simple strip() so descriptions remain
pure Markdown and Redoc renders headings, lists, and code blocks correctly.

* feat(docs): align API docs colors with Langflow brand

- Set primaryColor to #F471B5 (Langflow pink)
- Add HTTP method badge colors matching Langflow palette
- Set schema.linesColor and requireLabelColor to brand pink
- Set inline code color to pink, headers to #e3e3e3
- Set sidebar background to #18181b (matches frontend dark bg)
- Set rightPanel background to #0d0d0f, codeBlock to #161618
- Refactor: move color config from CSS to theme.theme where safe
- Remove dead search input CSS (search disabled via disableSearch:true)
- Consolidate duplicate .menu-content rules

* wip(docs): API docs styling — colors, components, light/dark themes

* fix(docs): fix Response samples h3 title padding and refactor HTTP method button CSS

* feat(docs): add sidebar dark background, active item styles, and right panel color adjustments

* fix(docs): add sidebar borders and remove operation divider border

* fix(docs): fix expanded response background and align dark/light theme colors

* refactor(docs): standardize selectors, comments and remove duplicate rules in redocusaurus.css

* refactor(docs): apply PR review — CSS custom properties, version pin, dom version comments, fix overflow

* fix(docs): fix Redocly badge visibility covered by sidebar background

* fix(docs): extend sidebar border-right to Redocly badge area

* refactor(docs): replace hardcoded #ffffff label color with --redoc-text-label variable

* fix(docs): lighten inline code background in API docs dark theme

Redoc's default typography.code.backgroundColor (rgba(38, 50, 56, 0.05))
is nearly invisible over the dark background. Override it with
rgba(255, 255, 255, 0.05) in dark theme only, excluding pre > code so
code sample blocks stay unaffected.

* feat(docs): align docs primary pink with API spec brand color

Use #f471b5 (API spec primaryColor) as --ifm-color-primary in dark theme
and #e44fa0 (slightly darkened for contrast on white) in light theme.
Remove dark-theme pink overrides in sidebar.css (#ff6ad0 CTA and
hsla(329, 55%, 68%) active TOC link) — they compensated for the old
muted pink and are redundant now that the primary itself is bright.

* feat(docs): lighten dark theme text colors for better readability

Bump body text (#a8a8b0 -> #bcbcc4), headings (#cdcdd4 -> #dcdce2)
and sidebar menu (#8a8a92 -> #9c9ca4) one step brighter.

* chore(docs): add IBM Equal Access accessibility-checker setup

Add accessibility-checker as devDependency with aceconfig.js (policy
IBM_Accessibility, JSON reports in docs/a11y-results/, gitignored).
Scan with: npx achecker <url> against a built docs site.

* fix(docs): WCAG AA contrast and ARIA fixes across docs and API reference

Validated with IBM Equal Access scans (light theme): home, quickstart and
component pages at 0 violations; /api from 3382 down to 167 (all remaining
are Redoc-internal DOM: schema table headers, svg/select labels).

Docs site:
- Light primary pink #d11074 — passes 4.5:1 on white and inline-code bg
- Light Prism palette darkened per-token to pass 4.5:1 on #f9f9fd
- TabItem swizzled to give tabpanels an accessible name (aria-label)
- codeBlockA11y client module: scrollable code blocks get role=region +
  unique label; non-scrollable ones lose the needless tabindex

API reference (Redocusaurus):
- redocA11y client module: role=main on api-content, role=navigation on
  sidebar — fixes 1924 aria_content_in_landmark violations
- HTTP method badges and response chips darkened to pass with white text
- Light-theme overrides: accessible pink #cd1072 for links, required
  markers, constraint chips, schema tree lines; darker grays for utility
  buttons and type labels (incl. 0.7-opacity wrapper fix)
- Sidebar active/hover items use regular text color, method badges keep
  their own colors; expandable property names match non-expandable ones

* fix(docs): WCAG AA contrast fixes for dark theme

Validated with IBM Equal Access scans in dark mode (temporary
colorMode.defaultMode flip during scanning): home, quickstart and
component pages at 0 violations; /api matches light at 167 remaining
(all Redoc-internal DOM: table headers, svg/select labels).

- Code block comments/line numbers #4a5060 -> #798197 (4.56:1 on #18181a)
- Redoc dark sample tokens: boolean/null #e95c59, number #5392b8
- Status-code tabs: lift docusaurus-theme-redoc's #303846 !important
  selected-tab rule with a higher-specificity override
- oneOf variant buttons: dark text in both themes (their white/pink
  backgrounds are theme-independent)
- redocA11y client module: patch response chip colors (success green /
  error red) to dark-accessible variants when data-theme=dark — a single
  Redoc theme color cannot pass on both light and dark derived
  backgrounds, and status is only distinguishable by computed color

* fix(docs): resolve remaining Redoc-internal accessibility violations

Extend the redocA11y client module with semantic patches for Redoc DOM
the theme cannot reach (validated: 0 IBM Equal Access violations on all
scanned pages in both light and dark themes):

- Decorative svg chevrons/arrows: aria-hidden=true (svg_graphics_labelled)
- Content-type dropdowns: aria-label (input_label_exists)
- Schema field tables (2-col name|description layout, no <th> anywhere):
  role=presentation — content reads in DOM order; role=rowheader on <td>
  is invalid ARIA inside a native table (table_headers_exists/related)
- Semantic patches run on the next animation frame after DOM changes so
  Redoc's lazy-rendered operations are covered immediately; the heavier
  color patch stays debounced

* ci(docs): gate docs accessibility with IBM Equal Access scans

Add test-docs-accessibility job to docs_test.yml (rides the existing
docs/** path filter from ci.yml): build + scan 4 representative pages
(home, quickstart, component page, /api) in light theme, then flip
colorMode.defaultMode to dark, rebuild and scan again.

- scripts/a11y-ci.sh: serves the build and runs npx achecker per page
  with one retry to absorb Redoc lazy-render timing flakes; any real
  violation fails the job (failLevels: violation)
- aceconfig.js: pin ruleArchive to 19May2026 so IBM rule updates don't
  break CI without a deliberate bump

* ci(docs): fix Chrome sandbox launch on Ubuntu 24.04 runners

Ubuntu 24.04 restricts unprivileged user namespaces via AppArmor, which
prevents puppeteer's Chrome (used by the IBM checker) from starting its
sandbox. Re-enable them with the documented sysctl workaround instead of
weakening the browser with --no-sandbox.

* fix(docs): align response status code with description text

Redoc sets vertical-align: top and a smaller line-height on the status
code <strong> inside response buttons, leaving "200" visually higher
than "Successful Response". Align both to the shared text baseline.

* refactor(docs): apply PR review feedback

- redocA11y: match only real Redoc routes (/api, /api/workflow) — a bare
  startsWith("/api") also matched docs pages like /api-request and
  leaked one body MutationObserver per navigation
- codeBlockA11y: also observe the hidden attribute — Docusaurus tabs
  toggle panels via hidden (no childList mutation), so scrollable blocks
  inside an initially hidden tab were never re-evaluated for tabindex
- Extract Prism themes to src/prismThemes.js (docusaurus.config.js was
  past the 600-line red flag)
- concepts-components.mdx (current + 1.9.0 + 1.8.0): comment pointing
  hardcoded snippets to recursive_character.py to mitigate drift

Validated: clean build + IBM Equal Access scans 4/4 passing.

* replace-openapi-file-with-1.10

* migrate-prism-changes-to-1.10-version

* a11y-script-dont-block

---------

Co-authored-by: Mendon Kissling <59585235+mendonk@users.noreply.github.com>
2026-06-12 13:58:04 +00:00
d76e217adc feat: enhance a11y scan workflow to resolve and scan latest release branches 2026-06-12 09:57:51 -04:00
583afd09b8 Merge branch 'release-1.11.0' into feat/a11y 2026-06-12 09:50:04 -04:00
66318cf7c2 Merge branch 'feat/a11y' of github.com:langflow-ai/langflow into feat/a11y 2026-06-10 14:46:56 -04:00
cd9ab691e8 feat: skip Puppeteer download during npm install in Dockerfiles for accessibility testing 2026-06-10 14:46:52 -04:00
db8da2a2fe Merge branch 'release-1.10.0' into feat/a11y 2026-06-10 13:40:54 -04:00
6d5ef555a0 feat: update a11y scan workflow to allow testing from feat/a11y branch 2026-06-10 11:46:36 -04:00
170acdea0a feat: add GitHub Actions workflow for IBM accessibility scans 2026-06-10 11:43:34 -04:00
29140c06f0 fix(ci): resolve validate-version output in release-lfx changelog link (1.11.0) (#13612)
fix(ci): resolve validate-version output in release-lfx changelog link

The create-release job references
needs.validate-version.outputs.current_version in its generated release
notes (the Full Changelog compare link), but validate-version was not in
the job's needs array, so the expression evaluated empty and the link
rendered as compare/v...lfx-vX.Y.Z (broken base).

Add validate-version to the create-release needs. This adds no real
serialization: create-release already waits on release-lfx, which
transitively requires validate-version via run-tests, and the job's
always() if-condition is unaffected.

Flagged by actionlint: property "validate-version" is not defined in
object type {build-docker, release-lfx}.
2026-06-10 08:42:28 -07:00
dea7b09257 fix(ci): create GitHub releases on the dispatched v-prefixed tag (1.11.0) (#13607)
fix(ci): create GitHub releases on the dispatched v-prefixed tag

The create_release job passed the bare version (v stripped) as the
release tag with no commit target, so when that tag did not exist
GitHub minted a new lightweight tag at the default-branch HEAD -- the
wrong commit, still carrying the previous version (main only adopts a
release's version via the post-release back-merge). Every release since
1.8.2 shipped a stray bare tag (1.8.2, 1.8.3, 1.9.0-1.9.6, 1.10.0)
pointing at a previous-version commit, and the GitHub release had to be
manually re-pointed to the real vX.Y.Z tag after each release.

- create_release now attaches the release to inputs.release_tag for
  stable releases; pre-releases keep their computed tag (e.g.
  1.10.0rc1) but it is minted at the release commit via 'commit:'.
- release-lfx.yml pins the minted lfx-v* tag to github.sha instead of
  the default branch.

The validate-tag-format guard (#12847) only blocks at dispatch time;
create_release was re-creating the very duplicates it guards against.
2026-06-10 08:41:41 -07:00
f188b5bc4f feat: enhance accessibility testing with JSON report aggregation and new tests 2026-06-10 11:31:11 -04:00
84c3bbebcd fix(ci): scope nightly migration-test pre-releases to the langflow stack (1.11.0) (#13604)
fix(ci): scope nightly migration-test pre-releases to the langflow stack

The previous fix (#13599) added a global --prerelease=allow, which let
UNRELATED dependencies resolve to alphas: on nightly run 27274206250
the stable->nightly upgrade pulled pydantic 2.14.0a1 + pydantic-yaml
1.6.1a1, and the pydantic alpha breaks langchain-core at import time
(RunnablePassthrough pydantic ValidationError), failing the nightly
boot right after a successful install. Clean installs were fine - only
this upgrade path resolved the alpha combo.

Scope pre-release eligibility to the langflow lockstep stack instead:
uv accepts a pre-release when the package's own requirement carries a
pre-release marker, but not via transitive pins, and the nightly chain
is langflow -> langflow-base -> lfx -> langflow-sdk with exact ==devN
pins. Request each directly; langflow-sdk versions independently
(0.2.0.devN), so an explicit .dev0 floor marks it eligible while lfx's
exact pin selects the version. The 'latest' branch gets the same
treatment via .dev0 floors on all four.

Verified by dry-run against PyPI: langflow/langflow-base/lfx at
1.11.0.dev2 + langflow-sdk 0.2.0.dev2 resolve with pydantic staying at
stable 2.13.4.
2026-06-10 07:19:36 -07:00
75e01157fe fix(ci): allow pre-releases when pinning the nightly in migration validation (1.11.0) (#13600)
fix(ci): allow pre-releases when pinning the nightly in migration validation

Migration Test: pip/venv (stable -> nightly) failed deterministically on
nightly run 27260425158 (twice, including a rerun):

  hint: langflow-base was requested with a pre-release marker (e.g.,
  langflow-base==1.11.0.dev1), but pre-releases weren't enabled
  (try: --prerelease=allow)

This is the first nightly publishing as a canonical .devN pre-release
of the langflow distribution (nightly -> stable bundle cutover). The
'latest' branch of the upgrade step already passes --prerelease=allow,
but the pinned-version branches do not. uv implicitly allows the
pre-release for the directly requested ==X.Y.Z.devN pin, yet langflow's
metadata pins langflow-base==X.Y.Z.devN transitively, and uv rejects
transitive pre-releases unless they are enabled - so the install fails
after the stable uninstall, sinking the migration test.

Add --prerelease=allow to both pinned-version install lines.
2026-06-10 04:50:26 -07:00
0555eeced1 fix(test): gate models.dev background refresh out of tests (#13596)
Integration tests failed twice in nightly run 27260425158 with pyleak
EventLoopBlockError - first Integration Tests 3.14, then 3.12 on the
rerun, each time in a different test. The blocking stack points at
refresh_models_dev_periodically: every app boot unconditionally starts
a lifespan task that immediately fetches https://models.dev/api.json,
so the request lands mid-test in whatever test happens to be running.
Under pyleak's asyncio debug instrumentation the fetch blocked the loop
0.797s against a 0.2s threshold. Whichever test draws the short straw
flakes - which is why it looked transient and moved between versions.

Add a LANGFLOW_MODELS_DEV_REFRESH env gate (default unchanged: enabled)
and disable it session-wide in the backend test conftest. Tests fall
back to the bundled static model lists, which is also deterministic.

Verified: with the gate set, app boot makes zero models.dev requests;
the previously failing integration test passes.
2026-06-10 04:36:38 -07:00
086e38898d fix(ci): anchor langflow-base version extraction in nightly docker build (1.11.0) (#13592)
fix(ci): anchor langflow-base version extraction in nightly docker build

The first nightly on the 1.11 workspace (tag v1.11.0.dev0, run
27253229568) failed in Build Nightly Base Package within seconds:
'Base version format is incorrect'. The extraction (uv tree, grep
langflow-base unanchored, awk field 3, first line) broke because uv
tree now prints the langflow-base workspace-root line
('langflow-base v1.11.0.dev0', two fields) before any dependency line
('langflow-base[complete] v1.11.0.dev0' under the langflow root, three
fields), so the first match yields an empty field 3 and the format
check exits 1. uv tree's stderr is discarded, which made the real
cause invisible in CI.

Anchor to the root line and take field 2 instead - the exact pattern
the langflow (main package) extraction in this same file already uses,
which is why the main-package builds passed on the same tag. Verified
both extractions print 1.11.0.dev0 against a local checkout of
v1.11.0.dev0.
2026-06-10 00:25:55 -07:00
d065523493 fix(test): raise spawn-child join timeout in test_multi_process_visibility (#13588)
The test spawns a child via multiprocessing spawn context, which
cold-imports the full langflow package (plus coverage's multiprocessing
hooks in CI) before appending a single event. The 10s join timeout is
routinely exceeded on a loaded CI runner sharing 4 vCPUs with a second
xdist worker: in nightly run 27253229568 (Unit Tests - Python 3.12 -
Group 5) the test failed all 12 executions (5 reruns x 2 step attempts),
each rerun exactly 10s apart - the join deadline, not a product bug.

Raise the liveness bound to 60s (join returns immediately when the
child exits, so the passing case is unaffected) and kill the child on
timeout so a hung spawn can't leak into later tests.
2026-06-09 23:13:35 -07:00
17447920f9 fix(ci): rebalance backend test splits with measured durations + raise unit-test step timeout (#13583)
Unit Tests - Python 3.12 - Group 3 has been failing at 98-99% on the
nightly: the job hits the nick-fields/retry 40-minute per-attempt timeout
and pytest is SIGTERM'd mid-test, so it looks like one flaky last test
when it is actually a deterministic timeout (and the internal retry plus
run-level retries can never succeed).

Root cause is twofold:

1. .test_durations was last regenerated ~May 2025 and covered only 2,219
   of ~9,500 current unit tests, so pytest-split weighted 77% of the
   suite at the 0.73s average. The expensive client-fixture tests
   (test_webhook.py, test_login.py - each pays a full create_app +
   lifespan boot per test, 60-120s late in a CI run) clustered into
   group 3's tail, making it ~8-10 minutes slower than its siblings
   (33:15 on 3.13, >40min on 3.12 which is additionally slowed by
   astrapy disabling SSL connection reuse on Python 3.12.0-11).
   The weekly store_pytest_durations workflow that should refresh the
   file has been dying at the 6-hour GitHub job limit every week (serial
   full-suite run no longer fits), so the file silently froze.

   This regenerates the file from real per-test wall-clock measured in
   the passing Python 3.13 nightly jobs (run 27246228762 attempt 1, all
   5 groups, parsed from the -vv xdist logs: per-worker start-to-start
   deltas). 9,508 tests now have measured durations; old entries are
   kept where no new measurement exists. Simulated least_duration
   split goes from one outlier group to 5 even groups (~24.6 min each)
   with the >50s tests spread 1-2 per group instead of 7 in one.

2. timeout_minutes 40 -> 50 gives headroom for matrix-cell variance
   (3.12 runs ~20% slower than 3.13) so a slightly slow cell degrades
   gracefully instead of burning 2x40min and failing the whole run.

Follow-ups (not in this PR): fix store_pytest_durations to run with
xdist or split groups so it fits the 6h limit; investigate the in-worker
degradation that makes client-fixture boots cost 8-12s early in a run
but 60-120s after ~30 minutes.
2026-06-09 21:28:02 -07:00
ee659ca38c fix(bundles): floor lfx pin at the minor line's .dev0 so nightlies resolve
The first 1.11.0.dev0 nightly failed its "Test Langflow Main CLI" step:
the fork bump's sync_bundle_lfx_pin.py re-synced every bundle floor to
lfx>=1.11.0, and PEP 440 sorts the nightly's 1.11.0.dev0 BELOW 1.11.0,
so the workspace-built bundles (whose metadata shadows the satisfiable
PyPI lfx-arxiv 0.1.1 during `uv pip install dist/*.whl`) reject the
branch's own lfx while langflow-base pins it exactly — unresolvable.

Floor at lfx>=X.Y.0.dev0,<(X+1).0.0 instead: X.Y.0.dev0 is the lowest
version PEP 440 admits in the minor line, so every devN / rcN / final
satisfies the floor while older lines and the next major stay excluded.
This closes the NIGHTLY.md activation-gate hole structurally — future
minor forks re-sync to a floor their own nightlies already satisfy.

- sync_bundle_lfx_pin.py: lfx_floor_spec emits the .dev0 floor
- port_bundle.py: mirrored _current_lfx_floor kept in step
- bundle pyprojects restamped via the script (arxiv/docling/duckduckgo/ibm)
- test_bundle_lfx_pin.py expectations updated (20/20 passing)
- NIGHTLY.md gate section annotated with the post-activation fix

uv.lock is unaffected (workspace lfx is recorded as an editable source
with no specifier — which is also why uv sync/lock passed in the same
job). The release.yml RC floor-relax sed still matches the new form;
now redundant but harmless. No bundle version bump needed: published
0.1.1 floors >=1.10.0.rc0, satisfiable by the whole 1.11 line.
2026-06-09 18:02:43 -07:00
7a784515e0 fix(lfx): restamp component index version after 1.11.0 fork bump (#13574)
The release-1.11.0 fork bumped lfx to 1.11.0 but left component_index.json's version field at 1.10.0. _read_component_index fails closed on exact version mismatch, so the bundled registry loads as None and the upgrade-gate tests fail (UpgradeFlowError: 'bundled component registry is empty or missing') across the LFX test matrix. That failure blocks the nightly's release-nightly-build job, so no canonical 1.11.0.devN is published and check-nightly-status blocks CI everywhere.

Surgical restamp: version -> 1.11.0 and recomputed sha256 (same orjson OPT_SORT_KEYS hashing and OPT_SORT_KEYS|OPT_INDENT_2 serialization as scripts/build_component_index.py). Entries unchanged. Verified the reader validation passes and the three failing tests go green.
2026-06-09 15:18:21 -07:00
fb64e45e75 chore: bump version to 1.11.0 2026-06-09 13:29:01 -07:00