11 KiB
Plugin Architecture & Extensibility Patterns
Version: 1.0 Date: 2025-11-28 Status: Canonical
This advisory consolidates the extensibility patterns used across Stella Ops modules, providing a unified view for architects and developers implementing custom integrations.
1. Overview
Stella Ops uses a plugin-based architecture enabling customers and partners to extend functionality without modifying core code. The platform supports three primary extension types:
| Type | Module | Purpose | Examples |
|---|---|---|---|
| Connectors | Concelier, Excititor | Ingest/export data from external sources | NVD, OSV, vendor VEX feeds |
| Plugins | Authority, Scanner | Extend runtime behavior | LDAP auth, custom analyzers |
| Analyzers | Scanner | Add detection capabilities | Language-specific, binary analysis |
2. Core Principles
2.1 Determinism
All plugins must produce deterministic outputs for identical inputs:
- No global state between invocations
- Timestamps in UTC ISO-8601
- Stable ordering of collections
- Reproducible hashing with documented algorithms
2.2 Offline-First
Plugins must function in air-gapped environments:
- No network access unless explicitly configured
- Local configuration and secrets
- Bundled dependencies (no runtime downloads)
- Offline-capable credential stores
2.3 Restart-Safe
Plugins load at service startup only:
- No hot-reload (security/determinism trade-off)
- Configuration changes require restart
- State persists in external stores (MongoDB, filesystem)
3. Plugin Lifecycle
┌─────────────────────────────────────────────────────────────────┐
│ Host Startup │
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 1. Configuration Load │
│ - Read YAML manifests from etc/<module>.plugins/ │
│ - Validate capability tokens │
│ - Resolve relative paths │
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 2. Assembly Discovery │
│ - Scan plugin binaries directory │
│ - Match assemblies to manifest descriptors │
│ - Load assemblies into isolated context │
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 3. Registrar Execution │
│ - Find IPluginRegistrar implementations │
│ - Bind options from configuration │
│ - Register services in DI container │
│ - Queue bootstrap tasks (optional) │
└─────────────────────────────────┬───────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ 4. Runtime │
│ - Host resolves plugin services via DI │
│ - Capability metadata guides feature exposure │
│ - Health checks report plugin status │
└─────────────────────────────────────────────────────────────────┘
4. Concelier Connectors
4.1 Purpose
Connectors ingest vulnerability advisories from external sources into the Concelier merge engine.
4.2 Interface
public interface IAdvisoryConnector
{
string ConnectorId { get; }
Task<IAsyncEnumerable<RawAdvisory>> FetchAsync(
ConnectorContext context,
CancellationToken ct);
Task<ConnectorHealth> CheckHealthAsync(CancellationToken ct);
}
4.3 Built-in Connectors
| Connector | Source | Format |
|---|---|---|
nvd |
NVD API 2.0 | CVE JSON |
osv |
OSV.dev | OSV JSON |
ghsa |
GitHub Advisory Database | GHSA JSON |
oval |
Vendor OVAL feeds | OVAL XML |
csaf |
CSAF repositories | CSAF JSON |
4.4 Developer Guide
See: docs/dev/30_EXCITITOR_CONNECTOR_GUIDE.md
5. Authority Plugins
5.1 Purpose
Authority plugins extend authentication with custom identity providers, credential stores, and client management.
5.2 Interface
public interface IAuthorityPluginRegistrar
{
void ConfigureServices(IServiceCollection services, PluginContext context);
void ConfigureOptions(IConfiguration config);
}
public interface IIdentityProviderPlugin
{
string ProviderId { get; }
AuthorityIdentityProviderCapabilities Capabilities { get; }
Task<AuthenticationResult> AuthenticateAsync(AuthenticationRequest request);
}
5.3 Capabilities
Plugins declare capabilities via manifest:
plugins:
descriptors:
ldap:
assemblyName: "StellaOps.Authority.Plugin.Ldap"
capabilities:
- password
- mfa
- clientProvisioning
| Capability | Description |
|---|---|
password |
Username/password authentication |
mfa |
Multi-factor authentication support |
clientProvisioning |
Dynamic OAuth client registration |
bootstrap |
Initial admin user creation |
5.4 Developer Guide
See: docs/dev/31_AUTHORITY_PLUGIN_DEVELOPER_GUIDE.md
6. Scanner Analyzers
6.1 Purpose
Analyzers extend the Scanner with language-specific or binary-level detection capabilities.
6.2 Interface
public interface IScanAnalyzer
{
string AnalyzerId { get; }
IReadOnlyList<string> SupportedEcosystems { get; }
Task<AnalysisResult> AnalyzeAsync(
ScanContext context,
IAsyncEnumerable<ScanArtifact> artifacts,
CancellationToken ct);
}
6.3 Built-in Analyzers
| Analyzer | Ecosystem | Detection Method |
|---|---|---|
syft |
Multi-ecosystem | SBOM generation |
grype-db |
Multi-ecosystem | Vulnerability matching |
elf-symbols |
Binary/ELF | Symbol table analysis |
buildid |
Binary/ELF | Build-ID extraction |
dotnet-deps |
.NET | deps.json parsing |
6.4 Surface Validation
The Scanner supports extensible surface validation for detecting risky patterns:
public interface ISurfaceValidator
{
string ValidatorId { get; }
Task<SurfaceValidationResult> ValidateAsync(
SurfaceContext context,
CancellationToken ct);
}
See: docs/modules/scanner/guides/surface-validation-extensibility.md
7. Manifest Structure
All plugins use a standard manifest format:
{
"pluginId": "example-plugin",
"version": "1.0.0",
"assemblyName": "StellaOps.Module.Plugin.Example",
"hostVersion": ">=2.0.0",
"capabilities": ["capability1", "capability2"],
"configuration": {
"requiredSettings": ["setting1"],
"optionalSettings": ["setting2"]
},
"dependencies": {
"packages": ["Dependency.Package@1.0.0"]
}
}
8. Security Considerations
8.1 Assembly Isolation
- Plugins load in dedicated assembly contexts
- Host enforces capability-based access control
- Network access requires explicit configuration
8.2 Configuration Validation
- Unknown capability tokens rejected at startup
- Path traversal in relative paths blocked
- Secrets never logged or exposed in diagnostics
8.3 Audit Trail
- Plugin loading events logged with assembly hash
- Configuration changes recorded
- Runtime errors captured with context
9. Offline Kit Integration
Plugins must support offline distribution:
offline-kit/
├── plugins/
│ ├── authority/
│ │ ├── StellaOps.Authority.Plugin.Ldap.dll
│ │ └── manifest.json
│ ├── scanner/
│ │ ├── StellaOps.Scanner.Analyzer.Custom.dll
│ │ └── manifest.json
│ └── checksums.sha256
├── config/
│ └── plugins.yaml
└── MANIFEST.json
9.1 Checksum Verification
All plugin assemblies verified against checksums.sha256 before loading.
9.2 Version Compatibility
Host rejects plugins with incompatible hostVersion requirements.
10. Testing Requirements
10.1 Unit Tests
- Registrar binds options correctly
- Services resolve from DI container
- Capability metadata accurate
10.2 Integration Tests
- Plugin loads in host process
- Health checks pass
- Functionality works end-to-end
10.3 Test Helpers
// Use StellaOps.Plugin.Tests helpers
var host = new PluginTestHost()
.WithPlugin<MyPlugin>()
.WithConfiguration(config)
.Build();
var plugin = host.GetRequiredService<IMyPlugin>();
var result = await plugin.DoSomethingAsync();
11. Related Documentation
| Resource | Location |
|---|---|
| General plugin guide | docs/dev/plugins/README.md |
| Concelier connector guide | docs/dev/30_EXCITITOR_CONNECTOR_GUIDE.md |
| Authority plugin guide | docs/dev/31_AUTHORITY_PLUGIN_DEVELOPER_GUIDE.md |
| Scanner extensibility | docs/modules/scanner/guides/surface-validation-extensibility.md |
| Platform architecture | docs/modules/platform/architecture-overview.md |
12. Sprint Mapping
No dedicated sprint - plugin infrastructure is foundational. Related tasks appear in:
- Module-specific sprints (Authority, Scanner, Concelier)
- Platform infrastructure sprints
13. Success Metrics
| Metric | Target |
|---|---|
| Plugin load time | < 500ms per plugin |
| Configuration validation | 100% coverage of manifest schema |
| Offline kit verification | All plugins checksum-verified |
| Documentation coverage | All plugin types documented |
Last updated: 2025-11-28