This commit is contained in:
Mateusz Gruszczyński committed 2026-10-06 15:12:59 +02:00
1 parent 464ff42cfd
commit f07429c267
53 files changed
+1049 -283

No files matched your search

+1 -1
View File
@@ -1,4 +1,4 @@
# Administration API access - 0.26.5
# Administration API access - 0.26.6
## Sign-in boundary
+7
View File
@@ -7,6 +7,13 @@
# Changelog
## 0.26.6
### Compiler follow-up
- Removed the redundant `country_resolved = true` assignment after route-level GeoIP resolution in `proxy::forward_entry`. The flag is only needed to prevent a second lookup before that branch; the removed write was never read and produced `unused_assignments` during a real Rust build. ACL/GeoIP behavior is unchanged.
- A fresh compiler-enabled lint/test run remains required on the Rust release host because this packaging workspace has no Rust toolchain.
## 0.26.0
### Compiler follow-up
+1 -1
View File
@@ -1,6 +1,6 @@
# Stored log explorer
RustProxy 0.26.5 provides an authenticated, read-only **Logs** workspace at `/logs`. The top bar has one **Logs** menu with separate **Stored logs** and **Live Logs** actions; the two data paths remain independent.
RustProxy 0.26.6 provides an authenticated, read-only **Logs** workspace at `/logs`. The top bar has one **Logs** menu with separate **Stored logs** and **Live Logs** actions; the two data paths remain independent.
## Separation from Live Logs
+1 -1
View File
@@ -1,4 +1,4 @@
# Installing and updating RustProxy 0.26.5
# Installing and updating RustProxy 0.26.6
The scripts prepare a Linux/systemd installation. This source archive is **not a
verified production build**: Rust/Cargo, real CA operations, live systemd startup
+7 -2
View File
@@ -8,6 +8,11 @@ Let's Encrypt/private-key material. It logs in to the RustProxy administration A
reads the current revision, merges generated vhosts into the existing configuration,
and writes only when `--apply` is supplied.
`migrate_npm.py` is the CLI entry point and requires the sibling modules
`scripts/migrate_npm_core.py` and `scripts/migrate_npm_api.py`. They use only the
Python standard library, so no `pip` packages are required. If the migrator is copied
or mounted outside the RustProxy source tree, keep all three files in the same directory.
## What is migrated
For each NPM `proxy_host` row:
@@ -104,9 +109,9 @@ RustProxy directory:
docker run --rm -it \
--network host \
-v /path/to/npm/data:/npm:ro \
-v "$PWD/scripts/migrate_npm.py:/migrate_npm.py:ro" \
-v "$PWD/scripts:/rustproxy-scripts:ro" \
python:3.13-alpine \
python /migrate_npm.py \
python /rustproxy-scripts/migrate_npm.py \
--database /npm/database.sqlite \
--rustproxy https://127.0.0.1:9090 \
--insecure-admin-tls
+2 -1
View File
@@ -15,6 +15,7 @@ This is the canonical index for the current project documentation. The authentic
- [0.25.1 release audit](V0.25.1_AUDIT.md) - historical Traffic/module-split release scope and compiler-regression guards.
- [0.25.0 specification audit](V0.25.0_AUDIT.md) - Web Server foundation point-by-point implementation status.
- [0.25.0 pre-production security audit](V0.25.0_SECURITY_PREPROD_AUDIT.md) - threat-oriented source/configuration review, fixes made in-session and mandatory runtime security gates.
- [0.26.6 implementation note](V0.26.6_IMPLEMENTATION.md) - composed ACL allow semantics, certificate-form reset, backend table preferences and NPM migration helper documentation.
- [0.26.5 implementation note](V0.26.5_IMPLEMENTATION.md) - interface-scaled form/select alignment and corrected Streams listener navigation.
- [0.26.4 implementation note](V0.26.4_IMPLEMENTATION.md) - 404 drafts, consistent modal controls, compact Overview settings and idle age-based backend rotation.
- [0.26.3 implementation note](V0.26.3_IMPLEMENTATION.md) - global interface scaling, chart themes, square draft dock and Settings navigation polish.
@@ -65,7 +66,7 @@ This is the canonical index for the current project documentation. The authentic
## Historical or version-labelled context
Version-labelled `V*.md` files are retained as historical implementation/audit records. Their version number describes the audited milestone. The current release implementation note is [V0.26.5_IMPLEMENTATION.md](V0.26.5_IMPLEMENTATION.md); [V0.26.4_IMPLEMENTATION.md](V0.26.4_IMPLEMENTATION.md) is retained as the prior administration/backend-lifecycle milestone, [V0.26.3_IMPLEMENTATION.md](V0.26.3_IMPLEMENTATION.md) as the prior appearance/UI milestone, [V0.26.2_IMPLEMENTATION.md](V0.26.2_IMPLEMENTATION.md) as the prior Logs/UI milestone and [V0.26.1_IMPLEMENTATION.md](V0.26.1_IMPLEMENTATION.md) as the prior protocol-attribution milestone. The latest retained audit is [V0.25.5_AUDIT.md](V0.25.5_AUDIT.md); older audit files remain historical evidence.
Version-labelled `V*.md` files are retained as historical implementation/audit records. Their version number describes the audited milestone. The current release implementation note is [V0.26.6_IMPLEMENTATION.md](V0.26.6_IMPLEMENTATION.md); [V0.26.5_IMPLEMENTATION.md](V0.26.5_IMPLEMENTATION.md) is retained as the prior interface-scaling/listener-navigation milestone, [V0.26.4_IMPLEMENTATION.md](V0.26.4_IMPLEMENTATION.md) as the prior administration/backend-lifecycle milestone, [V0.26.3_IMPLEMENTATION.md](V0.26.3_IMPLEMENTATION.md) as the prior appearance/UI milestone, [V0.26.2_IMPLEMENTATION.md](V0.26.2_IMPLEMENTATION.md) as the prior Logs/UI milestone and [V0.26.1_IMPLEMENTATION.md](V0.26.1_IMPLEMENTATION.md) as the prior protocol-attribution milestone. The latest retained audit is [V0.25.5_AUDIT.md](V0.25.5_AUDIT.md); older audit files remain historical evidence.
Older context documents such as [INTEGRATIONS_040](INTEGRATIONS_040.md), [MANAGEMENT](MANAGEMENT.md), [SECURITY_AUDIT](SECURITY_AUDIT.md), [ACME_RFC2136](ACME_RFC2136.md) and older version audits remain available for traceability but should not override the current functional/technical documents above.
+9 -7
View File
@@ -1,16 +1,18 @@
# Verification report - RustProxy 0.26.5
# Verification report - RustProxy 0.26.6
## Scope
RustProxy 0.26.5 is a compatibility-preserving administration UI patch on top of 0.26.4. SQLite remains schema 8 and the saved proxy configuration format is unchanged.
RustProxy 0.26.6 is a compatibility-preserving access-policy and administration workflow patch on top of 0.26.5. SQLite remains schema 8 and the saved proxy configuration format is unchanged.
The release makes compact toolbar selects and inputs share one scaled control box, wires ordinary form controls to the existing interface-scale field variables, and changes the Streams **Add TCP/UDP listener** shortcut to navigate to Settings -> Listeners instead of opening a new Stream editor. The 0.26.4 draft, modal consistency and idle backend-rotation fixes remain unchanged.
The release keeps backend diagnostics column/sort state synchronized with account-scoped administrator preferences, clears the certificate-creation form only after an ACME issue job reaches `ready`, documents all Python modules required by the NPM migrator, and composes explicit IP/country exceptions inside one ACL policy scope while retaining deny precedence and cumulative profile/vhost/location policies. The ACL profile UI now exposes guided block-by-default and allow-by-default modes with a live OR-policy preview, plus custom mode for mixed rules. Plain host IPs are accepted in addition to CIDRs.
## Source-level regression coverage
Rust-independent contracts require the shared toolbar control-height variable, scaled field variables in the common form-control rules, and the Streams listener shortcut handler to call the Settings/Listeners navigation path. Existing 0.26.4 draft, Enabled-control, backend-maintenance, source, security, memory, Web Server, documentation, packaging, upgrade and SQLite migration contracts remain enabled.
Rust-independent contracts require the shared preference application path to reapply backend table state, the ACME UI to defer form reset until the matching issue job succeeds, the NPM migration documentation to ship and mount all three helper modules, frontend/location routing to use the composed IP/country ACL evaluator, and the ACL profile editor to retain its guided modes, preview and IP normalization path. Rust unit coverage in `src/acl/tests.rs` exercises allow-country OR allow-IP, block-country OR deny-IP, explicit deny precedence and plain IPv4/IPv6 host rules, but those Rust tests require a compiler-enabled release host.
Browser JavaScript syntax checks cover the changed administration modules. The simulated Web Server UI test remains part of the release gates. Language packs and OpenAPI JSON are parsed, and the Docker Agent Go tests are run when available.
Existing source, security, memory, Web Server, documentation, packaging, upgrade, SQLite migration and administration JavaScript contracts remain enabled.
A compiler follow-up also removes a redundant route-level `country_resolved = true` write reported as `unused_assignments`; the write occurred after the flag's final read and therefore does not change GeoIP or ACL behavior.
## Verification status in this workspace
@@ -30,11 +32,11 @@ Browser JavaScript syntax checks cover the changed administration modules. The s
| `node --check` for changed administration JavaScript | PASS |
| language/OpenAPI JSON parse | PASS |
| `go test ./...` in `docker-agent` | PASS |
| `./dev.sh test` | Rust-independent gates PASS; exits 127 when the Rust stage is reached because Cargo is unavailable |
| `./dev.sh test` | Rust-independent gates through security contracts PASS; the wrapper hit the workspace command-time limit before its final non-Rust steps, which were then run individually and PASS. Cargo remains unavailable for the Rust stage. |
| `./dev.sh check` | BLOCKED: Rust/Cargo toolchain unavailable in this workspace |
| `cargo fmt --check` | BLOCKED: Rust/Cargo toolchain unavailable in this workspace |
| `cargo clippy --all-targets --all-features -- -D warnings` | BLOCKED: Rust/Cargo toolchain unavailable in this workspace |
| `cargo test --all-targets --all-features` | BLOCKED: Rust/Cargo toolchain unavailable in this workspace |
| complete release build | BLOCKED at Rust compilation: Rust/Cargo toolchain unavailable in this workspace |
The 0.26.5 source archive must not be described as compiler-verified until the Rust-enabled release-host gates pass. Rust-independent checks do not substitute for Rust parsing, type checking, Clippy or runtime tests.
The 0.26.6 source archive must not be described as compiler-verified until the Rust-enabled release-host gates pass. Rust-independent checks do not substitute for Rust parsing, type checking, Clippy or runtime tests.
+40
View File
@@ -0,0 +1,40 @@
# RustProxy 0.26.6 implementation note
## Scope
0.26.6 is a compatibility-preserving access-policy and administration workflow patch on top of 0.26.5. SQLite remains schema 8 and the saved proxy configuration document is unchanged.
## Backend table preferences
The backend diagnostics table continues to store visible columns, sort key and descending/ascending direction in the account-scoped administrator preferences. The shared preference application path now reapplies those values to the backend table whenever preferences are loaded or updated, instead of relying only on initial page activation.
## Certificate creation workflow
After `/api/acme/issue` accepts an issuance request, the UI remembers that job ID. The form is reset only when polling reports that same issue job as `ready`; a failed job cancels the pending reset so non-secret fields remain available for correction. Transient provider secrets continue to be cleared after submission for security. The submitted job remains visible in the ACME status UI.
## NPM migration helper
`scripts/migrate_npm.py` imports sibling modules `scripts/migrate_npm_core.py` and `scripts/migrate_npm_api.py`. They use the Python standard library and require no third-party package installation, but all three files must stay together. The documented container command now mounts the complete `scripts` directory.
## ACL policy composition
IP ACLs and country access are evaluated together inside each policy scope. Explicit IP denies and blocked countries take precedence. In **Allow only** country mode, either a listed country or an explicit IP allow can satisfy that scope, so a `default=deny` policy can express private/internal CIDRs **or** selected countries. An unresolved country fails the country branch but may still be admitted by an explicit IP allow.
Profile, vhost and location policy scopes remain cumulative: satisfying one scope never bypasses another scope or authentication. Country **Block** mode continues to reject listed countries while the IP ACL controls all other clients.
The reusable ACL editor exposes this as two guided modes without changing the saved configuration schema:
- **Block by default** — each selected country **OR** allowed IP/CIDR is an access exception. For example, `CN` plus `203.0.113.7` allows clients from China and also that single address from any other resolvable country.
- **Allow by default** — each selected country **OR** denied IP/CIDR is a block condition.
- **Custom** — retains manual default action, country mode and mixed IP allow/deny actions for advanced policies.
A live policy preview shows the effective default and OR branches before save. The editor also accepts a single IPv4/IPv6 address and normalizes it to a host rule; the backend accepts the same address form directly, so API-authored profiles do not require `/32` or `/128` either.
## Compatibility
- SQLite schema: 8, unchanged.
- Saved proxy configuration format: unchanged from 0.26.5.
- No data migration is required for upgrade from 0.26.5.
- Existing ACL/country configuration is reinterpreted only where allow-only countries previously conflicted with `default=deny` IP rules.
Verification status and environment limitations are recorded in [TEST_REPORT](TEST_REPORT.md).
+8 -4
View File
@@ -73,13 +73,17 @@ custom request-header rules, which cannot reintroduce removed credentials.
continues to use verified identity headers from that service.
Global host policies, reusable ACL profiles, vhost ACLs and location ACLs remain
cumulative: access requires all applicable policies **and** successful authentication.
cumulative: access requires all applicable policy scopes **and** successful authentication.
An ACL profile can be defined once under **ACL profiles**, combine default allow/deny
IPv4/IPv6 CIDR rules with country block/allow-only policy, then be attached to several
vhosts. Per-vhost rules remain available and are evaluated in addition to the profile.
Within an IP ACL, deny takes precedence. This is not an Nginx `satisfy any` mode: a
permitted IP cannot skip another applicable policy or a password. The graphical inline
ACL editor still supports default allow/deny and IPv4/IPv6 CIDR rules.
Within one policy scope, explicit IP deny rules and blocked countries take precedence.
When country mode is **Allow only**, a listed country or an explicit IP allow rule may
satisfy that scope; therefore `default=deny` can express e.g. private CIDRs **or** selected
countries. An unresolved country still fails closed unless the client matches an explicit
IP allow. This does not let a permitted IP skip another profile/vhost/location policy or
a password. The graphical inline ACL editor still supports default allow/deny and
IPv4/IPv6 CIDR rules.
Trusted-proxy settings control which peer can contribute the effective client IP;
untrusted forwarding headers do not grant network access.