Architecture overview
YapYap is an Electron app split into trust zones that share nothing they do not have to. The main process is the only trusted code that touches the system; every web page runs in a sandboxed, context-isolated renderer with no Node.js access, and talks to the main process only through narrow, checked channels.
| Zone | Runs | Trust |
|---|---|---|
| Main process | App logic, settings, IPC validation, extension host | Trusted |
| App chrome | YapYap's own UI, served from a custom app:// protocol | Trusted code, untrusted input |
| One sandboxed renderer per account, with its own persistent session | Untrusted (remote) | |
| Extensions | One hidden, sandboxed renderer per extension | Untrusted (third party) |
Processes and trust zones
- WhatsApp runs in one view per account inside the main window, each on its own persistent partition, so logins, storage and caches never cross accounts. The page reaches only WhatsApp's own origin: navigation and
window.openguards send every other link to your browser. Its one preload replaces the page'sNotificationand has three operations, each checked by the main process (ADR 0011). All knowledge of WhatsApp's page lives in the adapter (src/adapter/), whose scripts the main process runs in an isolated world on demand. They return plain flags or plain data, never page nodes, and they add no observers. - App chrome is YapYap's own UI: the sidebar, Settings, the Extensions window and every other dialog. It is served from
app://chrome/on an in-memory partition under a strict CSP. Its typed preload bridge can only invoke named operations, and the main process checks each call's sender and payload before acting. - Extensions each run in a hidden, sandboxed page on a partition of their own, served only from
extension://<id>/under a CSP that allows no eval and no inline or remote code. A request leaves the page only to a host the user approved, or to this computer withlocal-network. An extension's panel is a separate window with no preload; it reaches its extension's page over aBroadcastChannel, never the main process (ADR 0004). - The main process owns everything that touches the system: files, settings, secrets (through the system keychain), notifications, the tray, permissions and updates. It denies every permission by default (ADR 0001).
The security review checks this design against Electron's security checklist and a threat model for extensions.
Data flows
A WhatsApp notification
- WhatsApp Web creates a
Notification. The shim in the page's main world hands its title, body and tag to the preload, which forwards them. - The main process checks that the message came from a WhatsApp account view and that each field has the expected shape and size. Bad messages are dropped.
- YapYap shows a native notification, named after the account when there are several, and redacted if Settings → Privacy says so. Nothing is logged or stored.
- Clicking it brings YapYap forward, switches to the account and opens the chat. Reading the chat closes the notification.
An extension call
An extension never names its own identity: the main process knows which port a call came from, so an extension's storage and secrets are always its own. There is no operation that sends a message; an extension can only put a draft in the message box for you to send.
An AI assistant reply
- You open the assistant's panel and ask for replies. The panel asks the extension's page over its
BroadcastChannel. - The page reads the open chat through
chat:read-active, which needs your grant for that account and returns at most the number of messages you set. - The panel shows exactly what will be sent and asks before the first request for each chat.
- The page sends it to the provider you chose, with your API key from the system keychain, only to a host you approved, or only to this computer in local-only mode.
- You pick a reply, and the page inserts it as a draft through
composer:insert-draft. You read it and send it yourself.
See the AI assistant guide for the settings and the privacy page for everything YapYap keeps on disk.
Decisions
Each design choice is recorded in an Architecture Decision Record:
| Topic | ADR |
|---|---|
| Processes, trust zones, web preferences, permissions | 0001 |
| Toolchain and pinned versions | 0002 |
| Package formats and update channels | 0003 |
| Extension isolation, signatures, capabilities, audit log | 0004 |
| Tests, coverage and mutation testing | 0005 |
| Settings schema and migrations | 0006 |
| Branches, commits and merging | 0007 |
| Requirements that conflicted, and how each was settled | 0008 |
| Memory, CPU and startup budgets | 0009 |
| Static analysis | 0010 |
| WhatsApp notifications | 0011 |
| Translations and right-to-left support | 0012 |