Why a CI step
Teams already fail a build when a test breaks or a dependency has a known vulnerability. A wallet address that starts flowing to an analytics host after a routine SDK update usually fails nothing. It ships, and someone outside the team finds it later, if at all.
Privacy CI treats that as a regression. The same wallet journeys run on every build, and a new third-party disclosure shows up next to the commit that introduced it, with the request that carried it.
Three stages
| Stage | What it does | Status |
|---|---|---|
| 1 · Trace Lab | Inspect one captured trace. Findings name the host, request and field, with direct or heuristic evidence. Output: nodal.findings/v0. | In development |
| 2 · Privacy CI | Run named scenarios on each build, compare observed flows with the declared policy and the previous release, and flag new or unexpected third-party disclosures. | Planned |
| 3 · Observed Data Manifest | A machine-readable, version-specific report of what was observed in the named scenarios, which a team can publish with a release. | Planned |
Each stage reuses the one before it. Privacy CI runs the Trace Lab engine on traffic it captures itself; the manifest is a summary of what Privacy CI observed.
How Privacy CI would work
- Declare a policy. The team lists its own hosts and which wallet-related values may go to which kinds of host, for example addresses to RPC and the team’s API, nothing to analytics or session replay.
- Name the scenarios. Scripted wallet journeys with a test wallet: connect, view a portfolio, request a quote, sign a permit. Each has a stable name so results compare across builds.
- Run them on the build. Playwright runs each scenario against the build under test and records every request the page makes, as the wallet-flow example does today.
- Compare. Observed flows are checked against the policy and against the last accepted baseline.
- Report. The check fails or warns on new or undeclared third-party disclosures. Each one carries the host, request, field and evidence type, so an engineer can reproduce it.
Illustrative policy, not a final format:
# nodal.policy.yml (proposed)
firstParty: [app.example.test, api.example.test]
scenarios: [connect-wallet, swap-quote, sign-permit]
allow:
- value: wallet.address
to: [rpc, first-party]
deny:
- value: [wallet.address, tx.hash, ens.name]
to: [analytics, session-replay, advertising, error-tracking]
onUndeclared: fail # or warn
What it would check: the same request locations Trace Lab analyses today (path, query, headers, JSON, NDJSON, form and text bodies), in the scenarios that ran.
Observed Data Manifest
A JSON file tied to one build. It lists the scenarios that ran, the browser and capture method, each wallet-related value observed leaving the app, the hosts and categories that received it, and whether the policy declared it. It also lists what was not analysed.
Teams could publish it next to release notes, so integrators, auditors and users can see which flows were observed in testing and compare one release with the next. A signature could show who published a manifest. It cannot show that the app had no other behaviour.
{
"schema": "nodal.manifest/v0",
"app": "sample-dapp",
"build": "2.4.0",
"scenarios": ["connect-wallet", "swap-quote", "sign-permit"],
"environment": { "browser": "chromium", "capture": "har" },
"observed": [
{ "value": "wallet.address", "host": "rpc.example.test", "category": "rpc",
"declared": true, "scenarios": ["connect-wallet", "swap-quote"] }
],
"notAnalysed": ["websocket frames", "service workers", "browser extensions"],
"limits": "Observed in the listed scenarios only. Not proof of absence."
}
Limits
The manifest reports only what was observed in the stated tests. In particular, it is:
- Not proof that an app never leaks data. Journeys, builds, regions, feature flags and users that were not tested are not covered.
- Not a privacy certification, score or badge.
- Not a security guarantee or an audit.
- Blind to what the threat model lists as unresolved: WebSocket frames, service workers, browser extensions, hashed or encrypted payloads, and anything a server does after it receives data.
NODAL does not detect every leak, and it is not the first tool to look at dApp traffic. Its aim is a repeatable release workflow with evidence an engineer can act on.
Compatibility targets
The wider vision is privacy testing across wallet, app and network layers: test app data flows and wallet journeys in CI, with network-layer testing as research. The names below are compatibility targets, not partnerships. No named project has agreed to work with NODAL.
| Target | Layer | What NODAL does or would do | Status |
|---|---|---|---|
| MetaMask, Reown AppKit / WalletConnect | Wallet | Run common wallet-connection flows and show the data NODAL observed the app send. The wallet-flow examples run today with an EIP-6963 / EIP-1193 test wallet, directly and through Reown AppKit. WalletConnect QR flows are planned. | In development |
| Playwright | Test runner | Browser network events and route handlers capture every request the page makes. The foundation for automated Trace Lab scenarios and Privacy CI. | In development |
| GitHub Actions | Pipeline | Run Privacy CI during builds and releases and report undeclared disclosures as a check. | Planned |
| Nym, Ethereum anon-rpc | Network | Explore privacy-routed RPC testing. See below. | Exploring No integration announced |
Different layers
- NODAL looks at the content an app sends: which wallet-related values leave the page, to which hosts, in which field.
- MetaMask is a wallet; Reown AppKit and WalletConnect connect wallets to apps. NODAL drives their flows in tests; it does not change or assess them. Wallet-extension traffic and WalletConnect relay frames remain blind spots.
- Playwright drives the browser; GitHub Actions is where checks would run. Neither changes what NODAL can observe.
- Nym protects network metadata: who talks to whom, when and from where. NODAL does not measure this today.
Research: privacy-routed RPC Exploring
anon-rpc is a draft Ethereum specification for making anonymised RPC requests from a wallet or app: a hash-pinned worker runs in a sandbox and carries the requests. Nym provides a worker that routes them over its mixnet.
The question for NODAL: if an app says its RPC goes through a privacy route, can a test show which requests did not? Candidates worth checking:
- RPC calls sent straight to a public endpoint instead of through the worker.
- A silent fallback to a direct endpoint when the private route fails or is slow to start. The draft leaves fallback behaviour to the host.
- Reads made through a direct provider before the private route is ready.
- Non-RPC requests, such as analytics or price APIs, that send the address anyway.
Limits: the private route’s own traffic is relayed inside a sandbox and over a mixnet, so NODAL would see where requests did not go through it, not prove that the route itself is private. anon-rpc is a draft and may change. There is no NODAL integration with Nym or anon-rpc and no partnership.
Before teams rely on it
- Outside engineers review parser safety, test coverage and bypass paths.
- Each status label moves only when the feature exists and has been checked. Nothing here is labelled Live.