From ffe88a47c6cf23d98dd2d016ff54857ec271a1e3 Mon Sep 17 00:00:00 2001 From: Oliver Kieselbach Date: Wed, 29 Jul 2026 02:39:56 +0200 Subject: [PATCH] =?UTF-8?q?fix:=20/sla=20dead-ended=20on=20www=20=E2=80=94?= =?UTF-8?q?=20it=20is=20a=20portal=20page,=20not=20a=20public=20one?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit /sla sat in PUBLIC_PATH_PREFIXES only because SLA notifications historically linked www…/sla. It is a fully authenticated page (ProtectedRoute + token fetches), and since ProtectedRoute stands down on the public host, www/sla waited forever on "Loading SLA metrics...". Removed from the public prefixes: the nav stays on portal (no bounce), old www…/sla notification links bounce to portal/sla where auth works, and SlaBreachEvaluationService.DashboardUrl now links the portal host directly for future notifications. /sla added to robots disallow. Web tsc + 603/603, backend build clean + SLA suite 38/38. Co-Authored-By: Claude Fable 5 --- .../Services/SlaBreachEvaluationService.cs | 4 +++- src/Web/autopilot-monitor-web/app/robots.ts | 1 + src/Web/autopilot-monitor-web/lib/hostRouting.ts | 8 +++++++- 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Backend/AutopilotMonitor.Functions/Services/SlaBreachEvaluationService.cs b/src/Backend/AutopilotMonitor.Functions/Services/SlaBreachEvaluationService.cs index 8f680bf1..26886545 100644 --- a/src/Backend/AutopilotMonitor.Functions/Services/SlaBreachEvaluationService.cs +++ b/src/Backend/AutopilotMonitor.Functions/Services/SlaBreachEvaluationService.cs @@ -30,7 +30,9 @@ namespace AutopilotMonitor.Functions.Services /// public class SlaBreachEvaluationService { - private const string DashboardUrl = Constants.WebsiteBaseUrl + "/sla"; + // Portal host — /sla is an authenticated portal page; www…/sla links in + // already-sent notifications reach it via the client-side host bounce. + private const string DashboardUrl = Constants.PortalBaseUrl + "/sla"; private const int MaxConflictRetries = 4; private const int MinAppInstallSampleSize = 5; diff --git a/src/Web/autopilot-monitor-web/app/robots.ts b/src/Web/autopilot-monitor-web/app/robots.ts index 81924bfe..aa3ddeaa 100644 --- a/src/Web/autopilot-monitor-web/app/robots.ts +++ b/src/Web/autopilot-monitor-web/app/robots.ts @@ -26,6 +26,7 @@ export default function robots(): MetadataRoute.Robots { // query-based since the static export). "/sessions", "/diagnosis", + "/sla", "/admin/", "/settings", "/preview", diff --git a/src/Web/autopilot-monitor-web/lib/hostRouting.ts b/src/Web/autopilot-monitor-web/lib/hostRouting.ts index 22cf187e..f6569774 100644 --- a/src/Web/autopilot-monitor-web/lib/hostRouting.ts +++ b/src/Web/autopilot-monitor-web/lib/hostRouting.ts @@ -27,7 +27,13 @@ export const PUBLIC_PATH_PREFIXES = [ "/privacy", "/terms", "/roadmap", - "/sla", + // NOTE: /sla is deliberately NOT here. It is a fully authenticated portal + // page (ProtectedRoute + token fetches) that only LOOKED public because SLA + // notifications historically linked www…/sla. As a public path it dead-ends: + // ProtectedRoute stands down on the public host, so the page waits forever + // for a sign-in (prod incident 2026-07-29). Off the list, old www…/sla links + // bounce to portal/sla where auth works; new notifications link portal + // directly (SlaBreachEvaluationService.DashboardUrl). "/robots.txt", "/sitemap.xml", "/IndexNow.txt",