Files
wyndham-ARR/.project-docs/60-reflection/cases/2026-07-30-coordinate-hot-static-and-long-lived-backend.md
2026-07-31 15:11:42 +08:00

55 lines
2.8 KiB
Markdown

# Reflection: Coordinate Hot Static Assets With The Long-Lived Backend
## Trigger
The active port-8766 Python process predated the application-login routes, but it reads HTML/CSS/JavaScript from the
workspace on every request. Editing logout/login frontend assets therefore created a temporary new-frontend / old-backend
combination before any intentional process restart.
## Expected Behavior
A route-contract change should activate as one compatible release: the frontend should not advertise a control whose
backend endpoint is absent, and a fail-closed backend should not be restarted until required credentials exist.
## Actual Behavior
The long-lived process continued issuing anonymous CSRF sessions without `username` and returned 404 for `/login`,
while newer static files were immediately visible from disk. Restarting it without credentials would have taken the
whole portal offline.
## Root Cause
- Static assets and Python route code had different activation lifecycles.
- The current workstation process is manually coordinated rather than deployed as one immutable image/restart.
- Login correctly fails startup closed, so activation depends on an operator-owned secret choice.
## Evidence
- Files: `arr_web/app.py`, `arr_web/static/app.js`, `arr_web/static/h5.js`
- Runtime: PID 37865 on port 8766
- Evidence: `50-evidence/topics/2026-07-30-web-login-runtime-mismatch.md`
- Verification: old `/api/session` shape lacks `username`; old `/login` returns 404; isolated new runtime passes login/logout.
## Lesson
Treat hot-read static files plus a long-lived backend as a rolling mixed-version deployment. Before editing, inspect the
active route/session contract. Make new controls feature-detect the new response shape and stay hidden on the old one;
then restart once only after every fail-closed runtime input is ready.
## Action
- Logout controls start hidden and are revealed only when `/api/session` returns an authenticated `username`.
- Keep an old process running until every fail-closed secret exists; if it has already exited, restore only after the
complete previous non-secret runtime composition is also recovered.
- Store the Web password and OSS credentials in Keychain. The user-local launcher contains only allowlisted route
parsing, paths and Keychain labels; it never commits or prints values.
- A launchd-owned process cannot read this Desktop-hosted runtime under the current macOS privacy boundary. The active
local workaround is a desktop-authorized detached Screen session; production should use an approved supervisor and
non-Desktop deployment path.
- Record the exact coordinated restart and acceptance sequence in current state, evidence, stale items and commitments.
## Promotion
Promoted to the frontend compatibility contract, current-state restart gate, login-runtime evidence and this reusable
reflection. No broader ADR is required.