Files
git.stella-ops.org/docs/08_MODULE_SPECIFICATIONS.md

373 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#8 · Detailed Module Specifications — **StellaOps**
_This document defines every backend/agent module that composes Stella Ops,
their public contracts, configuration keys and extension points._
---
##0Scope
Describes **every .NET, and Angular project** that ships in the OSS Core, the plugin contracts they expose, and the runtime artefacts (Dockerfiles, Compose files) used to build and operate them. Commercial capabilities appear *only* as extension points.
---
##1Repository 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 selfcontained **`StellaOps.Api`** binary (plugins load at runtime).
---
##2Shared Libraries
| Project | Purpose | Key Interfaces |
|---------|---------|----------------|
| `StellaOps.Common` | Serilog sinks, Redis key helpers, DTO primitives. | `RedisKeys`, `Result<T>` |
| `StellaOps.Plugins` | Plugin contracts + Cosign verification. | `IStellaPlugin`, `IScannerRunner`, `ITlsProvider`, `IScheduleJob` |
| `StellaOps.Localization` | Loads JSON locale bundles (backend & Angular). | `ILocaleProvider`, `CultureMiddleware` |
Angular JSONbundle workflow matches the official i18n guide.
---
##3Core Backend Projects
| Project | Responsibility | Extensibility |
|---------|----------------|---------------|
| **`StellaOps.Api`** | ASP.NET host; sourcegen autowires module endpoints. | Attributes `[MapRestController]`, `[MapHealth]`. |
| **`StellaOps.Configuration`** | Bind `appsettings.json` → typed options; `/health`. | `IConfigValidator`. |
| **`StellaOps.Quota`** | Enforces **Freetier quota** (333 scans/day) with earlywarning banner, 5s soft backoff, 60s waitwall. | Swappable via `IQuotaStore` (e.g., Postgres). |
| **`StellaOps.JwtIssuer` *(new)* | Issues, refreshes and validates **ClientJWTs**. For offline sites it produces a 30day token during OUK build and again on every OUK import. | `ITokenSigner` (e.g., HSM) |
| **`StellaOps.TlsProvider.OpenSSL`** | Default TLS suites. | New suites via `ITlsProvider` plugin. |
| **`StellaOps.TlsProvider.OpenSSLGost`** | GOST suites. | — |
| **`StellaOps.VulnerabilityDatabase`** | Feedmerge CLI writing Redis. | `IAdditionalFeedSource` (OSV, GHSA, BDU). |
| **`StellaOps.Scheduling`** | Hangfire host inside API . | Jobs via `IScheduleJob`. |
| **`StellaOps.Scheduling.SbomsRescan`** | Nightly SBOM rescan (`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 OpenIddict4 . | External IdPs via plugin. |
| **`StellaOps.Registry`** | readonly Docker registry for agents + SBOMbuilder | Registryv2 (nginxhardened) | `IRegistryProvider` |
| **`StellaOps.MutePolicies`** | store YAML / Rego policies, validate & version | MongoDB + Redis | `IPolicyStore` |
| **`StellaOps.Attestor`** *(TODO)*| SLSA provenance + Rekor verification | Sigstore Rekor | `IAttestor` |
##3·ModuleDetails
> _Only contracts and configuration that may change in the next two quarters are shown; for stable, unchanging keys see the inline XMLdoc 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 *clientcredentials* and *password* grants.
* `IIdentityProvider` plugin can delegate token issuance to LDAP, SAML, Keycloak 
###3.3. StellaOps.Scanners
* **Primary flow** SBOMfirst; falls back to imageunpack if SBOM absent.
* **MultiFormat Support** sidecar `.sbom.type` file; autodetects (`SPDXID:` or `bomFormat` heuristics).
* **Delta Layer Workflow** `POST /layers/missing` (`SET DIFF` on Redis) responds <20ms; SanTech passes only new layers.
* **Plugin contract evolution**
```csharp
// current
Task<ScanResult> RunAsync(Stream sbomJson, CancellationToken ct);
// v2 (preferred)
Task<ScanResult> RunAsync(Stream sbom, SbomFormat fmt, CancellationToken ct);
```
###3.5StellOps.Registry
* **Purpose** internal, anonymous **readonly** 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 |
**Plugin contract**  `IRegistryProvider.PullAsync(string imageRef)` for mapping to Artifactory, Harbor, etc.
---
###3.6StellaOps.MutePolicies
* **Purpose** central PolicyasCode 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`.
**Plugin contract** `IPolicyStore` for GitOps backends, Vault, etc.
---
###3.7. StellaOps.Attestor *(Planned  Q12026)*
Handles SLSA provenance docs and Rekor log verification.
```csharp
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; plugins 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; lazyloaded feature modules, standalone component routes for UI plugins.
Static Go daemon / k8s DaemonSet; watches Docker/CRIO events; uploads SBOMs; optional enforce mode via policy plugin.
###3.11 StellaOps.Quota — **FreeTier Daily Quota Service**
**Responsibility**
* Track pertoken scan count (`quota:<token>` key in Redis).
* Reset counters at **00:00UTC** with key TTL.
* Inject HTTP headers
* `XStellaQuotaRemaining`
* `XStellaReset`
* Apply adaptive throttling:
* scans0199  normal;
* scans200332  UI banner flag `XStellaQuotaWarn:true`;
* scans333  respond **`429`** with escalating `RetryAfter` values
(5s for first 30 hits, then 60s).
* **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
{
/// <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)
```json
"Quota": {
"FreeTierDailyLimit": 333,
"WarnThreshold": 200,
"SoftRetrySeconds": 5,
"HardRetrySeconds": 60
}
```
**Extensibility**
* Override storage by providing an `IQuotaStore` plugin for Postgres or Mongo.
* UI plugins can subscribe to SSE `/quota/events` for custom dashboards.
###3.12 StellaOps.JwtIssuer — new section
|API |Path| Notes|
|-----|----|-------|
|`POST /token/offline` | Adminonly. | Generates a 30d ClientJWT for airgapped 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]
```
---
##4Plugins (signrequired)
| Plugin | Contract | Notes |
|---------|----------|-------|
| `StellaOps.Notifications.Plugin.MsTeams` | `INotifier` | Sends cards to Teams webhooks. |
| `StellaOps.Authority.AD` | `IIdentityProvider` | LDAP/ActiveDirectory token issue. |
| `StellaOps.Scheduling.Plugin.CommonCveFeed` | `IScheduleJob` | Merges OSV & NVDJSON 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`.
---
##5Agents
###5.1`StellaOps.Agent.Santech`
Distroless CLI;
Returns exitcode1 on policy violation, enabling CI blocking.
* **Role** CI helper: Build SBOM, call `/scan`, exit nonzero 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) .
---
##6Angular Frontend
| 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 .
---
##7Docker Artefacts
###7.1Dockerfiles
* **`backend/Dockerfile`** multistage .NET 9; singlefile publish; distroless runtime .
* **`frontend/Dockerfile`** Node 20 build Nginx static serve.
* Every plugin repo may include its own Dockerfile when shipping sidecars (e.g., custom scanner).
###7.2Compose Stacks
* **`docker-compose.yml`**
* Extends above with Redis 7 and Mongo 7 for small onprem 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 devloop.
Docker Compose override precedence matches official docs.
---
##8Performance Budget
| Flow | P95 target | Bottleneck |
|------|-----------:|-----------|
| SBOM fastpath | 5s | Redis queue depth (keep P99 <1ms) |
| Imageunpack | 10s | Trivy layer unpack. |
| Nightly rescan | 80SBOM/s | Runner CPU. |
---
##Change Log
| Version | Date | Notes |
|---------|------|-------|
| **v2.2** | 20250711 | Flat layout; stellaopsui naming; Dockerfiles & 3 Compose stacks; agents and localisation library. |
| v2.1 | 20250711 | First flatstructure draft. |
*(End of Module Specifications v2.2core)*