v0.32.0
This commit is contained in:
1 parent
d23fa5e154
commit
81ab39e70a
51 files changed
+5352
-1489
No files matched your search
+10
@@ -615,3 +615,13 @@ The runtime system diagnostics object includes `platform`, supplied by the share
|
||||
## Per-vhost User-Agent rate limiting (0.31.7)
|
||||
|
||||
The revisioned `/api/config` vhost rate-limit object accepts optional `user_agent_limits`, up to 64 entries with `pattern` (1..256 bytes, case-insensitive substring or `*` wildcard), `requests` (1..1000000), `window_seconds` (1..3600) and `burst` (0..1000000). The first matching rule replaces the standard and country rate for that request and uses a separate fixed-window counter for each (vhost, rule index, client IP). Requests with no matching User-Agent use the existing limiter. A User-Agent is trivially spoofable; these overrides are operational shaping, not access control. Global and vhost User-Agent blocklists continue to deny matching requests before rate limiting.
|
||||
|
||||
## Stream pools and dashboard widgets (0.32.0)
|
||||
|
||||
`GET /api/config` and `PUT /api/config/streams` preserve the existing revisioned JSON and session/CSRF gate. A Stream host may include `backends[]` (ID, address, weight, enabled, drain, max_sessions, health, metrics_enabled), `balance` and nullable `metrics_enabled`. With no `backends`, `upstream` retains its legacy single-backend behavior. Backend edits remain desired state until controlled restart. See [STREAMS.md](STREAMS.md).
|
||||
|
||||
`GET /api/status` retains `streams.active`, `streams.desired`, `streams.restart_required` and `streams.metrics`. Each active Stream metric view includes `backends[]` for health/active information and optional detailed counters. `/api/status?view=live` and the existing authenticated SSE snapshots carry the same backend observations inside `streams.metrics` without a separate polling source. Backend status is `unverified`, `checking`, `healthy`, `unhealthy` or `disabled`.
|
||||
|
||||
`GET`/`PUT /api/preferences` continue to own `dashboard_widgets` and `dashboard_hidden_widgets` (now 16 supported IDs, adding `stream_overview`, `stream_traffic`, `stream_sessions`, `stream_backend_health`). Legacy accounts have their missing Stream widget IDs appended **hidden**. Preferences affect only Dashboard presentation, not proxy configuration or metrics export. No new endpoint or permission was introduced.
|
||||
|
||||
Detailed backend metrics default to off in v0.32.0; per-Stream `metrics_enabled` sets the inherited value for its backends, and explicit per-backend `metrics_enabled` overrides it. Basic per-Stream counters remain available regardless of these flags.
|
||||
@@ -182,3 +182,9 @@ filters so multi-agent installations can be inspected independently from ordinar
|
||||
vhosts/backends.
|
||||
|
||||
Reference: https://prometheus.io/docs/instrumenting/exposition_formats/
|
||||
|
||||
## Stream pool metrics (0.32.0)
|
||||
|
||||
The existing global `include_streams` controls all Stream Prometheus families. Each configured Stream may set nullable `metrics_enabled` (default true); each backend may set its own nullable `metrics_enabled` (inherit from Stream). Detailed backend counters are emitted only when both flags are enabled. Basic per-Stream counters, backend active/drain and numeric health-state gauges remain observable with global Stream export enabled; routing and health monitoring never depend on these flags. Backend series use only configured `stream`, `backend` and `protocol` labels, never client IP or arbitrary UDP payload. `rust_proxy_stream_backend_health_state` encodes unverified=0, checking=1, healthy=2, unhealthy=3, disabled=4. Optional detailed families include bytes/packets, assignments, errors/rejects, sessions and health successes/failures. All counters reset on process startup.
|
||||
|
||||
For v0.32.0 Stream pools, backend-level `metrics_enabled` overrides the Stream default; missing/null values inherit it. Detailed backend accounting defaults off, including for legacy `upstream` configurations. Global `include_streams` independently gates all Stream Prometheus export.
|
||||
+5
-1
@@ -4,7 +4,7 @@
|
||||
|
||||
**Settings -> Appearance** contains dashboard-only preferences. They are stored per administrator in the existing `admin_preferences` SQLite document and do not create a proxy configuration revision. The preferences are theme (`dark`/`light`), language (`auto` or a language-pack id), global interface scale (70-125%), timestamp format (`24h`/`12h`), chart style (`default`, `soft`, `technical`, `high_contrast`, `neon`, `monochrome`, `warm` or `cool`), button style (`normal` or `compact`), table/log density (`normal`, `compact`, `ultra`), dashboard density (`normal`, `compact`, `ultra`), Overview card order and Overview card visibility. `auto` language follows the browser language when a matching pack exists and otherwise falls back to the configured default pack.
|
||||
|
||||
The scale applies to the complete authenticated administration surface, including navigation, workspace content, dialogs, overlays and the draft dock. Text fields, selects, textareas, checkboxes and radios also receive a small proportional control-size adjustment on top of global zoom so field proportions track the selected scale more visibly. Button style is independent: **Normal** keeps the refreshed control sizing and **Compact** restores the smaller source-style sizing, including generated entity actions and tab buttons inside dialogs. Table/log and dashboard density are additional layout controls and do not change the whole-interface scale. The dashboard editor can hide/show and reorder the telemetry cards at the top of Overview; this changes presentation only, not metric collection. The selected time format is shared by logs, backend/runtime diagnostics, audit/session timestamps, certificate views and configuration-history timestamps. Chart presets change colors, surfaces, grid and line presentation only; they do not change sampled data, and the palette selector exposes the main colors for each preset. Each Appearance subsection has its own reset action, and **Reset appearance** restores all documented Appearance defaults without touching unrelated account preferences. A small local cache is retained only to avoid a theme/scale flash before authentication, while the authenticated SQLite preference remains authoritative.
|
||||
The scale applies to the complete authenticated administration surface, including navigation, workspace content, dialogs, overlays and the draft dock. Text fields, selects, textareas, checkboxes and radios also receive a small proportional control-size adjustment on top of global zoom so field proportions track the selected scale more visibly. Button style is independent: **Normal** keeps the refreshed control sizing and **Compact** restores the smaller source-style sizing, including generated entity actions and tab buttons inside dialogs. Table/log and dashboard density are additional layout controls and do not change the whole-interface scale. The dashboard editor can hide/show and reorder the telemetry cards at the top of Overview; this changes presentation only, not metric collection. Stream card explanations appear on hover and keyboard focus instead of expanding the card list. Stream cards default hidden but, once switched on, remain present even when no Stream is active (neutral no-data state). The selected time format is shared by logs, backend/runtime diagnostics, audit/session timestamps, certificate views and configuration-history timestamps. Chart presets change colors, surfaces, grid and line presentation only; they do not change sampled data, and the palette selector exposes the main colors for each preset. Each Appearance subsection has its own reset action, and **Reset appearance** restores all documented Appearance defaults without touching unrelated account preferences. A small local cache is retained only to avoid a theme/scale flash before authentication, while the authenticated SQLite preference remains authoritative.
|
||||
|
||||
Unfinished Web Server, Vhost, Redirect and Stream editors remain session-only drafts. Their bottom-right dock uses square corners, can collapse to a single title bar, shows the age of each suspended draft and does not persist draft form values to SQLite.
|
||||
|
||||
@@ -536,3 +536,7 @@ The Prometheus card controls enabled, bind IP/port, URL path, client CIDRs,
|
||||
bearer-token environment variable name and optional collectors, including the bounded
|
||||
Traffic analytics collector. Only the variable name is exported; supply the actual secret to the service separately. See
|
||||
PROMETHEUS.md for immediate revocation, restart rules and scrape configuration.
|
||||
|
||||
## Stream Dashboard cards (0.32.0)
|
||||
|
||||
Under **Settings → Appearance → Dashboard layout**, the existing Show/Hide and Up/Down card controls now include Stream overview, traffic, sessions and backend health. They are opt-in and account-scoped, saved through the existing `/api/preferences` flow. Legacy 12-card orders migrate in memory with all four Stream cards hidden. They use the existing status/SSE stream and stop computing their charts while hidden; no backend monitoring or listener settings are changed when toggled. An explicitly enabled Stream card stays on Overview and shows a neutral no-data state when no Stream is active. Overview details and chart legends stay visible inside the cards (without hover tooltips); the appearance editor continues to show its own descriptions on hover or keyboard focus.
|
||||
+108
-42
@@ -1,61 +1,127 @@
|
||||
# TCP/UDP streams
|
||||
# TCP/UDP Stream pools (v0.32.0)
|
||||
|
||||
RustProxy 0.13.0 exposes raw Layer-4 forwarding on the main **Streams** page, alongside **Vhosts** and **Redirects**. A stream combines one dedicated TCP or UDP listener with one upstream. Stream traffic does **not** enter the HTTP pipeline: no HTTP vhost routing, ACL, cache, headers, compression, Tinyauth or TLS termination is applied.
|
||||
Layer-4 forwarding runs on dedicated TCP/UDP listeners and never traverses HTTP Vhosts, ACL, cache, headers, compression, TLS termination or authentication. The existing **Streams** page provides a card/modal editor and per-Stream RX/TX chart. Changes to Stream listeners and backend pool configuration remain **desired state** until the next controlled RustProxy restart; saving Appearance preferences does not restart the proxy.
|
||||
|
||||
## Dashboard workflow
|
||||
## Compatible configuration
|
||||
|
||||
Use **Streams > New stream** or **Add TCP/UDP listener**. The modal mirrors the Vhost workflow and contains Details, Listener & upstream, and Limits tabs. Existing streams are shown as searchable cards with live runtime counters and RX/TX rate charts.
|
||||
The legacy document still works without modification:
|
||||
|
||||
A saved listener change is desired state only until RustProxy restarts. The page keeps the active startup listener visible and marks changed/new/removed stream configuration as pending restart.
|
||||
```json
|
||||
{"streams":[{"id":"ssh","name":"SSH relay","enabled":true,"protocol":"tcp","listen":"0.0.0.0:2222","upstream":"10.0.0.20:22","connect_timeout_seconds":5,"idle_timeout_seconds":300,"max_connections":512}]}
|
||||
```
|
||||
|
||||
The HTTP/HTTPS listener editor remains under **Settings > Listeners**. Its bind addresses use the same chip-style interaction as vhost hostnames. Those named HTTP/HTTPS listeners are separate from stream listeners.
|
||||
Without `backends`, `upstream` is treated as one enabled backend with ID `primary`, weight 1, no active health probe and detailed metrics disabled by default (opt in explicitly). The legacy field is retained in serialized configuration and is set to the first backend address when a pool is explicitly configured. Existing listeners continue to require restart on change.
|
||||
|
||||
## Configuration document
|
||||
A TCP pool can be configured as follows (the same backend fields apply to UDP):
|
||||
|
||||
```json
|
||||
{
|
||||
"streams": [
|
||||
{
|
||||
"id": "ssh",
|
||||
"name": "SSH relay",
|
||||
"enabled": true,
|
||||
"protocol": "tcp",
|
||||
"listen": "0.0.0.0:2222",
|
||||
"upstream": "10.0.0.20:22",
|
||||
"connect_timeout_seconds": 5,
|
||||
"idle_timeout_seconds": 300,
|
||||
"max_connections": 512
|
||||
},
|
||||
{
|
||||
"id": "dns-udp",
|
||||
"name": "DNS UDP",
|
||||
"enabled": true,
|
||||
"protocol": "udp",
|
||||
"listen": "0.0.0.0:5353",
|
||||
"upstream": "10.0.0.53:53",
|
||||
"connect_timeout_seconds": 5,
|
||||
"idle_timeout_seconds": 30,
|
||||
"max_connections": 2048
|
||||
}
|
||||
"id":"ssh", "name":"SSH pool", "enabled":true, "protocol":"tcp",
|
||||
"listen":"0.0.0.0:2222", "upstream":"10.0.0.20:22",
|
||||
"balance":"round_robin", "metrics_enabled":true,
|
||||
"connect_timeout_seconds":5, "idle_timeout_seconds":300, "max_connections":512,
|
||||
"backends":[
|
||||
{"id":"node-a","name":"Server A","address":"10.0.0.20:22","enabled":true,"drain":false,"weight":2,"max_sessions":256,"metrics_enabled":true,"health":{"mode":"tcp_connect","interval_seconds":10,"timeout_ms":1000,"rise":2,"fall":2}},
|
||||
{"id":"node-b","name":"Server B","address":"10.0.0.21:22","enabled":true,"drain":false,"weight":1,"max_sessions":256,"metrics_enabled":false,"health":{"mode":"tcp_connect","interval_seconds":10,"timeout_ms":1000,"rise":2,"fall":2}}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
TCP uses a bidirectional byte relay with a connect timeout, inactivity timeout and connection limit. UDP creates a bounded per-client session mapped to one connected upstream socket, expires it after inactivity and limits concurrent sessions.
|
||||
`balance` is `round_robin` (default), `least_connections` (TCP), or `least_sessions` (UDP). The least-load variants use an active-assignment-to-weight ratio. Each new TCP connection selects one backend for its entire connection; a UDP client session selects once and remains pinned for its lifetime (idle timeout). `drain: true`, `enabled: false`, `Unhealthy` state, or a reached `max_sessions` prevents new assignments. In-flight TCP relays and UDP sessions retain their selected backend; a controlled process restart still follows the existing shutdown grace period and may end in-flight sessions.
|
||||
|
||||
## Runtime telemetry
|
||||
## Health monitoring
|
||||
|
||||
The administration status snapshot exposes fixed-cardinality metrics for active startup streams. The Streams page displays:
|
||||
Each backend has independent `enabled`, `health` and `metrics_enabled` controls. Disabled and draining backends can continue independent health monitoring if probes are explicitly configured; it does not get new sessions. Probe concurrency is globally limited to 16, at most one health task per enabled/configured backend, with lifecycle tied to the listener cancellation token. Timeouts, probe intervals and rise/fall thresholds are bounded by validation. TCP checks use a timed TCP connect without application payload.
|
||||
|
||||
- active TCP connections or UDP client sessions;
|
||||
- accepted connections/sessions and completed sessions;
|
||||
- capacity rejects and relay/upstream errors;
|
||||
- bytes received from clients and returned from upstreams;
|
||||
- UDP packet counters;
|
||||
- live RX/TX rates derived from monotonic backend byte counters.
|
||||
UDP checks cannot use a local UDP `connect()` as evidence that the remote service exists. For a validated active UDP probe define both `payload_hex` and an exact, nonempty `expect_hex` response (up to 128 bytes each), e.g.:
|
||||
|
||||
The chart history exists only in the current browser panel session. Backend counters are process-lifetime counters and reset on process restart.
|
||||
```json
|
||||
{"mode":"udp_probe","interval_seconds":10,"timeout_ms":1000,"rise":2,"fall":2,"payload_hex":"50494e47","expect_hex":"504f4e47"}
|
||||
```
|
||||
|
||||
## Listener safety
|
||||
**Do not enable UDP probing without the service owner's approval.** Unknown application protocols must leave checks `off`; `udp_probe` without an expected reply is `Unverified`, sends no datagrams and does not report Healthy. A backend without active checks is `Unverified` (routing still allowed), while probed backends show `Checking`, `Healthy`, `Unhealthy` or `Disabled`; hysteresis prevents state flapping. An Unhealthy backend stops receiving new sessions, but no ongoing TCP connection is reassigned. If the pool has no eligible backend, new sessions or datagrams are rejected and the legacy per-Stream `rejected` counter advances.
|
||||
|
||||
RustProxy validates collisions before publishing configuration. TCP stream listeners may not overlap HTTP/TLS, administration or Prometheus TCP listeners. UDP stream listeners may not overlap HTTP/3 UDP listeners. TCP and UDP may intentionally use the same numeric port because they are different transports. Direct loops into another RustProxy listener of the same transport are rejected.
|
||||
## Telemetry and Dashboard
|
||||
|
||||
The existing `/api/status` response and `/api/status?view=live` SSE/fallback add a bounded `backends` array under `streams.metrics[stream_id]`. It includes stable configured IDs, status, active sessions, health counts/last errors and (if enabled) optional completed/created/assignment, bytes, packets and error/reject metrics. `bytes_in` remains client → upstream, `bytes_out` upstream → client. A UDP datagram rejected before a session is established remains counted in the original per-Stream incoming counters, not backend delivered-byte counters.
|
||||
|
||||
In the editor, **Stream → Detailed metrics → Default (disabled)** means the absence of a Stream override resolves to `false` (it does **not** inherit from Prometheus). At the backend level, **Use Stream setting** resolves to that Stream's value; backend **Enabled**/**Disabled** override it. Prometheus retains `include_streams` as the separate global export gate. `metrics_enabled` defaults to `false` for detailed per-backend accounting (no new overhead on legacy streams). Stream-level `true` enables the default for its backends; backend-level `true`/`false` explicitly overrides the Stream value, while `null` inherits. This choice never changes session routing or health checks. Basic per-Stream counters and backend active gauges stay available. Backend label cardinality is bounded to IDs declared in config, never client IPs. History is a limited browser-memory window only; metrics are not persisted as periodic SQLite samples.
|
||||
|
||||
Under **Settings → Appearance → Dashboard layout**, toggle/reorder Stream overview, traffic, sessions and backend-health cards alongside existing telemetry cards. All Stream cards default hidden for existing accounts, including migrated 0.31.x layouts. An explicitly enabled card stays visible even when no Stream is configured, enabled or running; it displays a neutral **No stream data** state in that case rather than ignoring the Appearance setting. They use the existing API status/SSE/fallback and one dashboard refresh scheduler. Hiding a card avoids its chart computations, and changing visibility does not alter Stream runtime, existing widgets or global Prometheus settings. Widget descriptions in Appearance appear on hover/keyboard focus rather than permanently beneath settings labels. On the main Overview page, secondary values and RX/TX chart legend are always inline under the metric/graph (not tooltips), with the original six-column desktop layout and taller tiles for readability.
|
||||
|
||||
## Safety and operational limits
|
||||
|
||||
At most 128 Stream hosts and 32 backends per host, weights 1–16, 1–65535 stream/session concurrency and optional per-backend session caps. Validated concrete backend IPs and nonzero ports are required. Duplicate backend IDs, local listener loops, conflicting transport health modes and invalid probes are rejected before configuration is published. UDP client queues are bounded at 64 datagrams. The existing listener restart indicator remains authoritative, and no new public administration routes or polling tasks are added.
|
||||
|
||||
## Standalone TCP and UDP forwarding tests
|
||||
|
||||
The ready-to-use launcher and individual TCP/UDP test clients are all in `scripts/`.
|
||||
Start four loopback-only mock backends (TCP 9101/9102; UDP 9201/9202):
|
||||
|
||||
```bash
|
||||
./scripts/start_stream_backends.sh
|
||||
# Optional, only on an isolated test network: ./scripts/start_stream_backends.sh 0.0.0.0
|
||||
```
|
||||
|
||||
Point your corresponding Stream backend pools at these ports, restart RustProxy
|
||||
(the Stream configuration's existing restart requirement), then run:
|
||||
|
||||
```bash
|
||||
python3 scripts/test_stream_tcp.py client --port 2222 --sessions 32 --messages 5 --min-backends 2
|
||||
python3 scripts/test_stream_udp.py client --port 5353 --sessions 32 --messages 5 --min-backends 2
|
||||
```
|
||||
|
||||
Stop the launcher with `Ctrl+C`. Its four children are stopped together. If you
|
||||
prefer launching backend peers separately or need different ports, use the examples below.
|
||||
|
||||
These are **black-box clients for a real running RustProxy** plus small, intentionally
|
||||
loopback-only mock services. Do not aim them at live/production backends. Use
|
||||
separate terminals for each mock, and configure the Stream editor with these
|
||||
backend addresses. **Restart RustProxy after modifying Stream backends** (the
|
||||
existing Stream lifecycle still applies).
|
||||
|
||||
TCP example (Stream listener `127.0.0.1:2222`, backend pool `127.0.0.1:9121` and
|
||||
`127.0.0.1:9122`):
|
||||
|
||||
```bash
|
||||
# Terminal 1
|
||||
python3 scripts/test_stream_tcp.py server --port 9121 --backend-id node-a
|
||||
# Terminal 2
|
||||
python3 scripts/test_stream_tcp.py server --port 9122 --backend-id node-b
|
||||
# Terminal 3 - after enabling the TCP Stream listener in RustProxy
|
||||
python3 scripts/test_stream_tcp.py client --port 2222 --sessions 32 --messages 5 --min-backends 2
|
||||
```
|
||||
|
||||
UDP example (Stream listener `127.0.0.1:5353`, pool `127.0.0.1:9131` and
|
||||
`127.0.0.1:9132`):
|
||||
|
||||
```bash
|
||||
# Terminal 1
|
||||
python3 scripts/test_stream_udp.py server --port 9131 --backend-id node-a
|
||||
# Terminal 2
|
||||
python3 scripts/test_stream_udp.py server --port 9132 --backend-id node-b
|
||||
# Terminal 3 - after enabling the UDP Stream listener in RustProxy
|
||||
python3 scripts/test_stream_udp.py client --port 5353 --sessions 32 --messages 5 --min-backends 2
|
||||
```
|
||||
|
||||
Each client verifies exact round-trip payloads and logs per-backend session
|
||||
assignments. TCP verifies the selected backend stays unchanged through several
|
||||
messages on one connection; UDP verifies the same over datagrams from one
|
||||
client socket. Use `--min-backends 1` for a single backend, drain, or failover
|
||||
case. Compare the reported assignments with Stream metrics and Prometheus.
|
||||
`--parallel`, `--sessions`, `--messages`, and `--timeout` control test load.
|
||||
UDP mock services also respond to the **explicit** health probe `PING`/`PONG`
|
||||
(`payload_hex: 50494e47`, `expect_hex: 504f4e47`); do not apply this payload
|
||||
arbitrarily to real application servers.
|
||||
|
||||
To check the scripts themselves *without RustProxy*, run:
|
||||
|
||||
```bash
|
||||
python3 scripts/test_stream_tcp.py selftest
|
||||
python3 scripts/test_stream_udp.py selftest
|
||||
```
|
||||
|
||||
Selftests only exercise the Python mock peer/harness; they do not verify the
|
||||
RustProxy forwarding path, balance algorithms or real health check lifecycle.
|
||||
Run the `client` cases against your compiled proxy and manually repeat after
|
||||
disabling, draining, or stopping one mock backend to verify failover behavior.
|
||||
+48
-1
@@ -1,4 +1,51 @@
|
||||
# Verification report - RustProxy 0.31.9
|
||||
# Verification report - RustProxy 0.32.0
|
||||
|
||||
## 0.32.0 — Overview original six-column layout (2026-10-12)
|
||||
|
||||
- **Fix:** remove the Hotfix 3 four-column desktop override; restore the existing six-column Overview grid above 1200px, retaining the original 3-column/2-column responsive breakpoints and dashboard density settings. Use taller desktop cards so secondary labels and colored graph legends remain visible inline, without hover/focus behavior. No changes to Dashboard preferences, widgets, API, refresh scheduler or Vhosts behavior.
|
||||
- **PASS — regression & Chromium static fixture (not a live RustProxy panel):** `stream_0320_visibility_regression.mjs` rejects the four-column override and asserts the six-column desktop rule. Chromium computed six columns at 1280px (126px-tall compact cards), three at 1024px and two at 390px, with all 16 original+Stream cards present in fixture, captions and RX/TX legend visible, and no horizontal page overflow. This is not an authenticated application or a Rust runtime test.
|
||||
|
||||
## 0.32.0 — Overview inline legends and Vhosts edit-hint fix (2026-10-12)
|
||||
|
||||
- **Overview:** remove the hover/focus tooltip CSS previously affecting every Overview `small` caption on pointer devices; restore their permanent placement below numbers and graphs on desktop and touch. Remove `tabindex=0` from non-interactive stat articles (inner buttons remain keyboard-accessible). Keep the 0.32.0 Stream opt-in/empty-state behavior and unchanged status/SSE cadence.
|
||||
- **Layout:** Overview uses four wider columns above 1200px and the original responsive grid below that breakpoint; allow chart legends to wrap. Stream RX and TX share the already collected traffic rates and existing graph and now render as a two-color inline legend (no API/timer added). **Settings -> Appearance** description popovers remain unchanged.
|
||||
- **Vhosts:** the add/edit enabled checkbox still uses the shared enabled-state control, but its redundant `vhEnableHint` helper node is removed locally, as already done for Streams. This does not change how `enabled` is saved or processed.
|
||||
- **PASS — full Rust-independent `./dev.sh test`:** production-module/source contracts, SQLite/schema/upgrade checks, security and documentation checks, locale parity, and all bundled Node UI regressions. Includes modified Stream visibility and in-card RX/TX legend tests and the Vhost hint source test. The command ultimately stops at **127** because Cargo/Rust is not installed; no Rust tests ran.
|
||||
- **PASS — Chromium static-layout fixture (not a live authenticated panel):** desktop 1280px Overview has four columns (Stream traffic card 268px wide), labels remain visible and in place after hover, and colored RX/TX legend fits within the card. At 390px the layout has two columns with wrapped chart legends; both viewports have no horizontal overflow. Appearance help is hidden at rest and still appears on hover. Screenshots were checked manually.
|
||||
- **OPEN:** Cargo format/check/tests, a rebuilt running RustProxy panel, and authenticated browser/live TCP/UDP regressions on the operator host. No change was made to Rust Stream routing, system widgets, preference persistence or refresh scheduler in this patch.
|
||||
|
||||
## 0.32.0 — Stream Dashboard/Appearance hotfix 2 (2026-10-12)
|
||||
|
||||
- **Root cause addressed:** `stream-dashboard.js` unconditionally hid opted-in Stream cards whenever no enabled/running listener appeared in the current config/status. Visibility now follows existing Appearance preferences exclusively. When there is no running/configured Stream, explicitly selected cards show the translated neutral no-data state without extra polling or history samples. Disabled cards remain entirely hidden; legacy cards and layout controls are unchanged. Regression cases include saved opt-in, toggling, disabled/no-data and restart-pending Streams.
|
||||
- **Appearance UX:** descriptions of the four Stream widget controls are popovers on pointer hover or keyboard focus (`role=tooltip`, `aria-describedby`), rather than permanent second lines. The shared Overview metric tips remain unchanged. In the Stream editor, the redundant generic active-control hint is removed locally; `metrics_enabled=null` is labeled **Default (disabled)** on a Stream and **Use Stream setting** on a backend, consistent with existing runtime inheritance. The `include_streams` Prometheus export switch remains independent.
|
||||
- **Tools:** moved the separate Python TCP and UDP test clients from `scripts/tests/` to `scripts/`, added `scripts/start_stream_backends.sh` alongside them, and updated command examples and README. The launcher starts/stops both TCP peers (ports 9101, 9102) and both UDP peers (9201, 9202) in one group; no service is exposed beyond loopback unless explicitly requested.
|
||||
- **PASS — full Rust-independent `./dev.sh test` run:** Python/SQL/schema/security/docs/i18n checks and all bundled Node UI/regression tests passed, including both new Stream visibility cases; terminated **127** because Cargo is missing. Source line-count contract (including JS <=500 lines) passed after moving a local Stream UI change out of core.js.
|
||||
- **PASS — Chromium static Appearance fixture, not authenticated RustProxy:** 1280px and 390px viewports; Stream description tooltip hidden at rest, shown on hover or focus, 34px row height and no horizontal overflow.
|
||||
- **PASS — actual four-peer launcher test (mock-only):** direct Python client connections to TCP 9101/9102 and UDP 9201/9202 exchanged 4 messages per port over two sessions. Python TCP/UDP standalone selftests also passed. Neither path went through the RustProxy binary; it is not a real proxy routing/failover acceptance test.
|
||||
- **PASS:** `node --check` for modified browser modules, script syntax, locale/doc checks, `GOPROXY=off GOSUMDB=off go test ./...` for the Docker agent.
|
||||
- **Still pending on a Rust-equipped host:** Cargo build/check/test, actual admin session/browser UI, and TCP/UDP routing + health/failover/load tests through running RustProxy. This source hotfix is not runtime-production validated here.
|
||||
|
||||
## 0.32.0 — Dashboard follow-up and separate TCP/UDP test tools (2026-10-12)
|
||||
|
||||
- **Reported on a Rust-enabled host:** `src/stream/pool.rs` emitted one deprecated `AtomicU64::fetch_update` warning. The source now calls `AtomicU64::try_update` with the same memory orderings and session-capacity closure. The modified Rust source was **not compiled here**.
|
||||
- **Fixed in source:** Appearance layout now supplies the newly selected `dashboard_hidden_widgets` to Stream visibility immediately, instead of consulting stale `adminPreferences` during an initial load or a persisted switch. Cached Stream totals repaint on enabling or returning to Overview without an extra API request, timer or synthetic traffic sample. Disabled/nonexistent Streams remain absent.
|
||||
- **UX:** secondary Overview values (the `small` text below metrics) float above cards only on pointer hover/keyboard focus; card names and primary values remain visible. For touch-only devices, details retain their original inline presentation. Keyboard focus outlines are preserved.
|
||||
- **PASS — actual Chromium static layout check:** desktop 1280px hover and keyboard focus changed tooltip opacity from 0 to 1, mobile touch 390px retained inline detail opacity 1 and no horizontal overflow. This is **not** an authenticated RustProxy browser test.
|
||||
- **PASS — full Rust-independent `./dev.sh test` suite:** all Python/SQLite/security/docs/locale and Node UI regressions, including `stream_0320_visibility_regression.mjs`, completed. The tool terminated **127** at the expected missing-Cargo check. New navigation code was additionally checked against the existing Docker VHosts simulated regression. No Rust tests ran.
|
||||
- **PASS — standalone harness-only selftests:** `scripts/test_stream_tcp.py selftest` (8 local mock TCP sessions/24 messages) and `scripts/test_stream_udp.py selftest` (8 local mock UDP client sockets/24 datagrams). Both verify echo and same-session affinity against the Python mock **directly**, not through RustProxy.
|
||||
- **PASS:** `GOPROXY=off GOSUMDB=off go test ./...` for the bundled Docker Agent; `bash -n dev.sh`, `python3 -m py_compile` for the new Python scripts, Node source syntax, docs and i18n checks.
|
||||
- **PENDING on operator's Rust toolchain and live proxy:** `cargo fmt --check`, `cargo check --all-targets`, `cargo test`, compilation without warnings, and running both `client` scripts through actual configured TCP/UDP Stream listeners with mock upstreams, followed by drain/health/failover verification. No claim of production-ready runtime is made here.
|
||||
|
||||
## 0.32.0 — Stream pools and Appearance/Dashboard integration
|
||||
|
||||
- **Implemented, source inspection:** legacy single-upstream compatibility, bounded TCP/UDP backend pool with RAII assignments, weighted Round Robin and least-load selection, health modes and probe hysteresis, optional per-backend counters and Prometheus labels.
|
||||
- **Implemented, source inspection:** four hidden-by-default Stream Dashboard widgets and Appearance controls in the existing per-user preference mechanism, using the existing status stream/polling (no new timer or HTTP route).
|
||||
- **PASS — offline source/UI regressions:** `./dev.sh test` completed all Python checks, all browser-side Node.js tests (including `tools/checks/stream_0320_ui_test.mjs`), security and documentation checks, and language-pack checks. It then stopped at the Cargo prerequisite with exit code **127** because the Rust toolchain is absent; this is **not** a passed Rust test run.
|
||||
- **PASS — syntax/docs:** `node --check` on all 31 first-party browser JavaScript modules; `python3 tools/checks/docs_check.py`; `python3 tools/checks/langs_check.py`; JSON parsing for the OpenAPI specification.
|
||||
- **PASS — independent Go agent:** `GOPROXY=off GOSUMDB=off go test ./...` from `docker-agent/`.
|
||||
- **NEW, NOT EXECUTED (Rust):** legacy configuration parse/validation, duplicate IDs/self-loops, weighted RR/least sessions, cap/drain/lease accounting, TCP rise/fall, UDP Unverified, real TCP/UDP probe replies, real socket forwarding and UDP session pinning. These tests were added to `src/stream/tests.rs` but require the Rust 1.99+ toolchain.
|
||||
- **OPEN:** `cargo fmt --check`, `cargo check --locked --all-targets`, `cargo test --locked`, staging TCP/UDP health/recovery/load tests and authenticated Dashboard browser acceptance. No production-readiness claim is made without these checks.
|
||||
|
||||
|
||||
## 0.31.9 — Certificate API credential management (runtime acceptance open)
|
||||
|
||||
|
||||
Reference in new issue
Block a user