{"_id":"@anon-rpc/browser-harness","_rev":"4-72f7fc59d46cadba48d369e1a47c6a50","name":"@anon-rpc/browser-harness","dist-tags":{"latest":"0.3.2"},"versions":{"0.1.0":{"name":"@anon-rpc/browser-harness","version":"0.1.0","keywords":["anon-rpc","ethereum","privacy","rpc","kps","sandbox","wallet"],"license":"MIT","_id":"@anon-rpc/browser-harness@0.1.0","maintainers":[{"name":"voltrevo","email":"voltrevo@gmail.com"}],"homepage":"https://github.com/privacy-ethereum/anon-rpc","bugs":{"url":"https://github.com/privacy-ethereum/anon-rpc/issues"},"dist":{"shasum":"e3f3d9de876d2f66e3302cdc1c88392ca911c9bf","tarball":"https://registry.npmjs.org/@anon-rpc/browser-harness/-/browser-harness-0.1.0.tgz","fileCount":41,"integrity":"sha512-x+8Pac/q7nKRzcApl/1wUTLsisB8I4AlclKoD4H2FSly8oeu+TQNiWK5m97qyFL0edaSHspexLfdaIjTMVGDpA==","signatures":[{"sig":"MEYCIQDXAki4PsJcIt5xryNZ51/ZeMsiYEZyhowwwvKGNkQIBQIhAJCPrqr6ws+Y9IimfnzLnor8Kmfsf/qJkjsWRMuE4wDP","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":166077},"main":"./dist/host.js","type":"module","types":"./dist/types/host/index.d.ts","exports":{".":{"types":"./dist/types/host/index.d.ts","default":"./dist/host.js"},"./package.json":"./package.json"},"gitHead":"3f1ee1f95736b630d7a2701ba1325e8b5a8e508b","scripts":{"test":"node test/run.mjs","build":"node build.mjs && tsc -p tsconfig.build.json","typecheck":"tsc --noEmit && tsc -p test --noEmit","prepublishOnly":"npm run typecheck && npm test && npm run build"},"_npmUser":{"name":"voltrevo","email":"voltrevo@gmail.com"},"repository":{"url":"git+https://github.com/privacy-ethereum/anon-rpc.git","type":"git","directory":"impl/browser-harness"},"_npmVersion":"10.9.3","description":"anon-rpc browser harness: loads a hash-pinned anon-client worker under null-origin iframe isolation and exposes an anonymized fetch (SPEC §3.1 conformance target).","directories":{},"sideEffects":false,"_nodeVersion":"22.20.0","dependencies":{"@noble/hashes":"^1.5.0","@kpstreams/webrtc-client":"^0.1.0"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.24.0","typescript":"^5.6.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/browser-harness_0.1.0_1783315997904_0.7811570274182937","host":"s3://npm-registry-packages-npm-production"}},"0.2.1":{"name":"@anon-rpc/browser-harness","version":"0.2.1","keywords":["anon-rpc","ethereum","privacy","rpc","kps","sandbox","wallet"],"license":"MIT","_id":"@anon-rpc/browser-harness@0.2.1","maintainers":[{"name":"voltrevo","email":"voltrevo@gmail.com"}],"homepage":"https://github.com/privacy-ethereum/anon-rpc","bugs":{"url":"https://github.com/privacy-ethereum/anon-rpc/issues"},"dist":{"shasum":"14190b93fd0fbc172f5d5022f42dcdfc37cfe5f1","tarball":"https://registry.npmjs.org/@anon-rpc/browser-harness/-/browser-harness-0.2.1.tgz","fileCount":44,"integrity":"sha512-1DnFQCqtp4GxhK9cWFJ9c/1hXEjfIvydt5fjncDYaNmzHW6WBTzgv1osWtLXVrdykRqMKjUSeQ5I+4Gxh+fK5Q==","signatures":[{"sig":"MEQCIArMRxnVfyPs8RMye3G4ebBh5mkIHqwI+d+5NK8IIPgyAiBWal+hU3AYZE2ViKizs8Lwg2Sb6XL+OkiaN9smu/Dy8Q==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":204525},"main":"./dist/host.js","type":"module","types":"./dist/types/host/index.d.ts","exports":{".":{"types":"./dist/types/host/index.d.ts","default":"./dist/host.js"},"./package.json":"./package.json"},"gitHead":"5824b3416b90ee1f9f0e0c2c0bd3119d5c489f07","scripts":{"test":"node check-spec-version.mjs && node test/run.mjs","build":"node build.mjs && tsc -p tsconfig.build.json","typecheck":"tsc --noEmit && tsc -p test --noEmit","prepublishOnly":"npm run typecheck && npm test && npm run build"},"_npmUser":{"name":"voltrevo","email":"voltrevo@gmail.com"},"repository":{"url":"git+https://github.com/privacy-ethereum/anon-rpc.git","type":"git","directory":"impl/browser-harness"},"_npmVersion":"10.9.3","description":"anon-rpc browser harness: loads a hash-pinned anon-client worker under null-origin iframe isolation and exposes an anonymized fetch (SPEC §3.1 conformance target).","directories":{},"sideEffects":false,"_nodeVersion":"22.20.0","dependencies":{"@noble/hashes":"^1.5.0","@kpstreams/webrtc-client":"^0.2.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.28.0","typescript":"^5.6.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/browser-harness_0.2.1_1785119135396_0.6846357191752765","host":"s3://npm-registry-packages-npm-production"}},"0.3.0":{"name":"@anon-rpc/browser-harness","version":"0.3.0","keywords":["anon-rpc","ethereum","privacy","rpc","kps","sandbox","wallet"],"license":"MIT","_id":"@anon-rpc/browser-harness@0.3.0","maintainers":[{"name":"voltrevo","email":"voltrevo@gmail.com"}],"homepage":"https://github.com/privacy-ethereum/anon-rpc","bugs":{"url":"https://github.com/privacy-ethereum/anon-rpc/issues"},"dist":{"shasum":"b57b5c79df0f0f89d9131316bc13e20d7d59ecdc","tarball":"https://registry.npmjs.org/@anon-rpc/browser-harness/-/browser-harness-0.3.0.tgz","fileCount":44,"integrity":"sha512-e/3fuRaVkczb3B2FGURcFnQv8B2o8ZrgJ7ot4AOINBqKWk3PiATDrPkq9j+QIqNEWBW13gvH05JwrwGovI2nxg==","signatures":[{"sig":"MEUCIQD8MyGxx0hDZCKafvga0LOjIlLPZ39TtJ8ylAFtYJyq/wIgfCm8QGYemnFtrpMhFgaTrG6gnQRLMeiGJkdkFXezQdA=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":207040},"main":"./dist/host.js","type":"module","types":"./dist/types/host/index.d.ts","exports":{".":{"types":"./dist/types/host/index.d.ts","default":"./dist/host.js"},"./package.json":"./package.json"},"gitHead":"85679409fcc1b0f49dd035492f5741ef0a7d3b40","scripts":{"test":"node check-spec-version.mjs && node test/run.mjs","build":"node build.mjs && tsc -p tsconfig.build.json","typecheck":"tsc --noEmit && tsc -p test --noEmit","prepublishOnly":"npm run typecheck && npm test && npm run build"},"_npmUser":{"name":"voltrevo","email":"voltrevo@gmail.com"},"repository":{"url":"git+https://github.com/privacy-ethereum/anon-rpc.git","type":"git","directory":"impl/browser-harness"},"_npmVersion":"10.9.3","description":"anon-rpc browser harness: loads a hash-pinned anon-client worker under null-origin iframe isolation and exposes an anonymized fetch (SPEC §3.1 conformance target).","directories":{},"sideEffects":false,"_nodeVersion":"22.20.0","dependencies":{"@noble/hashes":"^1.5.0","@kpstreams/webrtc-client":"^0.2.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.28.0","typescript":"^5.6.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"tmp":"tmp/browser-harness_0.3.0_1785123624185_0.18932966582709487","host":"s3://npm-registry-packages-npm-production"}},"0.3.2":{"_id":"@anon-rpc/browser-harness@0.3.2","bugs":{"url":"https://github.com/ethereum/anon-rpc/issues"},"dist":{"shasum":"2d29b4440ef4fb8fb15d2afd40f3dcf537562dcf","tarball":"https://registry.npmjs.org/@anon-rpc/browser-harness/-/browser-harness-0.3.2.tgz","fileCount":48,"integrity":"sha512-W7Z4bRoHvEFVmSmdpyJM3Z+tV0VdS74bc/lMgTYAcikkI2mt74PAo/PR49xIHRfZA8HqNbW3l6O2O40wQhSV/Q==","signatures":[{"sig":"MEQCIBUIB03Txe+ErRW5XQWSONMPHDUO8sCrWkc6K7AzPKuoAiA5R26xXaN3BuV/BaFc4gcxuuGMSLkHEJPcGbSQ+SW1FA==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIFUv5yWPz4EDxO1gVuh50fiLfcqgkNqVyWPPUw9cEO8eAiAZtnb8TZYb1cMqhR6ledoDOSNLU3IPfWy/Tfn12ME/mQ=="}],"unpackedSize":231979},"main":"./dist/host.js","name":"@anon-rpc/browser-harness","type":"module","types":"./dist/types/host/index.d.ts","exports":{".":{"types":"./dist/types/host/index.d.ts","default":"./dist/host.js"},"./package.json":"./package.json","./iframe-boot.js":"./dist/iframe-boot.js"},"gitHead":"f2c8a758caaa555974a3c79769e8cb4a40ac1ae1","license":"MIT","scripts":{"test":"node check-spec-version.mjs && node test/run.mjs","build":"node build.mjs && tsc -p tsconfig.build.json","typecheck":"tsc --noEmit && tsc -p test --noEmit","prepublishOnly":"npm run typecheck && npm test && npm run build"},"version":"0.3.2","_npmUser":{"name":"voltrevo","email":"voltrevo@gmail.com"},"homepage":"https://github.com/ethereum/anon-rpc","keywords":["anon-rpc","ethereum","privacy","rpc","kps","sandbox","wallet"],"repository":{"url":"git+https://github.com/ethereum/anon-rpc.git","type":"git","directory":"impl/browser-harness"},"_npmVersion":"10.9.3","description":"anon-rpc browser harness: loads a hash-pinned anon-client worker under null-origin iframe isolation and exposes an anonymized fetch (SPEC §3.1 conformance target).","directories":{},"maintainers":[{"name":"voltrevo","email":"voltrevo@gmail.com"}],"sideEffects":false,"_nodeVersion":"22.20.0","dependencies":{"@noble/hashes":"^1.5.0","@kpstreams/webrtc-client":"^0.2.1"},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"esbuild":"^0.28.0","typescript":"^5.6.0","@types/node":"^22.0.0"},"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/browser-harness_0.3.2_1790582766717_0.6530097513224817"}}},"time":{"created":"2026-07-06T05:33:17.766Z","modified":"2026-09-28T08:06:07.095Z","0.1.0":"2026-07-06T05:33:18.030Z","0.2.1":"2026-07-27T02:25:35.792Z","0.3.0":"2026-07-27T03:40:24.327Z","0.3.2":"2026-09-28T08:06:06.803Z"},"bugs":{"url":"https://github.com/ethereum/anon-rpc/issues"},"license":"MIT","homepage":"https://github.com/ethereum/anon-rpc","keywords":["anon-rpc","ethereum","privacy","rpc","kps","sandbox","wallet"],"repository":{"url":"git+https://github.com/ethereum/anon-rpc.git","type":"git","directory":"impl/browser-harness"},"description":"anon-rpc browser harness: loads a hash-pinned anon-client worker under null-origin iframe isolation and exposes an anonymized fetch (SPEC §3.1 conformance target).","maintainers":[{"name":"voltrevo","email":"voltrevo@gmail.com"}],"readme":"# @anon-rpc/browser-harness\n\nA browser harness for [anon-rpc](https://github.com/ethereum/anon-rpc)\n— a standard that lets a wallet or application make **anonymized RPC requests**\nby running hash-pinned anon-client code inside a sandboxed worker.\n\nImplements the [anon-rpc specification](https://ethereum.github.io/anon-rpc/spec/)\nversion **0.3.2**. (The package version is kept `>=` the implemented spec\nversion; a package release without a spec change bumps past it.)\n\nThe harness:\n\n- resolves the anon-client bundle from an on-chain specifier contract — over\n  `https:` or over KPS itself via `kps:` resolver entries (SPEC §4.1–4.2) —\n  and verifies `keccak256(bytes) == workerHash()` before executing a single\n  byte (trust the hash, not the URL);\n- runs it in a **Web Worker inside a null-origin sandboxed iframe**, with no\n  ambient access to your DOM, storage, cookies, or keys;\n- grants it a small, explicit capability API — inbound fetch calls, a\n  [KPS](https://ethereum.github.io/kps/) key-pinned transport\n  (bridged so the worker never touches WebRTC), persistent storage\n  (IndexedDB on the host origin, namespaced per specifier), and logging;\n- hands you back one thing: an anonymized `fetch`.\n\n## Install\n\n```sh\nnpm install @anon-rpc/browser-harness\n```\n\n## Use\n\n```ts\nimport { AnonRpcWorker } from \"@anon-rpc/browser-harness\";\n\nconst worker = new AnonRpcWorker({\n  // The IWorkerSpecifier contract identifying the anon-client by hash.\n  address: \"0x…\",\n  // Optional: structured-cloneable value delivered to the worker as\n  // `anonRpcWorker.config`. Opaque to the harness; schema is the worker's.\n  config: { network: \"mainnet\" },\n  // Bootstrap provider used only to read the specifier (breaks the circular\n  // \"need the chain to reach the chain\" dependency).\n  preExisting: { rpcProvider },\n});\n\n// Optional: Wait for the worker to report that it is ready. You can start\n// making fetch calls before this - they'll just get buffered.\n// await worker.ready;\n\n// A standard fetch, routed through the sandboxed anon-client.\n// It is this-bound, so passing it around as a free function is fine.\nconst res = await worker.fetch(\"https://rpc.example/\", {\n  method: \"POST\",\n  body: JSON.stringify({ jsonrpc: \"2.0\", id: 1, method: \"eth_blockNumber\" }),\n});\n\nworker.close(); // tears down the iframe and worker\n```\n\n### Collecting the worker's logs\n\nA worker's §13 `log` calls go to the console unless you collect them. Pull them\nwith `acceptLog()` (SPEC §5, §13.1) and they stop being echoed there:\n\n```ts\nfor (;;) {\n  // Resolves with the next entry; waits when there is none. Rejects once the\n  // worker has failed or closed AND its retained entries are drained — so the\n  // lines explaining a failure arrive before the rejection does.\n  const { level, args } = await worker.acceptLog();\n  render(level, args);\n}\n```\n\nEntries are retained from the moment the worker starts, so a line logged\nduring boot is still there when you first ask. The buffer is bounded (1000\nentries) and drops the oldest beyond that; §13.1 makes this the one place a\nharness may lose a log call it has already accepted.\n\n### Strict Content Security Policies\n\nBy default the harness builds its null-origin iframe with `srcdoc` and an inline\nbootstrap script, which needs nothing from you. If your page's CSP omits\n`'unsafe-inline'` for `script-src`, that bootstrap will not run — a `srcdoc`\ndocument inherits the embedder's policy, and a policy can only be tightened\nfrom within a document, never relaxed. The symptom is a `ready` that never\nsettles, plus a CSP violation in the console.\n\nServe the harness's bootstrap page yourself and point `iframeUrl` (SPEC §5) at\nit:\n\n```ts\nnew AnonRpcWorker({ address, preExisting, iframeUrl: \"/anon-rpc-iframe.html\" });\n```\n\nThe page needs only the harness's own bootstrap script, which ships in this\npackage as `dist/iframe-boot.js`:\n\n```html\n<!doctype html><meta charset=\"utf-8\"><script src=\"/anon-rpc-iframe.js\"></script>\n```\n\nThe harness still applies `sandbox=\"allow-scripts\"` itself, so the document is\nplaced at an opaque origin whichever route it came from, and §6 requires the URL\nto be same-origin with your page — a cross-origin bootstrap would hand the\nisolation boundary to a third party, so the harness rejects one.\n\nFor MV3 browser extensions this is not optional and the page must additionally\nbe declared in the manifest's `sandbox.pages`;\n[`@anon-rpc/browser-extension-harness`](../browser-extension-harness) packages\nall of that.\n\n## Notes\n\n- Browser-only: the isolation model is a null-origin iframe and the KPS\n  transport runs over WebRTC. A native/Node harness would be a separate\n  package.\n- The worker-facing capability API (`anonRpcWorker`) and all conformance\n  requirements are defined in the\n  [specification](https://github.com/ethereum/anon-rpc/blob/main/SPEC.md).\n  A template anon-client to copy lives in\n  [`impl/passthrough-worker`](https://github.com/ethereum/anon-rpc/tree/main/impl/passthrough-worker).\n- Status: prototype-grade reference implementation of a draft spec; interfaces\n  track the spec and may change.\n\n## License\n\nMIT © Ethereum Foundation\n","readmeFilename":"README.md"}