Initial commit (history squashed)
	
		
			
	
		
	
	
		
	
		
			Some checks failed
		
		
	
	
		
			
				
	
				Build Test Deploy / authority-container (push) Has been cancelled
				
			
		
			
				
	
				Build Test Deploy / docs (push) Has been cancelled
				
			
		
			
				
	
				Build Test Deploy / deploy (push) Has been cancelled
				
			
		
			
				
	
				Build Test Deploy / build-test (push) Has been cancelled
				
			
		
			
				
	
				Docs CI / lint-and-preview (push) Has been cancelled
				
			
		
		
	
	
				
					
				
			
		
			Some checks failed
		
		
	
	Build Test Deploy / authority-container (push) Has been cancelled
				
			Build Test Deploy / docs (push) Has been cancelled
				
			Build Test Deploy / deploy (push) Has been cancelled
				
			Build Test Deploy / build-test (push) Has been cancelled
				
			Docs CI / lint-and-preview (push) Has been cancelled
				
			This commit is contained in:
		
							
								
								
									
										169
									
								
								docs/18_CODING_STANDARDS.md
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										169
									
								
								docs/18_CODING_STANDARDS.md
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,169 @@ | ||||
| #  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<T>, 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.<Area>           | 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<ScanResult> 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<T>()) 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 <Area>.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<T> & Memory<T> OK when perf‑critical, but measure first. | ||||
| Use await foreach over manual paginator loops. | ||||
|  | ||||
| ##  7 Error‑handling template | ||||
|  | ||||
| ```csharp | ||||
| public async Task<IActionResult> 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<T> 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 <Project>.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.                                                                                | | ||||
		Reference in New Issue
	
	Block a user