You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: ARCHITECTURE.md
+6-6Lines changed: 6 additions & 6 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -39,7 +39,7 @@ The relay server terminates only the browser WebSocket and yamux session. It use
39
39
## Core invariants
40
40
41
41
- Target document navigations use encrypted `/zp/p/<encrypted>#k=<key>&server=...` routes on the proxy origin.
42
-
- The `#k` fragment is decrypted in the browser shell, removed with `history.replaceState`, and not sent to the server.
42
+
- The `#k` fragment is decrypted in the browser shell, kept visible with canonical `server=` relay parameters, and never sent to the HTTP server.
43
43
- Every Service Worker-controlled request is classified. Unknown requests are blocked; there is no native `fetch(event.request)` fallback.
44
44
- Privileged runtime-to-Service-Worker control messages require a per-tab capability token injected into the runtime prelude and removed from target-visible DOM before target code runs.
45
45
- Target TCP connections are opened through WebSocket -> yamux -> SOCKS5 DOMAINNAME. With a Tor `-socks` address the relay byte-bridges to Tor; with `-socks internal` the relay validates the SOCKS5 CONNECT bytes and direct-dials the target for Tor-free testing. The kernel does not call `http.Transport` for target egress.
@@ -52,7 +52,7 @@ The relay server terminates only the browser WebSocket and yamux session. It use
| Share URL envelope |`web/zp-core.js`, `internal/shareurl/*`| Compatible JavaScript and Go implementations of `/zp/p/<encrypted>#k=<key>` using AES-256-CBC, HMAC-SHA256, HKDF, raw base64url, and inherited relay-server fragments. |
55
+
| Share URL envelope |`web/zp-core.js`, `internal/shareurl/*`| Compatible JavaScript and Go implementations of `/zp/p/<encrypted>#k=<key>&server=...` using AES-256-CBC, HMAC-SHA256, HKDF, raw base64url, and inherited relay-server fragments. |
56
56
| Service Worker |`web/sw.js`| Classifies every controlled request under `/zp/`, blocks unknowns, manages in-memory tab/entry state and inherited relay servers, requires per-tab capability tokens on privileged runtime bridge messages, calls the WASM kernel, exposes runtime bridge APIs. |
57
57
| Runtime prelude |`web/runtime-prelude.js`, `web/worker-prelude.js`| Installs target-realm containment hooks before target scripts run. Main-window fetch/XHR/EventSource/WebSocket/sendBeacon, navigation/form/history/location/storage/worker/iframe/device APIs are hooked; main-window and worker `fetch` bridge through `/zp/api/fetch`. Runtime membrane helpers (`__zp_get`, `__zp_set`, `__zp_assign`, `__zp_update`, `__zp_call`, `__zp_construct`, `__zp_getOwnPropertyDescriptor`, `__zp_ownKeys`) and dynamic compilation wrappers execute `Function`/`eval`/string timer bodies under the virtual global scope. |
@@ -62,16 +62,16 @@ The relay server terminates only the browser WebSocket and yamux session. It use
62
62
63
63
## Request flow
64
64
65
-
1. The shell registers `/zp/sw.js` with `scope: '/zp/'`, waits for a controller, canonicalizes an `http:` or `https:` target, encrypts it, and navigates to `/zp/p/<encrypted>#k=<key>` on the proxy origin.
66
-
2. The shell loaded on `/zp/p/<encrypted>#k=<key>` decrypts the fragment key in window context, validates the HMAC before decryption, normalizes repeated `server=` relay fragments, removes the fragment from the visible URL when policy allows, and sends `ZP_OPEN_SHARE` to the Service Worker.
65
+
1. The shell registers `/zp/sw.js` with `scope: '/zp/'`, waits for a controller, canonicalizes an `http:` or `https:` target, encrypts it, and navigates to `/zp/p/<encrypted>#k=<key>&server=...` on the proxy origin.
66
+
2. The shell loaded on `/zp/p/<encrypted>#k=<key>&server=...` decrypts the fragment key in window context, validates the HMAC before decryption, normalizes repeated or missing `server=` relay fragments, keeps the canonical fragment visible, and sends `ZP_OPEN_SHARE` to the Service Worker.
67
67
3. The Service Worker stores the decrypted target plus relay-server list in in-memory tab/entry maps and activates `/zp/p/<encrypted>` as a proxy document route.
68
68
4. A `/zp/p/<encrypted>` document request is resolved back to the target URL. The Service Worker calls `__go_jshttp` with `X-ZP-*` internal metadata plus inherited relay-server headers.
69
69
5. The WASM kernel ensures one long-lived WebSocket connection to the selected relay server or `/zp/ws-pipe`, wraps it in a yamux client, and opens one yamux stream per target TCP connection.
70
70
6. Each target connection performs SOCKS5 `CONNECT` with DOMAINNAME ATYP and a Tor `IsolateSOCKSAuth` username derived from the tab stream-isolation key and target site. In `-socks internal` mode the relay accepts that same binary SOCKS5 handshake locally and direct-dials the requested host:port; no external Tor process is used.
71
71
7. HTTPS fetch targets advertise `h2` and `http/1.1` through uTLS ALPN; target WebSocket connections advertise only `http/1.1`.
72
72
8.`internal/zphttp` dispatches negotiated `h2` connections through `golang.org/x/net/http2.ClientConn`; HTTP/1.1 fallback writes a direct request and reads the response with `http.ReadResponse`.
73
73
9. Redirects are followed inside the kernel so raw `Location` headers are not exposed to browser code.
74
-
10. HTML document responses are transformed: Rust rewrite asset plus runtime prelude are injected, document navigation URLs are rewritten to encrypted `/zp/p/<encrypted>#k=<key>` routes, risky tags and headers are removed, and the browser receives a same-origin `Response` with ZeroProxy CSP.
74
+
10. HTML document responses are transformed: Rust rewrite asset plus runtime prelude are injected, document navigation URLs are rewritten to encrypted `/zp/p/<encrypted>#k=<key>&server=...` routes, risky tags and headers are removed, and the browser receives a same-origin `Response` with ZeroProxy CSP.
75
75
76
76
## Shared URL flow
77
77
@@ -83,7 +83,7 @@ Shared links use this envelope:
83
83
84
84
`web/zp-core.js` and `internal/shareurl` derive separate HKDF-SHA256 AES-CBC and HMAC keys from the 64-byte seed. The MAC covers a fixed version prefix, IV, and ciphertext. Decryption verifies HMAC first, then decrypts and canonicalizes the target URL. Only `http:` and `https:` targets are accepted for document/fetch traffic; WebSocket wrappers accept only `ws:` and `wss:`.
85
85
86
-
The Go HTML transformer uses `internal/shareurl.New` when laundering document-navigation attributes, so transformed links/forms/frames keep using encrypted `/zp/p` routes instead of legacy virtual URL paths.
86
+
The Go HTML transformer uses `internal/shareurl.NewWithServers` when laundering document-navigation attributes, so transformed links/forms/frames keep using encrypted `/zp/p` routes with inherited relay-server fragments instead of legacy virtual URL paths.
Copy file name to clipboardExpand all lines: PHASE3_PLAN.md
+2-2Lines changed: 2 additions & 2 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -83,11 +83,11 @@ Relay server selection and inheritance:
83
83
- no fragment;
84
84
- normalized host, port, path, and query;
85
85
- bounded count and total serialized length.
86
-
- The fragment is parsed by the shell before target code runs, then removed with `history.replaceState`. The fragment is never sent to the origin server or target server.
86
+
- The fragment is parsed by the shell before target code runs, then kept visible in canonical `#k=...&server=...` form. The fragment is never sent to the origin server or target server.
87
87
- The shell sends `{ targetUrl, routeKey, servers }` to the Service Worker in `ZP_OPEN_SHARE`. The Service Worker stores `servers` in tab/entry context and passes them to the WASM kernel transport initialization and WebSocket stream path.
88
88
- Runtime-generated document navigations, forms, iframe navigations, worker bootstrap, module/script API calls, runtime fetch APIs, WebSocket, and `WebSocketStream` inherit `servers` from the active context. Target-authored URLs cannot override the relay server list.
89
89
- New share URLs created by ZeroProxy UI or runtime helpers include the current inherited `server` parameters unless the user explicitly chooses a different relay set through ZeroProxy-controlled UI.
90
-
- Cold restore without Service Worker memory must fail safely unless the URL fragment supplies both a valid `k` and a valid server list, or the deployment has an explicit default relay policy.
90
+
- Cold restore without Service Worker memory must activate from the URL fragment when it supplies `k` and relay `server` values; missing server values are canonicalized to the deployment's current `/zp/ws-pipe`relay.
91
91
92
92
### 1. Static document-navigation attributes are not rewritten
- AES-256-CBC + HMAC-SHA256 URL envelope with HKDF-separated encryption/MAC keys and HMAC verification before decryption.
19
19
- Service Worker request classifier that handles every controlled request, blocks unknown requests instead of falling back to native `fetch(event.request)`, and requires a per-tab runtime capability token on privileged runtime bridge messages.
20
20
- Go WASM exports: `__go_jshttp`, `__zp_stream`, `__zp_kernel_init`, and `__zp_cookie_set`.
21
21
- A single browser WebSocket pipe carrying yamux streams to the relay server, then SOCKS5 DOMAINNAME CONNECT, uTLS for HTTPS, HTTP/2 when ALPN selects `h2`, and HTTP/1.1 fallback/direct handling. `-socks 127.0.0.1:9050` preserves the Tor bridge; `-socks internal` is a Tor-free development/test mode that parses SOCKS5 on the relay and dials targets directly from the relay process.
22
-
- Tokenizer-based HTML transform that injects the runtime prelude, launders executable external scripts through `/__zp/api/script?u=...`, rewrites iframe/frame document URLs to encrypted `/p` routes, preserves author-visible anchor/form attributes for runtime navigation interception, removes or neutralizes preload/preconnect/manifest hints, drops dangerous tags and headers, routes executable event attributes through the Rust WASM rewriter, and handles `srcdoc`.
23
-
- Runtime containment for main-window `fetch`, XHR, EventSource, WebSocket, `sendBeacon`, navigation, forms, history/location masking, storage facades, workers, iframes, and high-risk device/network APIs. Main-window and worker `fetch` paths are bridged through `/__zp/api/fetch` so strict `connect-src 'self'` does not block target API calls before the Service Worker can route them. Runtime-to-Service-Worker control messages carry a closure-held per-tab capability token. The runtime also applies basic self-fingerprint masking for patched function source strings, Canvas/Audio extraction jitter, and speech voice lists; broad anti-bot spoofing is not a project goal.
22
+
- Tokenizer-based HTML transform that injects the runtime prelude, launders executable external scripts through `/zp/api/script?u=...`, rewrites iframe/frame document URLs to encrypted `/zp/p` routes with inherited `server=` relay fragments, preserves author-visible anchor/form attributes for runtime navigation interception, removes or neutralizes preload/preconnect/manifest hints, drops dangerous tags and headers, routes executable event attributes through the Rust WASM rewriter, and handles `srcdoc`.
23
+
- Runtime containment for main-window `fetch`, XHR, EventSource, WebSocket, `sendBeacon`, navigation, forms, history/location masking, storage facades, workers, iframes, and high-risk device/network APIs. Main-window and worker `fetch` paths are bridged through `/zp/api/fetch` so strict `connect-src 'self'` does not block target API calls before the Service Worker can route them. Runtime-to-Service-Worker control messages carry a closure-held per-tab capability token. The runtime also applies basic self-fingerprint masking for patched function source strings, Canvas/Audio extraction jitter, and speech voice lists; broad anti-bot spoofing is not a project goal.
24
24
- Rust WASM JavaScript rewriting is the only script rewrite engine: target-response CSP no longer permits `connect-src *`, external, module, worker, imported, inline, event-handler, and synchronous dynamic-function bodies are parsed before execution, dangerous global/window/location access is rewritten to runtime membrane helpers, parse/transform failures fail closed, constructor-constructor escapes are routed through runtime helpers instead of blocked, and blob/data worker scripts remain blocked when they cannot be rewritten synchronously.
25
-
- Relay server static asset service and `/__zp/ws-pipe` WebSocket endpoint.
25
+
- Relay server static asset service and `/zp/ws-pipe` WebSocket endpoint.
26
26
- Go and JavaScript share URL implementations that use the same envelope format.
27
27
28
28
Not complete enough for production or high-assurance acceptance:
@@ -110,7 +110,7 @@ Open the browser shell on the proxy origin:
110
110
http://proxy.localhost:8080/
111
111
```
112
112
113
-
Use `proxy.localhost` from the start so the shell, Service Worker, and encrypted `/p/<encrypted>#k=<key>` routes share one origin. The server starts even if Tor is not reachable. Target browsing needs either a configured Tor SOCKS5 listener or the explicit non-anonymous `-socks internal` test mode.
113
+
Use `proxy.localhost` from the start so the shell, Service Worker, and encrypted `/zp/p/<encrypted>#k=<key>&server=...` routes share one origin. The server starts even if Tor is not reachable. Target browsing needs either a configured Tor SOCKS5 listener or the explicit non-anonymous `-socks internal` test mode.
0 commit comments