#  18 · Coding Standards & Contributor Guide — **Stella Ops** *(v2.0 — 12 Jul 2025 · supersedes v1.0)* > **Audience** — Anyone sending a pull‑request to the open‑source Core. > **Goal** — Keep the code‑base small‑filed, plug‑in‑friendly, DI‑consistent, and instantly readable. --- ##  0 Why read this? * Cuts review time → quicker merges. * Guarantees code is **hot‑load‑safe** for run‑time plug‑ins. * Prevents style churn and merge conflicts. --- ##  1 High‑level principles 1. **SOLID first** – especially Interface & Dependency Inversion. 2. **100‑line rule** – any file > 100 physical lines must be split or refactored. 3. **Contract‑level ownership** – public abstractions live in lightweight *Contracts* libraries; impl classes live in runtime projects. 4. **Single Composition Root** – all DI wiring happens in **`StellaOps.Web/Program.cs`** and in each plug‑in’s `IoCConfigurator`; nothing else calls `IServiceCollection.BuildServiceProvider`. 5. **No Service Locator** – constructor injection only; static `ServiceProvider` is banned. 6. **Fail‑fast startup** – configuration validated before the web‑host listens. 7. **Hot‑load compatible** – no static singletons that survive plug‑in unload; avoid `Assembly.LoadFrom` outside the built‑in plug‑in loader. --- ##  2 Repository layout (flat, July‑2025)** ```text src/ ├─ backend/ │ ├─ StellaOps.Web/ # ASP.NET host + composition root │ ├─ StellaOps.Common/ # Serilog, Result, helpers │ ├─ StellaOps.Contracts/ # DTO + interface contracts (no impl) │ ├─ StellaOps.Configuration/ # Options + validation │ ├─ StellaOps.Localization/ │ ├─ StellaOps.PluginLoader/ # Cosign verify, hot‑load │ ├─ StellaOps.Scanners.Trivy/ # First‑party scanner │ ├─ StellaOps.TlsProviders.OpenSsl/ │ └─ … (additional runtime projects) ├─ plugins-sdk/ # Templated contracts & abstractions └─ frontend/ # Angular workspace tests/ # Mirrors src structure 1‑to‑1 ``` There are no folders named “Module” and no nested solutions. ##  3 Naming & style conventions | Element | Rule | Example | | ------------------------------------------------------------------------------- | --------------------------------------- | ------------------------------- | | Namespaces | File‑scoped, StellaOps. | namespace StellaOps.Scanners; | | Interfaces | I prefix, PascalCase | IScannerRunner | | Classes / records | PascalCase | ScanRequest, TrivyRunner | | Private fields | camelCase (no leading underscore) | redisCache, httpClient | | Constants | SCREAMING_SNAKE_CASE | const int MAX_RETRIES = 3; | | Async methods | End with Async | Task ScanAsync() | | File length | ≤ 100 lines incl. using & braces | enforced by dotnet format check | | Using directives | Outside namespace, sorted, no wildcards | — | Static analyzers (.editorconfig, StyleCop.Analyzers package) enforce the above. ##  4 Dependency‑injection policy Composition root – exactly one per process: ```csharp builder.Services .AddStellaCore() // extension methods from each runtime project .AddPluginLoader("/Plugins", cfg); // hot‑load signed DLLs ``` Plug‑ins register additional services via the IoCConfigurator convention described in the Plug‑in SDK Guide, §5. Never resolve services manually (provider.GetService()) outside the composition root; tests may use WebApplicationFactory or ServiceProvider.New() helpers. Scoped lifetime is default; singletons only for stateless, thread‑safe helpers. ##  5 Project organisation rules Contracts vs. Runtime – public DTO & interfaces live in .Contracts; implementation lives in sibling project. Feature folders – inside each runtime project group classes by use‑case, e.g. ```text ├─ Scan/ │ ├─ ScanService.cs │ └─ ScanController.cs ├─ Feed/ └─ Tls/ ``` Tests – mirror the structure under tests/ one‑to‑one; no test code inside production projects. ##  6 C# language features Nullable reference types enabled. record for immutable DTOs. Pattern matching encouraged; avoid long switch‑cascades. Span & Memory OK when perf‑critical, but measure first. Use await foreach over manual paginator loops. ##  7 Error‑handling template ```csharp public async Task PostScan([FromBody] ScanRequest req) { if (!ModelState.IsValid) return BadRequest(ModelState); try { ScanResult result = await scanService.ScanAsync(req); if (result.Quota != null) { Response.Headers.TryAdd("X-Stella-Quota-Remaining", result.Quota.Remaining.ToString()); Response.Headers.TryAdd("X-Stella-Reset", result.Quota.ResetUtc.ToString("o")); } return Ok(result); } } ``` RFC 7807 ProblemDetails for all non‑200s. Capture structured logs with Serilog’s message‑template syntax. ##  8 Async & threading * All I/O is async; no .Result / .Wait(). * Library code: ConfigureAwait(false). * Limit concurrency via Channel or Parallel.ForEachAsync, never raw Task.Run loops. ##  9 Testing rules | Layer | Framework | Coverage gate | | ------------------------ | ------------------------ | -------------------------- | | Unit | xUnit + FluentAssertions | ≥ 80 % line, ≥ 60 % branch | | Integration | Testcontainers | Real Redis & Trivy | | Mutation (critical libs) | Stryker.NET | ≥ 60 % score | One test project per runtime/contract project; naming .Tests. ##  10 Static analysis & formatting * dotnet format must exit clean (CI gate). * StyleCop.Analyzers + Roslyn‑Security‑Guard run on every PR. * CodeQL workflow runs nightly on main. ##  11 Commit & PR checklist * Conventional Commit prefix (feat:, fix:, etc.). * dotnet format & dotnet test both green. * Added or updated XML‑doc comments for public APIs. * File count & length comply with 100‑line rule. * If new public contract → update relevant markdown doc & JSON‑Schema. ##  12 Common pitfalls |Symptom| Root cause | Fix |-------|-------------|------------------- |InvalidOperationException: Cannot consume scoped service...| Mis‑matched DI lifetimes| Use scoped everywhere unless truly stateless |Hot‑reload plug‑in crash| Static singleton caching plugin types| Store nothing static; rely on DI scopes > 100‑line style violation |Large handlers or utils |Split into private helpers or new class ##  13 Change log | Version | Date | Notes | | ------- | ---------- | -------------------------------------------------------------------------------------------------- | | v2.0 | 2025‑07‑12 | Updated DI policy, 100‑line rule, new repo layout, camelCase fields, removed “Module” terminology. | | 1.0 | 2025‑07‑09 | Original standards. |