openova/products
e3mrah 76830d9c62
fix(catalyst): chroot — skip tenantDiscover polling, /auth/handover redirects authed user to / (#1077)
Two bugs surfaced live on console.omantel.biz on 2026-05-07.

TC-229 (P0) — chroot continuous /api/v1/tenant/discover 404 polling.
The Sovereign chroot's catalyst-api does not register the
tenant/discover endpoint (it is mother-only — only the Catalyst-Zero
apex `console.openova.io` knows about the tenant registry). The SPA's
bootstrapTenant() at app boot still ran on the chroot, returned 404,
and the SPA's React-Query layer kept re-issuing the call as the
Dashboard mounted/unmounted. 50+ HTTP 404 lines were captured during a
single Dashboard navigation. Fix: short-circuit bootstrapTenant() at
the single tenantDiscover.ts seam when DETECTED_MODE.mode ===
'sovereign'. Returns the existing 'unwired' status (no registry
available; proceed on the host's own identity), caches it so a second
call is a no-op, and never touches the network. Tenant identity on
chroot is already encoded in the session JWT (sovereign_fqdn /
deployment_id claims) so no registry payload is needed.

TC-004 (P1) — /auth/handover authenticated visit shows error page.
Fix #2 PR #1075 added the SPA-friendly handover-error page for browser
visits with no token. That branch fired even when the operator already
had a live catalyst_session cookie, so an authed user pasting the bare
/auth/handover URL saw "Handover incomplete" copy that confuses people
who are already logged in. Fix: add a three-way branch on no-token
visits — authenticated browser (302 to authHandoverRedirect, default
/dashboard), unauthenticated browser (existing 302 to handover-error
page from PR #1075), programmatic caller (existing 401 JSON contract
from auth_handover_test.go). New helper hasValidCatalystSession reads
the session token via auth.Config.ReadSessionToken (cookie / Bearer /
?access_token query — same channels RequireSession honours) and
validates it via auth.Config.ValidateToken (same path RequireSession
uses, including LocalPublicKey fallback for self-signed handover-
session JWTs). Returns false when authConfig is nil so unconfigured
Sovereigns / CI keep working unchanged.

Tests: TestAuthHandover_MissingTokenAuthedRedirectsToDashboard
(raw-JWT cookie + Bearer header), MissingTokenExpiredSessionFalls-
Through (expired session falls through to error page),
MissingTokenNoAuthConfigKeepsHTMLBranch (nil authConfig keeps the
existing branches working). Existing missing-token tests unchanged.

Files touched (per Fix Author #6 brief):
- products/catalyst/bootstrap/ui/src/shared/lib/tenantDiscover.ts
- products/catalyst/bootstrap/api/internal/handler/auth_handover.go
- products/catalyst/bootstrap/api/internal/handler/auth_handover_test.go

Co-authored-by: hatiyildiz <269457768+hatiyildiz@users.noreply.github.com>
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 21:52:21 +04:00
..
axon feat(axon): make qwen3-coder thinking mode toggleable via request parameter 2026-04-26 09:20:33 +02:00
catalyst fix(catalyst): chroot — skip tenantDiscover polling, /auth/handover redirects authed user to / (#1077) 2026-05-07 21:52:21 +04:00
cortex docs(pass-52): bundled date-sweep + cross-component namespace clean; knative clean 2026-04-28 00:37:21 +02:00
fabric docs(seaweedfs+guacamole): replace MinIO with SeaweedFS as unified S3 encapsulation; add Guacamole to bp-relay 2026-04-28 10:23:46 +02:00
fingate docs(pass-52): bundled date-sweep + cross-component namespace clean; knative clean 2026-04-28 00:37:21 +02:00
relay docs(seaweedfs+guacamole): replace MinIO with SeaweedFS as unified S3 encapsulation; add Guacamole to bp-relay 2026-04-28 10:23:46 +02:00