fix(frontend): sign out via Clerk when in Clerk mode
ci / e2e (push) Has been cancelled
ci / gates (push) Has been cancelled
ci / rust (push) Has been cancelled
ci / sandbox-k8s (push) Has been cancelled
ci / frontend (push) Has been cancelled

Sign-out only cleared the local cm_session cookie via DELETE /auth/session.
In Clerk mode the real session is Clerk's, so that left it intact and the
push to /login bounced the user straight back into the app (Clerk's <SignIn>
auto-redirects when a session exists). Detect clerk-js at runtime
(window.Clerk) and sign out through it; local/air-gapped builds have no
window.Clerk and keep the cookie flow (never loading the Clerk SDK).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
This commit is contained in:
Omar Sobh
2026-06-15 12:49:39 -07:00
co-authored by Claude Opus 4.8
parent 6071e1fd61
commit 90b1fe61e6
@@ -13,6 +13,21 @@ export function UserMenu({ user }: { user: User }) {
async function signOut() { async function signOut() {
setPending(true); setPending(true);
// In Clerk mode the real session is Clerk's, not the local cm_session
// cookie — so clear it via the Clerk client (clerk-js exposes window.Clerk).
// The local /auth/session DELETE only drops the local cookie and would
// leave the Clerk session intact, bouncing the user right back into the
// app. window.Clerk is absent in local/air-gapped builds, which fall
// through to the cookie flow (and never load the Clerk SDK).
const clerk = (
globalThis as {
Clerk?: { signOut: (opts?: { redirectUrl?: string }) => Promise<void> };
}
).Clerk;
if (clerk) {
await clerk.signOut({ redirectUrl: "/login" });
return;
}
await fetch("/auth/session", { method: "DELETE" }); await fetch("/auth/session", { method: "DELETE" });
router.push("/login"); router.push("/login");
router.refresh(); router.refresh();