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

ToolMin Version
.NET SDK10 LTS
StellaOps templatesinstall once via bash dotnet new install StellaOps.Templates::*
Cosign2.3 + — used to sign DLLs
xUnit2.6
Docker CLIonly 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

NeedPattern
SettingsPlugins:MyPlugin:* in appsettings.json.
SecretsRedis secure::(encrypted per TLS provider).
Dynamic cronImplement ICronConfigurable; UI exposes editor.

11 Testing & CI

LayerToolGate
UnitxUnit + Moq≥ 50 % lines
IntegrationTestcontainers ‑ run in CIJob completes < 5 s
Styledotnetformat 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

SymptomRoot causeFix
NotDetected.sig missingcosign sign …
VersionGateMismatchBackend 2.1 vs plug‑in 2.0Re‑compile / bump attribute
FileLoadExceptionDuplicateStellaOps.Common Ensure PrivateAssets=“all”
Redistimeouts Large writesBatch or use Mongo