postgres or http lane.
Use one when the resource speaks a protocol of its own: an in-house database, a vendor’s binary RPC, a legacy TCP service. The vendor writes the decoder once, in Rust, Go, C or any language with a wasm32 target, and ships a single .wasm file that runs on every architecture the Sidecar runs on.
Configure a lane
Aplugins list names each module and the protocol it decodes. A listener then names that protocol the way it names a built-in one:
config.yaml
Validate before you bind the port:
What a plug-in can do
The module declares its capabilities in its manifest, and the Sidecar turns each one on only when the module exports it:
A module that carries SQL text calls the Sidecar’s own classifier through a host import. The lexer stays in the Sidecar, so an
operation or table rule on a plug-in lane reads the same analysis a mysql lane reads.
Where the plug-in runs
The Sidecar owns the socket, the policy, the audit trail and the masker. The module owns one thing: the meaning of the bytes. Every box the module touches below is one export the ABI names; everything else is the same code path apostgres lane runs.
Orange is the module; green is the host answering a module’s import. The two dotted calls are the whole of what a module can ask the host for on the data path, and both run on the stack of the export that called them.
Reading the request path left to right:
filtersees every chunk first, before inspection and before forwarding. A module without the capability passes bytes through untouched.decodeturns the chunk into statements and reports how many bytes it consumed. The Sidecar keeps the remainder and hands it back with the next read, so the module never sees a torn frame as an error. A SQL-carrying module callsanalyze_sqlhere and gets the same classification amysqllane gets.- policy runs on the statements: guardrail rules (including
metadataon the module’s verb), OPA, the AI analyzer. The module is not consulted. - audit writes the statement before the forward. A denial writes a
violationinstead and the Sidecar asks the module for adenyframe to send the client; without the capability it closes the socket.
rewrite receives the same chunk, calls mask(column, value) for each cell it can name, and returns rebuilt frames. The host decides what to mask; the module decides which bytes are cells and recomputes its own length prefixes. The audit masked event counts what the masker changed.
Not on the data path: take_credential runs between decode and policy on a lane with per-request identity, trading the handle the module left on the statement for the credential; content runs when the analyzer wants a rendering of a statement.
Load time is a separate, one-off sequence:
Each accepted connection gets its own instance of the compiled module (or, under instances: per_lane, its own conn id in one shared instance). A trap, a deadline or a memory cap kills that instance and that connection only; the compiled module and every other connection stay up.
How it fails
Every failure stays inside the connection or the lane it belongs to, and none of them forwards a byte the module did not judge:- At load. A sha256 mismatch, a manifest that names another protocol, a capability without its export, an import the ABI does not grant, or a protocol name without the
x-prefix refuses the module. The lane does not start, and--validatereports the reason. - On a connection. A trap, a call past the manifest’s
call_timeout_ms, or memory abovememory_limit_pagescloses that connection’s instance. The Sidecar writes the deny frame when the module offers one and drops the connection. Other connections keep their own instances. - On bad output. A decode result that is not JSON, names an unknown field, or uses an operation outside the vocabulary ends the connection.
Control Plane
A Control Plane serves theplugins list and the lanes that use it like any other config section. The Sidecar reports a plugins capability on its handshake; the plane withholds the section from a build that does not report it, and grants an x- listener protocol by that capability alone. A Sidecar from before plug-ins existed never receives a document it cannot decode.
The plane serves a URL and a digest; the Sidecar fetches, verifies and loads. Point module at an https:// URL the Sidecar can reach, pin the digest, and the same document works for every Sidecar in the fleet.
Next
Writing a Plug-in
The Rust, Go and C SDKs, the manifest, fixtures and the conformance tool.
ABI Reference
Exports, imports, payloads and failure semantics, for any language with a wasm32 target.
Guardrail Rules
The
metadata rule type that reads a plug-in’s native verb.Config File
Every section and field.