125 lines
5.1 KiB
Markdown
Executable File
125 lines
5.1 KiB
Markdown
Executable File
# Plugin SDK Guide
|
|
|
|
This guide explains how StellaOps loads, validates, and wires restart-time plugins. It is intentionally cross-cutting: module-specific plugin contracts (Authority identity providers, Concelier connectors, Scanner analyzers, CLI command modules, etc.) live in the corresponding module dossiers under `docs/modules/`.
|
|
|
|
## 1) What a "plugin" means in StellaOps
|
|
|
|
StellaOps uses plugins to extend behavior without losing:
|
|
- Determinism (stable ordering, stable identifiers, replayable outputs).
|
|
- Offline posture (no hidden outbound calls; explicit trust roots and caches).
|
|
- Security boundaries (no client-controlled identity injection; signed artifacts where enforced).
|
|
|
|
Most services load plugins at process start (restart-time). Hot-reload is not a goal: restart-time loading keeps memory and dependency isolation predictable.
|
|
|
|
## 2) Service plugin loading model (restart-time)
|
|
|
|
Service plugins are loaded by the `StellaOps.Plugin` library:
|
|
- Discovery occurs in a configured plugin directory.
|
|
- Assemblies are loaded in an isolated `AssemblyLoadContext`.
|
|
- A compatibility gate runs before DI registration:
|
|
- version attribute presence and host compatibility
|
|
- optional signature verification
|
|
|
|
### 2.1 Plugin directory and discovery patterns
|
|
|
|
Default behavior (from `StellaOps.Plugin.Hosting.PluginHostOptions`):
|
|
- Base directory: `AppContext.BaseDirectory` (unless overridden).
|
|
- Plugin directory:
|
|
- `<PrimaryPrefix>.PluginBinaries` when `PrimaryPrefix` is set, otherwise `PluginBinaries`.
|
|
- Discovery glob(s):
|
|
- `<prefix>.Plugin.*.dll` for each configured prefix.
|
|
|
|
Hosts may override the directory and/or add explicit `searchPatterns` in their config. Use module operations docs to see the authoritative configuration for a given service.
|
|
|
|
### 2.2 Deterministic ordering
|
|
|
|
The loader is deterministic:
|
|
- When no explicit order is configured, discovered plugin assemblies are sorted by filename (case-insensitive).
|
|
- When an explicit order is configured, that order is applied first and the remainder stays sorted.
|
|
|
|
## 3) Version compatibility requirements
|
|
|
|
Plugins should declare the assembly-level attribute:
|
|
```csharp
|
|
using StellaOps.Plugin.Versioning;
|
|
|
|
[assembly: StellaPluginVersion("1.2.3", MinimumHostVersion = "1.0.0")]
|
|
```
|
|
|
|
The host can enforce:
|
|
- Required attribute presence (`RequireVersionAttribute`).
|
|
- Compatibility bounds (`MinimumHostVersion` / `MaximumHostVersion`).
|
|
- Strict major compatibility when `MaximumHostVersion` is not set (`StrictMajorVersionCheck`).
|
|
|
|
## 4) Dependency injection wiring
|
|
|
|
StellaOps supports two DI registration mechanisms.
|
|
|
|
### 4.1 Simple bindings via `ServiceBindingAttribute`
|
|
|
|
Annotate implementations with `ServiceBindingAttribute`:
|
|
```csharp
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using StellaOps.DependencyInjection;
|
|
|
|
[ServiceBinding(typeof(IMyContract), ServiceLifetime.Singleton, RegisterAsSelf = true)]
|
|
public sealed class MyPluginService : IMyContract
|
|
{
|
|
}
|
|
```
|
|
|
|
### 4.2 Advanced wiring via `IDependencyInjectionRoutine`
|
|
|
|
For full control, include a concrete `IDependencyInjectionRoutine` implementation. The host discovers and runs all routines in loaded plugin assemblies:
|
|
```csharp
|
|
using Microsoft.Extensions.Configuration;
|
|
using Microsoft.Extensions.DependencyInjection;
|
|
using StellaOps.DependencyInjection;
|
|
|
|
public sealed class MyPluginDi : IDependencyInjectionRoutine
|
|
{
|
|
public IServiceCollection Register(IServiceCollection services, IConfiguration configuration)
|
|
{
|
|
services.AddSingleton<IMyContract, MyPluginService>();
|
|
return services;
|
|
}
|
|
}
|
|
```
|
|
|
|
## 5) Signing and verification (Cosign)
|
|
|
|
When enabled, the host can verify plugin assemblies using Cosign (`cosign verify-blob`). The signature file is expected adjacent to the assembly:
|
|
- `MyPlugin.dll`
|
|
- `MyPlugin.dll.sig`
|
|
|
|
Verification is performed by `StellaOps.Plugin.Security.CosignPluginVerifier` and controlled by host configuration (for example `EnforceSignatureVerification` plus verifier options).
|
|
|
|
Offline note: verification can be performed without transparency log access when the host is configured accordingly (for example by ignoring tlog or using an offline receipt flow).
|
|
|
|
## 6) Repo layout (this monorepo)
|
|
|
|
In this repository, plugin binaries are typically staged under module-specific `*.PluginBinaries` directories (examples):
|
|
- `src/StellaOps.Authority.PluginBinaries/`
|
|
- `src/Concelier/StellaOps.Concelier.PluginBinaries/`
|
|
|
|
The authoritative loader configuration is owned by the host module and documented in its operations/architecture docs.
|
|
|
|
## 7) Testing expectations
|
|
|
|
Plugins should ship tests that protect determinism and compatibility:
|
|
- Stable ordering of outputs and collections.
|
|
- Stable timestamps (UTC ISO-8601).
|
|
- Fixture-backed inputs for offline operation.
|
|
- Compatibility checks for host version boundaries.
|
|
|
|
Reference tests for the generic plugin host live under:
|
|
- `src/__Libraries/__Tests/StellaOps.Plugin.Tests/`
|
|
|
|
## 8) Where to go next
|
|
|
|
- Authority plugins and operations: `docs/modules/authority/`
|
|
- Concelier connectors and operations: `docs/modules/concelier/`
|
|
- Scanner analyzers and operations: `docs/modules/scanner/`
|
|
- CLI command modules: `docs/modules/cli/`
|
|
|