123 lines
12 KiB
Markdown
123 lines
12 KiB
Markdown
# 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
|
|
|
|
- [x] Dedicated **Web Server** administration section exists.
|
|
- [x] Web Service can be created.
|
|
- [x] Document root is configurable.
|
|
- [x] Ordered index-file list is configurable.
|
|
- [x] Directory listing can be enabled/disabled and defaults to disabled.
|
|
- [x] Web Service can be edited and deleted; referenced deletion is rejected by validation and blocked in the UI.
|
|
- [x] Existing vhost/source configuration offers `Reverse Proxy` / `Web Server`.
|
|
- [x] Selecting Web Server offers an existing Web Service reference.
|
|
- [x] Vhost does not store document root/index/listing copies.
|
|
- [x] One Web Service can be reused by more than one vhost.
|
|
- [x] Web Server uses the existing locations system.
|
|
- [x] One vhost can mix Web Server and Reverse Proxy locations.
|
|
- [x] GET implemented.
|
|
- [x] HEAD implemented.
|
|
- [x] MIME implemented.
|
|
- [x] Web Service MIME overrides and fallback MIME implemented.
|
|
- [x] Optional static `Cache-Control` default and ordered extension/MIME cache rules implemented without a second object cache; vhost/location header rules can override them.
|
|
- [x] Fixed Web Service response headers implemented with framing/transport protections.
|
|
- [x] `try_files` and ordered internal/redirect rewrite rules implemented inside the selected Web Service.
|
|
- [x] 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.
|
|
- [x] 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.
|
|
- [x] Precompressed `.br`/`.gz` sidecars and configured forced-download extensions implemented.
|
|
- [x] 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.
|
|
- [x] Content-Length implemented.
|
|
- [x] File streaming implemented without loading the whole file into RAM.
|
|
- [x] Index lookup implemented.
|
|
- [x] Directory listing implemented.
|
|
- [x] Repeated directory-listing refreshes use fresh directory offsets; nested directories independently prefer index files before listing.
|
|
- [x] Directory slash redirect implemented with query preservation.
|
|
- [x] ETag implemented from metadata.
|
|
- [x] Last-Modified implemented.
|
|
- [x] 304 implemented.
|
|
- [x] Single Range implemented.
|
|
- [x] 206 implemented.
|
|
- [x] 416 implemented.
|
|
- [x] Document-root confinement implemented.
|
|
- [x] 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.
|
|
- [x] Web Server uses the existing RustProxy request/response pipeline.
|
|
- [x] No second URL router was added.
|
|
- [x] No second error-page subsystem was added.
|
|
- [x] 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.
|
|
- [x] Appropriate Rust tests and Rust-independent contract checks are present.
|
|
- [x] Configuration is stored/read through the existing revisioned configuration store; old configs default to Reverse Proxy.
|
|
- [x] Documentation has been reorganized.
|
|
- [x] Docs and Reader are wired to the same embedded Markdown set and API is separated into its own tab.
|
|
- [x] CHANGELOG has been cleaned of developer-only churn; detailed old material is archived as technical history.
|
|
- [x] 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:
|
|
|
|
```bash
|
|
./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.
|