feat(auth): proactive session expiry redirect across all delivery paths

- Split auth config into auth.config.ts (edge-safe, no argon2) and auth-edge.ts
  for middleware use; auth.ts now spreads the shared config
- Middleware wraps with auth() to redirect unauthenticated requests to /auth/signin
  before any page render; passes through /auth/, /api/, /invite/ paths
- SessionGuard client component watches useSession() and redirects on
  status=unauthenticated, closing the SPA navigation gap
- QueryCache + MutationCache in TRPCProvider redirect on UNAUTHORIZED tRPC errors
  without retrying; SessionProvider polls session state every 5 minutes
- Middleware tests updated for async auth wrapper and auth-edge mock

Co-Authored-By: claude-flow <ruv@ruv.net>
This commit is contained in:
2026-04-03 10:42:10 +02:00
parent ed4d4e4640
commit bf8577dbaf
8 changed files with 151 additions and 57 deletions
+2
View File
@@ -1,6 +1,7 @@
import { redirect } from "next/navigation";
import { AppShell } from "~/components/layout/AppShell.js";
import { MfaPromptBanner } from "~/components/security/MfaPromptBanner.js";
import { SessionGuard } from "~/components/security/SessionGuard.js";
import { auth } from "~/server/auth.js";
const MFA_PROMPT_ROLES = new Set(["ADMIN", "MANAGER"]);
@@ -17,6 +18,7 @@ export default async function AppLayout({ children }: { children: React.ReactNod
return (
<AppShell userRole={userRole}>
<SessionGuard />
{MFA_PROMPT_ROLES.has(userRole) && <MfaPromptBanner />}
{children}
</AppShell>