# Writing Plug‑ins for Stella Ops SDK *Preview 3* > **SDK status:** *Preview 3* is compatible with the **v0.1 α** runtime. > Interfaces freeze at **v0.2 β**; binary‑breaking changes are still possible > until then. | SDK NuGet | Runtime compat | Notes | |-----------|---------------|-------| | `StellaOps.SDK 0.2.0-preview3` | `stella-ops >= 0.1.0-alpha` | Current preview | | `StellaOps.SDK 0.2.x‑beta` | v0.2 β (Q1 2026) | Interface **freeze** | | `StellaOps.SDK 1.0.0` | v1.0 GA (Q4 2026) | Semantic Ver from here | --- ## 0 · Extension points | Area | Interface / format | Example | |------|--------------------|---------| | SBOM mutator | `ISbomMutator` | Inject SPDX licences | | Additional scanner | `IVulnerabilityProvider` | Rust Crates ecosystem | | Policy engine | **OPA Rego** file | Custom pass/fail rule | | Result exporter | `IResultSink` | Slack webhook notifier | *Hot‑plugging (live reload) is **post‑1.0**; modules are discovered once during service start‑up.* --- ## 1 · Five‑minute quick‑start (C# /.NET {{ dotnet }}) ```bash dotnet new classlib -n SlackExporter cd SlackExporter dotnet add package StellaOps.SDK --version 0.2.0-preview3 ```` ```csharp using System.Net.Http.Json; using StellaOps.Plugin; public sealed class SlackSink : IResultSink { private readonly string _webhook = Environment.GetEnvironmentVariable("SLACK_WEBHOOK") ?? throw new InvalidOperationException("Missing SLACK_WEBHOOK"); public string Name => "Slack Notifier"; public async Task ExportAsync(ScanResult result, CancellationToken ct) { var payload = new { text = $":rotating_light: *{result.Image}* " + $"→ {result.Findings.Count} findings (max {result.MaxSeverity})" }; using var client = new HttpClient(); await client.PostAsJsonAsync(_webhook, payload, ct); } } ``` ```bash dotnet publish -c Release -o out sudo mkdir -p /opt/stella/plugins/Slack sudo cp out/SlackExporter.dll /opt/stella/plugins/Slack/ sudo systemctl restart stella-ops ``` Start‑up log: ``` [PluginLoader] Loaded 1 plug‑in: • Slack Notifier ``` --- ## 2 · Packaging rules | Item | Rule | | ------ | ----------------------------------------- | | Folder | `/opt/stella/plugins//` | | DLLs | Your plug‑in + non‑GAC deps | | Config | Env‑vars or `settings.yaml` | | SBOM | Optional `addon.spdx.json` for provenance | --- ## 3 · Security sandbox * Runs as Linux user **`stella‑plugin` (UID 1001)**. * SELinux/AppArmor profile blocks inbound traffic; outbound :80/443 only. * cgroup default: **1 CPU / 256 MiB** (adjustable). * SHA‑256 of every DLL is embedded in the run report. --- ## 4 · Debugging | Technique | Command | | ----------------- | ---------------------------------- | | Verbose core log | `STELLA_LOG=debug` | | Per‑plug‑in log | Inject `ILogger` | | Dry‑run (no fail) | `--plugin-mode warn` | | Hot reload | *Not supported* (planned post‑1.0) | Logs: `/var/log/stella-ops/plugins/YYYY‑MM‑DD.log`. --- ## 5 · Interface reference (Preview 3) ```csharp namespace StellaOps.Plugin { public interface ISbomMutator { string Name { get; } Task MutateAsync( SoftwareBillOfMaterials sbom, CancellationToken ct = default); } public interface IVulnerabilityProvider { string Ecosystem { get; } Task> QueryAsync( PackageReference p, CancellationToken ct = default); } public interface IResultSink { string Name { get; } Task ExportAsync( ScanResult result, CancellationToken ct = default); } } ``` Full POCO docs: [https://git.stella-ops.org/stella-ops/sdk/-/tree/main/docs/api](https://git.stella-ops.org/stella-ops/sdk/-/tree/main/docs/api). --- *Last updated {{ "now" | date: "%Y‑%m‑%d" }} – constants auto‑injected.*