ctf-ad-mirror-tool-rust/docs/ui-polish-verification.md

5.4 KiB
Raw Permalink Blame History

UI follow-up — 2026-10-23

Scope: targeted improvements on the legacy layout and light functional testing. No redesign, no load test, no legacy credentials or game-host traffic. No backend HTTP contracts or forwarding modules changed.

Layout and readability

Before After
Bootstrap reset placed native dialog at x=0,y=0. web/app.css: explicit auto margin/inset; centered, bounded, scrollable dialogs. Reproduced before and measured after in browser.
Header controls squeezed selected-team IP and replica count onto extra lines. Header uses a full-width second row; name/IP ellipsis and stable replica suffix with full tooltip.
Bright native number spinners and shifting digit widths. Dark color scheme, spinner removal, numeric input mode/step and tabular counters.
Adding toolbar actions could crowd the mobile title. Compact action spacing and small-screen title size, preserving original columns.

Input and operator workflow

Before After
Reopening add-proxy cleared its draft. Draft retained until successful creation or page reload.
Rejected custom IP could disappear on next snapshot. Local dirty draft survives blur and snapshots; inline IPv4/IPv6 validation, Enter saves/retries, Escape restores saved value.
Changing direct IP discarded all replicas. Preserve replicas; backend removes only overlap with the new primary.
Whitespace-only names passed required validation. Trim/validate names before requests; settings reset stale custom-validity messages.
Team PUT was only reachable through API. Compact Teams dialog adds/renames teams; existing address is read-only and hidden state preserved.
Renamed team retained the old primary-control label. Accessible name and tooltip update with team name.
No in-panel configuration/scoreboard guidance. Compact help dialog with live existing scoreboard state, TOML/ForcAD example and route semantics.
Non-JSON API failure detail was discarded. Show bounded plain-text errors when returned by the server.
Demo wrapper deleted config/state after each exit. Optional persistent --data-dir, existing config never overwritten; --port-offset isolates new test fixtures. Echo cleanup tolerates reset peers.

Fresh verification

  • Native cargo fmt --check, cargo clippy --all-targets --locked -- -D warnings, cargo test --all-targets --locked: pass, 40 tests. Repeated after final frontend edits; node --check web/app.js and git diff --check pass.
  • Orb Ubuntu amd64: 41 tests including Linux loopback alias behavior; release build passes. Linux tests preceded the last frontend-only label/layout/validation changes; final Linux release embeds those final assets. No Linux-specific code changed.
  • macOS arm64 release built after final assets. Both local dist/ artifacts have refreshed and verified SHA256SUMS. Initial checksum command used wrong cwd; rerun from dist verified both files.
  • Browser Use on isolated fixture 127.0.0.1:16800: login, add IPv6 proxy, port range rejection, draft cancel/reopen, invalid IP via real keyboard, inline error retention through refresh, Escape restoration, valid IPv4 save, team create and rename, read-only existing address, port/policy editing, start, primary promotion retaining former primary as replica, robot toggle and logout.
  • Created test proxy deletion confirmed through native Chrome after Browser Use could not prepare popup headers for window.confirm; persisted state and a fresh browser tab confirmed the proxy was gone. This was a browser-control issue.
  • SIGSTOP only on isolated fixture: five-second watchdog disables mutations and shows stale warning; SIGCONT restores live state/buttons. Live demo unaffected.
  • Persistence: isolated fixture restart preserved created service/team and rename.
  • Actual 390×844 CSS viewport measured (accounting for existing browser 80% zoom): add-dialog rectangle x≈19,y≈203.55,w≈351.99,h≈436.64; no page horizontal overflow. Long help dialog bounded at y=20,h≈803.75 with scrolling. Override cleared.
  • Byte-exact 256 KiB echo with TCP half-close; replica bytes also 262144, no connect/I/O/replica errors or replica disconnections. This is a functional check, not a speed benchmark.
  • Console samples contained unrelated extension content.js errors; no application JavaScript exception observed. Does not establish absence of every possible bug.

Live demo and artifacts

GUI-session launchd job local.codex.mirror-tool-demo runs current macOS release. Plist is ignored test-results/mirror-ui-demo.plist, outside LaunchAgents; not an installed login service. Existing temporary config/state were copied before stopping old fixture; live authenticated snapshot confirmed identical teams/service settings. Current config data/demo/mirror.toml, state data/demo/state.json, both ignored. Panel http://127.0.0.1:16700, Echo listener 18081, echo upstreams 18082 (IPv4/IPv6). User's primary B / replica A / enabled state preserved. A fresh 21504-byte echo passed on updated demo, plus readiness, embedded assets and actual GUI verification.

Ignored screenshot evidence: test-results/ui-polish-final.png, test-results/ui-polish-mobile.png. Isolated test fixture stopped. The user's Zen window was not reloaded; updated demo is open in a separate Chrome tab. Instructions are in docs/configuration.md and linked from README. Real ForcAD tournament access, load/soak tests and network-failure losslessness are not claimed.