# Verification report - RustProxy 0.24.9 ## Scope RustProxy 0.24.9 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. - 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 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. - 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.