What a plugin can do
Lifecycle events, and advisory versus enforcing.
Written By Dustin
Last updated 29 minutes ago
A plugin is a WASM module bound to a lifecycle event and run in a capability-bounded sandbox. It replaces the outcome of a Git hook, not its implementation model — a Git hook is an arbitrary shell script running with your whole machine's authority, and a TOVIO plugin is a sandboxed guest that gets only what a manifest requested and a binding granted.
The events you will actually bind to
Those four are the MVP set, and most plugins never need another. The full vocabulary is twenty-four names, a closed set:
pre-snapshot, post-snapshot, pre-sync, post-sync, pre-land, post-land, conflict-created, resolve-requested, proposal-created, review-submitted, policy-changed, access-granted, access-revoked, lock-acquired, lock-released, agent-session-started, agent-scope-exceeded, release-created, archive-created, bundle-created, bundle-applied, git-imported, git-exported, transcript-parse.
Being bindable is not the same as being fired. An event is dispatched only where the subsystem that owns the operation has a firing site, and the four release and bundle events have no backing subsystem yet — no command, object kind, or transport format — so nothing dispatches them. Binding one early is legal and deliberate: the manifest can be authored, reviewed, and pinned ahead of the subsystem.
Two names people expect and will not find
- There is no
resolverevent.resolveris a plugin type (alongsidecheck,transform,policy-adapter, andnotifier); the event a resolver binds to isresolve-requested. - There is no
secret-scanevent.com.tovio.secret-scanis a plugin id, and it is bound topre-snapshotby default in every repo.
An event name that is not one of the twenty-four is refused at bind and at run with TVO-PLUGIN-004, rather than quietly accepted and never called.
Advisory, enforcing, required
--mode chooses whether a plugin can gate. --required is a separate flag that widens what gates.
The direction of that table is deliberate: ambiguity resolves to block. A plugin that could not produce a verdict has not passed, and a required gate that cannot run is not a gate that quietly lets the operation through.
Start advisory. Move to enforcing once you have watched it run against real content.
Deny by default
The sandbox provides no network, no filesystem, and no environment access unless the binding grants it. A plugin importing a host function it was not granted fails closed — TVO-PLUGIN-006 — rather than silently succeeding.
Protected plaintext is denied at execution preflight (TVO-PLUGIN-011) unless explicitly granted, and network likewise (TVO-PLUGIN-012). Key material is never provided to a plugin under any grant.
Running needs a feature build
Executing plugins requires the plugins-wasm build feature. Without it, plugin run and plugin test print a clean built without plugin execution message rather than pretending. The management surface — install, list, show, validate, verify, bind, bindings, doctor — works in every build.
As policy gates
tovio policy hook add <event> <plugin_id> --requiredA policy hook is an enforcing binding authored through the policy surface, so it reads as a gate rather than as one person's local preference.