singularity-forge/web
Andrew 6cc6c36a69 fix(web): auth token gate — synthetic 401 on missing token, unauthenticated boot state, and recovery screen (#2740)
When `gsd --web` is opened without the #token= hash fragment (manual URL
entry, bookmark, new tab), `authenticatedFetch` previously fell through to
a naked `fetch()` that always returned 401, flooding the console with
cascading errors and leaving the UI in a broken state with no recovery path.

Three changes:

1. `web/lib/auth.ts` — `authFetch()` now returns a synthetic 401 Response
   when `getAuthToken()` returns null instead of delegating to bare fetch.
   This makes missing-token failures consistent and immediately catchable
   by all callers without a network round-trip.

2. `web/lib/gsd-workspace-store.tsx` — Added `"unauthenticated"` to
   `WorkspaceStatus`. `refreshBoot()` now detects a 401 response from
   /api/boot and patches `bootStatus` to `"unauthenticated"` instead of
   throwing a generic error. This is a distinct state — not an error worth
   retrying, but a configuration problem the user must resolve.

3. `web/components/gsd/app-shell.tsx` — Added an early-return guard that
   renders a minimal "Authentication Required" screen when
   `bootStatus === "unauthenticated"`. The screen explains the problem and
   tells users to copy the full terminal URL (including `#token=…`) or
   restart with `gsd --web`.

Fixes #2731
2026-03-26 16:17:12 -06:00
..
app feat(web): Dark mode contrast — raise token floor and flatten opacity tier system (#2734) 2026-03-26 16:17:03 -06:00
components fix(web): auth token gate — synthetic 401 on missing token, unauthenticated boot state, and recovery screen (#2740) 2026-03-26 16:17:12 -06:00
hooks feat(web): browser-based web interface (#1717) 2026-03-21 12:16:54 -06:00
lib fix(web): auth token gate — synthetic 401 on missing token, unauthenticated boot state, and recovery screen (#2740) 2026-03-26 16:17:12 -06:00
public feat(web): browser-based web interface (#1717) 2026-03-21 12:16:54 -06:00
styles feat(web): browser-based web interface (#1717) 2026-03-21 12:16:54 -06:00
.gitignore feat(web): browser-based web interface (#1717) 2026-03-21 12:16:54 -06:00
components.json feat(web): browser-based web interface (#1717) 2026-03-21 12:16:54 -06:00
eslint.config.mjs feat(web): browser-based web interface (#1717) 2026-03-21 12:16:54 -06:00
next-env.d.ts feat(web): browser-based web interface (#1717) 2026-03-21 12:16:54 -06:00
next.config.mjs feat(web): browser-based web interface (#1717) 2026-03-21 12:16:54 -06:00
package-lock.json feat(web): browser-based web interface (#1717) 2026-03-21 12:16:54 -06:00
package.json feat(web): browser-based web interface (#1717) 2026-03-21 12:16:54 -06:00
postcss.config.mjs feat(web): browser-based web interface (#1717) 2026-03-21 12:16:54 -06:00
proxy.ts feat(web): browser-based web interface (#1717) 2026-03-21 12:16:54 -06:00
tsconfig.json feat(web): browser-based web interface (#1717) 2026-03-21 12:16:54 -06:00