55 lines
2.8 KiB
Markdown
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.
|