ADR 0002: Keep plugins behind a source-level Rust trait boundary
- Status: Accepted
- Date: 2026-07-31
Context
The runner must execute extensions without knowing their concrete implementation. Rust shared-library ABIs are not stable, and runtime discovery introduces signing, trust, isolation, capability, and version-negotiation requirements that are not resolved for the alpha release.
Decision
Plugins are Rust types implementing Plugin and are registered as Arc<dyn Plugin>. The registry operates only on the trait, serializable configuration, structured findings, and versioned errors. Public plugin enums and output/configuration structs are non-exhaustive.
The preview host and plugin API lines must match at major and minor version. Patch releases may add compatible behavior and defaulted trait methods; incompatible changes require a new alpha minor line. Runtime dynamic loading is explicitly out of scope until an ABI and trust model are accepted in a later ADR.
Consequences
- External crates can implement plugins without exposing concrete types to the runner.
- Plugins are linked by a host; the stock CLI does not discover arbitrary binaries.
- Adding enum variants does not force exhaustive downstream matches.
- Version mismatch is rejected during registration rather than failing later during execution.
Alternatives considered
- Stable C ABI: deferred because ownership and async boundaries would require a separate FFI design.
- WebAssembly plugins: promising for isolation, but deferred until capability and performance requirements are measured.
- In-process dynamic Rust libraries: rejected for the preview because Rust does not promise a stable ABI.