Background
The browser WorkBench can now build HTTPS onion proxy routes against the Docker cluster, but it is still a request-level tool. To make onion proxy usable as a browser-like surface, we need a controlled webview/gateway layer that keeps page, subresource, and dynamic requests inside Rings instead of letting the browser fetch them directly.
This should follow the Scramjet/Ultraviolet style architecture at the abstraction level, but must not vendor or copy their AGPL implementation.
Goal
Add a workspace submodule named webview as a reusable Rings webview gateway. The module should own URL encoding, request/response policy, rewriting, cookie/header handling, and a pluggable transport boundary. The Yew frontend and MV3 extension should consume this module instead of embedding proxy logic directly in UI code.
Proposed module shape
- Add
crates/webview with package name rings-webview.
- Keep the default core portable across native and wasm where possible.
- Use feature gates for browser-only integration points such as Service Worker helpers or JS bootstrap assets.
- Expose a transport trait such as
WebviewTransport / GatewayTransport that accepts normalized gateway requests and returns normalized responses.
- Provide an adapter path for the existing browser onion proxy request API first; native/local gateway adapters can come later.
Architecture
-
Controlled origin
- Serve proxied pages under a Rings-owned route, for example
/webview/<encoded-url>.
- Never render remote pages from their original origin directly.
-
Gateway interception
- In the extension/browser path, a Service Worker or equivalent gateway handler owns the proxied route prefix.
- It decodes the target URL, builds a gateway request, sends it through the transport, rewrites the response, and returns it to the browser.
-
URL rewriting
- Rewrite HTML URL-bearing attributes such as
href, src, action, srcset, and relevant metadata.
- Rewrite CSS
url(...) and @import references.
- Rewrite redirect
Location headers back into gateway URLs.
-
Runtime hooks
- Inject a small bootstrap runtime before page scripts.
- Route
fetch, XMLHttpRequest, WebSocket, EventSource, sendBeacon, Worker, and dynamic import-style URLs through the gateway where feasible.
- Treat full JavaScript rewriting as an incremental phase, not a first-step blocker.
-
Cookies and headers
- Maintain a virtual cookie jar keyed by target origin/domain/path.
- Convert upstream
Set-Cookie into jar entries and attach matching Cookie headers on proxied requests.
- Strip or rewrite browser-hostile headers such as
Content-Security-Policy, X-Frame-Options, Strict-Transport-Security, and hop-by-hop headers.
- Preserve useful headers such as content type, cache metadata, and redirects after policy normalization.
-
Frontend integration
- Add a Yew webview surface with a URL entry point and render area.
- Do not use iframe as the primary architecture.
- Keep UI state in Yew, but keep proxy/rewrite logic outside the DOM layer.
-
Extension integration
- Keep long-lived Rings node state in the existing extension/offscreen boundary.
- Route webview gateway requests through the existing onion proxy transport path first.
- Avoid direct network fetches from proxied page code.
Non-goals
- Do not implement Chrome global proxy settings in this issue.
- Do not build an iframe-based renderer.
- Do not mutate already-rendered DOM as the main rewrite strategy.
- Do not copy Scramjet or Ultraviolet code or add AGPL dependencies.
Acceptance criteria
crates/webview exists and is part of the root workspace as the webview submodule.
- The module exposes typed request, response, URL, cookie, header-policy, rewrite, and transport boundaries without
any-style untyped escape hatches in TS-facing code.
- Unit tests cover URL encode/decode, same-page relative URL rewriting, CSS URL rewriting, redirect rewriting, and cookie matching.
- A browser/wasm test or fixture proves that HTML subresources and at least
fetch/XHR-style dynamic requests are rewritten through the gateway prefix.
- The frontend can call into the webview module without embedding rewrite logic in Yew components.
- The extension path can send a gateway request through the existing onion proxy request API.
- No direct remote network request is intentionally emitted by proxied page resources.
- Licensing stays clean: no vendored Scramjet/Ultraviolet implementation and no AGPL dependency is introduced.
Suggested implementation phases
- Core crate skeleton: target URL model, gateway request/response types, transport trait, header policy, cookie jar, and deterministic URL rewriting tests.
- HTML/CSS rewriting: cover static page and subresource fixtures.
- Browser bootstrap: hook
fetch and XHR first, then expand to WebSocket/EventSource/Worker/import cases.
- Yew surface: add a minimal webview page that accepts a URL and renders gateway HTML.
- Extension/onion adapter: connect gateway requests to the existing onion proxy request path and validate with the Docker cluster.
- Hardening: add fixtures for redirects, cookies, CSP-heavy pages, relative base URLs, and error responses.
Background
The browser WorkBench can now build HTTPS onion proxy routes against the Docker cluster, but it is still a request-level tool. To make onion proxy usable as a browser-like surface, we need a controlled webview/gateway layer that keeps page, subresource, and dynamic requests inside Rings instead of letting the browser fetch them directly.
This should follow the Scramjet/Ultraviolet style architecture at the abstraction level, but must not vendor or copy their AGPL implementation.
Goal
Add a workspace submodule named
webviewas a reusable Rings webview gateway. The module should own URL encoding, request/response policy, rewriting, cookie/header handling, and a pluggable transport boundary. The Yew frontend and MV3 extension should consume this module instead of embedding proxy logic directly in UI code.Proposed module shape
crates/webviewwith package namerings-webview.WebviewTransport/GatewayTransportthat accepts normalized gateway requests and returns normalized responses.Architecture
Controlled origin
/webview/<encoded-url>.Gateway interception
URL rewriting
href,src,action,srcset, and relevant metadata.url(...)and@importreferences.Locationheaders back into gateway URLs.Runtime hooks
fetch,XMLHttpRequest,WebSocket,EventSource,sendBeacon,Worker, and dynamic import-style URLs through the gateway where feasible.Cookies and headers
Set-Cookieinto jar entries and attach matchingCookieheaders on proxied requests.Content-Security-Policy,X-Frame-Options,Strict-Transport-Security, and hop-by-hop headers.Frontend integration
Extension integration
Non-goals
Acceptance criteria
crates/webviewexists and is part of the root workspace as thewebviewsubmodule.any-style untyped escape hatches in TS-facing code.fetch/XHR-style dynamic requests are rewritten through the gateway prefix.Suggested implementation phases
fetchand XHR first, then expand to WebSocket/EventSource/Worker/import cases.