fix(login): backend-unreachable no longer masquerades as a fresh node
Demo images / Build & push demo images (push) Successful in 3m4s
Demo images / Build & push demo images (push) Successful in 3m4s
auth.isSetup failing (backend warming up after boot, transient proxy blip) dropped Login.vue into its catch and showed 'Set Up Your Node' on a fully-onboarded node — seen on framework-pt right after its network move, and the same fail-open class RootRedirect already fixed for the intro flash. Errors now fail toward the ordinary login form and a background probe re-asks until the backend answers; a genuinely fresh node flips to the setup form on the first successful probe. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Fable 5
parent
6833920778
commit
9c675e5c7d
@@ -381,19 +381,44 @@ onMounted(async () => {
|
|||||||
await pollServerStartup()
|
await pollServerStartup()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if password has been set up — show setup form if not
|
// Check if password has been set up — show setup form if not.
|
||||||
|
//
|
||||||
|
// An RPC failure is NOT evidence of a fresh node: a backend still warming
|
||||||
|
// up (or a transient proxy blip) used to land here and flip a
|
||||||
|
// fully-onboarded node into "Set Up Your Node" — seen on framework-pt
|
||||||
|
// right after a network move (2026-08-15), the same fail-open class
|
||||||
|
// RootRedirect fixed for the intro. Fail toward the ordinary login form
|
||||||
|
// and keep re-probing until the backend answers; a genuinely fresh node
|
||||||
|
// flips to setup the moment the first probe lands (and could not have
|
||||||
|
// completed setup against a dead backend anyway).
|
||||||
try {
|
try {
|
||||||
const result = await rpcClient.call<boolean>({ method: 'auth.isSetup', params: {}, timeout: 8000 })
|
const result = await rpcClient.call<boolean>({ method: 'auth.isSetup', params: {}, timeout: 8000 })
|
||||||
isSetup.value = Boolean(result)
|
isSetup.value = Boolean(result)
|
||||||
isSetupMode.value = !isSetup.value
|
isSetupMode.value = !isSetup.value
|
||||||
} catch {
|
} catch {
|
||||||
isSetup.value = false
|
isSetup.value = true
|
||||||
isSetupMode.value = true
|
isSetupMode.value = false
|
||||||
|
void retrySetupProbe()
|
||||||
} finally {
|
} finally {
|
||||||
isCheckingSetup.value = false
|
isCheckingSetup.value = false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
/** Re-probe auth.isSetup until it answers, then honour the real state. */
|
||||||
|
async function retrySetupProbe() {
|
||||||
|
for (let i = 0; i < 10; i++) {
|
||||||
|
await new Promise((r) => setTimeout(r, Math.min(2000 * (i + 1), 8000)))
|
||||||
|
try {
|
||||||
|
const result = await rpcClient.call<boolean>({ method: 'auth.isSetup', params: {}, timeout: 8000 })
|
||||||
|
isSetup.value = Boolean(result)
|
||||||
|
isSetupMode.value = !isSetup.value
|
||||||
|
return
|
||||||
|
} catch {
|
||||||
|
// still unreachable — keep the login form up and try again
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
function handleSetupWithSound() {
|
function handleSetupWithSound() {
|
||||||
if (!loading.value && password.value && password.value === confirmPassword.value) {
|
if (!loading.value && password.value && password.value === confirmPassword.value) {
|
||||||
|
|||||||
Reference in New Issue
Block a user