Add broker management and writer transfer UI
This commit is contained in:
@@ -237,6 +237,14 @@ Configuration modules generally choose RAM defaults without erasing incompatible
|
||||
|
||||
Bounds:256-byte/four-receive request,128-byte snapshot,96-byte result, one slot;30 URI handlers/six sockets, no new task/timer/stack-size/queue/schema expansion. Optional staged allocation failures retain other routes. Host tests/build pass; target and memory/stack margins pending. Full contract, resource evidence and checklist: `docs/phase8d14_implementation.md`.
|
||||
|
||||
## Typed Broker management (8D.16)
|
||||
|
||||
`web_broker_settings` provides admin-only bodyless GET management snapshot and GET/POST assignment/result routes, using Display-style bounded parsing, one login-isolated result slot and the existing typed dispatcher. Only a numeric ID is queued. Original principal/session and30-second dequeue deadline are checked before owner admission; already-admitted work can finish after logout. Optional staged registration preserves other services. Bounds:256-byte/four-receive request,2048-byte snapshot,96-byte result;33 handlers/six sockets, no new timer/task/queue/stack-size/assets changes.
|
||||
|
||||
The broker copies compact client rows and writer/lease generation together under its existing mutex with zero wait. Conditional assignment compares generation and connected non-reused target under the same force-writer lock before any effect. Lease grant/release/revoke events advance a separate saturating32-bit generation before delivery attempts, including same-writer ABA; counter clears and dropped events cannot invalidate this fence. UINT32_MAX disables conditional assignment, not ordinary transport/console recovery. Client IDs retain three slot/29 generation bits, but exhausted slots now retire until reboot rather than reusing IDs. Reboot invalidates originating web sessions. Existing unconditional force APIs and one-writer/multiple-observer policy remain unchanged.
|
||||
|
||||
Browser Settings/Broker shows safe ID/type/name/role/pending/HWM/drop rows and clears selection on Refresh. Native confirmation captures exact target/generation before session revalidation. Viewing/selecting never mutates; completion checks are bounded to10 one-second GETs/15seconds, no mutation replay. There are no contextual popovers or diagnostic/service controls. Complete contracts, wrap analysis, evidence and pending parent/target review: `docs/phase8d16_implementation.md`.
|
||||
|
||||
## Local UI and hardware boundaries
|
||||
|
||||
`board_pins.h` centralizes project-assigned RS-232, diagnostic, RGB LED, and local-UI hardware resources; UART0 GPIOs remain local to `main.c`, and native USB uses platform wiring. `local_display` solely owns I2C0, the SSD1315-compatible OLED, its static framebuffer, and display mutex. Display frames belong to the initiating task. Dirty-page commits and I2C transactions are bounded.
|
||||
|
||||
@@ -34,6 +34,8 @@ This is a semantic map, not a complete file inventory. Start here, then read the
|
||||
|
||||
## Session broker
|
||||
|
||||
- **8D.16 management:** `session_broker_get_management_snapshot()` copies compact eight-client rows plus writer/lease generation atomically with zero wait; `session_broker_assign_writer_current()` compares generation and target under the force-writer lock. 29-bit client generations retire slots instead of wrapping; saturating lease generation fences ABA, survives counter clear, and leaves ordinary recovery available. Actual canonical regressions extend `tests/session_broker_diagnostics/run.py`. Full contracts/wrap analysis: `docs/phase8d16_implementation.md`.
|
||||
|
||||
**Responsibility:** mediate all transport access to the serial service; provide one writer lease and multiple isolated observers.
|
||||
|
||||
- Files: `src/session_broker.{h,c}`, `src/session_console.{h,c}`
|
||||
@@ -59,6 +61,8 @@ This is a semantic map, not a complete file inventory. Start here, then read the
|
||||
|
||||
## Web and WebSocket serial
|
||||
|
||||
- **8D.16 Broker (2026-09-13):** `web_broker_settings.{c,h}` owns optional admin-only GET `/api/settings/broker`, GET/POST `/api/settings/broker-operation`; existing dispatcher queues only IDs. `web_ui.c` adds Serial/Display-style full-page rows and explicit confirmed assignment, no mutation on view/selection. 256-byte/four-receive request,2048-byte snapshot,96-byte result, one login-bound slot/no timer;33 handlers/six sockets, unchanged tasks/stacks/queue/assets/CPU160/combined WS send. Tests: cookie `--broker`6+shared, broker management/wrap, dispatcher, lifecycle25, UI119+HTML/CSP and broad regressions. Baseline100,196/1,765,233 B → final100,300/1,782,613 RAM/flash. Independent parent review and target sign-off pending. Contracts/resources/checklist: `docs/phase8d16_implementation.md`.
|
||||
|
||||
- **8D.14 Display (2026-09-09):** `web_display_settings.{c,h}` owns optional admin-only GET `/api/settings/display`, GET/POST `/api/settings/display-operation`; `web_ui.c` supplies Serial-style dim/off settings and bounded completion checks. `local_status_ui` owns generation-safe config/storage reservation shared with CLI; buttons do not edit timeouts. No I2C changes. 256-byte/four-receive request,128-byte snapshot,96-byte result, one slot/no timer;30 handlers/six sockets, unchanged tasks/stacks/queue/schema. Tests: cookie `--display` (7+shared), UI111, lifecycle23, dispatcher and broad regressions. Actual baseline100,100/1,748,513 B → final100,196 RAM/1,765,233 flash at160MHz. Target pending; exact API, reset ordering, deadlines, resource/validation limits: `docs/phase8d14_implementation.md`.
|
||||
|
||||
- **Current 8D.12/8D.13 — user functional sign-off 2026-09-08, including Settings presentation:** `web_network_settings.{c,h}` owns optional admin-only GET `/api/settings/network` and GET/POST `/api/settings/network-operation`; `web_ui.c` supplies Network, UTF-8/hex SSID editing and explicit transient-secret/connection controls. `wifi_manager` owns generation-checked secret-free snapshots/patch/save/stored-only load and radio transitions; `mdns_service` owns independent conditional hostname persistence, with manager reannouncement. Existing dispatcher receives IDs only. 768-byte request/2,048-byte snapshot/128-byte result, one slot/one-second timer with 30-second queued expiry plus scheduling latency; no hard cancellation. 27 handlers/six sockets, no task/stack/queue/schema growth. Parent integrated tests/build PASS; latest styling UI100 + renderer/CSP/Chromium checks, 99,548 B RAM / 1,744,325 B flash. User full-mix evidence accepted; loaded internal/DMA minima2,276/156 B remain resource follow-ups, not reserve approval. Full contract/exclusions/checklist: `docs/phase8d12_13_implementation.md`. Both phases user-authorized together; no 8D.14/M3 claim. Older next-phase statements below are historical.
|
||||
|
||||
@@ -4,6 +4,8 @@ This file is working memory. Update it during active work and before handoff; do
|
||||
|
||||
## Development state
|
||||
|
||||
- **8D.16 implemented (2026-09-13), user-authorized; host/build verified, independently reviewed; target sign-off pending:** Admin Settings/Broker has bounded detailed client rows and explicit confirmed writer assignment, no view/selection mutation, no8D.17/18 popovers/icons. `web_broker_settings` uses256-byte/four-receive requests,2048-byte snapshot,96-byte result, one login-isolated slot and existing typed dispatcher IDs/30-second dequeue deadline; no new timer/task/queue/stack/assets. Broker owns atomic zero-wait client/writer/lease snapshot and conditional generation+target check under force lock;29-bit client generations retire slots rather than wrap, separate saturated32-bit lease generation fences ABA/counter clears/dropped events, ordinary recovery retained.33 handlers/six sockets. PASS cookie Broker6+shared, canonical broker7+2 management/wrap, dispatcher, lifecycle25, UI119+five-view HTML/CSP, all existing cookie variants, canonical Network/accounts, parser294, console lifecycle/policy, transport/tickets/store, idle/diagnostics/performance/login and diff checks. Baseline pio7.14s100,196 RAM/1,765,233 flash; substantive-source final20.54s100,300/1,782,613 (+104/+17,380 B); final post-review confirmation21.20s unchanged. Initial worktree clean; CPU160 confirmed defaults/active/generated, signed-off combined WS send untouched. Tests fixed row-schema count and harness extraction/capacity/count issues. Independent final review found no actionable findings; reviewer reran broker7+2, cookie Broker/Display, dispatcher, lifecycle25, UI119+C/HTML/CSP, throughput and diff checks PASS. Parent final pio confirmation PASS6.93s at100,300/1,782,613 B; diff check PASS. Target/full-mix/HTTPD-dispatcher margins and user sign-off pending; no reserve/M3 claim. Exact API/wrap/resources/test limits and target checklist: `docs/phase8d16_implementation.md`. No upload/erase/commit/SDK changes. Older next8D.16 authorization wording below is historical.
|
||||
|
||||
- **8D.15 removed from plan (2026-09-09), explicit user scope decision:** Network diagnostics stay exclusive to the admin shell; no dedicated typed diagnostics endpoints/settings UI. Removed the planned deliverable from `docs/phase8d_plan.md`; retain later phase numbers, so next planned chunk after8D.14 is8D.16, only on separate request. Existing shell permissions and implemented Network settings/status unchanged. Documentation only; no firmware/build/device action or8D.14 target sign-off implied.
|
||||
|
||||
- **8D.14 Display implementation complete (2026-09-09), user-authorized; host-tested/build-verified, target pending:** Admin Settings → Display supplies typed dim/off0–86400s, Apply/Save/Load/Defaults/Reset, Serial-style label/value presentation and bounded result polling. `web_display_settings` owns one secret-free login-bound slot, 256-byte/four-receive requests,128-byte snapshot/96-byte results; IDs use the existing dispatcher. `local_status_ui` owns nonwrapping config generation and zero-wait reservation across NVS outside critical sections; CLI shares the gate, buttons retain independent activity/reprobe behavior. Reset now commits defaults before RAM publication (CLI too), eliminating rollback overwrite. Absent panel does not gate config if UI task is available; no I2C/renderer ownership change.30 handlers/six sockets, no new task/timer/stack size/queue/schema/assets changes.30-second dequeue admission deadline, not timed cancellation; admitted work may finish after logout. PASS Display7+shared auth, UI111+C/HTML/CSP, lifecycle23, dispatcher/accounts/policy, cookie all variants, canonical Network, parser294, transports/tickets/store/idle/diagnostics/throughput/broker/login regressions and diff check. Separate self-review fixed strict result status/action/replacement handling. Independent final review found no actionable findings and independently reran Display7+shared auth, dispatcher boundary, lifecycle23, UI111+C/HTML/CSP and diff checks PASS. Parent final pio confirmation PASS9.08s, unchanged100,196/1,765,233 B; diff check PASS. Actual pre-edit pio12.10s100,100 RAM/1,748,513 flash; final pio26.09s100,196/1,765,233 (+96/+16,720 B). CPU160 confirmed in defaults/active/generated configuration; throughput fix and user sign-off preserved. Initial worktree reported clean. Optional Chromium geometry attempt blocked by sandbox socket/crash-report restrictions; no geometry pass. Target display/save-reboot/absent-panel/buttons-concurrency/full-mix/heap/HTTPD-dispatcher margins and sign-off pending, no reserve approval or full M3 claim. Exact contracts/tests/resources/checklist: `docs/phase8d14_implementation.md`. No upload/erase/commit or later phase; older no-8D.14 authorization statements below are historical.
|
||||
|
||||
@@ -60,6 +60,14 @@ Phase 8D.2 adds a third identity: non-reused 64-bit originating web-session IDs
|
||||
|
||||
**Relevant files:** `src/session_broker.{h,c}`, `src/ssh_transport.c`, `src/web_serial_transport.c`, `src/admin_ssh_console.c`, `src/user_database.{h,c}`
|
||||
|
||||
## Confirmed writer transfer compares a lease version inside the broker lock
|
||||
|
||||
**8D.16 decision:** A client ID alone cannot authorize a stale browser confirmation: the writer may release and reacquire while a dialog is open. The compact management projection copies clients, writer and a separate lease generation under one zero-wait mutex acquisition. Conditional assignment validates target and lease generation in the same force-writer lock before any changes; existing unconditional console/recovery APIs remain available.
|
||||
|
||||
**Wrap contract:** Three-slot-bit/29-generation-bit broker IDs now retire exhausted slots instead of wrapping. A32-bit lease generation saturates at UINT32_MAX, survives counter clear, and advances for each grant/release/revoke emission before advisory queue delivery. Forced transfer can advance twice; it is an opaque version, not a count. Saturation rejects typed assignment but never prevents normal release/disconnect/request or recovery force. Future writer transitions must preserve the central event-emission invariant. Reboot resets broker state but invalidates web sessions, so authorized old browser work cannot span boots.
|
||||
|
||||
**Consequence:** Never implement snapshot-check-unlock-force, compare only current writer ID, or renew a confirmation implicitly during Refresh. UI must require explicit target selection and confirmation, retain uncertain-outcome handling and never retry mutations automatically. Bounded login-isolated result slots and the existing dispatcher remain the typed HTTP boundary. Details/tests: `docs/phase8d16_implementation.md`, `src/session_broker.{c,h}`, `src/web_broker_settings.{c,h}`.
|
||||
|
||||
## UART0 is the physical recovery authority
|
||||
|
||||
**Decision:** UART0 remains independent of UART1 and networking. The first administrator is created with normal `user add` on UART0; explicit unavailable-user-database recovery to empty is UART0-only and refuses healthy storage. No bootstrap command/API remains.
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
# Phase 8D.16 — Broker visibility and confirmed writer assignment
|
||||
|
||||
## Status and scope (2026-09-13)
|
||||
|
||||
User-authorized implementation complete; focused host regressions, broader regressions and production build pass. **Independent review complete with no actionable findings; target validation and user phase sign-off remain pending.** Reviewer independently reran broker management/wrap, cookie Broker and Display, dispatcher, lifecycle25, UI119+C/HTML/CSP, throughput and diff checks, all PASS. Parent final `pio run` confirmation PASS6.93s,100,300 B RAM/1,782,613 B flash; diff check PASS. Host doubles do not establish real multicore timing or target margins.
|
||||
|
||||
Settings → Broker is admin-only and uses the existing Serial/Display label/value and action styles. It shows up to eight connected clients with ID, type, name, writer/observer role, pending output bytes, output high-water and dropped bytes. Selection is explicit and Refresh clears it. Only Assign writer followed by confirmation submits a mutation. Viewing, selecting, refreshing, switching settings/terminals and reading results do not change the lease or close either terminal.
|
||||
|
||||
The initial Git status was clean. Preserve the previously signed-off combined binary WebSocket send and CPU160 configuration; neither was edited. No 8D.15 diagnostics UI (diagnostics remain shell-only), 8D.17/18 popovers/icon changes, disconnect/revoke-only UI, serial persistence/configuration change, new generic runner/task/timer/mutex allocation, queue depth/item or stack-size increase, generated assets, SDK patches, upload, erase, branch or commit. No full M3 or resource-reserve acceptance claim.
|
||||
|
||||
## Production files and ownership
|
||||
|
||||
- `src/session_broker.{c,h}` owns the atomic non-consuming compact management projection, conditional writer assignment and non-reused client IDs. All serial mediation, event queues and data buffers remain broker-owned.
|
||||
- `src/web_broker_settings.{c,h}` owns HTTP authorization/parsing/encoding, one originating-login-bound operation/result slot and typed execution adapter.
|
||||
- `src/admin_ssh_console.{c,h}` queues only a numeric operation ID on the existing four-entry request queue. The same dispatcher executes the broker API outside its critical sections, never through a constructed command string.
|
||||
- `src/web_server.c`, `src/CMakeLists.txt` compose three optional routes and the new source.
|
||||
- `src/web_ui.c` supplies authored HTML/JS, native select/confirmation, bounded result polling and uncertainty recovery. Loader/CSP and generated/vendored assets are unchanged.
|
||||
|
||||
## Authoritative broker contract and wrap analysis
|
||||
|
||||
`session_broker_get_management_snapshot()` takes the existing mutex with **zero wait**, copying writer ID, lease generation and all active compact rows in one lock acquisition. It never reads UART payloads or pops events. Busy/uninitialized snapshots are unavailable, not empty-success snapshots. Pending/HWM/drop fields describe broker output, not peer receipt; counters cover the connection or last counter clear. Disconnected clients disappear; global historical accounting remains unchanged.
|
||||
|
||||
`session_broker_assign_writer_current(target, generation)` requires a nonzero target and generation. It shares the existing force-writer implementation, with the generation comparison and connected-target lookup **inside the same broker mutex, before any lease/counter/event effects**. Stale generations return `ESP_ERR_INVALID_STATE`; absent/reused targets return `ESP_ERR_NOT_FOUND` when the generation is otherwise current. Both map to a typed `conflict` result. Assignment to the already-current target is a no-op only after validation; UI disables this redundant action. There is no compare-unlock-force race.
|
||||
|
||||
The existing unconditional force/release APIs and transport request/release policy remain available. At most one connected client owns the lease; assignment makes the former writer an observer. Already-accepted serial TX bytes are not recalled or discarded. Events remain advisory: transport reconciliation still uses authoritative broker state.
|
||||
|
||||
Two independent stale-reference problems required small broker changes:
|
||||
|
||||
1. **Client IDs:** three slot bits plus 29 generation bits; generations previously wrapped from `536870911` to `1`. Free slots at their maximum generation are now skipped/retired until reboot. The final generation is still usable, including ID `UINT32_MAX` in slot 7. Exhausting all eight slots returns the existing `ESP_ERR_NO_MEM` without DTR/client publication. No previously-issued ID is reused within a boot; no wider transport protocol ID or per-client allocation is introduced. Reboot resets broker IDs but invalidates all originating web sessions, so an old authorized confirmation cannot span boots.
|
||||
2. **Lease confirmation:** a separate 32-bit generation starts at 1, survives counter clear and advances under the mutex for each granted/released/revoked event, **before attempting advisory delivery**. All current lease transitions emit these events; denied requests and same-writer no-ops do not advance it. A forced transfer can advance twice (revoke plus grant), so this is an opaque version, not a transition count. Release/reacquire by the same writer invalidates old confirmation (ABA). At `UINT32_MAX` it saturates permanently; management snapshots remain readable but conditional assignment rejects and UI disables assignment. Ordinary transport requests, release/disconnect, console force and UART0/USB recovery remain available. Counter/event-sequence wrap cannot resurrect a confirmation because neither is used as its token.
|
||||
|
||||
New observer connections/disconnections do not invalidate unrelated confirmations. The selected target's non-reused ID still prevents reassignment to its replacement; any writer disconnect changes the lease generation. The central grant/release/revoke emission invariant must be preserved by future lease mutations.
|
||||
|
||||
## HTTP and operation contract
|
||||
|
||||
All routes require current cookie/principal authentication and administrator role. Normal users cannot read management details/results or transfer. GET retains the established bodyless/queryless/header/Origin policy. POST additionally requires canonical same-origin Origin, CSRF and exact supported JSON Content-Type, with no query or transfer encoding. Responses use no-store/nosniff/no-referrer; scratch cleanup and unread-body close behavior follow Display.
|
||||
|
||||
| Route | Method | Bound / response |
|
||||
|---|---|---|
|
||||
| `/api/settings/broker` | GET | 2,048-byte response buffer; exactly `generation`, `writer`, `clients`. 503 when broker unavailable/busy. |
|
||||
| `/api/settings/broker-operation` | POST | Nonempty, at most 256 bytes/four receive calls. Exactly `action:"assign"`, `generation` (1–4294967294), `target` (1–4294967295). 202 means admitted, not executed. |
|
||||
| `/api/settings/broker-operation` | GET | 96-byte response buffer; exactly `id`, `action`, `state`, latest result for this originating login only. |
|
||||
|
||||
Each client row has exactly `id`, `type`, `name_hex`, `pending`, `high_water`, `dropped`. Type is the existing enum (0 Console, 1 USB, 2 Web, 3 SSH, 4 Internal). Names are at most 23 bytes encoded as at most 46 lowercase hex characters; browser decoding and DOM `textContent` avoid JSON/HTML injection. Invalid UTF-8 displays replacement characters, while IDs remain the authoritative identity. `dropped` is an unsigned decimal **string**, preserving all 64 bits in JavaScript. Writer/observer role is derived from the same snapshot's writer ID. No passwords, tickets, verifiers, private keys or UART bytes are included.
|
||||
|
||||
The narrow flat parser rejects duplicates, missing/unknown fields, escaped names/actions, strings in numeric fields, nested values, leading zeros, negatives, fractions, exponents, integer overflow, embedded NUL and trailing garbage. Exact 256-byte whitespace-padded requests are supported. Excessive fragmentation/receive errors fail rather than retry/drain indefinitely.
|
||||
|
||||
One static slot is shared across administrators, but results are isolated by non-reused **web-session ID**, not username. Another login sees `{id:0,action:"none",state:"idle"}`. Pending/full/not-ready dispatcher or exhausted operation IDs returns 503/Retry-After 1. IDs never wrap; completed results are replaceable, not durable history or idempotency records.
|
||||
|
||||
The dispatcher checks original session/principal/admin and a **30-second dequeue admission deadline** before calling the conditional broker API. No timer or hard cancellation is added: a blocked dispatcher can retain the bounded pending record beyond the deadline until dequeue. Work admitted before logout/expiry/stop may finish; no delivery guarantee is made. Auth stop/restart invalidates queued originating identities. Principal material is wiped at completion and local copies are wiped on exit.
|
||||
|
||||
States: `idle` (no retained result for this login, not proof of cancellation), `pending` (queued/executing), `ok` (assignment/no-op completed at execution time, not a future lease guarantee), `conflict` (stale/exhausted generation, absent target or uninitialized broker; no change by this operation), `failed` (other owner failure), `cancelled` (currentness/dequeue deadline denied before owner admission).
|
||||
|
||||
Optional registration orders snapshot → result GET → mutation POST. Failed snapshot/result registration prevents later routes; failed POST removes result GET, unless unregister itself fails, leaving reads only. Other settings, authentication, serial/admin transports and recovery survive optional failures. Budget: **30 → 33 URI handlers**, six sockets/no LRU unchanged.
|
||||
|
||||
## Browser behavior
|
||||
|
||||
- Admin-only full-page Settings navigation; no empty placeholder, contextual popover, icon redesign or new ordinary-user status detail.
|
||||
- No default selected target; no transfer on opening/selecting. Refresh always clears selection rather than silently renewing a previous confirmation.
|
||||
- Confirmation identifies target ID/type/name and snapshot writer ID, explains observer transfer and already-queued UART bytes. The exact selected target/generation is captured before asynchronous session revalidation and submission; concurrent changes are rejected at the broker lock.
|
||||
- One explicit POST, no automatic mutation retry. At most ten one-second result GETs and a 15-second overall automatic-check deadline, including delayed session work. Manual Check Result remains available after uncertainty.
|
||||
- Lost acknowledgement, another-tab result replacement, invalid response and navigation preserve explicit uncertain-outcome messaging. Known terminal results refresh the snapshot once; stale/conflict requires fresh selection/confirmation.
|
||||
- Navigation, pagehide, logout and expiry abort/fence stale browser work and clear selected identities/rows. This is not backend cancellation. Both terminals retain their existing hidden-output draining and selected-input policy.
|
||||
|
||||
## Validation actually run
|
||||
|
||||
All commands below passed in this implementation session with bounded terminal runtimes:
|
||||
|
||||
- `python3 tests/session_broker_diagnostics/run.py`: existing seven diagnostic groups plus two management/wrap groups, actual broker/console under deterministic RTOS/serial doubles. Covers atomic/non-consuming projection, zero-wait contention, USB/SSH/Web interleavings, exactly-one-writer transfer, stale/reused targets, release/reacquire ABA, counter clear, local force-release, writer disconnect, saturation and final client IDs.
|
||||
- `python3 tests/web_cookie_auth/run.py --broker`: six new groups plus shared auth/store/installed-IDF boundary tests; actual HTTP policy/parser/operation module with broker dependency double. Bounds, safe eight-row encoding, session-isolated results, queue failure/replay, stale-owner result mapping, currentness/deadline/expiry/revocation/stop-restart and lost acknowledgement.
|
||||
- `python3 tests/admin_console_boundary/run.py`: actual dispatcher, including new Broker ID routing, zero/full/not-ready admission, unchanged four-slot capacity and no command-runner invocation; existing certificate and SSH adapters also pass.
|
||||
- `python3 tests/web_admin_transport/server_lifecycle.py`: 25 groups, including six Broker descriptor/name allocation positions, failed result unregister, failed stop/retry/restart and unrelated route isolation. Orchestration uses HTTPD/TLS doubles, not actual TLS allocation faults.
|
||||
- `python3 tests/web_ui_session/run.py`: **119 browser groups** (eight new Broker groups) plus actual C renderer/HTML structure/shared styles/no-store/loader-CSP checks. Snapshot validation, safe names/64-bit counters, no view/selection mutation, confirmation/cancel, stale completion, polling bounds, lost/replaced results, navigation/401/pagehide/logout fences. No real browser geometry or target visual pass claimed.
|
||||
- Cookie variants `--display`, `--network`, `--accounts`, `--serial-settings`, `--settings`, `--admin`; canonical `tests/web_network_settings/run.py`; `tests/web_auth_parse/run.py` (294 cases); `tests/admin_console_boundary/accounts.py`, `lifecycle.py`; `tests/admin_ssh_policy/run.py`; `tests/web_serial_performance/run.py` (including 513 installed-SDK wire comparisons); `tests/web_httpd_idle/run.py`; `tests/web_admin_transport/run.py --tickets`; `tests/web_session_store/run.py --serial`; `tests/web_diagnostics/run.py`; `tests/web_login_ui/run.py`.
|
||||
- `git --no-pager diff --check` passed.
|
||||
|
||||
Tests initially caught and fixed a six-field Broker row incorrectly checked as seven fields. Harness integration corrections: static helper collision with extracted console code, HTTP test output bound, and lifecycle route-count expectations. No remaining known focused test failures. Self-review inspected broker transitions/ID generation, HTTP/session policy, optional registration and browser confirmation/result flow; subsequent independent review found no actionable findings (see status above).
|
||||
|
||||
### Build/resource evidence
|
||||
|
||||
Actual pre-edit `pio run`: PASS **7.14 s**, **100,196 B RAM / 1,765,233 B flash**. Post-integration build: PASS82.93s. Final confirmation after formatting/review: PASS21.20s, unchanged sizes. Final substantive-source build: PASS **20.54 s**, **100,300 B RAM / 1,782,613 B flash**: **+104 B RAM / +17,380 B flash** versus baseline, within the existing 4 MiB application partition. Authored response sizes: HTML28,929 bytes; app JS109,731 bytes after copy-text cleanup (not generated assets). Existing nonfatal SDK `FATFS_PRINT_FLOAT` bool-default warning occurred in the integration build; no SDK/config workaround applied.
|
||||
|
||||
CPU160 verified in `sdkconfig.defaults`, active `sdkconfig.esp32-s3-devkitc-1-n16r8` and generated `config/sdkconfig.h`; PlatformIO's generic board banner still says240MHz and is not the configured frequency. No CPU/scheduling/throughput tuning was performed.
|
||||
|
||||
Static image delta excludes runtime URI allocation overhead and peak nested stack usage. Snapshot handler uses bounded 2,048-byte response plus compact eight-row snapshot and auth locals on the existing HTTPD stack; operation admission uses256-byte request/96-byte result buffers and one slot, no payload heap allocation. HTTPD/dispatcher live margins, full-mix internal/DMA/PSRAM minima and scheduling overhead are **unmeasured**. A build pass does not establish safe runtime reserves.
|
||||
|
||||
## Pending target checklist — not executed
|
||||
|
||||
- [ ] Compare admin Broker rows with UART0 broker snapshots/counters for zero, one and full supported client mix; verify ID/type/name/role/pending/HWM/drop semantics without consuming serial data. Normal user direct GET/POST requests must be denied.
|
||||
- [ ] Open Settings/Broker, select/cancel/Refresh, switch terminals/views and confirm no lease/socket change; exercise keyboard/touch selection and native confirmation on narrow/wide screens.
|
||||
- [ ] Assign among USB, role-user SSH and both web serial clients while both admin routes remain open. Verify exactly one writer, observers still receive binary output, former writer input is rejected, no in-band controls and already-accepted TX semantics.
|
||||
- [ ] Hold confirmation while target disconnects/reconnects; confirm old target fails without changing the current writer. Repeat with competing USB/SSH/browser writer requests, admin-shell force, local expected-writer release and same-writer release/reacquire. Refresh/reselect/confirm explicitly after conflict.
|
||||
- [ ] Test two independent admin logins and two tabs on one login: pending capacity, isolated/latest replaced results, lost POST/result response, bounded polling/manual recovery and no duplicate transfer. Logout/expiry/role revoke/HTTPS stop-restart while queued must reject stale admission; already-admitted work may finish.
|
||||
- [ ] With full mix at signed-off160MHz/230400 baud, repeat settled non-consuming throughput captures and verify binary transparency/drop isolation. Measure boot/full-mix/operation internal/DMA/PSRAM free/minimum/largest blocks and HTTPD/dispatcher stack minima, including maximum rows and concurrent HTTPS load.
|
||||
- [ ] Validate optional route allocation failures and failed stop/restart where a safe target fault-injection mechanism is available; unavailable settings must not remove UART0 or native USB recovery. Host failure injection is not target proof.
|
||||
- [ ] Record exact revision/build/client mix, observations and limits; independent review is complete, but explicit user 8D.16 sign-off remains required. No erase or identity/configuration migration is required.
|
||||
@@ -188,7 +188,7 @@ Typed operations must preserve subsystem owner/lock/persistence contracts and co
|
||||
| **8D.13 — Wi-Fi secrets and connection controls** | Explicit password replacement/clear semantics, bounded transient input, profile selection/reconnect and AP policy actions using manager-owned operations. | Preserve existing secrets when fields are omitted; never prefill saved secrets; document apply/save and likely connection loss; reconnect via STA/AP and verify UART0/USB recovery. No background secret fetch or general credential export. |
|
||||
| **8D.14 — Display settings** | **Implemented, host/build verified; target pending.** Typed local display configuration and explicit persistence via `local_ui_config`/generation-checked public UI APIs; [contract/evidence](phase8d14_implementation.md). | Host limits/storage/CLI-generation/activity/lifecycle regressions pass; actual save/reboot, absent-display and concurrent buttons/CLI target checklist remains pending. No I2C ownership changes or electrical diagnostics UI. |
|
||||
|
||||
| **8D.16 — Broker client visibility and writer transfer** | Admin-only detailed client snapshot plus explicit confirmed writer assignment using existing broker APIs; smallest broker change only if authoritative generation-safe validation is missing. | Stale/disconnected/reused target fails without changing the current lease; exactly one writer; normal users cannot obtain management details or transfer. Test concurrent USB/SSH/browser requests. No transfer on page open or selection alone. |
|
||||
| **8D.16 — Broker client visibility and writer transfer** | **Implemented, host/build verified; independent parent review and target sign-off pending.** Admin-only detailed snapshot plus explicit confirmed assignment through existing dispatcher/broker; smallest owner changes add atomic lease-version/target validation and nonwrapping IDs. [Contract/evidence](phase8d16_implementation.md). | Host stale/disconnected/reused target and lease ABA rejection, one writer, admin denial, bounded/session-isolated results, lifecycle and UI non-mutation regressions pass. Concurrent physical USB/SSH/browser/full-mix and stack-margin checklist remain pending. No transfer on page open/selection; no8D.17/18 popovers/icons. |
|
||||
| **8D.17 — Serial/Wi-Fi quick popovers** | UI-only reuse of completed typed endpoints, with full-page links and shared validation; start in `web_ui`. | Hover, focus, click/tap parity, Escape/outside-click dismissal, no mutation on opening, explicit apply/save, no secret exposure. No duplicate backend or new settings scope. |
|
||||
| **8D.18 — Client/writer contextual dialogs** | Reuse 8D.16 for live client popover and confirmed Active writer dialog. | Accessible pointer/keyboard/touch paths; refresh preserves explicit selection safely; stale confirmation is rejected visibly; normal users retain only ordinary status. No new writer policy. |
|
||||
| **8D.19 — Ordinary service/session controls** | Typed service status and targeted disconnect/start/stop controls, excluding actions that cut off the invoking HTTPS session; start in existing service APIs and generation-safe snapshots. | Explicit scope/confirmation, stale target rejection, owner-safe execution and failure isolation. Stop/start and disconnect do not clear settings/identities. Split by service if more than one owner adaptation is necessary. |
|
||||
|
||||
@@ -2,6 +2,16 @@
|
||||
|
||||
This document retains phase-specific regression procedures. The Phase 8A and 8B sections describe the behavior of those historical implementation baselines; they are not the current end-to-end acceptance behavior. In current Phase 8C firmware, HTTPS and SSH authenticate through the user database, role-`user` SSH sessions receive the broker-backed serial stream, and role-`admin` SSH sessions receive the administration shell. Use the Phase 8C section for current routing and shared-console validation. Never include generated or entered passwords in test logs.
|
||||
|
||||
## Current Broker management regression procedure — 8D.16
|
||||
|
||||
Implemented and host/build verified; **independent parent review, target validation and user sign-off pending**. The [8D.16 contract and target checklist](phase8d16_implementation.md) defines exact API, generation/wrap safety, resource bounds and evidence limits. This procedure is not an execution claim.
|
||||
|
||||
- Verify admin-only detailed client rows against non-consuming UART0 snapshots/counters; direct normal-user management GET/POST denied. Observe zero/one/full client mix without reading UART payloads as a probe.
|
||||
- Opening, selecting, cancelling, refreshing and navigating must leave writer and both terminals unchanged. Refresh clears selection. Native confirmation must identify exact target and snapshot writer; no8D.17/18 popover behavior is included.
|
||||
- Assign among USB/SSH/two browser serial clients with both admins connected. Disconnect/reuse target while confirmation is open; race writer release/reacquire, competing requests, shell force and local release. Stale confirmation must fail without changing the intervening lease; Refresh/reselect/confirm explicitly.
|
||||
- Test separate-login result isolation, same-login tab replacement, pending capacity, lost ACK/result, bounded polling/manual recovery, logout/expiry/revocation and HTTPS stop/restart. Never infer cancellation from connection loss or replay automatically.
|
||||
- At signed-off160MHz/230400 baud, check full-mix binary traffic/drop isolation, UART0/USB recovery and optional-route failure isolation. Capture exact revision/mix and internal/DMA/PSRAM plus HTTPD/dispatcher margins; host tests/build do not approve reserves or target throughput for this phase.
|
||||
|
||||
## Current Network settings regression procedure — 8D.12/8D.13
|
||||
|
||||
Both phases were authorized and implemented together. The [implementation record](phase8d12_13_implementation.md) defines the complete API, limits, result states, exclusions and pending target checklist. Backend/cookie Network PASS, UI agent97+renderer/CSP/review PASS and lifecycle agent21 PASS are reported evidence; final parent build/tests and target sign-off remain pending. Do not treat this procedure as executed or infer M3 completion/8D.14 authorization.
|
||||
|
||||
Reference in New Issue
Block a user