Skip to content

test(auth): promote the §4 tail to @stable — API-driven rewrite after upstream removed the OSS Admin Page (#1542, #1543) - #1545

Merged
rafaelgiln merged 1 commit into
mainfrom
test/issue-1542-1543-auth-tail-stable
Aug 21, 2026
Merged

test(auth): promote the §4 tail to @stable — API-driven rewrite after upstream removed the OSS Admin Page (#1542, #1543)#1545
rafaelgiln merged 1 commit into
mainfrom
test/issue-1542-1543-auth-tail-stable

Conversation

@rafaelgiln

Copy link
Copy Markdown
Collaborator

Closes #1542. Closes #1543.

Moves the auth tail — the ROADMAP.md pool item "ready to date" — to @stable: 13 QA-CHECKLIST.md §4.1/§4.2 bullets [-][x], plus one new bullet the audit earned. Six spec docs authored (none existed). Everything measured on nightly 1.12.0.dev33.

The audit that reshaped the batch

Baseline (--retries=0 --workers=1): 13/17 pass. The 4 reds decomposed into two product facts and one suite defect:

  1. Upstream removed the OSS Admin Pagelangflow-ai/langflow#14276 (2026-08-05, "SSO foundations, login seams, and remove OSS Admin Page"). On dev33 the user-menu slot compiles to a null stub and the SPA router registers no admin path (pages/AdminPage/ upstream holds only the /login/admin LoginPage). admin-user-management and auto-login-off died at the Admin Page click.
  2. The legacy-password defect underneath it: admin-user-management logged in with hardcoded "langflow", refused since 1.11.0.dev29 (Harness break: upstream disables legacy default superuser password under AUTO_LOGIN — breaks all manual-login tests #510) — helpers/auth/credentials.ts exists for exactly this and was never imported. Every admin login failed before even reaching the removed page.
  3. Login-budget collisions between specs (suite defect, measured twice): POST /api/v1/login is limited to 5/min per client IP, fixed window, counted before authentication. logout-flow (already @stable) timed out on mainpage_title right after auto-login-off's three form logins; later admin-password-change's UI login met the window its own four API calls had just spent — snapshot shows the form submitted and parked.

1. Covered tests (18 in the directory, 13 promoted + 1 new)

File Tests What changed
admin-user-management.spec.ts 4 Rewritten API-driven over /api/v1/users/, proving every state at the login endpoint: created-inactive → 400 "Waiting for approval"; activate → 200 + access_token; deactivate → 401 "Inactive user"; rename → new username 200, old 401. The two refusal branches are the product's own (read from the shipped authenticate_user: never-logged-in vs deactivated-after-use) and each test pins one — the first run of this rewrite failed on exactly that distinction. New 4th test pins #14276 itself: menu open + no Admin Page item, /admin falls through with the old page's own marker (Search Username) absent — an EE admin surface leaking back into OSS fails by name
auto-login-off.spec.ts 1 Surgery: keeps its two real subjects — login screen when auto-login is off, and two-way flow isolation with exact random names (A invisible to B, B invisible to A, while each still sees their own — pinning "filtered by owner", not "empty") — provisions the second user via API, and gains the id-scoped cleanup it never had (old version leaked 1 user + 2 flows per run)
admin-password-change.spec.ts 2 Passing already; its 5 login calls now ride the 429-absorbing helpers (its UI login was the measured victim), promoted
logout-flow.spec.ts 3 Already @stable; its 3 raw form logins swapped to the helper — it was the other measured victim
autoLogin.spec.ts 2 Promoted as-is
login-invalid-credentials.spec.ts 2 Promoted, with one tightening: under a hot window the app shows the same Error signing in toast for a 429, so the title-only assert could pass for the wrong reason — the refusal is now pinned to a 401 status through the helper
session-expired.spec.ts 4 Promoted as-is (refusal pair + valid-token control)

Out of scope, stated: login-rate-limit.spec.ts stays [-]@destructive (instance-global budget), @stable forbidden on it (#1010), bullet carries the lane. It also deliberately does not use the new helpers: there the 429 is the subject.

2. How it was built

  • New shared helpers (tests/helpers/auth/): login-request.ts (postLogin — API side) and sign-in-through-form.ts (browser side, response captured via waitForResponse registered before the click, so the status read cannot race the navigation). Both absorb only 429, waiting out the server-named retry_aftera string, not a number, converted with a +1 s edge margin — and return every other status untouched, so no credential verdict is ever hidden. Unit-tested (6 cases, npm run test:units).
  • Backend semantics read from the shipped source inside the running container (services/auth/service.py::authenticate_user), not guessed: the 400-vs-401 inactive branches above.
  • Live-confirmed surface: the Admin Page absence was established from the shipped frontend bundle (menu slot const H_i = e => null, router path table with no admin entry, zero Search Username occurrences) and upstream refs (pages/AdminPage/ = LoginPage only on release-1.12.0).
  • Cleanup: every created user deleted by id in afterEach/finally; both isolation flows deleted by ids captured from the editor URL. Nothing name-based, nothing delete-all.

3. Dependencies

  • None — no LLM, no provider key. Superuser token via get-auth-token (auto-login endpoint, spends no form budget).
  • Runs --workers=1 as the auth directory always has (shared login budget is per-IP); parallel-safe against the rest of the suite.

Validation (nightly 1.12.0.dev33, --retries=0 --workers=1)

  • Final burst 3× back-to-back with deliberately hot windows (~45 logins in ~13 min): 18/18 · 18/18 · 18/18, 0 flaky, 0 skipped, 0 🚨 Backend Error. Run 3 shows +60 s — one absorbed 429, visible and green: the in-vivo proof of the helper, stronger than a mocked one.
  • Two defect-simulating force-fails, both red with the designed message, then reverted: the pending-approval detail assert (Expected "Pending review" · Received "Waiting for approval") and the isolation count flip (Expected 1 · Received 0).
  • JSON-reporter stats throughout, never \r progress lines.
  • typecheck 0 errors · lint 0 errors · test:units green (incl. the new helper's 6 cases) · checklist guard + coverage guard + validate:specs green.
  • --trace=on skipped deliberately: hangs UI specs on this local Docker VM (Colima) — known constraint; CI captures trace on first retry.

🤖 Generated with Claude Code

… upstream removed the OSS Admin Page (#1542, #1543)

Validates and promotes the auth directory (13 checklist bullets -> [x],
+1 new): autoLogin, login-invalid-credentials, session-expired,
admin-password-change, auto-login-off and a rewritten
admin-user-management, with spec docs for all six (none existed).

Upstream removed the OSS Admin Page in langflow-ai/langflow#14276
(2026-08-05): no menu item (null stub), no admin route. The rewrite
drives /api/v1/users/ instead and proves every lifecycle state at the
login endpoint — including the product's two distinct refusal branches
(never-logged-in inactive: 400 "Waiting for approval"; deactivated
after use: 401 "Inactive user", read from the shipped authenticate_user)
— and adds a guard pinning the removal itself, so an EE admin surface
leaking back into OSS fails by name. The rewrite also buries the
hardcoded legacy password "langflow" (refused since 1.11.0.dev29, #510)
that made every admin login fail.

auto-login-off keeps its two real subjects (login screen + two-way flow
isolation), provisions the second user via API, and gains the id-scoped
cleanup it never had (it leaked one user and two flows per run).

New shared helpers absorb the login endpoint's per-IP rate limit
(5/min, fixed window, every attempt counts): login-request.ts for API
logins and sign-in-through-form.ts for the browser, both waiting out
the server-named retry_after (a string, converted) and never hiding a
non-429 verdict. Measured collisions motivated them: logout-flow timed
out right after auto-login-off's three form logins, and
admin-password-change's own UI login met the window its API calls had
just spent. login-invalid-credentials pins its refusal to a 401 status
so a hot window cannot pass it for the wrong reason;
login-rate-limit.spec.ts stays raw on purpose — there the 429 is the
subject.

Validated on nightly 1.12.0.dev33: burst 3x back-to-back (windows
deliberately hot) 18/18 each at --retries=0 --workers=1, zero flaky,
zero backend errors; one absorbed 429 visible as +60s in run 3. Two
defect-simulating force-fails red with named messages, then reverted.
Unit lane covers the helper (6 cases).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@rafaelgiln
rafaelgiln merged commit 08a7bfe into main Aug 21, 2026
7 checks passed
@rafaelgiln
rafaelgiln deleted the test/issue-1542-1543-auth-tail-stable branch August 24, 2026 21:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant