Skip to content

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.

ZoneRunsTrust
Main processApp logic, settings, IPC validation, extension hostTrusted
App chromeYapYap's own UI, served from a custom app:// protocolTrusted code, untrusted input
WhatsAppOne sandboxed renderer per account, with its own persistent sessionUntrusted (remote)
ExtensionsOne hidden, sandboxed renderer per extensionUntrusted (third party)

Processes and trust zones ​

YapYap's processes and trust zonesThe trusted main process sits between three kinds of sandboxed renderer: WhatsApp accounts, YapYap's own chrome and extensions. Each reaches the main process through its own checked channel. WhatsApp views reach only web.whatsapp.com, extensions reach only hosts they were allowed, and the main process alone asks GitHub for updates.web.whatsapp.comthe internetGitHub releasesupdate metadata onlyHosts an extension may reachapproved HTTPS hosts, loopbackMain process (Node.js): trustedsettings · accounts · IPC checks · permissions · network filtersextension host · capability checks · audit log · updatesWhatsApp accountsone view per accountpersist:account-<uuid>notification shim preloadadapter in an isolated worlduntrusted, remoteApp chromeapp://chrome/, in memorysidebar, settings, dialogstyped preload bridgestrict CSP, no remote codetrusted code, untrusted inputExtensionsone hidden page eachextension://<id>, own partitionpanels: windows, no preloadCSP and network filteruntrusted, third partyHTTPSfilterednotificationbridge, probeschecked IPCone RPC port,checked calls
Solid outlines are trusted code; dashed outlines are untrusted content.
  • 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.open guards send every other link to your browser. Its one preload replaces the page's Notification and 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 with local-network. An extension's panel is a separate window with no preload; it reaches its extension's page over a BroadcastChannel, 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 ​

  1. 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.
  2. 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.
  3. 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.
  4. Clicking it brings YapYap forward, switches to the account and opens the chat. Reading the chat closes the notification.

An extension call ​

How YapYap checks an extension's callA call from an extension page crosses its port and is checked in order: the message envelope and parameters, the extension's grant for the account on screen, and its rate. Only then does the host method run, with a timeout, reaching the adapter or the system and returning plain data. Each call's operation and outcome go to the audit log, never its parameters or result.Extension pagecalls the host APIShapeenvelope, paramsGrantfor this accountRate5 a second, 20 burstHost method10 s timeoutAdapter, OSplain data backAudit logoperation and outcome, never parameters or resultsevery call
Any failed check ends the call with a typed error, which the audit log records too.

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 ​

  1. You open the assistant's panel and ask for replies. The panel asks the extension's page over its BroadcastChannel.
  2. 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.
  3. The panel shows exactly what will be sent and asks before the first request for each chat.
  4. 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.
  5. 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:

TopicADR
Processes, trust zones, web preferences, permissions0001
Toolchain and pinned versions0002
Package formats and update channels0003
Extension isolation, signatures, capabilities, audit log0004
Tests, coverage and mutation testing0005
Settings schema and migrations0006
Branches, commits and merging0007
Requirements that conflicted, and how each was settled0008
Memory, CPU and startup budgets0009
Static analysis0010
WhatsApp notifications0011
Translations and right-to-left support0012

Released under the MIT License. Development supported by Ensita. YapYap is unofficial and not affiliated with WhatsApp or Meta.