This commit is contained in:
StellaOps Bot
2025-12-14 23:20:14 +02:00
parent 3411e825cd
commit b058dbe031
356 changed files with 68310 additions and 1108 deletions

View File

@@ -82,53 +82,53 @@ Add this to **`MyPlugin.Schedule.csproj`** so the signed DLL + `.sig` land in th
---
##5DependencyInjection Entrypoint
Backend autodiscovers restarttime bindings through two mechanisms:
1. **Service binding metadata** for simple contracts.
2. **`IDependencyInjectionRoutine`** implementations when you need full control.
###5.1Service binding metadata
Annotate implementations with `[ServiceBinding]` to declare their lifetime and service contract.
The loader honours scoped lifetimes and will register the service before executing any custom DI routines.
~~~csharp
using Microsoft.Extensions.DependencyInjection;
using StellaOps.DependencyInjection;
[ServiceBinding(typeof(IJob), ServiceLifetime.Scoped, RegisterAsSelf = true)]
public sealed class MyJob : IJob
{
// IJob dependencies can now use scoped services (Mongo sessions, etc.)
}
~~~
Use `RegisterAsSelf = true` when you also want to resolve the concrete type.
Set `ReplaceExisting = true` to override default descriptors if the host already provides one.
###5.2Dependency injection routines
For advanced scenarios continue to expose a routine:
~~~csharp
namespace StellaOps.DependencyInjection;
public sealed class IoCConfigurator : IDependencyInjectionRoutine
{
public IServiceCollection Register(IServiceCollection services, IConfiguration cfg)
{
services.AddSingleton<IJob, MyJob>(); // schedule job
services.Configure<MyPluginOptions>(cfg.GetSection("Plugins:MyPlugin"));
return services;
}
}
~~~
---
##6Schedule Plugins
##5DependencyInjection Entrypoint
Backend autodiscovers restarttime bindings through two mechanisms:
1. **Service binding metadata** for simple contracts.
2. **`IDependencyInjectionRoutine`** implementations when you need full control.
###5.1Service binding metadata
Annotate implementations with `[ServiceBinding]` to declare their lifetime and service contract.
The loader honours scoped lifetimes and will register the service before executing any custom DI routines.
~~~csharp
using Microsoft.Extensions.DependencyInjection;
using StellaOps.DependencyInjection;
[ServiceBinding(typeof(IJob), ServiceLifetime.Scoped, RegisterAsSelf = true)]
public sealed class MyJob : IJob
{
// IJob dependencies can now use scoped services (Mongo sessions, etc.)
}
~~~
Use `RegisterAsSelf = true` when you also want to resolve the concrete type.
Set `ReplaceExisting = true` to override default descriptors if the host already provides one.
###5.2Dependency injection routines
For advanced scenarios continue to expose a routine:
~~~csharp
namespace StellaOps.DependencyInjection;
public sealed class IoCConfigurator : IDependencyInjectionRoutine
{
public IServiceCollection Register(IServiceCollection services, IConfiguration cfg)
{
services.AddSingleton<IJob, MyJob>(); // schedule job
services.Configure<MyPluginOptions>(cfg.GetSection("Plugins:MyPlugin"));
return services;
}
}
~~~
---
##6Schedule Plugins
###6.1 Minimal Job
@@ -216,4 +216,213 @@ On merge, the plugin shows up in the UI Marketplace.
| NotDetected | .sig missing | cosign sign |
| VersionGateMismatch | Backend 2.1 vs plugin 2.0 | Recompile / bump attribute |
| FileLoadException | Duplicate | StellaOps.Common Ensure PrivateAssets="all" |
| Redis | timeouts Large writes | Batch or use Mongo |
| Redis | timeouts Large writes | Batch or use Mongo |
---
## 14 Plugin Version Compatibility (v2.0)
**IMPORTANT:** All plugins **must** declare a `[StellaPluginVersion]` attribute. Plugins without this attribute will be rejected by the host loader.
Declare your plugin's version and host compatibility requirements:
```csharp
using StellaOps.Plugin.Versioning;
// In AssemblyInfo.cs or any file at assembly level
[assembly: StellaPluginVersion("1.2.0", MinimumHostVersion = "1.0.0", MaximumHostVersion = "2.0.0")]
```
| Property | Purpose | Required |
|----------|---------|----------|
| `pluginVersion` (constructor) | Your plugin's semantic version | **Yes** |
| `MinimumHostVersion` | Lowest host version that can load this plugin | Recommended |
| `MaximumHostVersion` | Highest host version supported | Recommended for cross-major compatibility |
| `RequiresSignature` | Whether signature verification is mandatory (default: true) | No |
### Version Compatibility Rules
1. **Attribute Required:** Plugins without `[StellaPluginVersion]` are rejected
2. **Minimum Version:** Host version must be `MinimumHostVersion`
3. **Maximum Version:** Host version must be `MaximumHostVersion` (if specified)
4. **Strict Major Version:** If `MaximumHostVersion` is not specified, the plugin is assumed to only support the same major version as `MinimumHostVersion`
### Examples
```csharp
// Plugin works with host 1.0.0 through 2.x (explicit range)
[assembly: StellaPluginVersion("1.0.0", MinimumHostVersion = "1.0.0", MaximumHostVersion = "2.99.99")]
// Plugin works with host 2.x only (strict - no MaximumHostVersion means same major version)
[assembly: StellaPluginVersion("1.0.0", MinimumHostVersion = "2.0.0")]
// Plugin version 3.0.0 with no host constraints (uses plugin major version as reference)
[assembly: StellaPluginVersion("3.0.0")]
```
---
## 15 Plugin Host Configuration (v2.0)
Configure the plugin loader with security-first defaults in `PluginHostOptions`:
```csharp
var options = new PluginHostOptions
{
// Version enforcement (all default to true for security)
HostVersion = new Version(2, 0, 0),
EnforceVersionCompatibility = true, // Reject incompatible plugins
RequireVersionAttribute = true, // Reject plugins without [StellaPluginVersion]
StrictMajorVersionCheck = true, // Reject plugins crossing major version boundaries
// Signature verification (opt-in, requires infrastructure)
EnforceSignatureVerification = true,
SignatureVerifier = new CosignPluginVerifier(new CosignVerifierOptions
{
PublicKeyPath = "/keys/cosign.pub",
UseRekorTransparencyLog = true,
AllowUnsigned = false
})
};
var result = await PluginHost.LoadPluginsAsync(options, logger);
// Check for failures
if (result.HasFailures)
{
foreach (var failure in result.Failures)
{
logger.LogError("Plugin {Path} failed: {Reason} - {Message}",
failure.AssemblyPath, failure.Reason, failure.Message);
}
}
```
### Host Options Reference
| Option | Default | Purpose |
|--------|---------|---------|
| `HostVersion` | null | The host application version for compatibility checking |
| `EnforceVersionCompatibility` | **true** | Reject plugins that fail version checks |
| `RequireVersionAttribute` | **true** | Reject plugins without `[StellaPluginVersion]` |
| `StrictMajorVersionCheck` | **true** | Reject plugins that don't explicitly support the host's major version |
| `EnforceSignatureVerification` | false | Reject plugins without valid signatures |
| `SignatureVerifier` | null | The verifier implementation (e.g., `CosignPluginVerifier`) |
### Failure Reasons
| Reason | Description |
|--------|-------------|
| `LoadError` | Assembly could not be loaded (missing dependencies, corrupt file) |
| `SignatureInvalid` | Signature verification failed |
| `IncompatibleVersion` | Plugin version constraints not satisfied |
| `MissingVersionAttribute` | Plugin lacks required `[StellaPluginVersion]` attribute |
---
## 16 Fail-Fast Options Validation (v2.0)
Use the fail-fast validation pattern to catch configuration errors at startup:
```csharp
using StellaOps.DependencyInjection.Validation;
// Register options with automatic startup validation
services.AddOptionsWithValidation<MyPluginOptions, MyPluginOptionsValidator>(
MyPluginOptions.SectionName);
// Or with data annotations
services.AddOptionsWithDataAnnotations<MyPluginOptions>(
MyPluginOptions.SectionName);
```
Create validators using the base class:
```csharp
public sealed class MyPluginOptionsValidator : OptionsValidatorBase<MyPluginOptions>
{
protected override string SectionPrefix => "Plugins:MyPlugin";
protected override void ValidateOptions(MyPluginOptions options, ValidationContext context)
{
context
.RequireNotEmpty(options.BaseUrl, nameof(options.BaseUrl))
.RequirePositive(options.TimeoutSeconds, nameof(options.TimeoutSeconds))
.RequireInRange(options.MaxRetries, nameof(options.MaxRetries), 0, 10);
}
}
```
---
## 17 Available Templates (v2.0)
Install and use the official plugin templates:
```bash
# Install from local templates directory
dotnet new install ./templates
# Or install from NuGet
dotnet new install StellaOps.Templates
# Create a connector plugin
dotnet new stellaops-plugin-connector -n MyCompany.AcmeConnector
# Create a scheduled job plugin
dotnet new stellaops-plugin-scheduler -n MyCompany.CleanupJob
```
Templates include:
- Plugin entry point with version attribute
- Options class with data annotations
- Options validator with fail-fast pattern
- DI routine registration
- README with build/sign instructions
---
## 18 Migration Guide: v2.0 to v2.1
### Breaking Change: Version Attribute Required
As of v2.1, all plugins **must** include a `[StellaPluginVersion]` attribute. Plugins without this attribute will be rejected with `MissingVersionAttribute` failure.
**Before (v2.0):** Optional, plugins without attribute loaded with warning.
**After (v2.1):** Required, plugins without attribute are rejected.
### Migration Steps
1. Add the version attribute to your plugin's AssemblyInfo.cs:
```csharp
[assembly: StellaPluginVersion("1.0.0", MinimumHostVersion = "2.0.0", MaximumHostVersion = "2.99.99")]
```
2. If your plugin must support multiple major host versions, explicitly set `MaximumHostVersion`:
```csharp
// Supports host 1.x through 3.x
[assembly: StellaPluginVersion("1.0.0", MinimumHostVersion = "1.0.0", MaximumHostVersion = "3.99.99")]
```
3. Rebuild and re-sign your plugin.
### Opt-out (Not Recommended)
If you must load legacy plugins without version attributes:
```csharp
var options = new PluginHostOptions
{
RequireVersionAttribute = false, // Allow unversioned plugins (NOT recommended)
StrictMajorVersionCheck = false // Allow cross-major version loading
};
```
---
## Change Log
| Version | Date | Changes |
|---------|------|---------|
| v2.1 | 2025-12-14 | **Breaking:** `[StellaPluginVersion]` attribute now required by default. Added `RequireVersionAttribute`, `StrictMajorVersionCheck` options. Added `MissingVersionAttribute` failure reason. |
| v2.0 | 2025-12-14 | Added StellaPluginVersion attribute, Cosign verification options, fail-fast validation, new templates |
| v1.5 | 2025-07-11 | Template install, no hot-reload, IoC conventions |