# 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