6.2 KiB
# 10 · Plug‑in SDK Guide — Stella Ops (v 1.5 — 11 Jul 2025 · template install, no reload, IoC)
## 0 Audience & Scope
Guidance for developers who extend Stella Ops with schedule jobs, scanner adapters, TLS providers, notification channels, etc. Everything here is OSS; commercial variants simply ship additional signed plug‑ins.
## 1 Prerequisites
Tool | Min Version |
---|---|
.NET SDK | 9.0.200 |
StellaOps templates | install once via bash dotnet new install StellaOps.Templates::* |
Cosign | 2.3 + — used to sign DLLs |
xUnit | 2.6 |
Docker CLI | only if your plug‑in shells out to containers |
## 2 Repository & Build Output
Every plug‑in is hosted in git.stella‑ops.org
.
At publish time it must copy its signed artefacts to:
src/backend/Stella.Ops.Plugin.Binaries/<MyPlugin>/
├── MyPlugin.dll
└── MyPlugin.dll.sig
The back‑end scans this folder on start‑up, verifies the Cosign signature, confirms the [StellaPluginVersion]
gate, then loads the DLL inside an isolated AssemblyLoadContext to avoid dependency clashes
## 3 Project Scaffold
Generate with the installed template:
dotnet new stellaops-plugin-schedule \
-n MyPlugin.Schedule \
--output src
Result:
src/
├─ MyPlugin.Schedule/
│ ├─ MyJob.cs
│ └─ MyPlugin.Schedule.csproj
└─ tests/
└─ MyPlugin.Schedule.Tests/
## 4 MSBuild Wiring
Add this to MyPlugin.Schedule.csproj
so the signed DLL + .sig
land in the canonical plug‑in folder:
<PropertyGroup>
<StellaPluginOut>$(SolutionDir)src/backend/Stella.Ops.Plugin.Binaries/$(MSBuildProjectName)</StellaPluginOut>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\StellaOps.Common\StellaOps.Common.csproj"
PrivateAssets="all" />
</ItemGroup>
<Target Name="CopyStellaPlugin" AfterTargets="Publish">
<MakeDir Directories="$(StellaPluginOut)" />
<Copy SourceFiles="$(PublishDir)$(AssemblyName).dll;$(PublishDir)$(AssemblyName).dll.sig"
DestinationFolder="$(StellaPluginOut)" />
</Target>
## 5 Dependency‑Injection Entry‑point
Back‑end auto‑discovers the static method below:
namespace StellaOps.DependencyInjection;
public static class IoCConfigurator
{
public static IServiceCollection Configure(this IServiceCollection services,
IConfiguration cfg)
{
services.AddSingleton<IJob, MyJob>(); // schedule job
services.Configure<MyPluginOptions>(cfg.GetSection("Plugins:MyPlugin"));
return services;
}
}
## 6 Schedule Plug‑ins
### 6.1 Minimal Job
using StellaOps.Scheduling; // contract
[StellaPluginVersion("2.0.0")]
public sealed class MyJob : IJob
{
public async Task ExecuteAsync(CancellationToken ct)
{
Console.WriteLine("Hello from plug‑in!");
await Task.Delay(500, ct);
}
}
### 6.2 Cron Registration
services.AddCronJob<MyJob>("0 15 * * *"); // everyday
15:00 Cron syntax follows Hangfire rules
## 7 Scanner Adapters
Implement IScannerRunner. Register inside Configure:
services.AddScanner<MyAltScanner>("alt"); // backend
selects by --engine alt If the engine needs a side‑car container, include a Dockerfile in your repo and document resource expectations. ## 8 Packaging & Signing
dotnet publish -c Release -p:PublishSingleFile=true -o out
cosign sign --key $COSIGN_KEY out/MyPlugin.Schedule.dll # sign binary only
sha256sum out/MyPlugin.Schedule.dll > out/.sha256 # optional checksum
zip MyPlugin.zip out/* README.md
Unsigned DLLs are refused when StellaOps:Security:DisableUnsigned=false.
## 9 Deployment
docker cp MyPlugin.zip <backend>:/opt/plugins/ && docker restart <backend>
Check /health – "plugins":["MyPlugin.Schedule@2.0.0"]. (Hot‑reload was removed to keep the core process simple and memory‑safe.)
## 10 Configuration Patterns
Need | Pattern |
---|---|
Settings | Plugins:MyPlugin:* in appsettings.json. |
Secrets | Redis secure:: (encrypted per TLS provider). |
Dynamic cron | Implement ICronConfigurable; UI exposes editor. |
## 11 Testing & CI
Layer | Tool | Gate |
---|---|---|
Unit | xUnit + Moq | ≥ 50 % lines |
Integration | Testcontainers ‑ run in CI | Job completes < 5 s |
Style | dotnet | format 0 warnings |
Use the pre‑baked workflow in StellaOps.Templates as starting point.
## 12 Publishing to the Community Marketplace
Tag Git release plugin‑vX.Y.Z and attach the signed ZIP. Submit a PR to stellaops/community-plugins.json with metadata & git URL. On merge, the plug‑in shows up in the UI Marketplace.
## 13 Common Pitfalls
Symptom | Root cause | Fix |
---|---|---|
NotDetected | .sig missing | cosign sign … |
VersionGateMismatch | Backend 2.1 vs plug‑in 2.0 | Re‑compile / bump attribute |
FileLoadException | Duplicate | StellaOps.Common Ensure PrivateAssets="all" |
Redis | timeouts Large writes | Batch or use Mongo |