From 08685babd0827406a600cf31ae69b2547f4dfdb1 Mon Sep 17 00:00:00 2001 From: Dmitrii Vasilev Date: Mon, 21 Sep 2026 20:01:25 +0700 Subject: [PATCH] fix(queen-web): every deploy built, started, and was refused by its own healthcheck Four merges on 2026-09-21 -- #1075, #1078, #1079, #1082 -- and then #1084 on top of them, all FAILED on the trinity Railway service, all at the same place: Attempt #1 failed with HTTP 403. Continuing to retry for 29s ... five attempts ... 1/1 replicas never became healthy! Healthcheck failed! The build succeeds every time and the container starts every time. The 403 is the server refusing the platform, not the app being broken. `npm start` is `vite preview`, and vite's preview server has answered an unrecognised Host with 403 since 6.0.9, when the DNS-rebinding guard was turned on by default. Railway's probe arrives as `healthcheck.railway.app`, which was in no list, so it was refused -- and the message that says exactly this is printed into the response body, which a healthcheck discards. Reproduced at the pinned version rather than guessed. The first attempt at this was run with `npx vite preview`, which quietly installed vite@8.3.0 and served the foreign Host with 200 -- a clean result from the wrong program. With the lockfile's 6.4.1: Host: healthcheck.railway.app -> 403 Blocked request. This host ... is not allowed. Host: 127.0.0.1 -> 200 and after this change: Host: healthcheck.railway.app -> 200 Host: trinity-production-6945.up.railway.app -> 200 Host: evil.example.com -> 403 A leading dot allows a domain and all of its subdomains, so one entry covers both the probe and the generated service domain, which can be reissued. `allowedHosts: true` would have switched the guard off for everything; the last line above is the reason not to. Co-Authored-By: Claude Opus 5 --- apps/queen-web/vite.config.ts | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/apps/queen-web/vite.config.ts b/apps/queen-web/vite.config.ts index 19bea13bc3..70edcaaad7 100644 --- a/apps/queen-web/vite.config.ts +++ b/apps/queen-web/vite.config.ts @@ -17,6 +17,22 @@ export default defineConfig({ }, }, }, + // Railway serves this through `npm start`, which is `vite preview`. Vite's + // preview server answers any Host it was not told about with 403 -- the + // DNS-rebinding guard that arrived in 6.0.9 and is on by default. The + // platform's own probe comes in as `healthcheck.railway.app`, so every + // deployment built cleanly, started, and then failed its healthcheck five + // times in thirty seconds. Four merges on 2026-09-21 never reached a running + // replica, and the build log said SUCCESS above the failure each time. + // + // A leading dot allows a domain and every subdomain, so one entry covers both + // the probe and the generated `*.up.railway.app` service domain -- neither of + // which is written down anywhere else, and the generated one can be reissued. + // The guard stays on for every other Host: `allowedHosts: true` would switch + // it off entirely, which is more than this failure asks for. + preview: { + allowedHosts: ['.railway.app'], + }, build: { outDir: 'dist', sourcemap: true,