Plugin Store

Everything you can plug into Busbar.

Busbar ships small and complete: a memory store, token auth, and env/file secrets in the box. Everything heavier is something you add without recompiling the core: where state lives (stores), how requests are trusted (auth), where a config secret value resolves from (secrets), your own code on the request path (hooks), and where telemetry goes (exporters). As of busbar 1.5.0 that is a working system, not a roadmap: a plugin is one signed archive you download, drop in a directory, and the binary you already run verifies and loads it. How it works is below the grid. Browse them, and vote for what you want built next.

Identity provider Yours

Your auth

Trust requests your own way?

HMAC-signed requests, a bespoke token service, a SASO scheme of your own: the auth contract is small and stackable. Tell us how you need requests trusted and we’ll help you wire it in.

Contact us, or open a PR against the repo.

Hook Gate Yours

Your hook

Built something worth sharing?

A guardrail, a router, a cost meter, an audit sink: anything that runs on the path. Tell us what it does and where it lives, and we’ll list it here and link straight to your repo.

Contact us, or open a PR against the repo.

Secret Yours

Your secret backend

Have a secrets manager Busbar should speak?

AWS Secrets Manager, GCP Secret Manager, Azure Key Vault, 1Password: the secret contract is one method, resolve a reference to bytes. Tell us what you need and we’ll help you build it.

Contact us, or open a PR against the repo.

Store Yours

Your store

Have a backend Busbar should speak?

The store is a small, sync contract: keys, budgets, usage, metering. If you want Busbar’s state in DynamoDB, Mongo, or your own service, the contract is the whole job. Tell us what you need and we’ll help you build it.

Contact us, or open a PR against the repo.

How a plugin loads

A plugin is a plugin. Stores, identity providers, secret modules, and hooks share one format, one loader, and one trust model; the kind field in the manifest is the only thing that tells them apart. Distribution is one signed .tar.gz per plugin and architecture: download it, drop it in plugins/, done. Busbar unpacks and verifies the archive entirely in memory (on Linux the library loads from an anonymous memfd, so nothing ever touches disk), and the bytes that were verified are exactly the bytes that load.

It is safe by default. The loader is off until you set plugins.enabled: true, so a tarball dropped next to a gateway that hasn't opted in is inert. Busbar's own plugins verify against a release key embedded in the binary: trusted with zero configuration. Unsigned or third-party plugins are logged and skipped unless you explicitly allow them (allow_unsigned, allow_third_party, and a per-publisher key allowlist), and version floors stop an old plugin from being loaded beside a newer binary.

And it is inspectable before it carries traffic. busbar --list-plugins prints every plugin in the directory with its signature state and exactly why it will or won't load, without executing any of them. busbar --validate checks the config and every plugin manifest through the same path a real boot uses: if it passes, boot succeeds; if anything is wrong (a bad config, a malformed manifest, two plugins claiming one name), Busbar names it and refuses to start rather than booting degraded.

The point of the whole design: the default binary stays lean (~12 MB, with the memory store and token auth built in), and durable governance (SQLite, Postgres, Valkey, and MySQL) is a download you drop in, not a recompile.

Exporters are configured, not downloaded

One honest exception, so nothing on this page over-promises: the exporters above ship inside the binary. You turn one on by naming an instance under the top-level export: map (<name>: { module: …, settings: … }, the same named-definition shape hooks: and identity-providers: use), and there is no tarball to fetch, no signature to trust, and no plugins.enabled to flip. Name none and Busbar emits nothing: no recorder, no /metrics route, no tracer, no request-log payload built at all.

Each instance also declares its own projection: streams: names what that sink is entitled to, drawn from a frozen vocabulary of metrics, logs, traces, costs, decisions, events, identity, prompts, and completions. It is not a filter applied on the way out: Busbar builds each payload to the projection, so a stream an instance did not subscribe to is never serialized and never crosses the plugin boundary. Subscribing to something this release cannot deliver, a stream with no producer yet or one the module cannot carry, is a boot error naming the instance rather than a sink that validates and quietly receives nothing. See the projection.

export is nonetheless a real plugin kind alongside store, secret, auth, and hook: the same neutral C symbols, plus two operations of its own (streams, asked once at load, and deliver). What has not shipped is the config seam, so module: takes the built-in names only and today the exporters are the set you see here. The export docs cover every module, its settings, and the observability: / metrics: migration.

Hooks or exporters?

Two of the kinds above put your own logic in the request's path, and it's easy to reach for the wrong one. The line is simple: hooks can stop the request. Exporters tell you what happened.

HooksExporters
TimingReal time, mid-requestAfter the fact, delayed by milliseconds or seconds
PowerPreventative and modifying: can block, reject, restrict, rewriteNever preventative; observe and emit only
PurposeChange what happensRecord what happened
ScopeBound to pools, fire at declared phasesEngine-wide
SeesRequests that reach themEverything the engine knows, including events that are not requests
What you wantWhich kindWhy
Prompt compressionHookmust happen before the request leaves
PII redactionHookthe entire point is that the PII does not go
Alert when someone sends credentials to a model Hook an exporter alerting 200 ms later is too late. The credential has already reached the provider. Alerting without the power to stop is not a control, it is notification of a breach.
A record of what everyone didExporterafter the fact, must be complete, must never block a request
Dashboards, metrics, tracesExporterobservation, never on the critical path

Worth stating plainly: an auditor written as a hook is structurally incomplete. Hooks fire at request phases and are bound to pools, so a hook-based auditor cannot see requests refused before it ran (admission shedding, auth failure at the door, budget exhaustion), admin/config changes, or any pool it is not bound to. "Show me every attempt, including the denied ones" is a question only an exporter can answer.

New to the request path? Start with the hooks docs for the config shape, the tap/gate lifecycle, and how a hook falls back safely without ever blocking a request. Stores and auth are set in configuration; telemetry egress, and the data boundary an exporter never crosses, is export.