Files
RustProxy/docs/TEST_REPORT.md
T
2026-10-03 18:53:51 +02:00

59 lines
7.8 KiB
Markdown

# Verification report - RustProxy 0.24.10
## Scope
RustProxy 0.24.10 implements the Secret Store + password-encrypted full backup/restore and optional ERROR-only file logging specifications. Secret Store adds schema version 7, encrypts ACME DNS-provider credentials with a local master key, migrates legacy provider `.ini` files, and recreates plaintext credential files only around the external Certbot operation. Full backup/restore uses Argon2id plus authenticated AES-256-GCM encryption, an explicit manifest, Secret Store key wrapping, staged validation and atomic data-directory activation. Error-file logging is a separate, disabled-by-default asynchronous bounded sink with JSON/RAW formats, central secret redaction and external `logrotate` rotation.
The release also retains the 0.24.8 overview cache diagnostics, 0.24.7 transform resource controls and 0.24.6 cache/background-worker memory hardening described by the earlier audit material below.
## Source contracts reviewed
- SQLite schema version 7 includes the generic encrypted `secret_store` table; stored secret values are AES-256-GCM ciphertext with per-record nonces and the application master key lives outside SQLite in a private file.
- Cloudflare, OVH and RFC2136 ACME credentials are validated, imported into Secret Store, decrypted only when required, and legacy provider `.ini` files are removed after successful migration. Certbot credential files are temporary and removed in `finally` paths.
- `rust-proxy backup create` writes a new `.rpb` file outside the data directory, derives an independent backup key with Argon2id, encrypts authenticated chunks with AES-256-GCM, excludes cache/log/runtime data and wraps the Secret Store master key inside the encrypted backup.
- `rust-proxy backup restore` requires an interactive password, decrypts into private staging, validates manifest/checksums/schema/configuration/Secret Store decryptability before activation, then switches the data directory by rename with rollback on activation failure.
- `error_log` is independent from normal access logging, defaults disabled, accepts only `ERROR`, supports JSON/RAW, uses a bounded queue and a single asynchronous writer, handles filesystem failures without terminating RustProxy, and relies on system `logrotate` rather than application rollover.
- Error File stays in the existing revisioned `logging` section: its separate dashboard form and the access-log form both save a composite `{ logging, error_log }` value through `/api/config/logging`. A database-reopen regression verifies that `enabled`, path and format survive restart, the standalone `/api/config/error_log` route is intentionally absent, and historical access-only `/api/config/logging` payloads remain accepted for compatibility. The redundant Error Log help sentence is absent from the panel.
- The stderr/journald path, access-log sinks and the optional error-file sink share secret-redaction helpers for authorization/provider/password/private-key material.
- The KV secret-redaction expression uses a hash-delimited Rust raw string, avoiding the `E0762` unterminated-character-literal parser failure while preserving the same redaction character class.
- The release checker preserves the existing dashboard contract while using bundled roots plus common system CA bundles (`SSL_CERT_FILE`, `CURL_CA_BUNDLE`, FreeBSD/OPNsense and Linux paths), follows at most five credential-free HTTP(S) redirects without HTTPS-to-HTTP downgrade, and reports network/TLS/HTTP/parser failures at `ERROR` level so the optional error-file sink receives them.
- The overview Cache RAM block keeps separate histories for HOT allocated bytes, transient RAM, fill bytes, COLD queue bytes, COLD I/O bytes and COLD disk bytes; the disk series is never included in process RAM accounting.
- HOT and transient histories are rendered against their runtime limits, while COLD storage is rendered against the configured COLD byte budget.
- The long `memoryAccountingHint` remains translated and available on demand through the Process information control instead of consuming permanent dashboard height. Response time history is no longer collapsible and has the same compact information control explaining that it charts successive samples of the cumulative mean duration of completed HTTP exchanges.
- Transform `preset`, `memory_budget_bytes` and `max_inflight` are part of the normal revisioned Settings document and therefore persist in SQLite; the reopen test covers them.
- Existing configurations default to 128 MiB transform temporary memory and 32 concurrent attempts.
- New transform attempts use atomic runtime byte/concurrency reservations and fail open with fixed `memory_pressure` / `concurrency_pressure` reasons rather than queueing full-body work.
- Presets modify only resource limits; transform type switches and extension allow-lists remain independent.
- Global transform representation/eligibility settings participate in cache compatibility identity. Resource-only preset/budget/concurrency fields do not.
- OpenAPI and both language packs expose the new controls and preset states.
- `GET /api/status` exposes `transform_resources` and `memory_accounting`; the latter keeps process RSS separate from HOT/transient cache accounting and treats transform bytes as an overlapping conservative reservation.
- Cache runtime telemetry exposes COLD byte/object limits so the overview can show disk occupancy against configured capacity without mixing disk and RAM.
- `GET /api/transform` exposes current process-wide reserved transform bytes and active slots alongside the existing counters.
- 0.24.6 aggregate/decode bounds, allocation reductions and bounded cache/background workers remain in place.
- The bounded transform-body collection path maps its boxed body error explicitly into `anyhow::Error`; source/release regressions reject the incompatible `.context(...)` form that was reported by an external compiler run.
- A subsequent external Rust compile reached warning-only status and reported four lint warnings. The source now keeps the COLD transient read lease explicitly alive via `_read_lease`, names the RAII-only `TransientLease` field `_inner`, and removes the two dead CSS `last_char` assignments without lint suppression. Offline source/release regressions pin those shapes; a compiler-enabled rerun is still required to confirm a warning-clean build.
## Verification status in this workspace
| Check | Status |
|---|---|
| `python3 scripts/preflight.py` | PASS |
| `python3 scripts/langs_check.py` | PASS |
| `python3 scripts/memory_contracts.py` | PASS |
| Browser JavaScript `node --check` | PASS for all administration JS bundles |
| OpenAPI/language JSON parse | PASS |
| Shell `bash -n` | PASS |
| Python syntax / bytecode compile, including ACME provider worker | PASS |
| Secret Store / encrypted backup / error-log / portable update-check source-contract regression checks | PASS |
| SQLite schema 7 migration smoke (`secret_store`) | PASS |
| Docker agent `go test ./...` / `go vet ./...` / `go build ./...` | PASS |
| `python3 scripts/check_source.py` | PASS |
| `python3 scripts/release_smoke.py` | PASS |
| FreeBSD/OPNsense live release-check execution | NOT RUN in this workspace; source contract and platform CA paths are covered, target runtime confirmation is still required |
| `./dev.sh fmt` / `cargo fmt --all` | BLOCKED: Rust/Cargo toolchain unavailable in this workspace |
| `./dev.sh check` / `cargo check --locked --all-targets` | BLOCKED: Rust/Cargo toolchain unavailable in this workspace |
| `./dev.sh test` Rust phase | BLOCKED: Rust/Cargo toolchain unavailable in this workspace |
| Sustained per-preset transform RSS/heap profiling | release-host acceptance gate |
See [V0.24.8_AUDIT.md](V0.24.8_AUDIT.md) for the dashboard change and [V0.24.7_AUDIT.md](V0.24.7_AUDIT.md) for the retained transform resource-control design and runtime acceptance gate.