# Policy AOC Linting Rules
**Document ID:** `DESIGN-POLICY-AOC-LINTING-001`
**Version:** 1.0
**Status:** Published
**Last Updated:** 2025-12-06
## Overview
This document defines the linting and static analysis rules for Policy Engine and related library projects. These rules enforce determinism, nullability, async consistency, and JSON property ordering to ensure reproducible policy evaluation.
## Target Projects
| Project | Path | Notes |
|---------|------|-------|
| StellaOps.Policy.Engine | `src/Policy/StellaOps.Policy.Engine/` | Primary target |
| StellaOps.Policy | `src/Policy/__Libraries/StellaOps.Policy/` | Core library |
| StellaOps.PolicyDsl | `src/Policy/StellaOps.PolicyDsl/` | DSL compiler |
| StellaOps.Policy.RiskProfile | `src/Policy/StellaOps.Policy.RiskProfile/` | Risk scoring |
| StellaOps.Policy.Storage.Postgres | `src/Policy/__Libraries/StellaOps.Policy.Storage.Postgres/` | Storage layer |
### Excluded
- `**/obj/**` - Build artifacts
- `**/bin/**` - Build outputs
- `**/*.Tests/**` - Test projects (separate rules)
- `**/Migrations/**` - Generated EF migrations
## Rule Categories
### 1. Determinism Rules (Error Severity)
Enforced by `ProhibitedPatternAnalyzer` at `src/Policy/StellaOps.Policy.Engine/DeterminismGuard/`.
| Rule ID | Pattern | Severity | Remediation |
|---------|---------|----------|-------------|
| DET-001 | `DateTime.Now` | Error | Use `TimeProvider.GetUtcNow()` |
| DET-002 | `DateTime.UtcNow` | Error | Use `TimeProvider.GetUtcNow()` |
| DET-003 | `DateTimeOffset.Now` | Error | Use `TimeProvider.GetUtcNow()` |
| DET-004 | `DateTimeOffset.UtcNow` | Error | Use `TimeProvider.GetUtcNow()` |
| DET-005 | `Guid.NewGuid()` | Error | Use `StableIdGenerator` or content hash |
| DET-006 | `new Random()` | Error | Use seeded random or remove |
| DET-007 | `RandomNumberGenerator` | Error | Remove from evaluation path |
| DET-008 | `HttpClient` in eval | Critical | Remove network from eval path |
| DET-009 | `File.Read*` in eval | Critical | Remove filesystem from eval path |
| DET-010 | Dictionary iteration | Warning | Use `OrderBy` or `SortedDictionary` |
| DET-011 | HashSet iteration | Warning | Use `OrderBy` or `SortedSet` |
### 2. Nullability Rules (Error Severity)
| Rule ID | Description | EditorConfig |
|---------|-------------|--------------|
| NUL-001 | Enable nullable reference types | `nullable = enable` |
| NUL-002 | Nullable warnings as errors | `dotnet_diagnostic.CS8600-CS8609.severity = error` |
| NUL-003 | Null parameter checks | `ArgumentNullException.ThrowIfNull()` |
### 3. Async/Sync Consistency Rules (Warning Severity)
| Rule ID | Description | EditorConfig |
|---------|-------------|--------------|
| ASY-001 | Async void methods | `dotnet_diagnostic.CA2012.severity = error` |
| ASY-002 | Missing ConfigureAwait | `dotnet_diagnostic.CA2007.severity = warning` |
| ASY-003 | Sync over async | `dotnet_diagnostic.MA0045.severity = warning` |
| ASY-004 | Task.Result in async | `dotnet_diagnostic.MA0042.severity = error` |
### 4. JSON Property Ordering Rules
For deterministic JSON output, all DTOs must use explicit `[JsonPropertyOrder]` attributes.
| Rule ID | Description | Enforcement |
|---------|-------------|-------------|
| JSN-001 | Explicit property order | Code review + analyzer |
| JSN-002 | Stable serialization | `JsonSerializerOptions.WriteIndented = false` |
| JSN-003 | Key ordering | `JsonSerializerOptions.PropertyNamingPolicy` with stable order |
### 5. Code Style Rules
| Rule ID | Description | EditorConfig |
|---------|-------------|--------------|
| STY-001 | File-scoped namespaces | `csharp_style_namespace_declarations = file_scoped` |
| STY-002 | Primary constructors | `csharp_style_prefer_primary_constructors = true` |
| STY-003 | Collection expressions | `csharp_style_prefer_collection_expression = true` |
| STY-004 | Implicit usings | `ImplicitUsings = enable` |
## Severity Levels
| Level | Behavior | CI Impact |
|-------|----------|-----------|
| Error | Build fails | Blocks merge |
| Warning | Build succeeds, logged | Review required |
| Info | Logged only | No action required |
## CI Integration
### Build-time Enforcement
Policy projects use `TreatWarningsAsErrors=true` in `.csproj`:
```xml
true
enable
```
### Static Analysis Pipeline
The `.gitea/workflows/policy-lint.yml` workflow runs:
1. **dotnet build** with analyzer packages
2. **DeterminismGuard analysis** via CLI
3. **Format check** via `dotnet format --verify-no-changes`
### Required Analyzer Packages
```xml
```
## Baseline Suppressions
Create `.globalconfig` for legacy code that cannot be immediately fixed:
```ini
# Legacy suppressions - track issue for remediation
[src/Policy/**/LegacyCode.cs]
dotnet_diagnostic.DET-010.severity = suggestion
```
## Runtime Enforcement
The `DeterminismGuardService` provides runtime monitoring:
```csharp
using var scope = _determinismGuard.CreateScope(scopeId, timestamp);
var result = await evaluation(scope);
var analysis = scope.Complete();
if (!analysis.Passed) { /* log/reject */ }
```
## Acceptance Criteria
1. All Policy projects build with zero errors
2. `dotnet format` reports no changes needed
3. DeterminismGuard analysis passes
4. New code has no nullable warnings
5. Async methods use `ConfigureAwait(false)`
## Related Documents
- [Deterministic Evaluator Design](./deterministic-evaluator.md)
- [Policy Engine Architecture](../architecture.md)
- [CONTRACT-POLICY-STUDIO-007](../../contracts/policy-studio.md)