4.8 KiB
RustProxy implementation rules
Read README.md, ROADMAP.md and docs/TEST_REPORT.md before making changes.
The project name is RustProxy; the Cargo package/binary remains rust-proxy for
compatibility. Current source version: 0.29.4.
Delivery
Maintain English documentation and Markdown files. Keep translations in discovered langs/*.json packs, with en_US as fallback. Never hardcode a two-language switch. Preserve the existing logo. CHANGELOG.md uses version headings with no release dates. Patch increments may be bundled; substantial optional integrations raise the minor version. 0.7.0 adds managed renewal, server deployment helpers, Basic Auth and visual locations. The reported compression threshold type mismatch is removed without narrowing. Cloudflare Tunnel and Docker discovery are deferred.
Deliver a complete archive with dev.sh, tests and an updated verification report. Do not include databases, credentials, real certificates/keys, target directories, node_modules or fabricated Cargo.lock content. Preserve an actually resolved lockfile when a compiler-enabled environment can produce it.
Engineering
Keep proxy traffic independent from control-plane database queries and providers.
Use async I/O, streaming bodies, bounded DNS work, bounded queues and explicit
cancellation. Hold request and connection permits through full body/tunnel lifetimes.
Run ACLs before opening OR reusing an upstream connection. Resolve only configured
backend origins; validate every DNS answer and use the validated addresses directly.
Backend TLS certificate verification defaults OFF when tls_verify is omitted for vhost
backends. Administrators may explicitly enable chain/identity verification per HTTPS backend.
This compatibility default is limited to application backends: never widen it to Tinyauth or
other verifier clients. Disabling verification must not weaken backend address/DNS/loop/control-
plane protections.
Preserve the explicit auth module path and upgrade regression coverage. Replace managed source directories instead of leaving obsolete modules during upgrades. Keep administrator intent, provider observations and live connection state separate. Hot changes must publish validated, immutable snapshots after a successful revisioned SQLite write. Invalid updates leave the old snapshot active.
Verification
Run ./dev.sh check and ./dev.sh test when Rust is available. Run the SQL and upgrade
scripts even when it is not. UI tests use a simulated API; the Python protocol-peer
self-test is not a test of RustProxy. Record these distinctions accurately.
Do not mark a stage accepted or production-ready on the basis of static inspection.
Review real protocol behavior, restored data and resource bounds before expanding
scope. Do not expand provider work ahead of the core real-runtime acceptance gate. Keep that gate explicitly open until Rust runs.
Vhost invariants
Use the accepted socket's actual local address and TLS state for frontend selection;
never infer a private binding or sticky identity from forwarding headers. Vhosts receive
frontend sockets only through frontend.listener_ids referencing listeners.endpoints.
Keep hostname ownership unambiguous. Socket/ALPN changes require restart, with actual
and desired plans visible.
Keep health observations separate from desired configuration. Preserve observations only for compatible members; re-enabled/changed origins require new health checks. Keep backend leases through request/response/tunnel completion. Do not replay failed writes to another backend. Cookies are routing affinity, never authentication. Health probes must use the same origin/DNS policy, bounded concurrency and cancellation. Retain HTTP/1.1 in TLS HTTP/2 negotiation; do not implement fallback by replaying traffic.
Vhost configuration invariants
The pre-production route/inline-listener compatibility importer has been removed. Persist only the current vhost document and named listener references; old documents must fail validation instead of being silently converted. Keep path-pinned origins distinct from balanced pools. Do not silently widen listener bindings. ACME secrets belong in private credentials files, not SQLite, stdout, argv or API. HTTP-01 only serves bounded tokens for domains in the active job. No CA call on boot. The exporter checks actual peer CIDRs and is disabled by default; secret configuration stores a variable name, never a token. Keep metric labels bounded by configuration.
Administration access regression gate (0.8.1)
No new public admin routes without updating the exact method/path allowlist and access tests. Operational assets and the OpenAPI schema are private. Keep the public login document/bundle separate from the dashboard. Documentation uses the existing cookie session/CSRF, not a second auth mechanism. Preserve the pinned Swagger build configuration and keep external validators/CDNs disabled.