---
name: roslyn-validator
description: SmartStack C# static analysis — 10 rules (SS001-SS010) per layer
group: validation
cli: cli/
allowed-tools: [Read, Glob, Grep, Bash]  # Bash: CLI invocation
---

# Skill: Roslyn Validator

> Validates SmartStack conventions on generated C# files.
> Analysis via regex (not real Roslyn AST) — lightweight and fast.

## When to use this skill

- After code generation by layers 0-6 (entity, migration, business, controller)
- Before a merge/PR to verify compliance
- To audit an existing project

## The 10 Rules

### Controller (SS001-SS007)

| Code | Rule | Severity |
|------|------|----------|
| SS001 | Inherits `ControllerBase` + `[ApiController]` | error |
| SS002 | Single `IService` injection — no DbContext | error |
| SS003 | `[NavRoute]` present, format `module.section` | error |
| SS004 | `[RequirePermission]` on each public endpoint | error |
| SS005 | Returns DTOs only — never domain entities | error |
| SS006 | `CancellationToken` as last async parameter | error |
| SS007 | NavRoute unique across entire project | error |

### Service (SS008)

| Code | Rule | Severity |
|------|------|----------|
| SS008 | Service without DbContext — uses IRepository | error |

### Repository (SS009)

| Code | Rule | Severity |
|------|------|----------|
| SS009 | Repository without business logic (no throw BusinessException) | error |

### Entity (SS010)

| Code | Rule | Severity |
|------|------|----------|
| SS010 | Entity inherits `BaseEntity` | error |

## CLI Invocation

```bash
# Validate entire project
npx --prefer-offline tsx skills/validation/roslyn/cli/index.ts --src <directory>

# Validate single layer
npx --prefer-offline tsx skills/validation/roslyn/cli/index.ts --src <directory> --layer controller
npx --prefer-offline tsx skills/validation/roslyn/cli/index.ts --src <directory> --layer service
npx --prefer-offline tsx skills/validation/roslyn/cli/index.ts --src <directory> --layer repository
npx --prefer-offline tsx skills/validation/roslyn/cli/index.ts --src <directory> --layer entity
```

## JSON Output

```json
{
  "timestamp": "2026-03-31T...",
  "checks": [
    { "code": "SS001", "status": "ok", "count": 3 },
    { "code": "SS004", "status": "error", "file": "ClientController.cs", "line": 45, "message": "Endpoint [HttpDelete] without [RequirePermission]" }
  ],
  "errors": 1,
  "warnings": 0
}
```

## Expected Behavior

1. User requests a validation
2. Claude Code identifies the source directory and target layer
3. Claude Code calls the CLI with `--src` and `--layer`
4. CLI returns JSON with results
5. Claude Code presents results and suggests corrections

## Conversation Example

```
User: Validate conventions on my controllers
Claude Code: Launching static analysis...
→ npx --prefer-offline tsx skills/validation/roslyn/cli/index.ts --src ./src --layer controller
← { "checks": [...], "errors": 0, "warnings": 0 }
Claude Code: All controllers follow SmartStack conventions (SS001-SS007).
```

## Exit Codes

| Code | Meaning |
|------|---------|
| 0 | Success — no errors |
| 1 | Errors detected |
| 2 | Internal CLI error (invalid input, missing directory) |
