Contribute
Architecture
An Electron app whose main process owns protocols, nodes, permissions and the wallet. The renderer is UI, and pages only reach privileged features through narrow providers.
Source on GitHubOn this page
Processes#
| Layer | Directory | Owns |
|---|---|---|
| Main process | src/main/ |
Protocol handlers, per-profile node lifecycles, permissions, wallet, downloads, updates, persistence |
| Renderer | src/renderer/ |
Browser UI: tabs, navigation, menus, settings, internal freedom:// pages, dapp integration and consent prompts |
| Shared | src/shared/ |
Constants and utilities used by both, including the IPC channel allowlist |
The renderer talks to the main process only through the allowlisted channels
in src/shared/ipc-channels.js. Protocol
and privileged logic belongs in the main process. Before you move
responsibilities between processes or add an IPC channel, read the
architecture boundaries playbook;
changes to those boundaries need maintainer approval.
Other top-level directories: test-e2e/ (Playwright), config/ (runtime
templates, default data, entitlements), scripts/ (build, download,
smoke-test tooling), assets/ (icons) and docs/.
Protocols and nodes#
The main process handles bzz:, ipfs:, ipns:, web3:, rad: and
.onion navigation, runs each profile's nodes, and resolves decentralized
names.
- Swarm runs on Ant (
antd), a node that speaks the Bee HTTP API. Its wire and identity contract (endpoints, port 1633, config keys, key files) deliberately keeps Bee's names; the playbook lists what must not be renamed. - IPFS uses the freedom-ipfs native addon.
- Radicle runs in-process through the embedded libradicle addon. No CLI,
HTTP daemon or local port is involved, and
rad:URLs are served from the node's storage. web3:needs no node: the handler reads a contract's ERC-8244html()document through the chain-data router the wallet uses.- Tor is an optional Arti binary for
.onionsites.
Page providers#
window.swarm, window.radicle and window.ethereum are installed in the
main world of every web page's top frame before the page's own scripts run.
A request travels through three places:
| Step | Files |
|---|---|
| Page shim (injected) | src/main/webview-preload.js |
| Consent prompts and UX | src/renderer/lib/swarm-provider.js, src/renderer/lib/radicle-provider.js |
| Authority: grants, validation, node calls | src/main/swarm/swarm-provider-ipc.js, src/main/radicle/radicle-provider-ipc.js |
The main process re-checks every grant; the renderer's prompts are UX, not the security boundary. Grants are keyed by the address-bar origin, which the main process derives itself. Requests from pages to the local node API on port 1633 are blocked, so pages reach the node only through the provider.
Security model#
- Context isolation is on and Node integration is off in web content.
- Privileged internal APIs are limited to trusted
freedom://pages or the narrow provider surfaces above. - Web permissions are denied by default and granted through per-site prompts.
- Nodes run locally by default; external endpoints are explicit per-profile settings.
File security findings publicly on GitHub; see Community.