ctf-ad-mirror-tool-rust/docs/ui-report.md

3.5 KiB
Raw Blame History

Operator UI implementation

The UI preserves the service-column workflow and compact per-team primary/replica controls. Russian labels match the previous operator surface. The visual direction is a navy instrument panel, warm route markers, lavender utility accents and restrained status colors; no animation, external fonts, CDN or frontend build is needed.

Contracts and behavior

  • / loads only /app.css and deferred /app.js; no inline handlers, inline styles or scripts. All dynamic names, addresses, events and errors are assigned as text nodes.
  • Bootstrap checks /api/session, then reads /api/snapshot and opens one /api/events EventSource. Login uses the documented password body. Authenticated mutations include the returned CSRF token.
  • Service start/stop, primary/replica selection, automatic selection and replica policy use PUT with the complete latest ServiceConfig. Successful mutations refresh the snapshot; failures expose the backend message and reconcile controls with the last confirmed snapshot.
  • Service dialog supports all configuration fields, optional primary while stopped and add/edit. Existing service ID is immutable in the editor; duplicate add IDs are rejected locally. Team add also permits a rename with the same ID/address; changing an existing address is rejected. Service deletion is disabled while enabled/running and requires an explicit confirmation with name, listener and route details.
  • Service and team DOM nodes are keyed and updated in place. SSE never rebuilds open modal fields or focused route controls. Write controls are locked during mutations, while snapshots continue to update telemetry.
  • Bandwidth uses byte-counter deltas divided by snapshot timestamp deltas, separately for upstream and downstream. Counter decreases and backwards timestamps reset the baseline; duplicate timestamps retain the previous rate. Absolute primary and replica bytes remain visible.
  • SSE interruption immediately marks the panel stale; lack of snapshots for eight seconds does the same. Session checks after disruption use a bounded 2–30 second backoff and stop while the stream is healthy. EventSource handles stream reconnects; 401 returns to login and closes the stream. Page lifecycle closes/reopens the stream without duplicating it.
  • TCP health is unknown until checked, with old checks marked stale after 15 seconds. TCP reachability is separate from checker health. ForcAD stale/disconnected state is explicit globally and on checker badges; stolen/lost counters are shown alongside status.
  • Native dialogs provide focus containment and Escape dismissal (disabled during save), controls have visible focus, table headers/captions and descriptive labels, notices use status/alert roles, layout fits mobile widths, and reduced-motion preferences are respected.

Verification and remaining integration work

node --check web/app.js passes. Source inspection confirms one EventSource creation site, no interval polling, no innerHTML, no inline event/style attributes and no external asset URLs. The UI implementation did not modify backend, Cargo files or legacy templates and did not contact game hosts.

Real browser checks against the integrated backend, CSP response headers, authentication failures, modal focus under live updates, mutation errors, mobile layout, and stream/session recovery are delegated to the integrating parent task. Rust format/clippy/test gates and Orb checks belong to that integration; this report does not claim they have passed.