Files
wyndham-ARR/.project-docs/50-evidence/topics/2026-07-30-web-login-runtime-mismatch.md
2026-07-31 15:41:36 +08:00

6.8 KiB

Web Login Runtime Mismatch

Metadata

  • Date: 2026-07-30
  • Status: Resolved; authenticated live runtime verified
  • Scope: Live ARR Web process on port 8766
  • Confidence: Fact
  • Source: Listener/process inspection, Keychain/launcher validation, loopback/LAN HTTP probes, source/config inspection, automated tests and isolated browser verification
  • Last verified: 2026-07-31
  • Stale trigger: Port-8766 process restart, login credential configuration, route/config change or LAN-address change

Finding

The first page-failure check found a partial runtime mismatch: PID 37865 was still bound to 0.0.0.0:8766 and returned HTTP 200 for /, /h5, /api/health and /assets/app.js on loopback and the then-current LAN address 192.168.3.48, while /login alone returned 404. The long-lived Python process predated the new login routes but read newer static files from disk.

The 23:03 recheck found a complete service outage instead. No process listens on 8766, PID 37865 is gone, and /, /h5, /login, /healthz, /api/health and /assets/styles.css all fail with connection refused on loopback. The workstation's Wi-Fi address has also changed to 192.168.3.103, where root and login probes likewise fail. No matching Web/worker/ngrok process, 8765/8766/8877 listener or launch agent was found. There is no retained process log, so the evidence does not prove why PID 37865 exited.

The login change was nevertheless relevant to recovery: current source intentionally refuses startup when ARR_WEB_USERNAME or ARR_WEB_PASSWORD is absent. After the operator supplied both values, each was placed in a separate macOS Keychain item and a credential-free local launcher restored the prior controlled database, OSS, processing, monthly and company-report inputs. Detached Screen session arr2-web-8766 owns the sole *:8766 listener.

On 2026-07-31 the operator requested a credential rotation. Both values were replaced through interactive no-echo Keychain input, the password item was rebuilt under stable non-credential account metadata, and the credential-free launcher remained valid. A controlled restart replaced only the resolved Web listener and recreated the same detached Screen topology; no credential value is recorded here.

Completed Source Implementation

  • arr_web.auth validates runtime ARR_WEB_USERNAME / ARR_WEB_PASSWORD with constant-time comparison and a bounded per-client attempt ledger. Missing/invalid configuration fails Web startup closed.
  • The authenticated SessionLedger issues random server-side sessions and per-session CSRF tokens, expires/revokes them and retains HttpOnly, SameSite=Strict plus optional Secure cookie behavior.
  • Login assets, POST /api/login and minimal /healthz are the only anonymous routes. Desktop/H5 documents redirect to an allowlisted login target; all business APIs, detailed health, uploads, traces and downloads reject anonymous access.
  • Desktop and H5 clients redirect expired sessions to login and expose CSRF logout. Logout starts hidden when an old anonymous /api/session response lacks username; this kept PID 37865's mixed-version UI compatible before activation.
  • Caddy Basic Auth was removed; Caddy remains the HTTPS boundary and the Web application owns human authentication.

Verification

  • Python and all three JavaScript files pass syntax checks.
  • The final focused auth/Web/company/deployment set passes 33 tests. Full discovery passes 317 tests in 97.311 seconds with 10 expected environment/fixture skips and no failures/errors.
  • Isolated real-browser verification passed generic wrong-credential feedback, password visibility, successful desktop and /h5 return, desktop/H5 logout, zero console warnings/errors and no horizontal overflow at 375, 768, 1024 and 1440 CSS pixels.
  • Ruby's standard YAML parser loaded the Compose file and deployment contracts confirm login env/readiness/Caddy shape. Docker is unavailable on this workstation, so no live Compose expansion or image build is claimed.
  • Live activation passes anonymous root 303 and business API 401; exact login, hardened cookie/session/CSRF, authenticated desktop/H5/history reads, all five readiness flags, logout and post-logout rejection. Loopback and 192.168.3.103 return /healthz 200; LAN root redirects to login and LAN /login returns 200.
  • A 2026-07-31 follow-up found the service still healthy under the same detached Screen process, while DHCP had moved the workstation address back to 192.168.3.48. Loopback and .48 root return 303 to login, /healthz and the login document return 200, and the in-app browser rendered the complete login gateway. The prior .103 URL is now stale.
  • The same-day visual follow-up removed the login page's workflow narrative, numbered steps, duplicate brand placement, welcome/access introduction and support disclaimers. The live gateway now presents one ARR Report heading, the username and password fields, password visibility and the existing submit/error states. Thirty-three focused Web/auth/UI tests pass; browser checks at 390x844 and 1280x720 have no horizontal overflow or console warnings/errors.
  • The credential-rotation acceptance rejects the prior pair and accepts the new pair, then verifies anonymous root/API boundaries, hardened cookie/session/CSRF, desktop/H5, logout revocation, all six current detailed readiness flags and loopback plus 192.168.3.48 health. Two read-only snapshots remained 30 daily jobs, 4 monthly versions and 4 company jobs; latest creation times predate the 15:30 +08 restart. Nine focused auth/deployment tests pass, and literal scans of the workspace, launcher, state logs and process list are clean.
  • The initial activation totals were 24 daily jobs, 4 monthly versions and 3 company jobs. No XML upload, company-report generation, Booking activation, monthly worker or other business mutation was started by either activation or rotation acceptance.

Activation Result and Operating Boundary

  • Current LAN entry as of 2026-07-31: http://192.168.3.48:8766/; DHCP may change this address again.
  • /Users/chillishark/.local/bin/arr2-web-8766 is owner-executable only and contains paths/Keychain labels, not secret values. Its --check mode validates required private inputs without printing them.
  • The active Screen session is detached but not a reboot-persistent process manager. A future controlled restart should validate the launcher, stop the exact 8766 listener and start one screen -dmS arr2-web-8766 session.
  • The latest requested values were rotated successfully, but the password still matches the username. A future strength rotation should use a distinct high-entropy password, update only Keychain and restart once; never commit the value or put it in process arguments.

Live login/readiness is complete. A no-PII upload-filename check and one released 5/5 company-report job remain separate business-mutation acceptance work.