# 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) ~~~text 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` | | `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) | `IRegistryProvider` | | **`StellaOps.MutePolicies`** | store YAML / Rego policies, validate & version | MongoDB + Redis | `IPolicyStore` | | **`StellaOps.Attestor`** *(TODO)*| SLSA provenance + Rekor verification | Sigstore Rekor | `IAttestor` | ## 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:` or `bomFormat` heuristics). * **Delta Layer Workflow** – `POST /layers/missing` (`SET DIFF` on Redis) responds < 20 ms; SanTech passes only new layers. * **Plug‑in contract evolution** ```csharp // current Task RunAsync(Stream sbomJson, CancellationToken ct); // v2 (preferred) Task 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 Mongo `policies_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. ```csharp public interface IAttestor { Task CreateAsync(ImageRef img, Sbom sbom); Task 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:` 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 escalating `Retry‑After` values (5 s for first 30 hits, then 60 s). * **Offline token awareness** — if `token.valid == false` and `OfflineMode == true`, return HTTP *451 ComplianceBlock* so that CLI gives a clear actionable error. * New config: ```json "Quota": { "OfflineGraceDays": 7 // show banner this many days before token expiry } ``` **Interface** ```csharp public interface IQuotaService { /// Returns true when the call is allowed. Task CheckAsync(string token, CancellationToken ct); } public readonly record struct QuotaVerdict( bool IsAllowed, int Remaining, DateTimeOffset ResetUtc, TimeSpan RetryAfter); ``` **Configuration** (`appsettings.json` keys) ```json "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) ```yaml 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)*