Files
RustProxy/docs/V0.25.0_AUDIT.md
T
2026-10-07 22:22:54 +02:00

12 KiB

RustProxy 0.25.0 specification audit

This document maps every numbered section of the RustProxy 0.25 plan to the implementation. It distinguishes implemented source from release-host runtime verification. The workspace used for this package has no Rust/Cargo toolchain, so no compiler or live H1/H2/H3 result is claimed here.

Status legend:

  • IMPLEMENTED - the required source/configuration/UI/documentation exists and Rust-independent contracts pass.
  • RELEASE GATE - implementation exists, but compiler/runtime acceptance still has to run on a Rust-enabled host.

Sections 1-22

Spec section Status Implementation / evidence
1. Goal of 0.25 IMPLEMENTED Web Server is integrated as a source in the existing proxy request pipeline rather than as a second HTTP server.
2. Target concept IMPLEMENTED CompiledSource selects Reverse Proxy or Web Server; Reverse Proxy remains the default for old/missing source fields.
3. Separate Web Service IMPLEMENTED Config.web_services contains reusable web_server::Service objects independent of vhosts.
4. Attach service to vhost IMPLEMENTED Vhost/location Source::WebServer stores only web_service_id; filesystem settings remain in the service.
5. Full usage flow IMPLEMENTED Dashboard workflow is Web Server -> create service -> Vhosts -> select Web Server -> select service.
6. Reuse one service IMPLEMENTED One Web Service can be referenced by multiple vhosts/locations; a dedicated configuration test covers two vhosts using the same service.
7. Locations integration IMPLEMENTED Existing location matcher selects static/proxy source; one vhost can mix / static and /api reverse proxy without a second URL router.
8. First-stage configuration IMPLEMENTED Model, validation, normal revisioned storage, section API and CRUD UI are present. No SQLite schema migration is needed because the existing serialized configuration document stores web_services.
9. Static File Server IMPLEMENTED GET/HEAD, expanded built-in + per-service MIME, Content-Length, streamed bodies, directories, ordered static/PHP index files, slash redirect, listing, precompressed sidecars and forced-download policy are implemented.
10. Directory Listing IMPLEMENTED Service-level switch defaults OFF; listing escapes HTML, percent-encodes names/URLs, distinguishes directories and does not reveal filesystem paths. Each request uses a fresh directory description so refreshes do not inherit an exhausted readdir offset; generated listings send Cache-Control: no-store. Disabled listing returns a normal error that remains eligible for the existing custom-error pipeline.
11. Index IMPLEMENTED The ordered index list is optional (0..16). Every requested directory checks configured names in order and serves the first regular file; only that directory's empty/no-match result falls through to listing/error policy.
12. HTTP validators IMPLEMENTED Metadata-derived ETag/Last-Modified and If-None-Match/If-Modified-Since -> 304 are implemented without hashing full files.
13. Range IMPLEMENTED Single byte Range, If-Range, Accept-Ranges, Content-Range, 206 and 416 are implemented for the selected static/precompressed representation; multipart ranges remain intentionally outside the current scope.
14. Filesystem security IMPLEMENTED Routing rejects malformed/ambiguous encoding and dot segments. Default Unix access uses openat + O_NOFOLLOW; Linux can optionally follow a symlink only when each opened descriptor resolves inside the canonical root. PHP-FPM requires the deny policy.
15. Existing RustProxy architecture IMPLEMENTED Host/location routing, ACL, Basic Auth/Tinyauth, response/security headers, custom error pages, compression and H1/H2/H3 transport stay in the existing outer pipeline.
16. Cache IMPLEMENTED No Web Server object cache was added. Static files use filesystem/OS page cache and HTTP validators/ranges. Web Services support a default Cache-Control plus ordered ext:/mime: rules; existing vhost/location response-header rules apply later. Reverse Proxy cache remains unchanged.
17. Tests IMPLEMENTED / RELEASE GATE Rust unit/integration source plus Rust-independent source/UI/docs contracts cover static behavior, configuration, security and integration ordering. Rust tests cannot be executed here without Cargo; live H1/H2/H3 acceptance is still required.
18. Future extensibility IMPLEMENTED try_files, Web Service rewrites, bounded .htaccess migration compatibility and bounded FastCGI/PHP-FPM were added without changing the Web Service / source-selection architecture. Remaining follow-up is limited to named locations, optional PATH_INFO, multipart Range, full Apache compatibility and non-Unix confinement.
19. Documentation cleanup IMPLEMENTED docs/README.md is canonical; functional, admin/operations, development/testing, technical, audits and historical records are separated. Duplicated historical release notes were removed from README, completed roadmap history was moved to docs/ROADMAP_HISTORY.md, and /docs embeds the Markdown set in Reader.
20. CHANGELOG IMPLEMENTED Root CHANGELOG is now operator-facing. Pre-cleanup compiler/refactor/test detail is preserved separately in docs/CHANGELOG_TECHNICAL_ARCHIVE.md.
21. README / Docs / Reader IMPLEMENTED README now describes the current 0.25 release instead of duplicating release history; ROADMAP contains active/future work with completed milestones archived. The docs index, Reader/API split, local Markdown links and current version references are checked automatically. Migration history includes 0.24.10 -> 0.25.0.
22. Definition of Done IMPLEMENTED / RELEASE GATE All source/documentation items below are implemented; compiler/runtime and live transport acceptance remain the only unexecuted release gate in this workspace.

Definition of Done - item by item

  • Dedicated Web Server administration section exists.
  • Web Service can be created.
  • Document root is configurable.
  • Ordered index-file list is configurable.
  • Directory listing can be enabled/disabled and defaults to disabled.
  • Web Service can be edited and deleted; referenced deletion is rejected by validation and blocked in the UI.
  • Existing vhost/source configuration offers Reverse Proxy / Web Server.
  • Selecting Web Server offers an existing Web Service reference.
  • Vhost does not store document root/index/listing copies.
  • One Web Service can be reused by more than one vhost.
  • Web Server uses the existing locations system.
  • One vhost can mix Web Server and Reverse Proxy locations.
  • GET implemented.
  • HEAD implemented.
  • MIME implemented.
  • Web Service MIME overrides and fallback MIME implemented.
  • Optional static Cache-Control default and ordered extension/MIME cache rules implemented without a second object cache; vhost/location header rules can override them.
  • Fixed Web Service response headers implemented with framing/transport protections.
  • try_files and ordered internal/redirect rewrite rules implemented inside the selected Web Service.
  • Bounded .htaccess compatibility implemented for common rewrite/front-controller, index/listing, MIME, header, Expires and PHP AddHandler migration rules; security-sensitive unsupported handlers/access scopes fail closed.
  • Web Service application presets added as one-shot normal-configuration generators (Static, SPA, PHP generic, WordPress, Drupal, Laravel, Symfony, Joomla, PrestaShop, Downloads) with optional explicit hardening for common exploit probes/sensitive paths and fingerprint-header removal.
  • Precompressed .br/.gz sidecars and configured forced-download extensions implemented.
  • FastCGI/PHP-FPM implemented with bounded concurrency/timeouts, Unix socket or loopback TCP endpoints, advanced request/header/stderr limits, Authorization forwarding control, validated custom FastCGI/PHP_VALUE parameters and no PHP source fallback.
  • Content-Length implemented.
  • File streaming implemented without loading the whole file into RAM.
  • Index lookup implemented.
  • Directory listing implemented.
  • Repeated directory-listing refreshes use fresh directory offsets; nested directories independently prefer index files before listing.
  • Directory slash redirect implemented with query preservation.
  • ETag implemented from metadata.
  • Last-Modified implemented.
  • 304 implemented.
  • Single Range implemented.
  • 206 implemented.
  • 416 implemented.
  • Document-root confinement implemented.
  • Symlink handling cannot escape the root; deny is the default and Linux can optionally follow only targets verified inside the canonical root. PHP-FPM requires deny.
  • Web Server uses the existing RustProxy request/response pipeline.
  • No second URL router was added.
  • No second error-page subsystem was added.
  • No second object-cache subsystem was added.
  • [~] Existing vhost features remain on the shared code path and source contracts verify ordering; full compiler/runtime regression execution is a release-host gate.
  • Appropriate Rust tests and Rust-independent contract checks are present.
  • Configuration is stored/read through the existing revisioned configuration store; old configs default to Reverse Proxy.
  • Documentation has been reorganized.
  • Docs and Reader are wired to the same embedded Markdown set and API is separated into its own tab.
  • CHANGELOG has been cleaned of developer-only churn; detailed old material is archived as technical history.
  • README and ROADMAP describe the actual 0.25 state, historical release/roadmap material is separated into CHANGELOG/audits/archives, and the remaining release-host gate is explicit.

Reported Axum E0277 correction

The reported .fallback(forward) error was caused by passing &Request<Body> into the asynchronous Web Server function. That shared borrow survived across .await; because the body is not Sync, the forward() future no longer satisfied Axum 0.8's Send handler requirement.

Static dispatch now clones only the request metadata needed by the local filesystem source (Method, HeaderMap, Uri) and moves those owned values into web_server::serve. The Web Server no longer holds a shared Request<Body> reference across an await. The Rust-independent contract explicitly rejects the former call shape.

Reported Reader build-artifact correction

The Reader initially embedded a generated OUT_DIR/docs-content.json. A clean/incremental build could therefore reach include_bytes! without that artifact being present. Reader documents are now direct include_str! compiler inputs from the project and docs/ tree; the JSON response is serialized once from those embedded strings. The Reader no longer depends on a generated documentation file in target/, and docs_check.py verifies that every top-level Markdown document is embedded.

Verification performed in this workspace

  • python3 tools/checks/check_source.py - PASS.
  • python3 tools/checks/release_smoke.py - PASS.
  • python3 tools/checks/memory_contracts.py - PASS.
  • python3 tools/checks/web_server_contracts.py - PASS.
  • python3 tools/checks/docs_check.py - PASS.
  • python3 tools/checks/langs_check.py - PASS.
  • node --check for app, Settings, Docs Reader, Web Server and vhost administration JavaScript - PASS.
  • OpenAPI and both language JSON files parse - PASS.
  • bash -n dev.sh - PASS.
  • go test ./... in docker-agent - PASS.
  • ./dev.sh test - all Rust-independent phases PASS, then exits because cargo is not installed in this workspace.

Remaining release-host gate

Before a production release, run on a host with the stable Rust toolchain:

./dev.sh fmt
./dev.sh check
./dev.sh test

Then run live static-file acceptance over HTTP/1.1, HTTP/2 and HTTP/3, including ACL/auth/custom-error/header behavior and a large streamed file. This is verification work, not a missing source feature.