Regression from the leak-scrub: vite.config read $process.env.VITE_HMR_HOST, but the dev container
bind-mounts .env without exporting it into the process environment — so it was ALWAYS empty and the
hmr host fell back to 'localhost'. On a remote dev box the browser then loaded the Vite client + app.css
+ app.js from localhost:5173 (ERR_CONNECTION_REFUSED) → the whole panel rendered unstyled. Switch to
Vite's loadEnv (reads the .env file, same source the other VITE_* vars use) and fall back to undefined
(Vite infers the host from the request) instead of a hard 'localhost'. The real address stays in the
untracked dev .env (documented in .env.example, no IP committed). Verified: dev assets load 200 + the
login renders styled, and `npm run build` (prod) still succeeds.
Audit leak-hygiene findings:
- The operator's real internal dev-VM/WireGuard IPs (10.10.90.136/.162/.165) were shipped in
vite.config.js (hmr.host), lang hint/placeholder strings, a code comment and the CHANGELOG.
vite HMR host is now env-driven (VITE_HMR_HOST, dev .env only); all other occurrences are replaced
with RFC5737 documentation addresses (203.0.113.x). Tests updated in lockstep.
- docs/ is export-ignored from the git tree and named in promote.sh's refuse-to-publish list, but was
never .dockerignore'd, so `COPY . .` baked the private docs (with private host/URL refs) into the
public image, which the git-tree leak-guard never inspects. Added docs/ (and art/) to .dockerignore.
- /update.log (new repo-root update transcript) gitignored.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>