old sprints work, new sprints for exposing functionality via cli, improve code_of_conduct and other agents instructions
This commit is contained in:
@@ -1,88 +1,679 @@
|
||||
# Stella Ops Code of Conduct
|
||||
*Contributor Covenant v2.1 + project‑specific escalation paths*
|
||||
|
||||
> We pledge to make participation in the Stella Ops community a
|
||||
> harassment‑free experience for everyone, regardless of age, body size,
|
||||
> disability, ethnicity, sex characteristics, gender identity and expression,
|
||||
> level of experience, education, socio‑economic status, nationality,
|
||||
> personal appearance, race, religion, or sexual identity and orientation.
|
||||
# StellaOps Engineering Code of Conduct
|
||||
*Technical excellence + safe for change = best-in-class product*
|
||||
|
||||
---
|
||||
|
||||
## 0 · Our standard
|
||||
## 0 · Mission and Values
|
||||
|
||||
This project adopts the
|
||||
[**Contributor Covenant v2.1**](https://www.contributor-covenant.org/version/2/1/code_of_conduct/)
|
||||
with the additions and clarifications listed below.
|
||||
If anything here conflicts with the upstream covenant, *our additions win*.
|
||||
**StellaOps** is a sovereign, self-hostable release control plane delivering reproducible, auditable, and secure software releases for non-Kubernetes container estates. We are committed to building a **best-in-class product that is safe for change** — where every contribution improves quality, maintainability, and security without regression.
|
||||
|
||||
### Our Engineering Pledge
|
||||
|
||||
We pledge to uphold:
|
||||
|
||||
1. **Technical Excellence** — Code that is deterministic, testable, and production-ready from day one.
|
||||
2. **Safety for Change** — Comprehensive testing, minimal surprise, and zero tolerance for silent failures.
|
||||
3. **Security by Design** — Input validation, least privilege, cryptographic correctness, and defense in depth.
|
||||
4. **Maintainability First** — Clear contracts, minimal coupling, immutable outputs, and self-documenting code.
|
||||
5. **Transparency and Auditability** — Every decision, every release, every change is traceable and reproducible.
|
||||
|
||||
This document codifies the **technical standards** all contributors must follow. Behavioral expectations are covered in [COMMUNITY_CONDUCT.md](./COMMUNITY_CONDUCT.md).
|
||||
|
||||
---
|
||||
|
||||
## 1 · Scope
|
||||
## 1 · Core Principles
|
||||
|
||||
| Applies to | Examples |
|
||||
|------------|----------|
|
||||
| **All official spaces** | Repos under `git.stella-ops.org/stella-ops.org/*`, Matrix rooms (`#stellaops:*`), issue trackers, pull‑request reviews, community calls, and any event officially sponsored by Stella Ops |
|
||||
| **Unofficial spaces that impact the project** | Public social‑media posts that target or harass community members, coordinated harassment campaigns, doxxing, etc. |
|
||||
### 1.1 Quality
|
||||
|
||||
Quality is not negotiable. Every line of code must be:
|
||||
|
||||
- **Correct** — Does what it claims, handles errors gracefully, fails fast when assumptions break
|
||||
- **Tested** — Unit tests for logic, integration tests for contracts, E2E tests for workflows
|
||||
- **Deterministic** — Same inputs always produce same outputs; no hidden state, no timing dependencies
|
||||
- **Observable** — Logs structured events, emits metrics, traces execution paths
|
||||
- **Documented** — Self-explanatory code; architecture decisions recorded; APIs have examples
|
||||
|
||||
**Why it matters**: Quality debt compounds. A shortcut today becomes a week-long incident tomorrow. We build for the long term.
|
||||
|
||||
---
|
||||
|
||||
## 2 · Reporting a violation ☎️
|
||||
### 1.2 Maintainability
|
||||
|
||||
| Channel | When to use |
|
||||
|---------|-------------|
|
||||
| `conduct@stella-ops.org` (PGP key [`keys/#pgp`](https://stella-ops.org/keys/#pgp)) | **Primary, confidential** – anything from micro‑aggressions to serious harassment |
|
||||
| Matrix `/msg @coc-bot:libera.chat` | Quick, in‑chat nudge for minor issues |
|
||||
| Public issue with label `coc` | Transparency preferred and **you feel safe** doing so |
|
||||
Code is read 10x more than it's written. Optimize for the next engineer:
|
||||
|
||||
We aim to acknowledge **within 48 hours** (business days, UTC).
|
||||
- **Clear intent** — Names reveal purpose; functions do one thing; classes have single responsibilities
|
||||
- **Low coupling** — Modules depend on interfaces, not implementations; changes propagate predictably
|
||||
- **High cohesion** — Related logic lives together; unrelated logic stays separate
|
||||
- **Minimal surprise** — Standard patterns over clever tricks; explicit over implicit
|
||||
- **Refactorable** — Tests enable confident changes; abstractions hide complexity without obscuring behavior
|
||||
|
||||
**Why it matters**: Unmaintainable code slows velocity to zero. We build systems that evolve, not calcify.
|
||||
|
||||
---
|
||||
|
||||
## 3 · Incident handlers 🛡️
|
||||
### 1.3 Security
|
||||
|
||||
| Name | Role | Alt‑contact |
|
||||
|------|------|-------------|
|
||||
| Alice Doe (`@alice`) | Core Maintainer • Security WG | `+1‑555‑0123` |
|
||||
| Bob Ng (`@bob`) | UI Maintainer • Community lead | `+1‑555‑0456` |
|
||||
Security is a design constraint, not a feature:
|
||||
|
||||
If **any** handler is the subject of a complaint, skip them and contact another
|
||||
handler directly or email `conduct@stella-ops.org` only.
|
||||
- **Defense in depth** — Multiple layers: input validation, authorization, cryptographic verification, audit trails
|
||||
- **Least privilege** — Services run with minimal permissions; users see only what they need
|
||||
- **Fail secure** — Errors deny access; missing config stops startup; invalid crypto rejects requests
|
||||
- **Cryptographic correctness** — Use vetted libraries; never roll your own crypto; verify all signatures
|
||||
- **Supply chain integrity** — Pin dependencies; scan for vulnerabilities; generate SBOMs; issue VEX statements
|
||||
- **Auditability** — Every action logged; every release signed; every decision traceable
|
||||
|
||||
**Why it matters**: Security failures destroy trust. We protect our users' infrastructure and their reputation.
|
||||
|
||||
---
|
||||
|
||||
## 4 · Enforcement ladder ⚖️
|
||||
## 2 · Scope and Authority
|
||||
|
||||
1. **Private coaches / mediation** – first attempt to resolve misunderstandings.
|
||||
2. **Warning** – written, includes corrective actions & cooling‑off period.
|
||||
3. **Temporary exclusion** – mute (chat), read‑only (repo) for *N* days.
|
||||
4. **Permanent ban** – removal from all official spaces + revocation of roles.
|
||||
This Code of Conduct applies to:
|
||||
|
||||
All decisions are documented **privately** (for confidentiality) but a summary
|
||||
is published quarterly in the “Community Health” report.
|
||||
- All code contributions (C#, TypeScript, Angular, SQL, Dockerfiles, Helm charts, CI/CD pipelines)
|
||||
- All documentation (architecture, API references, runbooks, sprint files)
|
||||
- All testing artifacts (unit, integration, E2E, performance, security tests)
|
||||
- All infrastructure-as-code (Terraform, Ansible, Compose, Kubernetes manifests)
|
||||
|
||||
**Authority**: This document supersedes informal guidance. When in conflict with external standards, StellaOps rules win. Module-specific `AGENTS.md` files may impose stricter requirements but cannot relax the rules defined here.
|
||||
|
||||
---
|
||||
|
||||
## 5 · Appeals 🔄
|
||||
## 3 · Mandatory Reading
|
||||
|
||||
A sanctioned individual may appeal **once** by emailing
|
||||
`appeals@stella-ops.org` within **14 days** of the decision.
|
||||
Appeals are reviewed by **three maintainers not involved in the original case**
|
||||
and resolved within 30 days.
|
||||
Before contributing to any module, you **must** read and understand:
|
||||
|
||||
1. **This document** — The engineering code of conduct (you're reading it now)
|
||||
2. [docs/README.md](../README.md) — Project overview and navigation
|
||||
3. [docs/07_HIGH_LEVEL_ARCHITECTURE.md](../07_HIGH_LEVEL_ARCHITECTURE.md) — System architecture
|
||||
4. [docs/modules/platform/architecture-overview.md](../modules/platform/architecture-overview.md) — Platform design
|
||||
5. [TESTING_PRACTICES.md](./TESTING_PRACTICES.md) — Testing requirements and evidence standards
|
||||
6. The relevant module's architecture dossier (`docs/modules/<module>/architecture.md`)
|
||||
7. The module's `AGENTS.md` if present (e.g., `src/Scanner/AGENTS.md`)
|
||||
|
||||
**Enforcement**: Pull requests that violate documented architecture or module-specific constraints will be rejected with a reference to the violated document.
|
||||
|
||||
---
|
||||
|
||||
## 6 · No‑retaliation policy 🛑
|
||||
## 4 · Code Quality Standards
|
||||
|
||||
Retaliation against reporters **will not be tolerated** and results in
|
||||
immediate progression to **Step 4** of the enforcement ladder.
|
||||
### 3.1 Compiler Discipline
|
||||
|
||||
**Rule**: All projects must enable `TreatWarningsAsErrors`.
|
||||
|
||||
```xml
|
||||
<!-- In .csproj or Directory.Build.props -->
|
||||
<PropertyGroup>
|
||||
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
```
|
||||
|
||||
**Rationale**: Warnings mask regressions and code quality drift. Zero-warning builds are mandatory.
|
||||
|
||||
---
|
||||
|
||||
## 7 · Attribution & licence 📜
|
||||
### 3.2 Determinism: Time, IDs, and Randomness
|
||||
|
||||
* Text adapted from Contributor Covenant v2.1 –
|
||||
Copyright © 2014‑2024 Contributor Covenant Contributors
|
||||
Licensed under [CC BY 4.0](https://creativecommons.org/licenses/by/4.0/).
|
||||
**Rule**: Never use `DateTime.UtcNow`, `DateTimeOffset.UtcNow`, `Guid.NewGuid()`, or `Random.Shared` directly in production code.
|
||||
|
||||
**Required**: Inject `TimeProvider` and `IGuidGenerator` abstractions.
|
||||
|
||||
```csharp
|
||||
// ❌ BAD - nondeterministic, untestable
|
||||
public class BadService
|
||||
{
|
||||
public Record CreateRecord() => new Record
|
||||
{
|
||||
Id = Guid.NewGuid(),
|
||||
CreatedAt = DateTimeOffset.UtcNow
|
||||
};
|
||||
}
|
||||
|
||||
// ✅ GOOD - injectable, testable, deterministic
|
||||
public class GoodService(TimeProvider timeProvider, IGuidGenerator guidGenerator)
|
||||
{
|
||||
public Record CreateRecord() => new Record
|
||||
{
|
||||
Id = guidGenerator.NewGuid(),
|
||||
CreatedAt = timeProvider.GetUtcNow()
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
**Rationale**: Deterministic outputs enable reproducible builds, reliable tests, and cryptographic verification. Nondeterministic code breaks evidence chains.
|
||||
|
||||
---
|
||||
|
||||
### 3.3 Culture-Invariant Parsing and Formatting
|
||||
|
||||
**Rule**: Always use `CultureInfo.InvariantCulture` for parsing and formatting dates, numbers, percentages, and any string that will be persisted, hashed, or compared.
|
||||
|
||||
```csharp
|
||||
// ❌ BAD - culture-sensitive, locale-dependent
|
||||
var value = double.Parse(input);
|
||||
var formatted = percentage.ToString("P2");
|
||||
|
||||
// ✅ GOOD - culture-invariant, deterministic
|
||||
var value = double.Parse(input, CultureInfo.InvariantCulture);
|
||||
var formatted = percentage.ToString("P2", CultureInfo.InvariantCulture);
|
||||
```
|
||||
|
||||
**Rationale**: Current culture causes nondeterministic behavior across environments. All outputs must be reproducible regardless of locale.
|
||||
|
||||
---
|
||||
|
||||
### 3.4 ASCII-Only Output
|
||||
|
||||
**Rule**: Use ASCII-only characters in comments, output strings, and log messages. No mojibake (`ƒ?`), Unicode glyphs (`✓`, `→`, `バ`), or box-drawing characters.
|
||||
|
||||
```csharp
|
||||
// ❌ BAD - non-ASCII glyphs
|
||||
Console.WriteLine("✓ Success → proceeding");
|
||||
|
||||
// ✅ GOOD - ASCII only
|
||||
Console.WriteLine("[OK] Success - proceeding");
|
||||
```
|
||||
|
||||
**Exceptions**: When Unicode is **required** (e.g., internationalized user messages), use explicit escapes (`\uXXXX`) and document the rationale.
|
||||
|
||||
**Rationale**: Non-ASCII characters break in constrained environments (containers, SSH, logs). ASCII ensures universal readability.
|
||||
|
||||
---
|
||||
|
||||
### 3.5 Immutable Collection Returns
|
||||
|
||||
**Rule**: Public APIs must return `IReadOnlyList<T>`, `ImmutableArray<T>`, or defensive copies. Never expose mutable backing stores.
|
||||
|
||||
```csharp
|
||||
// ❌ BAD - exposes mutable backing store
|
||||
public class BadRegistry
|
||||
{
|
||||
private readonly List<string> _scopes = new();
|
||||
public List<string> Scopes => _scopes; // Callers can mutate!
|
||||
}
|
||||
|
||||
// ✅ GOOD - immutable return
|
||||
public class GoodRegistry
|
||||
{
|
||||
private readonly List<string> _scopes = new();
|
||||
public IReadOnlyList<string> Scopes => _scopes.AsReadOnly();
|
||||
}
|
||||
```
|
||||
|
||||
**Rationale**: Mutable returns create hidden coupling and race conditions. Immutability is a safety contract.
|
||||
|
||||
---
|
||||
|
||||
### 3.6 No Silent Stubs
|
||||
|
||||
**Rule**: Placeholder code must throw `NotImplementedException` or return an explicit error status. Never return success from unimplemented paths.
|
||||
|
||||
```csharp
|
||||
// ❌ BAD - silent stub masks missing implementation
|
||||
public async Task<Result> ProcessAsync()
|
||||
{
|
||||
// TODO: implement later
|
||||
return Result.Success(); // Ships broken feature!
|
||||
}
|
||||
|
||||
// ✅ GOOD - explicit failure
|
||||
public async Task<Result> ProcessAsync()
|
||||
{
|
||||
throw new NotImplementedException("ProcessAsync not yet implemented. See SPRINT_20251218_001_BE_ReleasePromotion.md");
|
||||
}
|
||||
```
|
||||
|
||||
**Rationale**: Silent stubs ship broken features. Explicit failures prevent production incidents.
|
||||
|
||||
---
|
||||
|
||||
### 3.7 CancellationToken Propagation
|
||||
|
||||
**Rule**: Always propagate `CancellationToken` through async call chains. Never use `CancellationToken.None` in production code.
|
||||
|
||||
```csharp
|
||||
// ❌ BAD - ignores cancellation
|
||||
public async Task ProcessAsync(CancellationToken ct)
|
||||
{
|
||||
await _repository.SaveAsync(data, CancellationToken.None); // Wrong!
|
||||
await Task.Delay(1000); // Missing ct
|
||||
}
|
||||
|
||||
// ✅ GOOD - propagates cancellation
|
||||
public async Task ProcessAsync(CancellationToken ct)
|
||||
{
|
||||
await _repository.SaveAsync(data, ct);
|
||||
await Task.Delay(1000, ct);
|
||||
}
|
||||
```
|
||||
|
||||
**Rationale**: Proper cancellation prevents resource leaks and enables graceful shutdown.
|
||||
|
||||
---
|
||||
|
||||
### 3.8 HttpClient via IHttpClientFactory
|
||||
|
||||
**Rule**: Never instantiate `HttpClient` directly. Use `IHttpClientFactory` with configured timeouts and retry policies.
|
||||
|
||||
```csharp
|
||||
// ❌ BAD - direct instantiation
|
||||
public class BadService
|
||||
{
|
||||
public async Task FetchAsync()
|
||||
{
|
||||
using var client = new HttpClient(); // Socket exhaustion risk
|
||||
await client.GetAsync(url);
|
||||
}
|
||||
}
|
||||
|
||||
// ✅ GOOD - factory with resilience
|
||||
public class GoodService(IHttpClientFactory httpClientFactory)
|
||||
{
|
||||
public async Task FetchAsync()
|
||||
{
|
||||
var client = httpClientFactory.CreateClient("MyApi");
|
||||
await client.GetAsync(url);
|
||||
}
|
||||
}
|
||||
|
||||
// Registration with timeout/retry
|
||||
services.AddHttpClient("MyApi")
|
||||
.ConfigureHttpClient(c => c.Timeout = TimeSpan.FromSeconds(30))
|
||||
.AddStandardResilienceHandler();
|
||||
```
|
||||
|
||||
**Rationale**: Direct `HttpClient` creation causes socket exhaustion. Factories enable connection pooling and resilience patterns.
|
||||
|
||||
---
|
||||
|
||||
### 3.9 Bounded Caches with Eviction
|
||||
|
||||
**Rule**: Do not use `ConcurrentDictionary` or `Dictionary` for caching without eviction policies.
|
||||
|
||||
```csharp
|
||||
// ❌ BAD - unbounded growth
|
||||
private readonly ConcurrentDictionary<string, CacheEntry> _cache = new();
|
||||
|
||||
public void Add(string key, CacheEntry entry)
|
||||
{
|
||||
_cache[key] = entry; // Never evicts, memory grows forever
|
||||
}
|
||||
|
||||
// ✅ GOOD - bounded with eviction
|
||||
private readonly MemoryCache _cache = new(new MemoryCacheOptions
|
||||
{
|
||||
SizeLimit = 10_000
|
||||
});
|
||||
|
||||
public void Add(string key, CacheEntry entry)
|
||||
{
|
||||
_cache.Set(key, entry, new MemoryCacheEntryOptions
|
||||
{
|
||||
Size = 1,
|
||||
SlidingExpiration = TimeSpan.FromMinutes(30)
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
**Rationale**: Unbounded caches cause memory exhaustion in long-running services. Bounded caches with TTL/LRU eviction are mandatory.
|
||||
|
||||
---
|
||||
|
||||
### 3.10 Options Validation at Startup
|
||||
|
||||
**Rule**: Use `ValidateDataAnnotations()` and `ValidateOnStart()` for all options classes. Implement `IValidateOptions<T>` for complex validation.
|
||||
|
||||
```csharp
|
||||
// ❌ BAD - no validation until runtime failure
|
||||
services.Configure<MyOptions>(config.GetSection("My"));
|
||||
|
||||
// ✅ GOOD - validated at startup
|
||||
services.AddOptions<MyOptions>()
|
||||
.Bind(config.GetSection("My"))
|
||||
.ValidateDataAnnotations()
|
||||
.ValidateOnStart();
|
||||
```
|
||||
|
||||
**Rationale**: All required config must be validated at startup, not at first use. Fail fast prevents runtime surprises.
|
||||
|
||||
---
|
||||
|
||||
## 5 · Cryptographic and Security Standards
|
||||
|
||||
### 4.1 DSSE PAE Consistency
|
||||
|
||||
**Rule**: Use one spec-compliant DSSE PAE helper (`StellaOps.Attestation.DsseHelper`) across the codebase. Never reimplement PAE encoding.
|
||||
|
||||
```csharp
|
||||
// ❌ BAD - custom PAE implementation
|
||||
var pae = $"DSSEv1 {payloadType.Length} {payloadType} {payload.Length} ";
|
||||
|
||||
// ✅ GOOD - use shared helper
|
||||
var pae = DsseHelper.ComputePreAuthenticationEncoding(payloadType, payload);
|
||||
```
|
||||
|
||||
**Rationale**: DSSE v1 requires ASCII decimal lengths and space separators. Reimplementations introduce cryptographic vulnerabilities.
|
||||
|
||||
---
|
||||
|
||||
### 4.2 RFC 8785 JSON Canonicalization
|
||||
|
||||
**Rule**: Use a shared RFC 8785-compliant JSON canonicalizer for digest/signature inputs. Do not use `UnsafeRelaxedJsonEscaping` or `CamelCase` naming for canonical outputs.
|
||||
|
||||
```csharp
|
||||
// ❌ BAD - non-canonical JSON
|
||||
var json = JsonSerializer.Serialize(obj, new JsonSerializerOptions
|
||||
{
|
||||
Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
|
||||
});
|
||||
|
||||
// ✅ GOOD - use shared canonicalizer
|
||||
var canonicalJson = CanonicalJsonSerializer.Serialize(obj);
|
||||
var digest = ComputeDigest(canonicalJson);
|
||||
```
|
||||
|
||||
**Rationale**: RFC 8785 ensures deterministic JSON serialization. Non-canonical JSON breaks signature verification.
|
||||
|
||||
---
|
||||
|
||||
### 4.3 DateTimeOffset for PostgreSQL timestamptz
|
||||
|
||||
**Rule**: PostgreSQL `timestamptz` columns must be read via `reader.GetFieldValue<DateTimeOffset>()`, not `reader.GetDateTime()`.
|
||||
|
||||
```csharp
|
||||
// ❌ BAD - loses offset information
|
||||
var createdAt = reader.GetDateTime(reader.GetOrdinal("created_at"));
|
||||
|
||||
// ✅ GOOD - preserves offset
|
||||
var createdAt = reader.GetFieldValue<DateTimeOffset>(reader.GetOrdinal("created_at"));
|
||||
```
|
||||
|
||||
**Rationale**: `GetDateTime()` loses offset information and causes UTC/local confusion. All timestamps must be stored and retrieved as UTC `DateTimeOffset`.
|
||||
|
||||
---
|
||||
|
||||
### 4.4 Explicit CLI Options for Paths
|
||||
|
||||
**Rule**: Do not derive repository root from `AppContext.BaseDirectory` with parent directory walks. Use explicit CLI options (`--repo-root`) or environment variables.
|
||||
|
||||
```csharp
|
||||
// ❌ BAD - fragile parent walks
|
||||
var repoRoot = Path.GetFullPath(Path.Combine(
|
||||
AppContext.BaseDirectory, "..", "..", "..", ".."));
|
||||
|
||||
// ✅ GOOD - explicit option with fallback
|
||||
[Option("--repo-root", Description = "Repository root path")]
|
||||
public string? RepoRoot { get; set; }
|
||||
|
||||
public string GetRepoRoot() =>
|
||||
RepoRoot ?? Environment.GetEnvironmentVariable("STELLAOPS_REPO_ROOT")
|
||||
?? throw new InvalidOperationException("Repository root not specified. Use --repo-root or set STELLAOPS_REPO_ROOT.");
|
||||
```
|
||||
|
||||
**Rationale**: Parent walks break in containerized and CI environments. Explicit paths are mandatory.
|
||||
|
||||
---
|
||||
|
||||
## 6 · Testing Requirements
|
||||
|
||||
**All code contributions must include tests.** See [TESTING_PRACTICES.md](./TESTING_PRACTICES.md) for comprehensive guidance.
|
||||
|
||||
### 5.1 Test Project Requirements
|
||||
|
||||
**Rule**: All production libraries/services must have a corresponding `*.Tests` project covering:
|
||||
- (a) Happy paths
|
||||
- (b) Error/edge cases
|
||||
- (c) Determinism
|
||||
- (d) Serialization round-trips
|
||||
|
||||
```
|
||||
src/
|
||||
Scanner/
|
||||
__Libraries/
|
||||
StellaOps.Scanner.Core/
|
||||
__Tests/
|
||||
StellaOps.Scanner.Core.Tests/ <-- Required
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5.2 Test Categorization
|
||||
|
||||
**Rule**: Tag tests correctly:
|
||||
- `[Trait("Category", "Unit")]` for pure unit tests
|
||||
- `[Trait("Category", "Integration")]` for tests requiring databases, containers, or network
|
||||
|
||||
```csharp
|
||||
// ❌ BAD - integration test marked as unit
|
||||
public class UserRepositoryTests // Uses Testcontainers/Postgres
|
||||
{
|
||||
[Fact] // Missing category
|
||||
public async Task Save_PersistsUser() { ... }
|
||||
}
|
||||
|
||||
// ✅ GOOD - correctly categorized
|
||||
[Trait("Category", "Integration")]
|
||||
public class UserRepositoryTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task Save_PersistsUser() { ... }
|
||||
}
|
||||
|
||||
[Trait("Category", "Unit")]
|
||||
public class UserValidatorTests
|
||||
{
|
||||
[Fact]
|
||||
public void Validate_EmptyEmail_ReturnsFalse() { ... }
|
||||
}
|
||||
```
|
||||
|
||||
**Rationale**: Unit tests must run fast and offline. Integration tests require infrastructure. Mixing categories breaks CI pipelines.
|
||||
|
||||
---
|
||||
|
||||
### 5.3 Test Production Code, Not Reimplementations
|
||||
|
||||
**Rule**: Test helpers must call production code, not reimplement algorithms.
|
||||
|
||||
```csharp
|
||||
// ❌ BAD - test reimplements production logic
|
||||
[Fact]
|
||||
public void Merkle_ComputesCorrectRoot()
|
||||
{
|
||||
var root = TestMerkleHelper.ComputeRoot(leaves); // Drift risk!
|
||||
Assert.Equal(expected, root);
|
||||
}
|
||||
|
||||
// ✅ GOOD - test exercises production code
|
||||
[Fact]
|
||||
public void Merkle_ComputesCorrectRoot()
|
||||
{
|
||||
var root = MerkleTreeBuilder.ComputeRoot(leaves);
|
||||
Assert.Equal(expected, root);
|
||||
}
|
||||
```
|
||||
|
||||
**Rationale**: Reimplementations in tests cause test/production drift. Only mock I/O and network boundaries.
|
||||
|
||||
---
|
||||
|
||||
### 5.4 Offline and Deterministic Tests
|
||||
|
||||
**Rule**: All tests must run without network access. Use:
|
||||
- UTC timestamps
|
||||
- Fixed seeds
|
||||
- `CultureInfo.InvariantCulture`
|
||||
- Injected `TimeProvider` and `IGuidGenerator`
|
||||
|
||||
**Rationale**: Network-dependent tests are flaky and break in air-gapped environments. Deterministic tests are reproducible.
|
||||
|
||||
---
|
||||
|
||||
## 7 · Architecture and Design Principles
|
||||
|
||||
### 6.1 SOLID Principles
|
||||
|
||||
All service and library code must follow:
|
||||
|
||||
1. **Single Responsibility Principle (SRP)** — One class, one reason to change
|
||||
2. **Open/Closed Principle (OCP)** — Open for extension, closed for modification
|
||||
3. **Liskov Substitution Principle (LSP)** — Subtypes must be substitutable for base types
|
||||
4. **Interface Segregation Principle (ISP)** — Clients should not depend on interfaces they don't use
|
||||
5. **Dependency Inversion Principle (DIP)** — Depend on abstractions, not concretions
|
||||
|
||||
---
|
||||
|
||||
### 6.2 Directory Ownership
|
||||
|
||||
**Rule**: Work only inside the module's directory defined by the sprint's "Working directory". Cross-module edits require explicit approval and documentation.
|
||||
|
||||
**Example**:
|
||||
- Sprint scope: `src/Scanner/`
|
||||
- Allowed: Edits to `StellaOps.Scanner.*` projects
|
||||
- Forbidden: Edits to `src/Concelier/` without explicit approval
|
||||
|
||||
**Rationale**: Directory boundaries enforce module isolation and prevent unintended coupling.
|
||||
|
||||
---
|
||||
|
||||
### 6.3 No Backup Files in Source
|
||||
|
||||
**Rule**: Add backup patterns to `.gitignore` and remove stray artifacts during code review.
|
||||
|
||||
```gitignore
|
||||
*.Backup.tmp
|
||||
*.bak
|
||||
*.orig
|
||||
*~
|
||||
```
|
||||
|
||||
**Rationale**: Backup files pollute the repository and create confusion.
|
||||
|
||||
---
|
||||
|
||||
## 8 · Documentation Standards
|
||||
|
||||
### 7.1 Required Documentation
|
||||
|
||||
Every change must update:
|
||||
|
||||
1. **Module architecture docs** (`docs/modules/<module>/architecture.md`)
|
||||
2. **API references** (`docs/api/`)
|
||||
3. **Sprint files** (`docs/implplan/SPRINT_*.md`)
|
||||
4. **Risk/airgap docs** if applicable (`docs/risk/`, `docs/airgap/`)
|
||||
|
||||
---
|
||||
|
||||
### 7.2 Sprint File Discipline
|
||||
|
||||
**Rule**: Always update task status in `docs/implplan/SPRINT_*.md`:
|
||||
- `TODO` → `DOING` → `DONE` / `BLOCKED`
|
||||
|
||||
Sprint files are the single source of truth for project state.
|
||||
|
||||
---
|
||||
|
||||
## 9 · Security and Hardening
|
||||
|
||||
### 8.1 Input Validation
|
||||
|
||||
**Rule**: All external inputs (HTTP requests, CLI arguments, file uploads, database queries) must be validated and sanitized.
|
||||
|
||||
**Required**:
|
||||
- Use `[Required]`, `[Range]`, `[RegularExpression]` attributes on DTOs
|
||||
- Implement `IValidateOptions<T>` for complex validation
|
||||
- Reject unexpected inputs with explicit error messages
|
||||
|
||||
---
|
||||
|
||||
### 8.2 Least Privilege
|
||||
|
||||
**Rule**: Services must run with minimal permissions:
|
||||
- Database users: read-only where possible
|
||||
- File system: restrict to required directories
|
||||
- Network: allowlist remote hosts
|
||||
|
||||
---
|
||||
|
||||
### 8.3 Dependency Security
|
||||
|
||||
**Enforcement**: PRs introducing new dependencies must include:
|
||||
- SBOM entry
|
||||
- VEX statement if vulnerabilities exist
|
||||
- Justification for the dependency
|
||||
|
||||
---
|
||||
|
||||
## 10 · Technology Stack Compliance
|
||||
|
||||
### 9.1 Mandatory Technologies
|
||||
|
||||
- **Runtime**: .NET 10 (`net10.0`) with latest C# preview features
|
||||
- **Frontend**: Angular v17
|
||||
- **Database**: PostgreSQL ≥16
|
||||
- **Testing**: xUnit, Testcontainers, Moq
|
||||
- **NuGet**: Standard feeds configured in `nuget.config`. Always strive to use latest stable verison of dependencies. Never specify versions on nugets on the csproj files. Use src/Directory.Packages.props to specify versions.
|
||||
|
||||
---
|
||||
|
||||
### 9.2 Naming Conventions
|
||||
|
||||
- Module projects: `StellaOps.<ModuleName>`
|
||||
- Libraries: `StellaOps.<LibraryName>`
|
||||
- Tests: `StellaOps.<ModuleName>.Tests`
|
||||
|
||||
---
|
||||
|
||||
## 11 · Enforcement and Compliance
|
||||
|
||||
### 10.1 Pull Request Requirements
|
||||
|
||||
All PRs must:
|
||||
|
||||
1. Pass all unit and integration tests
|
||||
2. Pass determinism checks
|
||||
3. Include test coverage for new code
|
||||
4. Update relevant documentation
|
||||
5. Follow sprint file discipline
|
||||
6. Pass security scans (no high/critical CVEs)
|
||||
|
||||
---
|
||||
|
||||
### 10.2 Rejection Criteria
|
||||
|
||||
PRs will be **rejected** if they:
|
||||
|
||||
- Violate any rule in this document
|
||||
- Introduce compiler warnings
|
||||
- Fail tests
|
||||
- Lack required documentation
|
||||
- Contain silent stubs or nondeterministic code
|
||||
|
||||
---
|
||||
|
||||
### 10.3 Continuous Improvement
|
||||
|
||||
This document is a **living standard**. Contributors are encouraged to:
|
||||
|
||||
- Propose improvements via PRs
|
||||
- Document new patterns in module-specific `AGENTS.md` files
|
||||
- Share lessons learned in sprint retrospectives
|
||||
|
||||
---
|
||||
|
||||
## 12 · Attribution and License
|
||||
|
||||
This Code of Conduct incorporates engineering standards from:
|
||||
|
||||
- **AGENTS.md** — Autonomous engineering workflows
|
||||
- **CLAUDE.md** — Claude Code integration guidance
|
||||
- **TESTING_PRACTICES.md** — Testing and evidence standards
|
||||
|
||||
Copyright © 2025 StellaOps Contributors
|
||||
Licensed under [AGPL-3.0-or-later](../../LICENSE)
|
||||
|
||||
---
|
||||
|
||||
**Last updated**: 2026-01-15
|
||||
**Next review**: 2026-04-15
|
||||
|
||||
Reference in New Issue
Block a user