From 0d8ec2b0000f9eb1e146dc6db86673e52b61003b Mon Sep 17 00:00:00 2001 From: Lyon <88232613+pikasTech@users.noreply.github.com> Date: Sun, 21 Jun 2026 09:35:37 +0800 Subject: [PATCH] fix(hwlab): stop web-probe auth fallback (#547) Co-authored-by: Codex --- .../src/hwlab-node-web-probe-runner-source.ts | 44 +++++++++++++++---- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/scripts/src/hwlab-node-web-probe-runner-source.ts b/scripts/src/hwlab-node-web-probe-runner-source.ts index b914f47d..a53ac4ab 100644 --- a/scripts/src/hwlab-node-web-probe-runner-source.ts +++ b/scripts/src/hwlab-node-web-probe-runner-source.ts @@ -105,16 +105,17 @@ try { } async function authenticate(browserContext) { - const apiAuth = await authenticateWithApiRetries(browserContext); - if (apiAuth.ok) return apiAuth; - return authenticateWithFormFallback(browserContext, apiAuth); + return authenticateWithApiRetries(browserContext); } async function authenticateWithApiRetries(browserContext) { const loginUrl = new URL("/auth/login", baseUrl).toString(); const attempts = []; - const maxAttempts = 3; + const maxAttempts = 5; + const initialDelayMs = 250; + const maxDelayMs = 5000; for (let attempt = 1; attempt <= maxAttempts; attempt += 1) { + const retryDelayMs = attempt < maxAttempts ? Math.min(maxDelayMs, initialDelayMs * (2 ** (attempt - 1))) : 0; try { const response = await browserContext.request.post(loginUrl, { data: { username, password }, @@ -126,6 +127,10 @@ async function authenticateWithApiRetries(browserContext) { const retryable = isRetryableAuthStatus(response.status()); const item = { attempt, + retryAttempt: attempt, + retryMaxAttempts: maxAttempts, + retryLabel: attempt + "/" + maxAttempts, + retryDelayMs: retryable && attempt < maxAttempts ? retryDelayMs : 0, method: "api", ...summary, retryable, @@ -144,6 +149,9 @@ async function authenticateWithApiRetries(browserContext) { cookieNames: cookieState.cookieNames, attempts, retryCount: attempt - 1, + retryMaxAttempts: maxAttempts, + lastRetryLabel: attempt + "/" + maxAttempts, + retryExhausted: false, fallbackUsed: false, valuesRedacted: true, }; @@ -152,6 +160,10 @@ async function authenticateWithApiRetries(browserContext) { } catch (error) { attempts.push({ attempt, + retryAttempt: attempt, + retryMaxAttempts: maxAttempts, + retryLabel: attempt + "/" + maxAttempts, + retryDelayMs: attempt < maxAttempts ? retryDelayMs : 0, method: "api", status: 0, statusText: "request-error", @@ -160,10 +172,11 @@ async function authenticateWithApiRetries(browserContext) { cookiePresent: false, }); } - if (attempt < maxAttempts) await sleep(300 * attempt); + if (attempt < maxAttempts && attempts[attempts.length - 1]?.retryable === true) await sleep(retryDelayMs); } const cookieState = await readAuthCookieState(browserContext); const last = attempts[attempts.length - 1] ?? null; + const retryable = authAttemptsRetryable(attempts); return { ok: false, method: "api", @@ -174,8 +187,11 @@ async function authenticateWithApiRetries(browserContext) { cookieNames: cookieState.cookieNames, attempts, retryCount: retryCountFromAttempts(attempts), + retryMaxAttempts: maxAttempts, + lastRetryLabel: last?.retryLabel ?? null, + retryExhausted: retryable && attempts.length >= maxAttempts, fallbackUsed: false, - retryable: authAttemptsRetryable(attempts), + retryable, errorSummary: last, valuesRedacted: true, }; @@ -1679,6 +1695,13 @@ function publicAuth(value) { const transientObserved = authAttemptsRetryable(value.attempts); const ok = value.ok === true; const retryable = ok ? false : value.retryable === true || transientObserved; + const retryMaxAttempts = Number.isInteger(value.retryMaxAttempts) ? value.retryMaxAttempts : null; + const lastRetryLabel = typeof value.lastRetryLabel === "string" + ? value.lastRetryLabel + : Array.isArray(value.attempts) && value.attempts.length > 0 + ? value.attempts[value.attempts.length - 1]?.retryLabel ?? null + : null; + const retryExhausted = value.retryExhausted === true || (retryable && retryMaxAttempts !== null && Array.isArray(value.attempts) && value.attempts.length >= retryMaxAttempts); return { ok, method: value.method ?? null, @@ -1690,6 +1713,9 @@ function publicAuth(value) { cookieNames: value.cookieNames, attempts: value.attempts ?? null, retryCount, + retryMaxAttempts, + lastRetryLabel, + retryExhausted, fallbackUsed: value.fallbackUsed === true || value.method === "form-fallback", fallback: value.fallback ?? null, errorSummary: cloneSummary(value.errorSummary ?? value.apiErrorSummary ?? null), @@ -1698,8 +1724,10 @@ function publicAuth(value) { transientObserved, commanderAction: ok ? null - : retryable - ? "retry same web-probe command after short backoff; inspect target /auth/login and Cloud Web/API rollout if repeated" + : retryExhausted + ? "auth retry exhausted; stop this web-probe run and inspect target /auth/login upstream before retrying" + : retryable + ? "retry same web-probe command after short backoff; inspect target /auth/login and Cloud Web/API rollout if repeated" : "inspect bootstrap admin credential source and target user state", fingerprint: authSummaryFingerprint(value), username,