Repository navigation
Conversation
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 95255e86c3
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| if (filters.monitor) | ||
| query.whereExists( | ||
| ProxyHost.knex()("proxy_host_monitor") | ||
| .select("id") | ||
| .where("host_id", ProxyHost.knex().ref("proxy_host.id")) | ||
| .where("state", filters.monitor), |
There was a problem hiding this comment.
Filter monitors by their effective state
When the workspace monitor filter is set to paused, this predicate searches the persisted proxy_host_monitor.state, but publicStatus() derives paused from a disabled proxy host or disabled monitor while leaving the stored state as its previous up, down, or unknown value. As a result, the Paused filter returns no matching hosts, while the Up/Down filters can incorrectly include paused hosts; the query needs to account for both host and monitor enablement.
Useful? React with 👍 / 👎.
| const revision = list.meta?.authorization_revision; | ||
| const suffix = typeof revision === "string" && /^[a-f0-9]{64}$/.test(revision) ? `.${revision}` : ""; |
There was a problem hiding this comment.
Rebuild imported access-list artifacts
When a GitOps backup containing an access list is restored on another instance, its exported meta.authorization_revision is imported unchanged, so this helper selects /data/access/<id>.<revision>. GitOps imports the database rows directly and neither copies nor rebuilds that immutable authorization artifact, causing the final Nginx validation to fail for attached hosts and leaving the imported access-list metadata pointing at a nonexistent file. Rebuild the imported users/CA locally and persist the resulting revision before regenerating host configurations.
Useful? React with 👍 / 👎.
| if ( | ||
| internalNginx.getFileFriendlyHostType(host_type) === "proxy_host" && | ||
| host.enabled && | ||
| host.meta?.wasm_filters?.some((filter) => filter.enabled) | ||
| ) { | ||
| const { prepareHost } = await import("./wasm.js"); | ||
| host.wasm = await prepareHost(host); | ||
| } |
There was a problem hiding this comment.
Mark Wasm hosts active after the reload
For every enabled Wasm host, prepareHost() writes a validated status before the production configuration is staged, but no activation path calls the newly added markHostActive() after Nginx reloads successfully. Consequently GET /nginx/wasm/hosts/:id and the Wasm tab can never report active; disabling all filters also leaves the previous validated or error status behind. Invoke the status transition only after the complete configuration batch is committed, passing null when the host no longer has an active chain.
Useful? React with 👍 / 👎.
| const configurationPath = path.join(root(), "hosts", `${host.id}-${digest(contents)}.json`); | ||
| await immutableFile(configurationPath, contents); |
There was a problem hiding this comment.
Remove obsolete Wasm credential files after activation
When an API-key filter is rotated or removed, the decrypted key is embedded in contents and written to a new content-addressed host JSON file, while the previous /data/wasm/hosts/<id>-*.json is never deleted anywhere in the repository. Each rotation therefore leaves the old credential recoverable indefinitely, and deleting the proxy host leaves every historical key file behind. Retain the previous file only until Nginx activation or rollback completes, then remove unreferenced files for that host and clear them on host deletion.
Useful? React with 👍 / 👎.
Keep manual updates separate from loaded relation graphs, restore driver-aware timestamps, retry monitor transaction conflicts, and recover valid hosts after a failed startup batch. Treat an absent implicit Docker socket as optional while preserving discovery.
Add administrator-managed Proxy-Wasm uploads, encrypted per-host module configuration, four native HTTP callbacks and real execution preflight. Preserve custom module metadata across worker activation and remove the withdrawn workspace UI and API while retaining migration compatibility.
ShieldPM now runs administrator-uploaded Proxy-Wasm HTTP filters and WASI Preview 1 applications directly on Proxy Hosts, with a separate manual command runner. The requested Host Workspace has been removed. The change also fixes the production startup and host-restoration failures reported during instance testing.
Execution modes
http-json-v1for explicit status, headers and binary responses.http-json-v1receives method, URI, query, headers and base64 body; return checked header/body changes and continue to the upstream, or return an explicit local response.memoryand_start. Run with explicit arguments, environment and stdin; inspect stdout, stderr and the original unsigned WASI exit code. Stop, navigation or HTTP disconnect terminates the real process.Standalone commands use the existing Node 26 built-in WASI adapter in a fixed disposable child process. The runtime allows at most two executions, 100–60,000 ms deadlines (10 seconds by default), 64 KiB inputs and 1 MiB combined normalized output. It passes no inherited environment or preopened directories. Input values and output are excluded from audit records. Upload and execution require
settings:update; compilation-only inspection never instantiates uploaded code.The private catalogs and immutable SHA-256 artifacts use bounded sizes, trusted directory selection, normalized paths, no-follow/single-inode reads, hash verification and serialized publication. Proxy-Wasm configuration and retained-worker references remain protected. Deletion removes catalog availability while preserving immutable bytes for accepted runs.
Unified host upload detects the actual bytecode contract and routes it to the appropriate catalog; standalone commands no longer hit the Proxy-Wasm ABI error there. The legacy runtime-specific endpoints remain strict and provide actionable guidance. Host WASI settings are encrypted and write-only, with stable-ID omission preservation and explicit
{}reset. Existing host rights permit selecting administrator-approved code; uploading or independently running code remains administrative.Per-request WASI uses a separate authenticated Unix listener, not an unauthenticated public API route. An immutable chain binds the approved digest, settings and filter token. Requests are bounded to 64 KiB body and 128 headers/32 KiB; arguments/environment retain their existing bounds. Guest framing/routing-header injection is rejected, HEAD/204/304 have no body, and disconnect terminates the actual child. Earlier Proxy-Wasm body callbacks finish before a later WASI handler can answer. A handler is last among request filters. The real preflight, accepted worker leases, rollback and catalog reference checks cover application entries too. A corrected invalid JSON draft now reliably re-enables the real host Save button.
Production runtime corrections
$status}into$statu. Install rendered bytes unchanged, preserve custom directives and include generator-source hashes in the startup fingerprint so existing damaged files are regenerated without a version bump.git_last_syncand maintenance windows, without timezone/DST/dateStrings drift. Actual MariaDB reproduces error 1292 before the fix. The supplied production SQL log is truncated, so this is a verified compatible cause rather than an assertion about an unseen driver message.Other implemented features
Weighted upstream pools, encrypted host revisions, incident history and durable notifications, real proxy caching independent of WAF selection, browser-session revocation and encrypted full-instance backup/restore remain included. The review's validator, domain-claim, Analytics, request-cancellation, scheduler, installer and accessibility improvements are retained. Host Workspace UI, routes, services, tags and profiles are removed; its historical migration stays compatible with already updated databases.
Host rollback follow-up (October 18)
A real MariaDB test now reproduces
ER_CHECKREAD/1020 at the reportedpatchCapturedHoststack when a concurrent status writer commits after domain-claim reads. The supplied production excerpt still omits the native SQL error, so this reproduction does not identify its missing code conclusively.[Host rollback]diagnostic with safe identifiers, without SQL, snapshots or credentials; never report a failed compensation as restored.Current follow-up commit:
1b5a976301ba537ddd06021c616418f96a3cf402.Validation
All eight final GitHub workflows passed on
1b5a9763, including CodeQL with no new alerts, all three Quality jobs and both architecture image/native/LXC checks. Production Unix WASI execution passed as UID 0 and UID 1000 on AMD64 and ARM64, with seven generated hosts per run.The local complete backend run had 2,900 passes, 100 explicit skips and one timeout in the unchanged WASI large-payload test under its original five-second budget. The unchanged HTTP-contract file passed 103/103 in isolation. The final exact-head GitHub Node 26 suite above passed all 2,902 cases without changing those budgets.
Runtime contract and documentation
Standalone support covers trusted administrator Preview 1 command modules. Node WASI is explicitly not a hostile-code security sandbox; per-memory and V8 heap limits do not cap total process RSS. Proxy-Wasm retains API7 0.7.0's existing header end-of-stream flag and generic body-rewriting limits. WASI request middleware can rewrite request bodies and handlers can produce their own responses; it does not implement asynchronous transformations of upstream responses, Preview 2/components, mounted directories or persistent application servers. These boundaries and the separate real/browser proofs are documented.
Host WASI integration and verification · October 18 runtime report · WASI applications · Proxy-Wasm filters
No application/dependency version changes, release, merge or production deployment.