VPN Works Rebuilt as One Core With Plugins: What Moved Where in 0.3.0
VPN Works started as five separate engines that each worked and didn’t add up to one thing. Version 0.3.0 rebuilt it from scratch as one small core, vpnw, with plugins for everything else.
The five engines of September were the Agent, Scope, Lab, Ledger and Exit. Each had its own binary, its own command line and its own browser demo. Underneath, the Agent’s code was already shaped like a core: a broker that takes every connection, a policy, paths, and one event model that everything spoke. What was missing was a way for everything else to plug into it.
So the project started again with an empty repository laid out for a platform, and pulled old code in only where the new layout needed it. The hard, tested parts came over almost as they were: the sealed sandbox, its seccomp filters, the policy’s decision order, the proxy paths and their failover. The rest had to earn its way back.

The Plugins
A plugin is a WebAssembly module that vpnw runs in a sandbox inside its own process, with wazero, a WebAssembly runtime written in Go. It gets no files, no network and no environment. It reaches vpnw only through the calls its manifest asks for, and vpnw refuses a module that imports anything else before running a single instruction of it. Three types run today:
- Observers watch a run’s events as they happen.
- Advisors read recorded traces and write advice.
- Guards can refuse a connection the policy allowed.
The rules are short. Plugins never carry traffic. One that crashes or runs past its time budget is stopped and the run carries on. A Guard that fails refuses everything after it. An Observer that falls behind loses events, counted and reported, instead of slowing anything down. Plugins are signed with Ed25519 and installed only from keys you trust.
What Moved Where
| Before 0.3.0 | Now |
|---|---|
| The Agent’s broker, policy, paths and sandbox | the core |
vpnw trace’s console output |
Trace, a built-in Observer plugin |
vpnw learn |
Learn, a built-in Advisor plugin |
| Ledger | next: an Observer plugin that seals the record |
| Exit | next: a companion server; its client side is still in vpnw |
| Lab | next: the test every tunnel must pass |
| Scope | later: an Advisor for gateway mode |
| Five browser demos | retired; see See It Run |
Trace and Learn going out of the core matters more than it looks. The console you read every day is a plugin, through the same interface and the same sandbox as anyone else’s. First-party plugins get no back door.
What It Cost
Safety has a price inside a WebAssembly sandbox. To stop a plugin that never returns, the runtime checks for the end of its time budget at every function call and loop, which makes plugin code four to five times slower. The alternative was worse: an earlier design ran plugins without those checks, and the tests caught a plugin in an endless loop freezing the whole process the next time Go’s garbage collector ran. So every plugin is held to its budget. A Guard’s decision takes about 0.15 ms; one event through the Trace plugin about 0.44 ms.
Then 0.4.0
The platform’s first new feature came the same day: WireGuard paths, run inside vpnw. They’re built into the core, because a tunnel carries traffic and plugins never do. What comes after is on the roadmap.