# 8 · Detailed Module Specifications — Stella Ops This document defines every backend/agent module that composes Stella Ops, their public contracts, configuration keys and extension points.
## 0 Scope
Describes every .NET, and Angular project that ships in the OSS Core, the plug‑in contracts they expose, and the runtime artefacts (Dockerfiles, Compose files) used to build and operate them. Commercial capabilities appear only as extension points.
## 1 Repository Layout (flat)
src/
│ docker-compose.yml
└─ docker-compose-library/
│ ├─ docker-compose.no-deps.yml
│ ├─ docker-compose.dep.redis.yml
│ ├─ docker-compose.dep.mongo.yml
│ ├─ docker-compose.dep.proxy.yml
│ ├─ docker-compose.dep.repository.yml
│ └─ docker-compose.local.yml
└─ backend/
│ ├─ Dockerfile
│ ├─ StellaOps.Web/
│ ├─ StellaOps.Common/
│ ├─ StellaOps.Plugins/
│ ├─ StellaOps.Configuration/
│ ├─ StellaOps.Localization/
│ ├─ StellaOps.TlsProvider.OpenSSL/
│ ├─ StellaOps.TlsProvider.OpenSSLGost/
│ ├─ StellaOps.TlsProvider.Plugin.CryptoPro/
│ ├─ StellaOps.VulnerabilityDatabase/
│ ├─ StellaOps.Scheduling/
│ ├─ StellaOps.Scheduling.SbomsRescan/
│ ├─ StellaOps.Scheduling.MutesExpire/
│ ├─ StellaOps.Scheduling.Plugin.CommonCveFeed/
│ ├─ StellaOps.Scheduling.Plugin.RussianCveFeed/
│ ├─ StellaOps.Scanners.Trivy/
│ ├─ StellaOps.Quota/
│ ├─ StellaOps.Reporting/
│ ├─ StellaOps.Notifications/
│ ├─ StellaOps.Notifications.Email/
│ ├─ StellaOps.Notifications.Plugin.MsTeams/
│ ├─ StellaOps.Authority/
│ ├─ StellaOps.Authority.AD/
│ ├─ StellaOps.Agent.Santech/
│ └─ StellaOps.Agent.Zastava/
└─ frontend/
├─ Dockerfile
├─ angular.json
├─ stella-ops-ui/
└─ libs/
├─ dashboard/
├─ scans/
├─ settings/
├─ core-ui/
└─ i18n/
All projects are referenced by StellaOps.sln
; dotnet publish -c Release -p:PublishSingleFile=true
builds a self‑contained StellaOps.Api
binary (plug‑ins load at runtime).
## 2 Shared Libraries
Project | Purpose | Key Interfaces |
---|---|---|
StellaOps.Common |
Serilog sinks, Redis key helpers, DTO primitives. | RedisKeys , Result<T> |
StellaOps.Plugins |
Plug‑in contracts + Cosign verification. | IStellaPlugin , IScannerRunner , ITlsProvider , IScheduleJob |
StellaOps.Localization |
Loads JSON locale bundles (backend & Angular). | ILocaleProvider , CultureMiddleware |
Angular JSON‑bundle workflow matches the official i18n guide .
## 3 Core Back‑end Projects
Project | Responsibility | Extensibility |
---|---|---|
StellaOps.Api |
ASP.NET host; source‑gen auto‑wires module endpoints. | Attributes [MapRestController] , [MapHealth] . |
StellaOps.Configuration |
Bind appsettings.json → typed options; /health . |
IConfigValidator . |
StellaOps.Quota |
Enforces Free‑tier quota (333 scans/day) with early‑warning banner, 5 s soft back‑off, 60 s wait‑wall. | Swappable via IQuotaStore (e.g., Postgres). |
**StellaOps.JwtIssuer (new) |
Issues, refreshes and validates Client‑JWTs. For offline sites it produces a 30‑day token during OUK build and again on every OUK import. | ITokenSigner (e.g., HSM) |
StellaOps.TlsProvider.OpenSSL |
Default TLS suites. | New suites via ITlsProvider plug‑in. |
StellaOps.TlsProvider.OpenSSLGost |
GOST suites. | — |
StellaOps.VulnerabilityDatabase |
Feed‑merge CLI writing Redis. | IAdditionalFeedSource (OSV, GHSA, BDU). |
StellaOps.Scheduling |
Hangfire host inside API . | Jobs via IScheduleJob . |
StellaOps.Scheduling.SbomsRescan |
Nightly SBOM re‑scan (0 2 * * * ). |
— |
StellaOps.Scheduling.MutesExpire |
Daily mute expiry cleanup. | — |
StellaOps.Scanners.Trivy |
Trivy CLI for SBOM & image scans . | Other engines implement IScannerRunner . |
StellaOps.Reporting |
RazorLight HTML reports. | IReportRenderer for SARIF, CycloneDX. |
StellaOps.Notifications |
DI contracts for alerts. | INotifier . |
StellaOps.Notifications.Email |
SMTP channel. | — |
StellaOps.Authority |
OAuth2 / OIDC via OpenIddict 4 . | External IdPs via plug‑in. |
StellaOps.Registry |
read‑only Docker registry for agents + SBOM‑builder | Registry v2 (nginx‑hardened) |
StellaOps.MutePolicies |
store YAML / Rego policies, validate & version | MongoDB + Redis |
StellaOps.Attestor (TODO) |
SLSA provenance + Rekor verification | Sigstore Rekor |
## 3 · Module Details
Only contracts and configuration that may change in the next two quarters are shown; for stable, unchanging keys see the inline XML‑doc in the codebase.
### 3.1. StellaOps.Configuration
- Responsibility – parse environment variables or
appsettings.json
; expose/health
,/metrics
. - Key extension point –
IConfigValidator
→ validate & normalise custom settings before DI builds.
### 3.2. StellaOps.Authority
- Responsibility – ship with OpenIddict 6, supporting client‑credentials and password grants.
IIdentityProvider
plug‑in can delegate token issuance to LDAP, SAML, Keycloak …
### 3.3. StellaOps.Scanners
- Primary flow – SBOM‑first; falls back to image‑unpack if SBOM absent.
- Multi‑Format Support – side‑car
.sbom.type
file; auto‑detects (SPDXID:
orbomFormat
heuristics). - Delta Layer Workflow –
POST /layers/missing
(SET DIFF
on Redis) responds < 20 ms; SanTech passes only new layers. - Plug‑in contract evolution
// current
Task<ScanResult> RunAsync(Stream sbomJson, CancellationToken ct);
// v2 (preferred)
Task<ScanResult> RunAsync(Stream sbom, SbomFormat fmt, CancellationToken ct);
### 3.5 StellOps.Registry
- Purpose – internal, anonymous read‑only Docker registry to avoid GHCR / Docker Hub pulls.
- Deployment – container
stellops.registry:2
; mounted volume/var/lib/registry
; optional TLS via env vars.
Key | Default | Notes |
---|---|---|
REGISTRY_READONLY |
true |
Forces 403 on PUT, 405 on DELETE |
REGISTRY_STORAGE_DELETE_ENABLED |
false |
Immutable tags |
Plug‑in contract — IRegistryProvider.PullAsync(string imageRef)
for mapping to Artifactory, Harbor, etc.
### 3.6 StellaOps.MutePolicies
- Purpose – central Policy‑as‑Code store (YAML v1 now, Rego soon).
- Persistence – current live rules in Redis (
policies:active
); immutable commits in Mongopolicies_history
.
REST verb | Path | Description |
---|---|---|
GET |
/policy/export |
download active YAML |
POST |
/policy/import |
upload YAML / Rego file |
POST |
/policy/validate |
lint without persisting |
CLI – SanTech gains --policy-file scan-policy.yaml
.
Plug‑in contract — IPolicyStore
for GitOps back‑ends, Vault, etc.
### 3.7. StellaOps.Attestor (Planned – Q1‑2026)
Handles SLSA provenance docs and Rekor log verification.
public interface IAttestor {
Task<ProvenanceDoc> CreateAsync(ImageRef img, Sbom sbom);
Task<bool> VerifyAsync(ProvenanceDoc doc);
}
### 3.7. StellaOps.FeedMerger
Nightly Hangfire job (01:00) merges NVD JSON; plug‑ins can provide ISourceFeed for OSV, GHSA, BDU feeds.
### 3.8. StellOps.Tls
Abstracts TLS stack; default OpenSSL; ITlsProvider lets enterprises swap in GOST or SM cipher suites.
### 3.9. StellaOps.Reporting
HTML / PDF generation via RazorLight; custom renderers via IReportRenderer.
### 3.10 UI
Angular 17 SPA; lazy‑loaded feature modules, standalone component routes for UI plug‑ins.
Static Go daemon / k8s DaemonSet; watches Docker/CRI‑O events; uploads SBOMs; optional enforce mode via policy plug‑in.
### 3.11 StellaOps.Quota — Free‑Tier Daily Quota Service
Responsibility
- Track per‑token scan count (
quota:<token>
key in Redis). - Reset counters at 00:00 UTC with key TTL.
- Inject HTTP headers
X‑Stella‑Quota‑Remaining
X‑Stella‑Reset
- Apply adaptive throttling:
- scans 0‑199 → normal;
- scans 200‑332 → UI banner flag
X‑Stella‑Quota‑Warn:true
; - scans ≥ 333 → respond
429
with escalatingRetry‑After
values
(5 s for first 30 hits, then 60 s).
- Offline token awareness — if
token.valid == false
andOfflineMode == true
, return HTTP 451 ComplianceBlock so that CLI gives a clear actionable error. - New config:
"Quota": {
"OfflineGraceDays": 7 // show banner this many days before token expiry
}
Interface
public interface IQuotaService
{
/// <summary>Returns true when the call is allowed.</summary>
Task<QuotaVerdict> CheckAsync(string token, CancellationToken ct);
}
public readonly record struct QuotaVerdict(
bool IsAllowed,
int Remaining,
DateTimeOffset ResetUtc,
TimeSpan RetryAfter);
Configuration (appsettings.json
keys)
"Quota": {
"FreeTierDailyLimit": 333,
"WarnThreshold": 200,
"SoftRetrySeconds": 5,
"HardRetrySeconds": 60
}
Extensibility
- Override storage by providing an
IQuotaStore
plug‑in for Postgres or Mongo. - UI plug‑ins can subscribe to SSE
/quota/events
for custom dashboards.
### 3.12 StellaOps.JwtIssuer — new section
API | Path | Notes |
---|---|---|
POST /token/offline |
Admin‑only. | Generates a 30 d Client‑JWT for air‑gapped clusters; returns ZIP that the admin can copy to the target host. |
OUK hook
- OUK builder calls JwtIssuer.SignOfflineToken(exp=+30d).
- Drops client.jwt into ouk/root/.
- Backend OUK importer places file under /var/lib/stella/tokens/.
## 4 · Compose / Helm Snippet (reference)
services:
registry:
image: stellops.registry:2
restart: unless-stopped
environment:
REGISTRY_READONLY: "true"
volumes:
- ./_registry:/var/lib/registry
ports:
- "5000:5000"
backend:
image: registry.local/stellops/backend:${TAG}
depends_on: [registry, redis]
## 4 Plug‑ins (sign‑required)
Plug‑in | Contract | Notes |
---|---|---|
StellaOps.Notifications.Plugin.MsTeams |
INotifier |
Sends cards to Teams webhooks. |
StellaOps.Authority.AD |
IIdentityProvider |
LDAP/Active‑Directory token issue. |
StellaOps.Scheduling.Plugin.CommonCveFeed |
IScheduleJob |
Merges OSV & NVD JSON hourly . |
StellaOps.Scheduling.Plugin.RussianCveFeed |
IScheduleJob |
Imports BDU XML daily. |
StellaOps.TlsProvider.Plugin.CryptoPro |
ITlsProvider |
Binds CryptoPro shared libs. |
Cosign signatures are mandatory; loader rejects unsigned DLLs when DisableUnsigned=false
.
## 5 Agents
### 5.1 StellaOps.Agent.Santech
Distroless CLI; Returns exit‑code 1 on policy violation, enabling CI blocking.
- Role – CI helper: Build SBOM, call
/scan
, exit non‑zero on high severity. - Flags –
--engine
,--threshold
,--registry-pull-token
,--pdf-out
,--delta
,--sbom-type
,--policy-file.
. - Auth – OAuth2 scanner scope.
### 5.2 StellaOps.Agent.Zastava
- Role – Passive container inventory → uploads SBOMs via
/agent/sbom
. - Modes –
off
,inventory
(Core default). - No kernel driver (unlike Falco) .
## 6 Angular Front‑end
Package | Path | Feature | Lazy |
---|---|---|---|
App | frontend/stella-ops-ui/ |
Shell, auth guards. | — |
dashboard |
libs/dashboard/ |
Live metrics tiles. | ✔ |
scans |
libs/scans/ |
List, detail, mute, diff. | ✔ |
settings |
libs/settings/ |
Feed cron, workers, TLS switch. | ✔ |
core-ui |
libs/core-ui/ |
Tailwind components. | — |
i18n |
libs/i18n/ |
Runtime locale switch, pipe. | — |
Lazy loading of workspace libs follows Nx/Angular guidance .
## 7 Docker Artefacts
### 7.1 Dockerfiles
backend/Dockerfile
– multi‑stage .NET 9; single‑file publish; distroless runtime .frontend/Dockerfile
– Node 20 build → Nginx static serve.- Every plug‑in repo may include its own Dockerfile when shipping side‑cars (e.g., custom scanner).
### 7.2 Compose Stacks
-
docker-compose.yml
- Extends above with Redis 7 and Mongo 7 for small on‑prem installs.
-
docker-compose.no-deps.yml
- backend, frontend, Trivy, Maven proxy.
- Assumes external Redis & Mongo.
-
docker-compose.local.yml
- Build images from local source and bring up backend, frontend, Redis, Mongo, Trivy, Maven proxy for dev‑loop.
Docker Compose override precedence matches official docs .
## 8 Performance Budget
Flow | P95 target | Bottleneck |
---|---|---|
SBOM fast‑path | ≤ 5 s | Redis queue depth (keep P99 < 1 ms) |
Image‑unpack | ≤ 10 s | Trivy layer unpack. |
Nightly re‑scan | 80 SBOM/s | Runner CPU. |
## Change Log
Version | Date | Notes |
---|---|---|
v2.2 | 2025‑07‑11 | Flat layout; stella‑ops‑ui naming; Dockerfiles & 3 Compose stacks; agents and localisation library. |
v2.1 | 2025‑07‑11 | First flat‑structure draft. |
(End of Module Specifications v2.2‑core)