From 5e9876bc5fc7f78fdc00789621badfa1fc55ce85 Mon Sep 17 00:00:00 2001 From: Oliver Kieselbach Date: Wed, 29 Jul 2026 02:48:08 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20hard=20page=20reloads=20on=20family=20ro?= =?UTF-8?q?utes=20=E2=80=94=20RSC=20.txt=20payloads=20were=20wildcard-rewr?= =?UTF-8?q?itten?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Client navigation to an exported route fetches its RSC payload (/index.txt). The legacy-path wildcards (/admin/backups/* etc.) matched those .txt paths and served the detail HTML instead — the Next router cannot parse HTML as a flight payload and falls back to a hard full-page navigation, resetting all client state (visible as the sidebar collapsing on every Backups/Customs-Archive navigation). Exact self-rewrites for all nine exported index.txt files now precede the wildcards; the swaConfig guard pins txt-before-wildcard for every family. Co-Authored-By: Claude Fable 5 --- .../autopilot-monitor-web/staticwebapp.config.json | 10 ++++++++++ .../utils/__tests__/swaConfig.guard.test.ts | 14 ++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/src/Web/autopilot-monitor-web/staticwebapp.config.json b/src/Web/autopilot-monitor-web/staticwebapp.config.json index e6d54258..b465824a 100644 --- a/src/Web/autopilot-monitor-web/staticwebapp.config.json +++ b/src/Web/autopilot-monitor-web/staticwebapp.config.json @@ -21,6 +21,16 @@ { "route": "/changelog", "redirect": "https://docs.autopilotmonitor.com/changelog/platform-changelog", "statusCode": 301 }, { "route": "/roadmap", "redirect": "/", "statusCode": 302 }, + { "route": "/sessions/index.txt", "rewrite": "/sessions/index.txt" }, + { "route": "/sessions/inspector/index.txt", "rewrite": "/sessions/inspector/index.txt" }, + { "route": "/diagnosis/index.txt", "rewrite": "/diagnosis/index.txt" }, + { "route": "/apps/index.txt", "rewrite": "/apps/index.txt" }, + { "route": "/apps/detail/index.txt", "rewrite": "/apps/detail/index.txt" }, + { "route": "/admin/backups/index.txt", "rewrite": "/admin/backups/index.txt" }, + { "route": "/admin/backups/detail/index.txt", "rewrite": "/admin/backups/detail/index.txt" }, + { "route": "/admin/customs-archive/index.txt", "rewrite": "/admin/customs-archive/index.txt" }, + { "route": "/admin/customs-archive/detail/index.txt", "rewrite": "/admin/customs-archive/detail/index.txt" }, + { "route": "/sessions", "rewrite": "/sessions/index.html" }, { "route": "/sessions/inspector", "rewrite": "/sessions/inspector/index.html" }, { "route": "/sessions/*", "rewrite": "/sessions/index.html" }, diff --git a/src/Web/autopilot-monitor-web/utils/__tests__/swaConfig.guard.test.ts b/src/Web/autopilot-monitor-web/utils/__tests__/swaConfig.guard.test.ts index d0d4b603..c724e985 100644 --- a/src/Web/autopilot-monitor-web/utils/__tests__/swaConfig.guard.test.ts +++ b/src/Web/autopilot-monitor-web/utils/__tests__/swaConfig.guard.test.ts @@ -87,7 +87,21 @@ describe("staticwebapp.config.json guard", () => { // trailingSlash:auto normalizes /apps to /apps/, which the /apps/* wildcard // matches — without the exact entry the list page serves the DETAIL html // (production incident 2026-07-29: /apps rendered the app-detail view). + // The exported RSC payloads (/index.txt) equally need exact + // self-rewrites before the wildcard: client navigation fetches them, and a + // wildcard-rewritten HTML response makes the Next router fall back to a + // HARD page load (production incident 2026-07-29: sidebar state reset on + // every /admin/backups navigation). const pairs: Array<[string, string]> = [ + ["/sessions/index.txt", "/sessions/*"], + ["/sessions/inspector/index.txt", "/sessions/*"], + ["/diagnosis/index.txt", "/diagnosis/*"], + ["/apps/index.txt", "/apps/*"], + ["/apps/detail/index.txt", "/apps/*"], + ["/admin/backups/index.txt", "/admin/backups/*"], + ["/admin/backups/detail/index.txt", "/admin/backups/*"], + ["/admin/customs-archive/index.txt", "/admin/customs-archive/*"], + ["/admin/customs-archive/detail/index.txt", "/admin/customs-archive/*"], ["/sessions", "/sessions/*"], ["/sessions/inspector", "/sessions/*"], ["/diagnosis", "/diagnosis/*"],