molecule-core/canvas/src
Hongming Wang 5a3dbb95e1 fix(api): probe /cp/auth/me before redirecting on 401
The actual cause-fix for the staging-tabs E2E saga (#2073/#2074/#2075).

Old behaviour: ANY 401 from any fetch on a SaaS tenant subdomain
called redirectToLogin → window.location.href = AuthKit. This is
wrong. Plenty of 401s don't mean "session is dead":

  - workspace-scoped endpoints (/workspaces/:id/peers, /plugins)
    require a workspace-scoped token, not the tenant admin bearer
  - resource-permission mismatches (user has tenant access but not
    this specific workspace)
  - misconfigured proxies returning 401 spuriously

A single transient one of those yanked authenticated users back to
AuthKit. Same bug yanked the staging-tabs E2E off the tenant origin
mid-test for 6+ hours tonight, leading to the cascade of test-side
mocks (#2073/#2074/#2075) that worked around the symptom without
fixing the cause.

This PR fixes it at the source. The new logic:

  - 401 on /cp/auth/* path → that IS the canonical session-dead
    signal → redirect (unchanged)
  - 401 on any other path with slug present → probe /cp/auth/me:
      probe 401 → session genuinely dead → redirect
      probe 200 → session fine, endpoint refused this token →
                  throw a real Error, caller renders error state
      probe network err → assume session-fine (conservative) →
                  throw real Error
  - slug empty (localhost / LAN / reserved subdomain) → throw
    without redirect (unchanged)

The probe adds one extra fetch on a 401, only when slug is set
and the path isn't already auth-scoped. That's rare and
worthwhile — a transient probe round-trip is cheap; an unwanted
auth redirect is a UX disaster.

Tests:
  - api-401.test.ts rewritten with the full matrix:
      * /cp/auth/me 401 → redirect (no probe, that IS the signal)
      * non-auth 401 + probe 401 → redirect
      * non-auth 401 + probe 200 → throw, no redirect  ← the fix
      * non-auth 401 + probe network err → throw, no redirect
      * empty slug paths (localhost/LAN/reserved) → throw, no probe
  - 43 tests in canvas/src/lib/__tests__/api*.test.ts all pass
  - tsc clean

The staging-tabs E2E spec's universal-401 route handler stays as
defense-in-depth (silences resource-load console noise + guards
against panels without try/catch), but the comment now describes
its role honestly: api.ts is the primary fix, the route is the
safety net.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-25 23:49:28 -07:00
..
__tests__ fix(canvas): include NEXT_PUBLIC_PLATFORM_URL in CSP connect-src 2026-04-20 12:55:03 -07:00
app Merge pull request #2066 from Molecule-AI/fix/e2e-staging-status-field 2026-04-25 05:58:36 +00:00
components Merge pull request #2045 from Molecule-AI/feat/flat-rate-pricing-1833 2026-04-25 05:54:06 +00:00
hooks initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
lib fix(api): probe /cp/auth/me before redirecting on 401 2026-04-25 23:49:28 -07:00
store fix(canvas): subtree-aware layout + org-import reliability + UX polish 2026-04-23 23:48:29 -07:00
stores initial commit — Molecule AI platform 2026-04-13 11:55:37 -07:00
styles fix(canvas): C1/C2/C3/C5 dark-theme CSS and ReactFlow colorMode 2026-04-16 10:45:16 +00:00
types feat(canvas): audit trail visualization panel (issue #753) 2026-04-17 16:03:28 +00:00
middleware.ts feat(router): /cp/* reverse-proxy to CP + same-origin canvas fetches 2026-04-20 13:01:40 -07:00