# RustProxy 0.26.7 implementation note ## Scope 0.26.7 is a compatibility-preserving cache observability, backend lifecycle and container documentation patch on top of 0.26.6. SQLite remains schema 8 and the saved proxy configuration document is unchanged. ## HOT/COLD cache occupancy The authenticated `/cache` page now renders explicit occupancy meters for both cache tiers. HOT and COLD object cards compare the current entry count with `max_entries` / `cold_max_entries`; HOT memory compares charged HOT bytes with `max_bytes`; COLD disk compares persisted bytes with `cold_max_bytes`. The cards also show the configured limit and percentage so the progress bars remain interpretable without estimating from the visual fill alone. The HOT byte meter intentionally uses allocated/charged HOT bytes, not only logical body length. This matches the budget enforced by cache admission. COLD uses persisted storage bytes. ## Backend rotation continuity Age-based recycling continues to run from the backend maintenance loop and request-count recycling remains request-driven. The isolated client rotation logic already advanced generation and rotation counters correctly. The release fixes a separate observability/lifecycle problem: rebuilding an otherwise compatible active routing snapshot created a new upstream client object, which restarted generation age, request count and rotation totals at zero. Pool rebuilds now retain the previous compiled backend when both ordinary and WebSocket upstream clients have exactly the same client factory: backend definition, address policy, keepalive settings, protocol mode and connect timeout. Health observations retain their existing compatibility rules independently. A real backend-policy change still creates a fresh client. This avoids retaining stale DNS/listener safety policy, TLS identity, keepalive or timeout behavior while keeping long-running rotation diagnostics continuous through unrelated snapshot publications. ## Container certificate tooling and documentation The OCI runtime image now creates a dedicated `/opt/rustproxy-certbot` Python environment and pins Certbot plus the supported Cloudflare, OVH and RFC2136 DNS plugins to the same release. The image therefore supports every certificate provider exposed by RustProxy without an extra image-extension step. Container documentation was refreshed to remove the obsolete statement that DNS plugins are absent and to use the current release tag in examples. Current cache, vhost/backend and installation documentation was reviewed alongside the release notes so the dashboard limits, rotation semantics and container prerequisites describe the implemented behavior. ## Compatibility - SQLite schema: 8, unchanged. - Saved configuration format: unchanged. - No migration is required from 0.26.6. - Backend rotation counters intentionally restart when the backend client policy itself changes. ## Cache Age and downstream compression follow-up The cache freshness clock remains RFC-oriented: ordinary stored HITs advance `Age` from `initial_age + resident elapsed time`, while a successful validator revalidation starts a new freshness calculation. `X-Cache-Resident-Age` remains the monotonic residency clock across revalidation and tier movement. Existing 0.26.6 custom `Age` rules remain accepted for configuration compatibility. Response-side Age rules are isolated to the final wire stage, so set/append/remove cannot feed back into stored freshness, TTL calculation or validator revalidation. Regression coverage explicitly checks that both the wire HIT header and `/cache` object age advance from the stored clock before any optional presentation override. Compression still refuses Authorization, private/no-store/no-transform, Set-Cookie, ranges, SSE, upgrades and already encoded responses. Cookie-bearing requests now have one bounded exception: a response can be compressed when it is already a shared-cache HIT accepted by cache policy or a local static Web Server response. This aligns the static-cookie cache exception with downstream compression without enabling compression for arbitrary dynamic cookie responses. The bundled compression tester no longer sends `Cache-Control: no-cache` by default because that header forces validator revalidation and can make cache `Age` appear to stay at zero; `--revalidate` retains the old diagnostic behavior explicitly.