From 5b37ed1ef0fd3817d25906fa77311a4aa513a949 Mon Sep 17 00:00:00 2001 From: Muhammadjazuli Date: Fri, 25 Sep 2026 03:20:18 +0100 Subject: [PATCH] fix(auth): harden session and image resilience Add WebP-aware image loading, activity-aware expiry warnings, transactional session-state consumption, and accurate bundle-boundary documentation. Closes #1313 Closes #1314 Closes #1315 Closes #1316 --- frontend/app/(protected)/map/page.tsx | 8 +- frontend/app/[locale]/(protected)/layout.tsx | 2 + .../(protected)/settings/data/page.tsx | 9 +- .../(protected)/settings/security/page.tsx | 6 +- frontend/app/[locale]/login/LoginForm.tsx | 16 +- frontend/components/SessionExpiryGuard.tsx | 17 + frontend/lib/__tests__/image-loader.test.ts | 43 ++ .../__tests__/session-expiry-warning.test.ts | 153 +++++ frontend/lib/__tests__/session-expiry.test.ts | 4 +- .../__tests__/session-state-preserver.test.ts | 282 ++++++++ frontend/lib/api-client.ts | 241 ++++++- frontend/lib/auth-session.ts | 105 ++- frontend/lib/bundle-config.ts | 15 +- frontend/lib/image-loader.ts | 80 ++- frontend/lib/session-expiry-warning.ts | 246 +++++-- frontend/lib/session-state-preserver.ts | 644 +++++++++++++++++- frontend/next.config.ts | 5 + frontend/test-utils/LoginForm.test.tsx | 62 +- frontend/test-utils/api-client.test.ts | 136 +++- frontend/test-utils/mocks/handlers.ts | 4 +- 20 files changed, 1900 insertions(+), 178 deletions(-) create mode 100644 frontend/components/SessionExpiryGuard.tsx create mode 100644 frontend/lib/__tests__/image-loader.test.ts create mode 100644 frontend/lib/__tests__/session-expiry-warning.test.ts create mode 100644 frontend/lib/__tests__/session-state-preserver.test.ts diff --git a/frontend/app/(protected)/map/page.tsx b/frontend/app/(protected)/map/page.tsx index ac2539d3..68d3ca7f 100644 --- a/frontend/app/(protected)/map/page.tsx +++ b/frontend/app/(protected)/map/page.tsx @@ -1,10 +1,12 @@ "use client"; import dynamic from "next/dynamic"; +import { clientOnlyBundleBoundary } from "@/lib/bundle-config"; -const MapPageContent = dynamic(() => import("./MapPageContent"), { - ssr: false, -}); +const MapPageContent = dynamic( + () => import("./MapPageContent"), + clientOnlyBundleBoundary, +); export default function MapPage() { return ; diff --git a/frontend/app/[locale]/(protected)/layout.tsx b/frontend/app/[locale]/(protected)/layout.tsx index c9ad4c43..47df3f9f 100644 --- a/frontend/app/[locale]/(protected)/layout.tsx +++ b/frontend/app/[locale]/(protected)/layout.tsx @@ -2,6 +2,7 @@ import { getTranslations, setRequestLocale } from "next-intl/server"; import { Link } from "@/i18n/navigation"; import LanguageSwitcher from "@/components/LanguageSwitcher"; import NotificationBell from "@/components/layout/NotificationBell"; +import { SessionExpiryGuard } from "@/components/SessionExpiryGuard"; export const dynamic = "force-dynamic"; @@ -20,6 +21,7 @@ export default async function ProtectedLayout({ return (
+