Repository navigation
Conversation
matt2e
force-pushed
the
mobile-web
branch
5 times, most recently
from
May 15, 2026 08:15
808c1dd to
075b8bf
Compare
matt2e
force-pushed
the
mobile-web
branch
2 times, most recently
from
June 28, 2026 03:35
6b9a11f to
5dcf4a0
Compare
matt2e
force-pushed
the
mobile-web
branch
3 times, most recently
from
July 9, 2026 03:26
d42d13f to
9c5f909
Compare
matt2e
force-pushed
the
mobile-web
branch
2 times, most recently
from
July 30, 2026 07:41
62e8088 to
b5016a7
Compare
matt2e
force-pushed
the
mobile-web
branch
2 times, most recently
from
August 11, 2026 10:51
60c1853 to
c9d8534
Compare
matt2e
force-pushed
the
mobile-web
branch
3 times, most recently
from
September 3, 2026 05:08
55ac096 to
fde912a
Compare
matt2e
force-pushed
the
mobile-web
branch
2 times, most recently
from
September 4, 2026 07:08
be89621 to
c3c3c23
Compare
matt2e
force-pushed
the
mobile-web
branch
3 times, most recently
from
October 15, 2026 12:08
b46417f to
66e81c9
Compare
matt2e
force-pushed
the
mobile-web
branch
3 times, most recently
from
October 28, 2026 12:44
5ca0602 to
9451a97
Compare
matt2e
force-pushed
the
mobile-web
branch
3 times, most recently
from
November 2, 2026 09:32
70b355a to
9d6a43e
Compare
matt2e
force-pushed
the
mobile-web
branch
3 times, most recently
from
November 9, 2026 13:16
8203cc3 to
adf4f03
Compare
Restore the Axum web server startup that was previously stubbed out, so Staged can be used from a phone or browser when STAGED_WEB_SERVER=1 is set. - Start the TLS listener on :5175, serving /api/invoke, the /api/events WebSocket, note media under /api/media, and the built frontend from dist/ - Drop the bearer-token/session-cookie auth layer and its dependencies (axum-extra, rand, subtle, time); the server is unauthenticated and only starts when explicitly opted in - Add `just dev-web` (Vite over HTTPS with an /api proxy to the server) and `just run-web` (release build serving the production bundle, with a readiness probe since release builds log nothing) - Configure Vite HTTPS, allowed host, and /api proxy from STAGED_WEB_CERT_PATH / STAGED_WEB_KEY_PATH / STAGED_WEB_HOST Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Matt Toohey <contact@matttoohey.com>
…ilure tests vitest resolves a run of consecutive queued doMocks in parallel, so the setup-failure tests' throwing re-mock of prPollingService raced the beforeEach mock of the same module and lost about half the time, letting the socket connect and the onRegistrationFailed wait time out. Queue a doUnmock in between so the override always lands last. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Matt Toohey <contact@matttoohey.com>
… unauthenticated Review follow-ups on the mobile-ui branch. - web_server.rs: remove `CorsLayer::permissive()` and the tower-http `cors` feature. With the auth layer gone, the permissive layer let any page in a browser that could reach the host POST to /api/invoke/* cross-origin and run repo actions. Nothing needs CORS: `just run-web` serves dist/ from the server's own origin and `just dev-web` proxies /api through Vite (same origin for the browser; Vite's http-proxy forwards server-side with `ws: true` for the /api/events upgrade, and axum's WebSocketUpgrade does not check Origin), so same-origin fetches and the WebSocket keep working with no CORS headers at all. - lib.rs gate, web_server.rs module doc, justfile recipe comments, README: say plainly that once STAGED_WEB_SERVER=1 is set the server binds 0.0.0.0:5175 with TLS and no authentication, so anyone who can reach the port can run every command the desktop window can, including repo actions. - web_server.rs `start()`: add a `STAGED_WEB_DIST` override, checked before the exe-relative candidates, and have `just run-web` export it as an absolute path instead of `cd src-tauri` so the release binary finds dist/ regardless of launch cwd. The 404 probe message now points at the variable. - transport.test.ts: the `mockPrPollClientId` comment no longer claims a vitest race. vitest 5.0.2 applies a batch of same-path `doMock`s sequentially in queue order, so the override already wins there; the `doUnmock` split is kept as an ordering guarantee that does not depend on vitest internals. Verified with `pnpm -s check` (0 errors), the transport test file (21/21), `cargo check` in src-tauri, `cargo fmt --check`, and Prettier on the changed frontend files. Signed-off-by: Matt Toohey <contact@matttoohey.com> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Matt Toohey <contact@matttoohey.com>
…rop unused dev:web script Review follow-ups on the mobile-ui branch. Dropping the CORS layer closed the invoke path (Json<Value> needs a Content-Type a cross-origin page cannot send without a preflight), but CORS never applied to WebSocket handshakes, so a page on any origin in a browser that could reach the host could still open wss://<host>:5175/api/events and read the full event stream: session content and the change feed. - web_server.rs `ws_events`: take the request headers and refuse the upgrade with 403 when an `Origin` is present and its authority does not match the request's `Host` exactly, host and port both (`host:5175` vs `host:5176`, or an implied vs explicit port, are different origins). The scheme is ignored since the server only speaks TLS. A missing `Origin` is allowed: that is a non-browser client, which the unauthenticated server does not try to keep out, and a browser page cannot omit the header. - Under `just dev-web` the page lives on the Vite origin and reaches the server through Vite's /api proxy, which rewrites Host to localhost:5175 (`changeOrigin: true`) but forwards the browser's Origin, so Origin and Host never match there. `STAGED_WEB_HOST:VITE_PORT`, both exported by the recipe into the Tauri process, is accepted as a second allowed authority, also exact on host and port. - The comparison is a pure `ws_origin_allowed(origin, host, dev_origin)` with `origin_authority` splitting the authority off the header value (`Origin: null`, empty and schemeless values never match). Unit tests cover same origin allowed (including case-insensitive host and default ports), different host rejected (including a host that merely contains ours, `null`, malformed, and no Host at all), different port rejected, absent Origin allowed, and the Vite dev authority allowed only when configured and only for the exact host and port. - Module doc: the "cannot drive it" paragraph now also covers the event stream and points at the Origin check. - package.json: remove the unreferenced `dev:web` script. `just dev-web` runs vite with its own flags through the Tauri beforeDevCommand and is the single definition; README and justfile never mentioned the script. Verified with `cargo test --lib web_server::tests` (21/21, 6 new), `cargo check`, `cargo clippy` and `cargo fmt --check` in src-tauri, and `pnpm -s check` (0 errors, 0 warnings). Signed-off-by: Matt Toohey <contact@matttoohey.com> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Matt Toohey <contact@matttoohey.com>
… back to the URI authority Review follow-up on the mobile-ui branch. The Origin check added in a31bbb3 compared `Origin` against the `Host` header and failed closed when `Host` was missing. That is correct for HTTP/1.1, but this server advertises `h2` over ALPN and axum's serve enables the RFC 8441 extended CONNECT protocol, so Chrome and Firefox open the WebSocket on the page's existing HTTP/2 connection. An h2 request has no `Host` header: the authority travels in `:authority`, which the h2 crate maps into the request URI and hyper does not copy into a `Host`. Every same-origin desktop browser on h2 was therefore refused with 403 and sat in the client's 2 s reconnect loop with no live events. `just dev-web` was unaffected because Vite's proxy speaks HTTP/1.1 to :5175, and the iOS-simulator check did not surface it. - web_server.rs `ws_events`: take the request `Uri` and derive the expected authority through a new `request_authority(headers, uri)`: the `Host` header first, else `uri.authority()`. `ws_origin_allowed` is unchanged and still fails closed when both are absent (origin-form URI, no Host). The refusal log now says "authority" rather than "Host". - Tests: the h2 shape (Origin present, Host absent, URI authority present and matching, with and without an explicit port) is allowed; the same shape with a mismatched host or port in the Origin is rejected; an origin-form URI with no Host still yields no authority and is rejected; and `Host` wins over an absolute-form request URI when both are present. - `ws_origin_allowed` doc: note that comparing `Origin` to the request's own authority instead of a fixed allow-list is only sound because the server is TLS-only. A DNS-rebinding host would match on both sides but fails the certificate check first, so a plain-HTTP variant must not reuse this check as-is. Verified with `cargo test --lib web_server::tests` (24/24, 3 new), `cargo check`, `cargo clippy` and `cargo fmt --check` in src-tauri. Signed-off-by: Matt Toohey <contact@matttoohey.com> Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Signed-off-by: Matt Toohey <contact@matttoohey.com>
Merged
3 tasks done
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Test plan