fix(auth): surface sign-up failures, trust serving origin, unbreakable mail probe

Self-hosted sign-up bounced back to the bootstrap screen for three
compounding reasons:

- better-auth's client resolves { data, error } on HTTP failure; the UI
  ignored res.error and showed "Account created — signing you in", hiding
  the real 403/429/500.
- trustedOrigins was a static localhost-only list. Browsing the instance
  via LAN IP or custom port failed every auth POST once cookies existed.
  Origins are now derived from the request's public host (forwarded by
  nginx), so any origin serving the app works.
- hasMailTransport threw when core.settings was unreadable (fresh volume,
  backend still migrating), so sign-up 500'd and the startup backfill
  could crash-loop the service. Both now degrade to "no transport".

Verified live: LAN-style origin sign-up succeeds, missing core.settings
logs a warn instead of exiting, and the frontend shows real errors.

Generated with [Devin](https://devin.ai)

Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
This commit is contained in:
Tomas DvorakandDevin committed 2026-09-28 16:23:01 +02:00
1 parent 3ad37c190b
commit 92b1810c07
4 files changed
+50 -9

No files matched your search

+13 -2
View File
@@ -735,11 +735,22 @@ export default function App() {
await runPending("auth-submit", async () => {
setAuthMessage("");
try {
// better-auth client resolves { data, error } instead of throwing on
// HTTP failures — surface res.error or the UI claims success while
// nothing was created.
if (mode() === "sign-up") {
await authClient.signUp.email({ email: email(), password: password(), name: name() });
const res = await authClient.signUp.email({ email: email(), password: password(), name: name() });
if (res.error) {
setAuthMessage(res.error.message ?? "Sign-up failed");
return;
}
setAuthMessage("Account created — signing you in.");
} else {
await authClient.signIn.email({ email: email(), password: password() });
const res = await authClient.signIn.email({ email: email(), password: password() });
if (res.error) {
setAuthMessage(res.error.message ?? "Sign-in failed");
return;
}
}
} catch (error) {
setAuthMessage(getErrorMessage(error, "Authentication failed"));