Skip to content

fix(httpd): redirect remote setup traffic to onboarding wizard#665

Merged
penso merged 2 commits intomainfrom
spurious-idea
Apr 11, 2026
Merged

fix(httpd): redirect remote setup traffic to onboarding wizard#665
penso merged 2 commits intomainfrom
spurious-idea

Conversation

@penso
Copy link
Copy Markdown
Collaborator

@penso penso commented Apr 11, 2026

Summary

Fixes #646 — remote visitors on fresh deployments (docker-compose with MOLTIS_NO_TLS=true) were stuck on a static "Authentication Not Configured" dead-end page that told them to run moltis auth reset-password. That CLI command is useless on a fresh install (no credentials to reset) and left users with no path to complete first-time setup.

The onboarding wizard's AuthStep already supports remote setup via a one-time setup code printed to stdout, but remote users were never sent there.

  • Redirect remote SetupRequired traffic to /onboarding (was /setup-required). Users can now enter the 6-digit setup code from docker compose logs moltis and complete setup normally.
  • The original //onboarding redirect loop ([Bug]: too many redirects over tailscale #350) is already fixed at the SPA template layer via should_redirect_from_onboarding, and the setup-code requirement still prevents an unauthorized remote visitor from claiming the instance.
  • Repurpose /setup-required as a stale-bookmark fallback: rewritten body with a prominent "Continue setup →" link to /onboarding and updated copy pointing users at the setup code. moltis auth reset-password is demoted to a side note for locked-out recovery scenarios.

Validation

Completed

  • cargo test -p moltis-httpd --test auth_middleware -- root_redirects_to_onboarding_for_remote setup_required_page_accessible_for_remote setup_required_redirects_to_login_after_setup onboarding_passes — 5/5 passing
  • cargo test -p moltis-web --lib --features vault,web-ui templates::tests::setup_required — passing
  • cargo check -p moltis-httpd -p moltis-web — clean
  • cargo +nightly-2025-11-30 fmt --all -- --check — clean
  • biome check --write crates/web/ui/e2e/specs/onboarding-auth.spec.js — clean

Remaining

  • just lint (OS-aware clippy)
  • just test (full test suite)
  • npx playwright test e2e/specs/onboarding-auth.spec.js (restored to visit / instead of /onboarding)

Manual QA

Mirror the bug report:

  1. docker build -t moltis-local .
  2. Start with MOLTIS_NO_TLS=true bound to a non-loopback interface (or access via LAN IP).
  3. From a different machine, visit http://<host>:<port>/.
  4. Expect: redirected to /onboarding, AuthStep shows "Setup code" input.
  5. docker compose logs moltis prints the 6-digit code.
  6. Paste the code, set a password (or register a passkey), complete the wizard.
  7. Confirm no redirect loop, no /setup-required dead-end, and subsequent visits after logout land on /login.

Security sanity check

  • Remote visitor without the setup code cannot complete POST /api/auth/setup (validated at crates/httpd/src/auth_routes.rs:179-183).
  • /api/* remote calls during SetupRequired still return AUTH_SETUP_REQUIRED 401 — unchanged.
  • Once setup is complete, /onboarding gets the normal auth gate back — unchanged.

Remote visitors on a fresh deployment were redirected to a static
/setup-required dead-end page that instructed them to run
`moltis auth reset-password`, which is useless on a fresh install and
left users stuck. The onboarding wizard already supports remote setup
via a one-time setup code printed to stdout, but remote users were
never sent there.

Redirect remote SetupRequired traffic to /onboarding so users can enter
the setup code (from `docker compose logs moltis`) and complete first-
time setup via the AuthStep. The original redirect loop between / and
/onboarding (#350) is already fixed at the SPA template layer via
should_redirect_from_onboarding, and the setup-code requirement still
prevents an unauthorized remote visitor from claiming the instance.

Repurpose /setup-required as a stale-bookmark fallback with a prominent
link to /onboarding and updated copy that points users at the setup
code in stdout. Drop the misleading reset-password instructions from
the primary flow.

Closes #646

Entire-Checkpoint: 4e8cfe8c7a17
@codspeed-hq
Copy link
Copy Markdown
Contributor

codspeed-hq bot commented Apr 11, 2026

Merging this PR will not alter performance

✅ 39 untouched benchmarks
⏩ 5 skipped benchmarks1


Comparing spurious-idea (45c797f) with main (5afb1bc)

Open in CodSpeed

Footnotes

  1. 5 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 11, 2026

Greptile Summary

Fixes the remote first-time setup dead-end (#646) by redirecting SetupRequired remote traffic to /onboarding instead of the static /setup-required page; the existing should_redirect_from_onboarding guard (returns false when auth_setup_pending is true) prevents the //onboarding redirect loop from #350. /setup-required is repurposed as a stale-bookmark fallback page with setup-code instructions and a prominent link back to /onboarding.

Confidence Score: 5/5

Safe to merge; redirect logic is sound, loop prevention is verified, and all findings are P2 style suggestions.

The core logic change is a single redirect target swap in auth_gate, backed by correct loop-prevention in onboarding_handler (should_redirect_from_onboarding returns false while auth_setup_pending is true). Tests cover the new redirect, the fallback page content, the post-setup redirect, and the E2E flow. The only finding is a P2 style suggestion to reuse an existing components.css class for the CTA button.

crates/web/src/templates/setup-required.html — minor CTA styling could reuse provider-btn-secondary

Important Files Changed

Filename Overview
crates/httpd/src/auth_middleware.rs Redirect target for remote SetupRequired changed from /setup-required to /onboarding; redirect-loop prevention correctly delegated to should_redirect_from_onboarding in onboarding_handler.
crates/httpd/tests/auth_middleware.rs Tests updated to assert /onboarding redirect target and new /setup-required content; added assertion for href=/onboarding link on the fallback page.
crates/web/src/templates.rs Template test assertions updated to match new setup-required.html heading and content; no logic changes.
crates/web/src/templates/setup-required.html Repurposed as stale-bookmark fallback with setup-code instructions and /onboarding CTA; new .cta class could reuse provider-btn-secondary from the already-imported components.css.
crates/web/ui/e2e/specs/onboarding-auth.spec.js E2E test now navigates to / instead of /onboarding directly, correctly validating the new server-side redirect behaviour.

Sequence Diagram

sequenceDiagram
    participant R as Remote Visitor
    participant MW as auth_gate
    participant OH as onboarding_handler
    participant SH as setup_required_handler

    Note over R,SH: Fresh install, setup incomplete
    R->>MW: GET /
    MW->>MW: SetupRequired (remote, not /onboarding)
    MW-->>R: 302 /onboarding

    R->>MW: GET /onboarding
    MW->>MW: SetupRequired + path is /onboarding, pass through
    MW->>OH: forward
    OH->>OH: onboarded false, auth pending true
    OH->>OH: should_redirect_from_onboarding returns false
    OH-->>R: 200 Onboarding SPA with setup-code AuthStep

    Note over R,SH: Stale bookmark hits /setup-required
    R->>MW: GET /setup-required
    MW->>MW: is_public_path, pass through
    MW->>SH: forward
    SH->>SH: is_setup_complete returns false
    SH-->>R: 200 Fallback page with link to /onboarding

    Note over R,SH: After setup is complete
    R->>MW: GET /setup-required
    MW->>SH: forward (public path)
    SH->>SH: is_setup_complete returns true
    SH-->>R: 302 /login
Loading

Reviews (1): Last reviewed commit: "fix(httpd): redirect remote setup traffi..." | Re-trigger Greptile

@codecov
Copy link
Copy Markdown

codecov bot commented Apr 11, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

Replace the custom `.cta` class padding/border/color definitions with
the shared `provider-btn` / `provider-btn-secondary` classes from
components.css so the CTA adopts the page theme colours instead of
falling back to default anchor colours (Greptile P2 review).

Entire-Checkpoint: 3d594e395d28
@penso penso merged commit c3da499 into main Apr 11, 2026
56 of 58 checks passed
@penso penso deleted the spurious-idea branch April 11, 2026 22:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: Unable to login to remote deployment

1 participant