Date: 2026-06-07
This document is the current repository-backed implementation-status report for ZeroProxy. It preserves the compatibility/privacy-membrane plan, compares it against the implementation present in this repository today, and updates the older partial-status language against the code and checked-in verification artifacts now present.
ZeroProxy is now aligned with the planned human-in-the-loop virtual-browsing architecture at repository release-gate scope. A real user drives a real browser, while target traffic is kept on the membrane path:
Service Worker -> Go WASM kernel -> WebSocket/smux -> SOCKS5 -> uTLS
Current repository-backed status:
- Static transformation policy is Rust-owned: JavaScript/SWC rewriting, HTML/lol_html rewriting, CSS URL rewriting, import maps, URL policy classification, and share-route generation.
internal/htmltxis a Go adapter into Rust/lol_html. It now has a streamingDocumentStreamRewriterbridge path and retains the old whole-document hook only as a fallback for older test hooks.- The Go WASM document path uses
ZPRewriter.createHTMLDocumentRewriterwhen available and falls back toZPRewriter.rewriteHTMLDocumentonly when the streaming hook is unavailable. - Runtime-set
srcdocprefers the same Rust full-document rewrite ABI and models parent target/referrer context. - Runtime helper ABI is stable and includes
__zp_get,__zp_set,__zp_call,__zp_construct,__zp_has,__zp_delete,__zp_typeof,__zp_ownKeys,__zp_getOwnPropertyDescriptor, and__zp_module_url. - Target-visible selector virtualization covers
href,src,srcset,action,formaction,poster,srcdoc, andxlink:hrefacrossquerySelector,querySelectorAll,matches, andclosest. - Service Worker request classification is fail-closed: unknown navigations are policy-blocked, unknown subresources return
Response.error(), and there is no nativefetch(event.request)fallback. - Frame sandbox containment and unsupported
data:,blob:, andjavascript:frame scheme behavior are tested and listed as expected deltas. - Representative-site corpus machinery, release-gate schema, redacted release artifact, redacted failure telemetry, root-surface oracle records, and transport timing summaries are checked in.
- Cookie/storage/SameSite, fetch/XHR, framework, event-listener, observer/input, dynamic DOM, DOM-mutation, frame/srcdoc/sandbox, performance, delivery-versioning, and rewrite long-tail matrices are checked in and pinned to source or oracle metadata.
- Go transport timings include queue wait, connection acquisition, stream open, SOCKS/TLS, first-byte, body duration, total duration, retry count/reason, reuse, protocol, and failure class where available.
- Runtime Performance entries expose target-visible resource timing where safe, wrap
PerformanceObserver, and count synthetic timing gaps.
Completion status: repository release-gate complete for the current status plan. The checked-in live representative corpus release artifact records 14 compared sites, 5 direct passes, 9 classified expected compatibility deltas, 0 triage sites, 0 unexpected script rewrite-induced failures, 0 generated JavaScript syntax errors, and 0 unexpected script fail-close fallbacks.
The remaining risk is operational rather than unclassified: the 9 checked-in representative-site expected deltas must be maintained and ideally reduced as future compatibility work lands.
ZeroProxy preserves three load-bearing security invariants:
- no direct target egress outside the membrane transport path;
- no native
fetch(event.request)fallback for unknown target requests; - no wildcard
connect-src, direct fetch escape, or fail-open script execution.
Transformation policy converges into rewriter-rs:
HTML / CSS / JS / import-map source
-> Rust transform engine
-> JS AST transform and codegen
-> HTML transform
-> CSS URL transform
-> import-map transform
-> dynamic code transform
-> runtime facade ABI
-> Service Worker / Go WASM kernel transport
The browser runtime is the execution ABI for rewritten code, not a second independent static rewriting policy. Public helper names such as __zp_get, __zp_set, __zp_call, __zp_construct, __zp_has, __zp_delete, __zp_typeof, __zp_ownKeys, __zp_getOwnPropertyDescriptor, and __zp_module_url are ABI surface and must remain stable unless the Rust rewriter and runtime are versioned together.
The planned HTML transformer is Rust-owned and backed by lol_html, so malformed and streaming HTML can be rewritten without a full-document parser. Static document policy covers:
srcdoc;- inline scripts;
- event handlers;
- inline styles;
- import maps;
- external script URLs;
- frame URLs;
- base and meta policy handling;
- preload/preconnect suppression;
- object/embed blocking;
- target-visible backup and masking attributes.
The Go internal/htmltx package is a thin adapter/streaming bridge with no independent rewrite policy. Behavior-preserving membrane/protocol migrations are expected to use a temporary differential harness during development, followed by permanent characterization/adversarial tests; temporary harnesses are not committed.
Static rewriting and runtime facades cover:
- free globals:
window,self,globalThis,location,origin,document,history,top,parent,opener,frames; - network and dynamic constructors:
fetch,XMLHttpRequest,WebSocket,EventSource,Worker,SharedWorker,sendBeacon,eval,Function, async/generator function constructors, string timers; - member and reflective access:
window.location,location.href,location.hash,document.defaultView,contentWindow,contentDocument,postMessage,Object.getOwnPropertyDescriptor,Reflect.ownKeys,Object.keys,Object.defineProperty,in,delete,typeof; - module syntax: static import/export sources, dynamic
import(),import.meta.url, import maps, module workers; - frame and event boundaries:
event.source,event.view, iframeparent/top/opener,srcdoc, and nested frame messaging.
The rewriter preserves local bindings, strings, comments, JSON content, class/object keys outside executable value position, target challenge tokens/configuration, and anything that would require manufacturing target CSP permission.
The runtime exposes explicit facade behavior for window, location, history, document, workers, network constructors, events, frame boundaries, storage, dynamic code, and fingerprinting/performance surfaces. Static rewritten code and dynamic code compiled under a scoped runtime environment observe the same facade semantics.
Proxy objects are acceptable for plain facade targets and virtual scopes. Native browser objects with non-configurable properties must not be proxied in ways that violate ECMAScript proxy invariants.
Ordinary http: and https: iframe/frame navigations use the same encrypted /zp/p/<route>#k=... document route used by top-level documents. Child documents then pass through the same HTML/JS/CSS/import-map transform and runtime ABI.
Frame-specific code is limited to:
- initial
about:blankcontainment before navigation; srcdoctransformation;contentWindowandcontentDocumentfacade installation;parent,top,opener, andframesmapping;postMessagetarget-origin/source/origin mapping;- original sandbox semantics preservation plus explicit security deltas;
- explicit blocking/classification of dangerous non-document navigations such as
javascript:, unsafedata:, and unsupportedblob:cases.
Runtime source is split by responsibility, then bundled for delivery:
- runtime ABI modules;
- facade modules;
- network modules;
- DOM modules;
- frame modules;
- worker modules;
- dynamic-code modules;
- Service Worker modules;
- Rust rewriter modules for JS, HTML, CSS, and import maps.
Delivery uses one target-document bootstrap injection, one bundled runtime asset for target documents, one bundled worker runtime asset, one bundled Service Worker asset, and a Rust rewriter WASM path exposed through the build output. Minification/mangling must not rename public ABI helpers.
ZeroProxy injection and polyfill surfaces should not break normal site compatibility checks that inspect:
- function source strings;
- descriptors;
- enumerability;
- property keys;
- prototypes;
- stack-visible names;
- frame/global identity.
Every injected wrapper or facade should be centrally masked or documented as an expected visible delta. The masking layer covers Function.prototype.toString, descriptors, ownKeys, global enumeration, frame wrappers, worker wrappers, dynamic-code wrappers, network wrappers, storage wrappers, history/location/document wrappers, and runtime-owned helper surfaces.
The compatibility oracle compares the JavaScript root visible surface against the native host browser. Starting from globalThis/window, it inventories visible objects, properties, descriptors, prototype chains, function source strings or redacted fingerprints/lengths, accessor source strings where safe, constructor names, Symbol.toStringTag, enumerable keys, own names, own symbols, Reflect.ownKeys, and target-visible string values. The comparison classifies deltas as expected security deltas, privacy/persona deltas, known compatibility gaps, implementation bugs, or native/browser-version deltas.
The root-surface comparison recurses only through safe, bounded object graphs and avoids invoking arbitrary page getters with side effects unless a probe is explicitly designed for that surface.
ZeroProxy-controlled documents and assets receive ZeroProxy CSP through response headers or Service Worker response construction, not committed HTML meta CSP.
Target CSP must not control the proxy-origin execution environment. Upstream CSP and report-only headers are stripped before browser Response construction. Target HTML meta CSP is removed or made inert during static and dynamic HTML transformation.
'unsafe-eval' is present only when target policy allows dynamic compilation and the dynamic body is rewritten before execution. Original target source must never execute on parse or rewrite failure.
Native-browser-vs-ZeroProxy E2E oracle tests cover:
- descriptors,
ownKeys, prototypes,toString, and global identity; - centralized artifact masking;
window,self,globalThis,location, andhistory;- iframe
contentWindow,contentDocument,parent,top,opener,srcdoc, nested frames, andabout:blank; - ordinary frame document loads using the same
/zp/proute and transport path as top-level documents; postMessage,event.origin,event.source, and cross-frame delivery;- request headers, response constructor policy, referrer policy, and CSP/header behavior;
- fetch, XHR, WebSocket, EventSource, workers, importScripts, dynamic import,
eval,Function, and string timers.
Expected differences are listed in checked-in expected-delta data. Raw script bodies, challenge tokens, clearance cookies, request bodies, challenge configuration, and raw challenge URLs must not be logged.
The representative-site corpus runs in native host-browser mode and ZeroProxy mode through the full membrane. It is an external compatibility signal, not a deterministic unit-test substitute. Site failures are categorized by surface and compared against native-host-browser behavior before being classified as ZeroProxy regressions.
Seed corpus:
| Site | Required primary-flow checks |
|---|---|
https://naver.com |
Desktop homepage load, full primary content load, ad iframe discovery, ad iframe nonblank/load-state check, major navigation/search entry points visible. |
https://m.naver.com |
Mobile homepage under mobile viewport/user-agent profile, full primary content load, ad iframe discovery, ad iframe nonblank/load-state check, major navigation/search entry points visible. |
https://www.google.com/search?q=zeroproxy |
Search result page render, result links visible, no unexpected script fail-close. |
https://www.google.com/maps |
Maps shell render, search box and map controls visible, map canvas/tile container nonblank, geolocation/permission behavior compared with native, tile/API request failures classified. |
| Embedded Google Maps fixture | Checked-in host fixture embedding a Google Maps embed URL in an iframe; iframe load, map content nonblank state, postMessage/frame behavior, sandbox/CSP deltas, and third-party widget console errors compared with native. |
https://www.wikipedia.org |
Static-heavy baseline render, search input visible, navigation links visible. |
https://github.com |
Modern app shell render, navigation/header visible, unauthenticated content visible. |
https://news.ycombinator.com |
Low-JS baseline, link list render, navigation visible. |
https://www.reddit.com |
JS-heavy app shell render, feed/container visible, console/runtime failures compared with native. |
https://x.com |
JS-heavy app shell render, unauthenticated landing/login boundary behavior compared with native. |
https://www.amazon.com |
Commerce-style homepage render, image/script/css load state, navigation/search controls visible. |
https://www.nytimes.com |
News/media layout render, image/script/css load state, paywall/consent behavior compared with native. |
https://www.cloudflare.com |
CDN/security/challenge-adjacent baseline, script and navigation render compared with native. |
https://ipleak.net |
Leak-test surface render, IP/DNS/WebRTC result containers visible, WebRTC/WebTransport no-goal behavior classified separately, raw IP/DNS values redacted and compared only by coarse consistency classes. |
The corpus captures only redacted operational data. It must not log raw page bodies, raw scripts, request bodies, cookies, challenge tokens, clearance cookies, challenge configuration, raw IP addresses, raw DNS resolver values, or sensitive URLs beyond normalized site identifiers and coarse failure categories.
The comparison pipeline records:
- console messages by level and normalized message fingerprint;
- uncaught exceptions and
pageerrorfingerprints; - request failures grouped by resource type, scheme, host class, and failure reason;
- response status buckets and content-type buckets;
- DOM readiness and load milestones;
- screenshot/layout-health snapshots;
- key selector visibility for primary content;
- visible text length and major container dimensions;
- iframe count, ad iframe candidates, and iframe load/nonblank state;
- script/style/image/font/media load status;
- Service Worker/runtime fail-close categories;
- transport connection counts, reuse rates, per-origin concurrency, and Go-originated timing summaries;
- real load/performance timings propagated from the Go network engine, Service Worker, runtime, and browser page context.
Rendering comparison is tolerant, not pixel-perfect. It checks blankness, primary containers, major controls, normalized console deltas, classified blocked/fail-closed paths, ad iframe state for Naver, map/tile state for Google Maps, and coarse/redacted leak-test state for ipleak.
Per-site triage records include site, viewport/profile, primary flow, first failing surface, native result, ZeroProxy result, normalized console delta, rendering delta, timing delta, transport delta, owner module, and status.
Telemetry explains failures without logging sensitive source material. It must not record raw script bodies, raw HTML bodies, request bodies, cookies, challenge tokens, clearance cookies, challenge configuration, or raw challenge URLs.
Allowed fields include coarse classifications such as rewrite kind, source size bucket, parser/rewrite error kind, retry path attempted, blocked URL scheme, blocked resource type, target content-type and charset, facade helper that threw, failed runtime API surface, Service Worker classification result, transport failure class, response status bucket, and lifecycle phase.
Telemetry is joinable with representative-site triage records so a broken site maps to its first failing surface without exposing target secrets.
Parse/rewrite failures remain fail-closed. The original target source never executes after a parse or rewrite failure. Safe retry paths may run before returning the final blocking script.
Recovery attempts include BOM stripping, classic-script HTML comment normalization, safe classic/module classification retry, future charset reinterpretation when response/document evidence supports it, event-handler and dynamic function wrapper variants, and syntax-proposal fixtures before allowing new syntax through.
The final fallback remains a blocking script such as a DOMException throw.
Dynamic DOM insertion is a first-priority compatibility milestone. Runtime insertion paths are compared with static Rust document policy and native host-browser behavior.
Planned dynamic surfaces include:
innerHTML,outerHTML,insertAdjacentHTML;document.writeanddocument.writeln;Range.createContextualFragment;DOMParser.parseFromString;appendChild(script),insertBefore(script),replaceChild(script);- template parsing and cloning;
- framework hydration that rewrites or reuses DOM nodes;
- dynamic
srcdoc.
The DOM manipulation inventory classifies every API family that can create, insert, replace, clone, parse, adopt, import, serialize, or mutate executable/URL-bearing markup as hooked, partial, irrelevant, expected limitation, or expected delta. Required families include node insertion/removal/replacement, HTML parsing sinks, node creation/import/adoption, attribute mutation, collection/template movement, frame-specific sinks, and script/style/link sinks.
Selector APIs should match target-visible URL attributes where native browser behavior would match, even when the raw browser DOM contains /zp/... routes or backup data-zp-* attributes.
Coverage includes:
Document.prototype.querySelector;Document.prototype.querySelectorAll;Element.prototype.querySelector;Element.prototype.querySelectorAll;Element.prototype.matches;Element.prototype.closest;- URL-bearing attribute selectors for
href,src,srcset,action,formaction,poster,srcdoc,xlink:href, and relevant reflected properties; - equality, prefix, suffix, substring, includes-token, and dash-match selector operators where feasible;
- selector lists and nested selectors where browser parsing permits them.
Unsupported selector cases are documented as expected compatibility gaps. The implementation must not expose data-zp-* internals or route selectors to target code while adding virtualization.
Cookie/storage/SameSite diagnostics cover redirect-chain Set-Cookie, SameSite Lax/Strict/None/Secure behavior, iframe and third-party-shaped cookie visibility, document.cookie vs network Cookie header behavior, expiry/domain/path handling, storage namespace sharing across reload/popup/iframe/same-origin/cross-origin cases, storage events, IndexedDB, and CacheStorage.
Fetch/XHR diagnostics cover mode, credentials, redirect, referrerPolicy, cache, integrity, keepalive, no-cors and opaque response behavior, abort before headers, abort during body streaming, XHR timeout/abort events, upload stream behavior, replayable body behavior, range requests, response URL/redirected state, response header filtering, and sync XHR policy.
Cookie values, typed secrets, request bodies, and sensitive state are redacted.
Framework fixtures cover React hydration, Next/Vite-style module graphs and dynamic chunks, Vue hydration/event binding, Angular zone/timer patching, Webpack runtime dynamic chunk loading, import maps, framework-driven innerHTML and template cloning, and worker/module-worker loading where relevant.
Event-listener compatibility covers addEventListener, removeEventListener, dispatchEvent, listener identity, duplicate registration, function/object listeners, options objects, AbortSignal, ordering across phases, propagation/default prevention, on* properties, rewritten inline handlers, cross-frame message events, facade event targets, and descriptor/toString/own-key visibility. ZeroProxy internal listeners and listener stores must not be enumerable, obtainable, or removable by target code through standard page APIs.
Observer/input parity covers MutationObserver, IntersectionObserver, ResizeObserver, pointer/mouse/touch/keyboard/composition/input/focus/wheel/scroll events, callback/event ordering, framework hydration, lazy loading, infinite scroll, maps, drag interactions, menus, mobile layouts, IME-style text input, and contenteditable editors. Telemetry must not log typed text, clipboard data, selected text, raw pointer paths, or sensitive form values.
Performance work measures JS rewrite latency, dynamic eval/Function/string timer rewrite latency, HTML transform first-byte delay and total time, WASM rewriter initialization time, runtime bootstrap cost, and page-load overhead on the compatibility corpus.
The Go network engine is the source of truth for target-side transport timings and emits redacted per-request metadata upward through:
Go network engine -> Go WASM kernel -> Service Worker response metadata -> runtime/browser comparison report
Required fields include request id, tab/isolation id hash, target origin hash or normalized host class, queue wait, connection acquisition, connection reused vs newly opened, SOCKS connect, TLS handshake, negotiated protocol, request header write, first response byte, response body duration, total duration, retry count, failure class, and stream/session reuse class where safe.
The page-visible Performance API exposes target-visible names with real measured timing data where safe:
performance.getEntries();performance.getEntriesByType('navigation');performance.getEntriesByType('resource');performance.getEntriesByName();PerformanceObserver;PerformanceObserverEntryList;toJSON()on performance entries.
The transport engine avoids excessive target connections and behaves closer to a modern browser stack while preserving the membrane egress path. It includes per-origin HTTP/1.1 pooling/reuse limits, HTTP/2 session reuse and multiplexing where negotiated, bounded global/per-origin concurrency, request queueing/backpressure, idle timeout, health/retry behavior, priority-aware scheduling where available, isolation-aware pool keys, and reuse/queue/failure metrics.
WebRTC and WebTransport remain out of scope and are classified separately as unsupported direct-network surfaces.
The browser asset organization matches the planned source split:
- Runtime entry:
web/runtime-prelude-entry.mjs - Page runtime source:
web/runtime-prelude.mjs,web/runtime/** - Worker runtime entry/source:
web/worker-prelude-entry.mjs,web/worker-prelude.js,web/runtime/workers/facades.mjs - Service Worker entry/source:
web/sw-entry.mjs,web/sw.js,web/sw/** - Shared core:
web/zp-core.js - HTTP/Rust rewriter bridge:
web/http-rewriter.js, generatedrust-rewriter.js
scripts/build.mjs writes runtime, worker runtime, Service Worker, Rust rewriter JS/WASM, zp-core.js, http-rewriter.js, wasm_exec.js, Go kernel.wasm, and native zeroproxy-server. --minify remains opt-in; fixed-name/no-hash delivery and ABI-sensitive public helper names are documented in test/fixtures/delivery-versioning-minification.json.
rewriter-rs/src/lib.rs exports the public WASM ABI:
rewrite_scriptrewrite_script_with_contextrewrite_cssrewrite_import_maprewrite_html_documentcreate_html_document_rewritermake_share_urlrewrite_script_urlrewrite_fetch_urlrewrite_srcsetresolve_target_url- classifiers for link rel, blocked elements, meta policy, attr policy, script type, and event handler attrs
rewriter-rs/src/js/swc_rewriter.rs uses SWC parsing, resolver marks, and codegen. It rewrites free globals, selected constructors, member/call/assignment/update/in/delete/typeof/optional-chain surfaces, static imports/exports, dynamic imports, and import.meta.url. Local shadowing is preserved through resolver marks.
rewriter-rs/src/html/document.rs uses lol_html and handles runtime prelude injection, script URL rewriting, inline script rewriting, event-handler rewriting, style rewriting, import-map rewriting, passive resource URLs, navigation attributes, srcset, srcdoc, base/meta policy, link policy, object/embed blocking, and backup attributes. It exposes both string and streaming document rewriting; streaming tests assert parity with the string path across chunk boundaries.
internal/htmltx/transform.go validates options, builds boot prelude HTML, and delegates to supplied Rust document rewriter hooks. TransformTo prefers DocumentStreamRewriter, streams chunks through WriteChunk, flushes returned bytes before EOF, then calls End. If the stream factory is unavailable and a string DocumentRewriter hook exists, it falls back to the compatibility string path.
cmd/wasm-kernel/main.go passes both DocumentStreamRewriter: rewriteHTMLDocumentStreamFromJS and DocumentRewriter: rewriteHTMLDocumentFromJS into htmltx.TransformTo. The streaming hook calls ZPRewriter.createHTMLDocumentRewriter.
The page runtime installs a large facade/membrane in web/runtime-prelude.mjs using modules under web/runtime/**.
Implemented areas include:
- central artifact masking in
web/runtime/abi/artifact-masking.mjs; - native capture in
web/runtime/abi/native-capture.mjs; - dynamic code facade in
web/runtime/dynamic-code/*; - DOM attribute policy and dynamic HTML/script/style insertion hooks;
- document, location, history, navigator, storage, event, performance, and fingerprinting facades;
- HTTP fetch, Request, XHR, EventSource, sendBeacon handling;
- WebSocket and WebSocketStream facades;
- Worker, SharedWorker, blob worker, data worker, and module worker hooks;
- frame accessors, child rewrite helpers, postMessage mapping, and sandbox containment;
- target-visible selector virtualization for rewritten URL-bearing attributes.
Additional helper ABI includes __zp_assign, __zp_update, __zp_optionalGet, __zp_optionalCall, __zp_nav_assign, __zp_nav_replace, __zp_runClassic, and __zp_runEvent.
web/sw.js classifies every request before target transport:
- internal assets;
- proxy document routes under
/zp/p/<route>; - runtime APIs under
/zp/api/*; - virtual subresources recovered from context;
- unknown requests.
Unknown navigation returns a POLICY_BLOCKED response. Unknown subresources return Response.error(). Native fetch is bound only for first-party asset and kernel loads.
Target document/subresource fetches call:
transportFetch -> self.__go_jshttp(new Request(target, init))
The Go WASM kernel exposes __go_jshttp, __zp_stream, __zp_kernel_init, and __zp_cookie_set from cmd/wasm-kernel/main.go.
The Go transport path then routes through:
zphttp.Engine -> Mux.OpenStream -> SOCKS5 DOMAINNAME CONNECT -> uTLS/HTTP or WebSocket upgrade
Important properties:
internal/zphttp/roundtrip.gorejects non-http(s) target schemes for HTTP.internal/wsproto/client.gorejects non-ws/wss schemes for WebSocket and upgrades overEngine.DialTarget.internal/socks5/client.gorequires DOMAINNAME targets and rejects IP literals.internal/zphttp/roundtrip.gosets target browser identity headers and strips internal/self-set headers.internal/zphttp.Engine.RoundTripuses browser-like per-origin/global active request scheduling with priority/FIFO queueing and cancellation cleanup.
Status: achieved for current repository gates.
Evidence:
web/sw.jsdefault fetch branch fails closed.test/js/membrane-invariants.test.jsverifies unknown request classification, unknown navigation blocking, unknown subresourceResponse.error(), and absence of rawfetch(event.request)fallback.web/zp-core.jsbuilds default-deny CSP without wildcardconnect-src.- Target egress path is implemented through
cmd/wasm-kernel/main.go,internal/zphttp/roundtrip.go,internal/wsproto/client.go,internal/socks5/client.go, andinternal/utlskernel/dial.go.
Status: achieved for static transformation policy.
Evidence:
- JS AST rewrite is in Rust/SWC.
- HTML document transform is in Rust/lol_html.
- CSS URL rewrite is in Rust.
- Import-map rewrite is in Rust.
- Static URL policy classifiers are exported from Rust.
internal/htmltxis an adapter into the Rust document transform.test/js/rewriter.test.jsverifies Rust ownership of script, HTML, CSS, import-map, and static URL/classification paths.
Runtime enforcement still contains policy for DOM mutations, inserted markup, network facades, frames, workers, and artifact masking. That is expected runtime membrane behavior rather than a remaining independent static parser policy.
Status: achieved for the adapter seam.
Evidence:
rewriter-rs/src/html/document.rsis backed bylol_htmland exposesStreamingDocumentRewriter.rewriter-rs/src/lib.rsexportscreate_html_document_rewriterto WASM.scripts/build.mjsexposesZPRewriter.createHTMLDocumentRewriterandZPRustRewriter.createHTMLDocumentRewriter.cmd/wasm-kernel/main.gopassesDocumentStreamRewriter: rewriteHTMLDocumentStreamFromJSintohtmltx.TransformTo.internal/htmltx/transform.gostreams input chunks throughWriteChunkand writes returned output before EOF.internal/htmltx/transform_test.goproves first output arrives before input EOF.- Rust tests prove streaming output matches string rewrite output across UTF-8 chunk boundaries.
Status: broad and repository-gated.
Evidence:
- Rust rewriter handles planned free globals and helper surfaces, including long-tail
deleteandtypeofhelpers. - Runtime implements fetch/XHR/EventSource/WebSocket/WebSocketStream/Worker/SharedWorker/sendBeacon/dynamic code.
- Module imports, dynamic imports, import maps, and module workers are covered.
- Frame and message boundaries have runtime modules and E2E coverage.
test/fixtures/rewrite-surface-long-tail.jsonclassifies document/domain, base URL, service worker, worklet, CSP/reporting, WebTransport/WebRTC, and storage/cache/IndexedDB long-tail surfaces.
Status: substantially implemented and tested.
Evidence:
- Location, history, document, worker, network, event, frame, storage, performance, and fingerprinting facades are present.
- Static rewritten code and dynamic code share runtime helper surfaces.
- Dynamic
Function,eval, and string timers route through rewritten/scoped runtime paths. - Tests verify descriptor assignability, dynamic eval path, function masking, and many runtime hooks.
Status: mostly achieved with explicit deltas.
Evidence:
- Static HTML treats iframe/frame
srcas navigation and rewrites to encrypted share routes. - Runtime hooks dynamic frame
srcmutations and frame insertion. - Service Worker handles
ZP_FRAME_ROUTE. - Frame accessors and postMessage mapping exist under
web/runtime/frames/*. - Static Rust HTML rewrites
srcdocthroughrewrite_document. - Runtime-set
srcdocroutes throughinjectSrcdoc/Rust document rewrite path and stores target-visible backup attributes. test/fixtures/frame-srcdoc-sandbox-milestone.jsontracks ordinary frame routing, static/dynamicsrcdoc, sandbox token deltas, and third-party widget/login/payment/challenge frame patterns.test/e2e/expected-deltas.jsonallowlists current long-tail frame/sandbox/unsupported-scheme deltas.
Status: bundled delivery achieved; default minification remains opt-in and documented.
Evidence:
- Runtime, worker runtime, and Service Worker are split by responsibility and bundled by Vite.
- Tests assert bundled classic assets and absence of visible multi-script runtime injection.
- Injection inventory snapshot exists.
test/fixtures/delivery-versioning-minification.jsondocuments package version source, fixed runtime asset names, classic-IIFE delivery, fixed-name/no-hash asset policy, opt-in--minify, and Rust rewriter version string.
Status: implemented for current repository oracle scope.
Evidence:
createArtifactMaskingprovides central native-lookingFunction.prototype.toStringmasking.- Runtime hides
ZP,ZPRewriter,ZPRustRewriter,ZPHTTPRewriter,__ZP_*,__zp_*, and ZeroProxy-marked symbols from enumeration and descriptor probes. - DOM serialization, selector, and attribute masking are implemented and documented in
docs/masking-surfaces.md. - Worker runtime has matching masking.
- E2E differential probes include descriptors, ownKeys, toString, globals, frame wrappers, workers, and dynamic code.
scripts/compat-corpus.mjsrecords bounded root-surface oracle data and classifies deltas in corpus reports.
Status: achieved for current gates.
Evidence:
- Tests forbid committed HTML CSP meta.
- Response helpers set ZeroProxy CSP.
- Upstream policy headers are stripped through response policy handling.
- Static Rust HTML drops CSP/report-only meta.
- Runtime suppresses dynamic meta policy insertion.
- Unsafe eval is gated by the dynamic-compile branch.
- Script rewrite failures produce blocking code instead of executing original source.
Status: achieved for current repository/local/corpus scope.
Evidence:
test/e2e/proxy.test.jsincludes native-vs-ZeroProxy differential behavior.test/e2e/expected-deltas.jsonrecords accepted local differences and long-tail frame/worker/wrapper limitations.- The E2E fixture probes policy headers, descriptors, function source strings, ownKeys/global artifacts, frame document/srcdoc observations, workers/shared workers, fetch/XHR/EventSource/WebSocket, request headers, and fingerprinting surfaces.
test/e2e/representative-sites.release.jsonrecords the live corpus release gate with 0 triage sites and 9 classified expected-delta sites.
Status: achieved for current measurable repository paths; future work can improve precision and shrink synthetic gaps.
Evidence:
- Rust rewriter initialization, JS rewrite latency, dynamic
rewriteFunctionBody, runtime bundle size, and compile budgets are represented in tests/manifests. internal/zphttp.TransportTimingdefines redacted per-request timing with body duration and retry fields.internal/zphttp.Engine.RoundTrippopulates timing from scheduler, connection, SOCKS/TLS, response-header/body, and retry observations where available.internal/swhttp.ResponseToJSmoves timing metadata into non-enumerableResponse.__zpTransportTimingand removes the internal handoff header before browserResponseconstruction.web/sw.jsstores bounded redacted timing records and serves them throughZP_TRANSPORT_TIMINGS.web/runtime/network/http.mjsrecords hidden Go transport timing metadata from runtime fetch responses.web/runtime/facades/fingerprinting.mjsexposes Go-backed resource timing entries, wrapsPerformanceObserver/takeRecords, and counts synthetic gaps.scripts/compat-corpus.mjsjoins Service Worker timing summaries into representative-site reports.
Status: achieved as a checked-in runner and current release artifact.
Evidence:
test/e2e/representative-sites.jsonchecks in the representative seed corpus.test/fixtures/representative-sites/embedded-google-maps.htmlis the embedded Maps host fixture.scripts/compat-corpus.mjsruns native, ZeroProxy, or comparison mode and emits redacted triage/release records.test/js/compat-corpus.test.jsverifies seed completeness, redaction, triage classification, release gate schema, root-surface, and timing/failure telemetry behavior.test/e2e/representative-sites.release.jsonrecords 14 compared sites, 5 direct pass sites, 9 expected-delta sites, and 0 triage sites.
Status: implemented for bounded/priority-aware scheduling and reuse telemetry; safe coalescing remains an intentional future extension.
Evidence:
internal/zphttp.Enginehas HTTP/1.1 idle connection reuse and HTTP/2 connection reuse primitives.RoundTripacquires a browser-style request slot before target transport work and releases it when the response body reaches EOF or is closed.- Scheduler limits are partitioned by target authority plus tab/isolation key.
- Over-limit requests queue by Fetch priority (
X-Zp-Fetch-Priority) and FIFO order within the same priority. - Canceled contexts are removed from the queue without leaking scheduler state.
- Tests cover per-origin queueing/backpressure, priority ordering, canceled queued requests, retry telemetry, and scheme-separated HTTP/2 keys.
Status: achieved for current corpus/rewrite/runtime/SW evidence.
Evidence:
scripts/compat-corpus.mjsemitszp.failure.telemetry.v1records with first failing surface, owner module, severity, console/pageerror deltas, request/response delta keys, missing selectors, iframe deltas, timing buckets, Go timing availability, and native/ZeroProxy OK state.- Records declare redaction properties and avoid raw URLs, raw console text, raw IP addresses, raw source/body/cookie/token data.
web/http-rewriter.jsretries safe parse-recovery variants before the final block fallback.- Recovery variants include leading BOM stripping, classic-script HTML-comment normalization, and classic/module classification retry where safe.
- Final fallback remains blocked.
Status: checked in and pinned to implementation/oracle metadata.
Evidence:
test/fixtures/dynamic-dom-insertion-matrix.jsonandtest/js/dynamic-dom-insertion-matrix.test.js.test/fixtures/dom-mutation-inventory.jsonandtest/js/dom-mutation-inventory.test.js.test/fixtures/cookie-storage-samesite-matrix.jsonandtest/js/cookie-storage-samesite-matrix.test.js.test/fixtures/fetch-xhr-compat-matrix.jsonandtest/js/fetch-xhr-compat-matrix.test.js.test/fixtures/framework-compatibility/manifest.jsonandtest/js/framework-compatibility-fixtures.test.js.test/fixtures/event-listener-compat-matrix.jsonandtest/js/event-listener-compat-matrix.test.js.test/fixtures/observer-input-event-parity-matrix.jsonandtest/js/observer-input-event-parity-matrix.test.js.test/fixtures/frame-srcdoc-sandbox-milestone.jsonandtest/js/frame-srcdoc-sandbox-milestone.test.js.
| Phase | Status | Difference from plan |
|---|---|---|
| 1. Freeze baseline tests, add redacted rewrite-failure telemetry, classify fail-close paths | Achieved | Fail-close tests, telemetry records, and corpus release counters exist. |
| 2. Define/enforce rewrite surface model and runtime ABI | Achieved | ABI helpers including delete/typeof are installed and long-tail surfaces are classified. |
| 3. Split runtime source files | Done | Runtime and SW source are split and bundled. |
| 4. Single-injection bundled delivery with ABI-safe mangling | Mostly done | Bundled delivery exists; default minification is opt-in and documented rather than enabled by default. |
| 5. Rust JS AST transform/codegen | Done | SWC implementation exists and is tested. |
| 6. Move HTML policy into Rust/lol_html streaming rewriting | Achieved for adapter seam | Policy moved; streaming bridge and first-byte tests exist. |
| 7. Move CSS/import-map/inline/external script policy to Rust | Achieved for static policy | Dynamic mutation policy remains runtime-owned by design. |
| 8. Collapse iframe/frame handling to document routing plus boundary wiring | Mostly achieved | Frame routes and boundary wiring exist; unsupported schemes/sandbox cases are explicit expected deltas. |
| 9. Expand dynamic code and worker support | Mostly achieved | Function/eval/timers/workers/module workers/blob/data handling exists; unsupported cases fail closed/classified. |
| 10. Native-vs-ZeroProxy oracle and expected deltas | Achieved for current scope | Local fixture and live corpus expected deltas are checked in. |
| 11. Reduce injection inventory and remove HTML/meta CSP reliance | Achieved | Snapshot and CSP tests exist. |
| 12. Performance budgets and regression gates | Achieved for current measurable surfaces | First-byte/body/retry/timing paths are represented; future work can lower synthetic-gap counts. |
| 13. Representative-site corpus and browser-comparison pipeline | Achieved | Runner, seed corpus, embedded Maps fixture, release artifact, and redacted triage/release records exist. |
| 14. Browser-equivalent pooled/reuse network engine | Partially achieved | Bounded scheduling, priority queueing, reuse timing, and isolation-aware keys exist; safe coalescing remains future work. |
| 15. Redacted failure telemetry and safe parse-failure recovery | Achieved for current scope | Corpus telemetry, rewrite recovery, and fail-closed fallback are wired. |
| 16. Dynamic DOM insertion parity | Matrix/oracle metadata achieved | Per-row behavior fixtures can continue to expand, but current inventory is checked in and pinned. |
| 17. Cookie/storage/SameSite diagnostics and fetch/XHR matrices | Matrix/oracle metadata achieved | Dedicated redacted matrices exist and are wired to source. |
| 18. Framework compatibility fixtures | Achieved as checked-in fixtures | Fixtures exist; external-site corpus remains the broader signal. |
| 19. Dedicated frame/srcdoc/sandbox milestone | Achieved as milestone matrix plus implementation | Static/runtime srcdoc, sandbox, and unsupported schemes are tracked. |
| 20. Real performance telemetry propagation | Achieved for repository paths | Go timing reaches hidden Response metadata, Service Worker buffer, runtime Performance, and corpus reports. |
| 21. Page-visible Performance API real data | Achieved for Go-backed resource entries | Runtime fetch entries use real Go phases; synthetic gaps are counted. |
| 22. Complete DOM manipulation hook inventory | Achieved | Classified inventory exists. |
| 23. JS-root visible surface oracle | Achieved for bounded safe graph scope | Corpus records/classifies bounded root-surface deltas. |
| 24. Target-visible selector virtualization | Achieved for planned current attrs | Includes srcdoc and xlink:href. |
| 25. Event-listener compatibility matrix and internal-listener invisibility oracle | Matrix/oracle metadata achieved | Dedicated matrix exists; message wrapping and internal-listener invisibility are represented. |
| 26. Observer and input-event parity matrices | Matrix/oracle metadata achieved | Dedicated matrix exists with redaction constraints. |
| Completion condition | Current status | Evidence |
|---|---|---|
| 0 corpus-defined script rewrite-induced failures | Achieved. Full live release artifact records 0 unexpected rewrite-induced script failures after expected-delta classification. | test/e2e/representative-sites.release.json, scripts/compat-corpus.mjs |
| 0 generated JavaScript syntax errors | Achieved. Full live release artifact records 0 unexpected generated syntax errors after expected-delta classification. | test/e2e/representative-sites.release.json, test/js/rewriter.test.js, rewriter-rs/src/* tests |
| 0 unexpected script fail-close fallbacks | Achieved. Full live release artifact records 0 unexpected fail-close fallbacks. | test/e2e/representative-sites.release.json, test/js/rewriter.test.js, test/js/compat-corpus.test.js |
| Native-vs-ZeroProxy differences eliminated or listed | Achieved for current scope. Local E2E fixture differences are listed; live corpus has 9 classified expected deltas and 0 triage sites. | test/e2e/proxy.test.js, test/e2e/expected-deltas.json, test/e2e/representative-sites.release.json |
No independent rewrite policy in internal/htmltx |
Achieved. Go validates options, prepares boot config, and delegates to Rust hooks. | internal/htmltx/transform.go, test/js/static-policy.test.js |
| Rust/lol_html HTML transform without full-document Go policy | Achieved. Rust owns HTML policy and exposes string + streaming rewriters. | rewriter-rs/src/html/document.rs, rewriter-rs/src/lib.rs |
| Streaming first-byte/partial-flush HTML bridge | Achieved for adapter seam. | internal/htmltx/transform.go, internal/htmltx/transform_test.go, rewriter-rs/src/html/document.rs |
| Ordinary iframe/frame loads share top-level transform/runtime path | Mostly achieved. Unsupported schemes are blocked/classified. | web/runtime-prelude.mjs, test/e2e/proxy.test.js, test/e2e/expected-deltas.json |
| Frame-specific behavior limited to boundary wiring and explicit deltas | Achieved for current local scope. | web/runtime/frames/*.mjs, test/fixtures/frame-srcdoc-sandbox-milestone.json, test/e2e/expected-deltas.json |
| Injection inventory minimized and snapshot tested | Achieved. | internal/htmltx/testdata/injection_inventory.json, test/js/static-policy.test.js |
| Representative-site corpus with browser comparison | Achieved. Full live release gate passes. | test/e2e/representative-sites.json, scripts/compat-corpus.mjs, test/e2e/representative-sites.release.json |
| Naver desktop/mobile full-content and ad-iframe checks | Pass or classified expected delta in live artifact. | test/e2e/representative-sites.release.json |
| Google Maps and embedded Maps checks | Pass or classified expected delta in live artifact. | test/e2e/representative-sites.release.json, test/fixtures/representative-sites/embedded-google-maps.html |
| ipleak surface rendering and redacted IP/DNS classification | Pass or classified expected delta in live artifact. | test/e2e/representative-sites.release.json |
| Real measured timing records from browser/runtime/SW/Go | Achieved for repository paths. | internal/zphttp/roundtrip.go, internal/swhttp/bridge_js.go, web/sw.js, web/runtime/facades/fingerprinting.mjs, scripts/compat-corpus.mjs |
| Browser-equivalent pooled/reuse network engine | Partially achieved. Bounded scheduling, priority queueing, partitioned keys, retry/reuse timing exist; safe coalescing remains future work. | internal/zphttp/roundtrip.go, internal/zphttp/roundtrip_test.go |
| Redacted failure telemetry | Achieved for current corpus/rewrite/runtime/SW scope. | scripts/compat-corpus.mjs, web/http-rewriter.js, web/sw.js, test/js/compat-corpus.test.js |
| Safe parse-failure recovery paths | Achieved for BOM/comment and safe classic/module recovery variants, final fail-closed fallback. | web/http-rewriter.js, test/js/rewriter.test.js |
| Dynamic DOM insertion parity matrix | Achieved as checked-in prioritized matrix/oracle metadata. | test/fixtures/dynamic-dom-insertion-matrix.json, test/js/dynamic-dom-insertion-matrix.test.js |
| Complete DOM manipulation hook inventory | Achieved as checked-in classified inventory. | test/fixtures/dom-mutation-inventory.json, test/js/dom-mutation-inventory.test.js |
| Target-visible selector virtualization | Achieved for href, src, srcset, action, formaction, poster, srcdoc, and xlink:href. |
web/runtime-prelude.mjs, test/js/membrane-invariants.test.js |
| Cookie/storage/SameSite diagnostics | Achieved as checked-in redacted matrix/oracle metadata. | test/fixtures/cookie-storage-samesite-matrix.json, test/js/cookie-storage-samesite-matrix.test.js |
| Fetch/XHR compatibility matrix | Achieved as checked-in matrix/oracle metadata. | test/fixtures/fetch-xhr-compat-matrix.json, test/js/fetch-xhr-compat-matrix.test.js |
| Framework compatibility fixtures | Achieved as checked-in fixture entries. | test/fixtures/framework-compatibility/manifest.json, test/js/framework-compatibility-fixtures.test.js |
| Frame/srcdoc/sandbox dedicated milestone | Achieved as dedicated milestone matrix with implementation evidence. | test/fixtures/frame-srcdoc-sandbox-milestone.json, test/js/frame-srcdoc-sandbox-milestone.test.js |
| Event-listener matrix and internal-listener invisibility oracle | Achieved as checked-in matrix/oracle metadata. | test/fixtures/event-listener-compat-matrix.json, test/js/event-listener-compat-matrix.test.js |
| Observer/input parity matrix and redacted telemetry | Achieved as checked-in matrix/oracle metadata. | test/fixtures/observer-input-event-parity-matrix.json, test/js/observer-input-event-parity-matrix.test.js |
| Performance API exposes real measured target timing data | Achieved for Go-backed resource entries with target-visible names; synthetic gaps are counted. | web/runtime/facades/fingerprinting.mjs, web/runtime/network/http.mjs, test/js/compat-pipeline.test.js |
| JS-root visible objects/properties/strings comparison | Achieved for bounded safe graph records and classified corpus deltas. | scripts/compat-corpus.mjs, test/js/compat-corpus.test.js |
| CSP/security invariants green | Achieved and tested. | web/sw.js, web/zp-core.js, test/js/membrane-invariants.test.js |
| Full local verification green | Achieved in the recorded work-session evidence. | See verification section. |
test/js/membrane-invariants.test.js: no direct native fetch fallback, fail-closed unknown requests, masking hooks, CSP invariants, selector virtualization hooks.test/js/static-policy.test.js: source-level policy invariants, thin Go wrapper over Rust HTML policy,lol_htmlbacking, CSP/meta policy constraints, unsafe-eval constraints.test/js/rewriter.test.js: Rust WASM public API, JS rewrite latency budgets, HTML/CSS/import-map/static URL policy, module graph URL rewriting, fail-close classification, parse-recovery paths.test/js/compat-pipeline.test.js: runtime network shims, streaming response/upload bridge, WebSocket SW/kernel isolation, real transport timing metadata wiring.test/js/compat-corpus.test.js: seed corpus completeness, release-gate schema, redaction, triage classification, failure telemetry, root-surface and timing summaries.test/e2e/proxy.test.js: browser integration, runtime network APIs, workers/module workers, frames/postMessage/frame relation, native-vs-ZeroProxy differential oracle, performance artifact masking.test/js/*matrix.test.jsandtest/js/*fixtures.test.js: matrix and fixture coverage for dynamic DOM, DOM mutation, cookie/storage/SameSite, fetch/XHR, framework fixtures, event listeners, observer/input parity, frame/srcdoc/sandbox, performance gates, delivery versioning, and rewrite long-tail surfaces.- Go tests under
internal/*andcmd/*: transport, scheduling, timing, headers, cookies, share URLs, bridge, and wasm-kernel behavior. - Rust tests under
rewriter-rs/src/*: parser, rewriter, CSS, import-map, HTML/lol_html streaming/string parity, and share URL behavior.
Observed in the prior status-changing work session and preserved in this document:
npm run test:jspassed: 152 tests.npm run test:e2epassed: 1 browser integration test.go test ./...passed.npm run test:wasmpassed forcmd/wasm-kernelandinternal/swhttp.cargo test --manifest-path rewriter-rs/Cargo.tomlpassed: 48 tests.node scripts/compat-corpus.mjs --mode both --sites wikipedia --timeout-ms 15000 --release-out /tmp/zeroproxy-release-one.json --fail-on-release-gatepassed for the focused live Wikipedia corpus slice.node scripts/compat-corpus.mjs --mode both --release-out test/e2e/representative-sites.release.json --fail-on-release-gatepassed for the full live representative corpus: 14 compared, 5 direct pass, 9 expected-delta, 0 triage, 0 unexpected script rewrite-induced failures, 0 unexpected generated syntax errors, 0 unexpected fail-close fallbacks.npm run lintpassed (lint:go,lint:rust,lint:js) with existing Biome warning-level findings.
Code/document evidence rechecked for this update:
internal/htmltx/transform.gohas streamingDocumentStreamRewritersupport and string fallback.cmd/wasm-kernel/main.gowiresrewriteHTMLDocumentStreamFromJSandrewriteHTMLDocumentFromJS.rewriter-rs/src/lib.rsexportscreate_html_document_rewriter.rewriter-rs/src/html/document.rsrewritessrcdocthroughrewrite_documentand contains streaming parity tests.web/runtime-prelude.mjsinstalls__zp_delete,__zp_typeof, runtimesrcdochandling, and selector virtualization forsrcdoc/xlink:href.internal/zphttp/roundtrip.go,internal/swhttp/bridge_js.go,web/runtime/network/http.mjs,web/runtime/facades/fingerprinting.mjs, andscripts/compat-corpus.mjscarry Go-to-runtime timing propagation, body/retry fields, PerformanceObserver wrapping, and corpus timing summaries.test/e2e/representative-sites.release.jsonrecords the current passing release-gate metrics.
The requested status-plan work is complete in repository terms. Future work should focus on shrinking explicit compatibility deltas and improving operational confidence rather than inventing new status scaffolding:
- Reduce the 9 live corpus
expectedDeltaSitesone site/surface at a time, keeping pass-or-classified release gating. - Add safe connection coalescing only where certificate, origin, privacy partition, and isolation constraints permit it.
- Continue expanding row-level native-vs-ZeroProxy fixtures behind the checked-in matrices where they give better behavior evidence than source needles.
- Lower synthetic Performance timing gaps and improve static/document resource timing merge precision.
- Keep expected-delta entries bounded, redacted, and evidence-backed as representative-site behavior changes.
No unclassified release blocker is recorded by the current repository artifacts. The active maintenance risk is the explicit allowlist burden: future changes must not silently grow expected deltas, leak sensitive telemetry, or weaken the membrane transport path. New deltas found by corpus runs should be classified with evidence or fixed at the source.