# Browser Session and Terminal Selector Tests Run from the repository root: ```sh python3 tests/web_ui_session/run.py ``` Requires a host C compiler, Python 3, and Node with Fetch/Response/ReadableStream support (Node 18+). All compiler outputs and rendered scripts are temporary; no firmware build, generated assets, or device writes are performed. The runner compiles production `src/web_ui.c` with HTTPD and vendored-asset data doubles. It reuses the HTTPD stub text from `tests/web_login_ui/run.py`, without importing/executing that runner. Node executes the actual C-rendered application and inline asset-failure script, not a separately maintained implementation. Coverage: - Resource selection, NULL/invalid input, setter/send failure propagation, eight-header ceiling, no-store document/application, unchanged vendor caching, nosniff/no-referrer/frame denial, exact inline-loader CSP hash and login fallback. - Session validation before initial/retried/restored connections; memory-only CSRF header and empty ticket/logout bodies; safe-text username/absolute expiry. - 401 shutdown and navigation once; manual recovery on 403; bounded Retry-After display/backoff for capacity; network errors never assert successful logout. - Confirmed 204 logout, lost response confirmed by session 401, uncertain logout, cancellation, explicit recovery, and stale session/ticket/status/logout/WS work. - Pagehide/bfcache restoration, late response bodies, and superseded session checks. - Existing writer controls, 1,024-byte binary input chunks, raw binary output, observer input gating, and explicit Disconnect pausing reconnect. - Authentication/ticket response cap 512 bytes, existing status cap 3,072 bytes, 15-second request deadline, single status request in flight, bounded retry delay, and unchanged 5,000-line terminal scrollback. - Admin-only navigation, explicit protected-ticket open, 20 switches preserving serial socket/client/writer IDs, separate output and selected-only input. - Independent 64 KiB pending output limits, visible dropped-byte counters and resumed hidden output draining; 512-byte admin input frames and overflow close. - Admin close/reopen/remote exit isolation, 401/logout/expiry/pagehide cancellation, late tickets/callbacks, handshake timeout, selected resize and three listener cleanup/restore cycles. - Session identity changes (username, role or session-stable CSRF) force a clean document before view adoption, close old admin and prevent replacement-session logout; same-session restore retains both scrollbacks behind validation gating. - Undefined initial dimensions recover at unchanged bounds; failed fits never populate the cache, readiness retries stop at three, and teardown fences stale callbacks even after restore. - Read-only admin Settings/Serial: 10 selection cycles preserve both sockets/IDs, drain hidden output and block terminal input; exact eight-field/256-byte schema, explicit refresh, error/timeout containment, late cancellation/restore/identity, and concurrent serial reconnect without superseding admission. - 8D.9 typed Serial actions: draft validation, Reset-only confirmation, bounded JSON/CSRF, explicit working/persisted effects, automatic bounded result checks, failure/timeout containment, session fencing and preserved sockets/writer identity. - Lost-acknowledgement and replaced-result uncertainty survives repeated result checks, failed reads, refresh and navigation; a newly acknowledged explicit submission starts a new result context. - Immediate completion on the first GET, pending then completion, 10-attempt exhaustion and manual recovery, 15-second overall abort during fetch/body reads, delayed timers/replies, automatic read errors, visible stale snapshots during refresh and after refresh failure for every terminal outcome, late refresh cancellation, no routine confirmations and Reset cancellation. Navigation, pagehide/restore, logout, expiry and changed identity cancel checks without automatic resumption. - Repeated current Settings selection is a no-op during submission, between and during result checks, and during completion refresh: requests, timers, visible values/control state, final outcome and socket/writer identity remain intact. **35 Node groups total.** ## Automatic result-check budget After a valid POST acknowledgement, the UI waits **1,000 ms** before the first result GET and between completed pending-result checks. It makes **at most 10 GET attempts** and uses an independent **15,000 ms overall deadline**, measured with the monotonic browser clock from acknowledgement. Each attempt first revalidates the session; that time is included in the deadline. There is only one automatic check in flight. Delayed timer callbacks and replies also check this deadline. Expiry actively aborts the in-flight request and releases the UI for manual recovery; late completions cannot update the view. The first limit reached stops automatic checking. A read error also stops it. The budget does not cancel backend work and is not a server execution deadline. **POST is never automatically retried.** Lost acknowledgement requires explicit Check Result recovery; manual checks do not restart automatic polling. Exhausted or cancelled polling never resumes on navigation or bfcache restoration. Every known terminal result, including failure/cancellation, triggers one working snapshot refresh while retaining the operation outcome and any uncertainty warning. Snapshot refresh is outside the auto-check budget and retains the existing 15-second per-request bound (session validation and snapshot GET are separate requests). Settings remain visible but conflicting controls are disabled during work; old snapshots are explicitly stale during pending/uncertain work or a failed refresh. A successful refresh replaces the browser draft. Only Reset asks for confirmation, specifically because it overwrites saved configuration. Tests use a deterministic clock and individually fired timer callbacks, including callbacks invoked after cancellation and fetch/body doubles that ignore abort. These deliberately exercise fences beyond normal browser cancellation behavior. ## Integration and known gaps This covers 8D.3 session behavior, the 8D.6 selector, 8D.8 Settings and the 8D.9 Serial UI. Operation responses are fetch doubles, not end-to-end execution of `web_serial_settings.c`, dispatcher work, serial reconfiguration or NVS persistence. The renderer still relies on its caller to authenticate resources; protected asset failures must be 401, never a redirect to HTML served as JavaScript. No Basic fallback is implemented here. Existing 8D.5 server authorization/protocols are unchanged. These tests model DOM, timers, fetch cancellation and WebSocket events. They do not prove real-browser CSP enforcement, script-loading errors, TLS/HTTPD behavior, actual bfcache policy, cookie expiry, server revocation, or hardware serial byte integrity, actual xterm escape parsing, hidden prompts, or desktop/mobile layout. Prior 8D.6 signoff stands; the new Settings build and pending target checklist are in `docs/phase8d8_implementation.md`. No target resource reserve is claimed. Browser secret references are dropped and never persisted/logged, but JavaScript cannot securely wipe engine-managed strings.