Back to skills
SKILL.md
Reachtokarthikr Agent Skills .
ASecurity**MANDATORY POST-WRITE CHECKLIST — runs after every file is created or modified.** This skill simulates a professional CI/CD quality gate combining VS Code diagnostics, SonarQube static analysis, vulnerability scanning, security auditing, and performance optimization. It applies to all languages in the stack: T-SQL, C#/.NET, TypeScript/React, HTML/CSS, JSON/config files. ---
- 4 stars
- 0 votes
- 0 copies
- 3 views
- Added September 12, 2026
Works with
Security analysis
92/100- Installs packages at runtime which could introduce malicious dependencies
- Installs packages at runtime which could introduce malicious dependencies
Pro scans all 2 files and shows the line behind each finding
npx -y skills add aibot88/sec_skill_store --skill reachtokarthikr-agent_skills-. --agent claude-codeAre you the author of Reachtokarthikr Agent Skills .?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/aibot88-reachtokarthikr-agent-skills)# Code Quality Gate Skill
**MANDATORY POST-WRITE CHECKLIST — runs after every file is created or modified.**
This skill simulates a professional CI/CD quality gate combining VS Code diagnostics, SonarQube static analysis, vulnerability scanning, security auditing, and performance optimization. It applies to all languages in the stack: T-SQL, C#/.NET, TypeScript/React, HTML/CSS, JSON/config files.
---
## When This Skill Activates
This skill activates **automatically after every code change**. It is not optional.
| Trigger | Example |
|---------|---------|
| New file created | `create_file` for any `.cs`, `.ts`, `.tsx`, `.sql`, `.json`, `.html`, `.css`, `.csproj` |
| File edited | `str_replace` on any code file |
| Bug fix applied | After fixing a reported issue |
| Refactor completed | After restructuring code |
| User says "review" / "check" / "audit" | Explicit quality review request |
| Before delivery to `/mnt/user-data/outputs/` | Final gate before presenting files |
**RULE: Never copy files to `/mnt/user-data/outputs/` until all 6 layers pass with zero Critical/High issues.**
---
## The 6-Layer Quality Gate
Every file change must pass through ALL 6 layers in order. If any layer produces Critical or High severity findings, fix them before proceeding to the next layer. Medium/Low findings should be noted and fixed where practical.
```
Layer 1: VS Code Problems Tab → Syntax, type errors, warnings
Layer 2: Lint Check (ALL langs) → ESLint, Roslyn, SQL Lint, Prettier, Stylelint, HTMLHint, JSONLint
Layer 3: SonarQube-Lite Analysis → Code smells, complexity, duplication, maintainability
Layer 4: Vulnerability Scan → Dependencies, injection, secrets, data exposure
Layer 5: Security Hardening → OWASP Top 10, auth/authz, input validation
Layer 6: Optimization & Standards → Performance, best practices, team conventions
```
---
## ARCHITECTURAL MANDATE — Stored Procedures ONLY (No Inline SQL, No EF)
**🔴 CRITICAL RULE — NO EXCEPTIONS. This overrides all other patterns. Violations block delivery.**
All database access MUST go through stored procedures called via **Dapper + SpHelper**. The following are **permanently BANNED** in this codebase:
### ⌠BANNED — Inline SQL / Raw Queries
```
🔴 BANNED: conn.QueryAsync<T>("SELECT * FROM Users WHERE Id = @Id", ...)
🔴 BANNED: conn.ExecuteAsync("INSERT INTO Users (...) VALUES (...)", ...)
🔴 BANNED: conn.QueryAsync<T>($"SELECT * FROM Users WHERE Email = '{email}'")
🔴 BANNED: new SqlCommand("SELECT ...", conn)
🔴 BANNED: SqlCommand.CommandType = CommandType.Text
🔴 BANNED: FromSqlRaw("SELECT ...")
🔴 BANNED: FromSqlInterpolated($"SELECT ...")
🔴 BANNED: Database.ExecuteSqlRaw(...)
🔴 BANNED: Database.ExecuteSqlInterpolated(...)
🔴 BANNED: Any string containing SELECT/INSERT/UPDATE/DELETE in C# code
🔴 BANNED: Dapper calls without CommandType.StoredProcedure — must go through SpHelper
```
### ⌠BANNED — Entity Framework Core (ALL of it — zero tolerance)
```
🔴 BANNED: DbContext / DbSet<T>
🔴 BANNED: IEntityTypeConfiguration<T> / Fluent API
🔴 BANNED: modelBuilder.ApplyConfigurationsFromAssembly(...)
🔴 BANNED: dbContext.Users.Where(...).ToListAsync()
🔴 BANNED: dbContext.SaveChangesAsync() / SaveChanges()
🔴 BANNED: dbContext.Add() / Update() / Remove() / AddRange() / RemoveRange()
🔴 BANNED: AsNoTracking() (implies EF query)
🔴 BANNED: Include() / ThenInclude() (EF eager loading)
🔴 BANNED: EF migrations: dotnet ef migrations add ...
🔴 BANNED: Microsoft.EntityFrameworkCore NuGet package in any .csproj
🔴 BANNED: LINQ-to-SQL / LINQ-to-Entities (dbContext.Users.Select(...))
🔴 BANNED: ExecuteUpdateAsync / ExecuteDeleteAsync (EF 7+ bulk ops)
🔴 BANNED: HasKey() / HasIndex() / HasOne() / HasMany() / WithOne() / WithMany()
🔴 BANNED: OnModelCreating() override
🔴 BANNED: any file named *DbContext.cs, *Context.cs (EF context files)
🔴 BANNED: Data/Migrations/ folder
```
### ✅ REQUIRED — The ONLY Allowed Data Access Pattern
```
✅ REQUIRED: Dapper + SpHelper → calls stored procedures ONLY
✅ REQUIRED: CommandType.StoredProcedure on every database call
✅ REQUIRED: SpHelper.ManageAsync<T>(spName, params) → INSERT/UPDATE/DELETE via SP
✅ REQUIRED: SpHelper.GetByIdAsync<T>(spName, id) → Single record via SP
✅ REQUIRED: SpHelper.GetListAsync<T>(spName, params) → Paged list via SP
✅ REQUIRED: SpHelper.GetWithChildrenAsync<P,C>(spName, id)→ Parent+Children via SP
✅ REQUIRED: DynamicParameters for all SP parameters
✅ REQUIRED: @CorrelationId + @RequestId injected via SpHelper.WithTracking()
✅ REQUIRED: Every SP defined in .sql files following _Manage / _Get pattern
✅ REQUIRED: Repository classes use SpHelper, never direct Dapper or ADO.NET
```
### ✅ Required NuGet Packages (Data Access ONLY these)
```xml
<!-- ALLOWED — the ONLY data access packages -->
<PackageReference Include="Dapper" Version="2.*" />
<PackageReference Include="Microsoft.Data.SqlClient" Version="5.*" />
<!-- ⌠BANNED — if any of these appear in .csproj, it is a CRITICAL violation -->
<!-- <PackageReference Include="Microsoft.EntityFrameworkCore" /> -->
<!-- <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" /> -->
<!-- <PackageReference Include="Microsoft.EntityFrameworkCore.Design" /> -->
<!-- <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" /> -->
<!-- <PackageReference Include="Microsoft.EntityFrameworkCore.Relational" /> -->
<!-- <PackageReference Include="Microsoft.EntityFrameworkCore.InMemory" /> -->
```
### Detection Commands (MUST run on every C# / .csproj file change)
```bash
echo "â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•"
echo " SP-ONLY MANDATE CHECK — ZERO TOLERANCE"
echo "â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•"
VIOLATIONS=0
# ── Inline SQL detection (🔴 CRITICAL) ──
echo "--- Checking for inline SQL ---"
if grep -rn "CommandType\.Text" --include="*.cs" 2>/dev/null; then
echo "🔴 CRITICAL: CommandType.Text found — must use CommandType.StoredProcedure"
((VIOLATIONS++))
fi
if grep -rn "FromSqlRaw\|FromSqlInterpolated\|ExecuteSqlRaw\|ExecuteSqlInterpolated" --include="*.cs" 2>/dev/null; then
echo "🔴 CRITICAL: Raw SQL via EF methods found"
((VIOLATIONS++))
fi
if grep -rn '"SELECT \|"INSERT \|"UPDATE \|"DELETE \|"EXEC ' --include="*.cs" 2>/dev/null; then
echo "🔴 CRITICAL: Inline SQL string found in C# code"
((VIOLATIONS++))
fi
if grep -rn '\$"SELECT\|\$"INSERT\|\$"UPDATE\|\$"DELETE' --include="*.cs" 2>/dev/null; then
echo "🔴 CRITICAL: Interpolated SQL string found — SQL injection risk"
((VIOLATIONS++))
fi
if grep -rn "new SqlCommand" --include="*.cs" 2>/dev/null; then
echo "🔴 CRITICAL: Raw SqlCommand found — must use SpHelper"
((VIOLATIONS++))
fi
# Direct Dapper without SP type (allowed only inside SpHelper itself)
if grep -rn "\.QueryAsync<\|\.QueryFirstOrDefaultAsync<\|\.ExecuteAsync(" --include="*.cs" 2>/dev/null | grep -v "SpHelper.cs" | grep -v "CommandType.StoredProcedure"; then
echo "🔴 CRITICAL: Direct Dapper call outside SpHelper — must go through SpHelper"
((VIOLATIONS++))
fi
# ── Entity Framework detection (🔴 CRITICAL) ──
echo "--- Checking for Entity Framework ---"
if grep -rn "DbContext\|DbSet<" --include="*.cs" 2>/dev/null; then
echo "🔴 CRITICAL: Entity Framework DbContext/DbSet found"
((VIOLATIONS++))
fi
if grep -rn "using Microsoft.EntityFrameworkCore" --include="*.cs" 2>/dev/null; then
echo "🔴 CRITICAL: EF Core using directive found"
((VIOLATIONS++))
fi
if grep -rn "EntityFrameworkCore" --include="*.csproj" 2>/dev/null; then
echo "🔴 CRITICAL: EF Core NuGet package referenced in .csproj"
((VIOLATIONS++))
fi
if grep -rn "\.Include(\|\.ThenInclude(" --include="*.cs" 2>/dev/null; then
echo "🔴 CRITICAL: EF eager loading (Include/ThenInclude) found"
((VIOLATIONS++))
fi
if grep -rn "AsNoTracking\|SaveChangesAsync\|SaveChanges()" --include="*.cs" 2>/dev/null; then
echo "🔴 CRITICAL: EF persistence method found"
((VIOLATIONS++))
fi
if grep -rn "modelBuilder\|OnModelCreating\|IEntityTypeConfiguration\|HasKey(\|HasIndex(\|HasOne(\|HasMany(" --include="*.cs" 2>/dev/null; then
echo "🔴 CRITICAL: EF model configuration / Fluent API found"
((VIOLATIONS++))
fi
if grep -rn "ExecuteUpdateAsync\|ExecuteDeleteAsync" --include="*.cs" 2>/dev/null; then
echo "🔴 CRITICAL: EF bulk operation found"
((VIOLATIONS++))
fi
if find . -name "*DbContext.cs" -o -name "*Context.cs" 2>/dev/null | grep -v "TrackingContext\|HttpContext\|LogContext"; then
echo "🔴 CRITICAL: EF Context file found"
((VIOLATIONS++))
fi
if [ -d "Data/Migrations" ] || [ -d "Migrations" ]; then
echo "🔴 CRITICAL: EF Migrations folder found"
((VIOLATIONS++))
fi
# ── Verify correct pattern exists ──
echo "--- Verifying SP-only pattern ---"
grep -rn "CommandType.StoredProcedure" --include="*.cs" 2>/dev/null && echo "✅ StoredProcedure CommandType found" || echo "âš ï¸ No StoredProcedure calls found"
grep -rn "class SpHelper" --include="*.cs" 2>/dev/null && echo "✅ SpHelper class found" || echo "âš ï¸ SpHelper not found — required"
grep -rn "DynamicParameters" --include="*.cs" 2>/dev/null && echo "✅ DynamicParameters usage found" || echo "âš ï¸ No DynamicParameters found"
grep -rn "WithTracking" --include="*.cs" 2>/dev/null && echo "✅ WithTracking (CorrelationId/RequestId injection) found" || echo "âš ï¸ WithTracking not found — tracking IDs may be missing"
echo "â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•"
if [ $VIOLATIONS -gt 0 ]; then
echo "⌠SP-ONLY MANDATE: $VIOLATIONS CRITICAL VIOLATIONS — DELIVERY BLOCKED"
else
echo "✅ SP-ONLY MANDATE: PASSED — all data access through stored procedures"
fi
echo "â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•"
```
### Why This Mandate Exists
| Concern | Stored Procedures (✅ our way) | Inline SQL / EF (⌠banned) |
|---------|-------------------------------|----------------------------|
| **SQL Injection** | Parameterized by design | Risky string interpolation |
| **Performance** | Cached execution plans, DBA-tunable | Plan recompilation, N+1 queries, lazy loading traps |
| **Request Tracking** | @CorrelationId/@RequestId in every SP call | No tracking — invisible to log.RequestLog |
| **Audit Trail** | SP logs START/SUCCESS/ERROR automatically | Changes happen silently, no audit |
| **DBA Control** | DBAs tune queries without code deploys | Locked in compiled C# code |
| **Soft Delete** | Enforced in SP (IsActive = 0, always) | Dev might forget, hard-delete data permanently |
| **Business Logic** | Centralized in SP + service layer | Scattered across EF configs, LINQ, migrations |
| **Schema Changes** | Idempotent .sql scripts, version-controlled | EF migration conflicts, snapshot drift |
| **Consistency** | Same _Manage/_Get pattern everywhere | Mixed patterns, every dev does it differently |
| **Debugging** | grep log.RequestLog by RequestId | No centralized logging, hunt through app logs |
### Correct Architecture Flow
```
React (UI) → API Controller → Service (optional) → Repository → SpHelper → Dapper → Stored Procedure → SQL Server
↑
Uses DynamicParameters
Injects @CorrelationId + @RequestId
CommandType.StoredProcedure ALWAYS
```
**Every data operation follows this chain. No shortcuts. No "just a quick EF query". No "inline SQL is faster for this one case".**
---
## Layer 1 — VS Code Problems Tab Simulation
Simulate what VS Code's Problems tab would show: Errors, Warnings, and Information diagnostics. Check every changed file.
### For ALL Languages
| Check | Severity | What to Look For |
|-------|----------|------------------|
| Syntax errors | 🔴 Error | Missing brackets, semicolons, unclosed strings, invalid tokens |
| Undefined references | 🔴 Error | Variables, functions, types, tables used but never declared |
| Type mismatches | 🔴 Error | Assigning string to int, wrong function argument types |
| Unused imports/usings | 🟡 Warning | `using System.Linq;` when no LINQ is used |
| Unused variables | 🟡 Warning | Declared but never read |
| Unreachable code | 🟡 Warning | Code after `return`, `throw`, `RETURN` |
| Deprecated API usage | 🟡 Warning | `DateTime` instead of `DateTime2`, `TEXT` instead of `NVARCHAR(MAX)` |
| Missing null checks | 🟡 Warning | Nullable types accessed without `?.` or null guard |
| Implicit `any` (TypeScript) | 🟡 Warning | Untyped parameters, missing return types |
| Missing `await` | 🔴 Error | Async call without `await` — fire-and-forget bug |
### Language-Specific Checks
#### T-SQL
```
✅ All identifiers resolved (tables, columns, SPs exist or are in context)
✅ Matching BEGIN/END blocks
✅ SET NOCOUNT ON present in every SP
✅ SET XACT_ABORT ON present in _Manage SPs
✅ GO batch separators between CREATE/ALTER statements
✅ No SELECT * in production code (list columns explicitly)
✅ All CASE expressions have matching END
✅ String literals use N'' prefix for NVARCHAR columns
✅ No orphaned temp tables (created but never dropped or used)
✅ THROW has correct 3-param syntax (number, message, state)
```
#### C# / .NET
```
✅ Namespace matches folder structure
✅ All interfaces implemented fully
✅ All abstract methods overridden
✅ async methods return Task/Task<T>, not void (except event handlers)
✅ IDisposable types wrapped in using/await using
✅ No raw Task.Result or .Wait() (deadlock risk)
✅ CancellationToken accepted and forwarded in async chains
✅ Nullable reference types handled (no CS8600, CS8601, CS8602 warnings)
✅ Constructor parameters match DI registrations
✅ No ambiguous method overloads
🔴 NO inline SQL strings (SELECT/INSERT/UPDATE/DELETE in C# code)
🔴 NO Entity Framework (DbContext, DbSet, SaveChanges, Include, migrations)
🔴 NO raw SqlCommand or CommandType.Text
🔴 ALL data access through SpHelper → Stored Procedures → Dapper
🔴 NO EF NuGet packages in .csproj (EntityFrameworkCore.*)
```
#### TypeScript / React
```
✅ No TypeScript strict mode violations (noImplicitAny, strictNullChecks)
✅ All imports resolve to existing modules
✅ JSX elements have matching closing tags
✅ React hooks follow Rules of Hooks (no conditional hooks, correct deps)
✅ useEffect cleanup functions present where needed (subscriptions, timers, AbortController)
✅ Key prop present on mapped elements
✅ No direct DOM manipulation (use refs instead)
✅ Event handlers typed correctly (React.ChangeEvent<HTMLInputElement>, etc.)
✅ Generic type parameters specified (no implicit any on useState<>, useRef<>)
✅ Exported types match their usage in consuming modules
```
### Validation Commands (run where applicable)
```bash
# TypeScript — compile check
npx tsc --noEmit 2>&1 | head -50
# ESLint
npx eslint . --ext .ts,.tsx --format compact 2>&1 | head -50
# .NET build
dotnet build --no-restore 2>&1 | grep -E "(error|warning) [A-Z]{2}[0-9]+" | head -50
# SQL syntax (basic)
# Use sqlcmd dry-run or grep for common syntax errors
grep -n "SELECT \*" *.sql # No SELECT * in production
grep -n "GETDATE()" *.sql # Should use SYSUTCDATETIME()
grep -n "= NULL" *.sql # Should use IS NULL
grep -n "EXEC(" *.sql # Check for SQL injection in dynamic SQL
```
### Output Format
```
## Layer 1 — VS Code Problems Tab
| # | File | Line | Severity | Code | Message |
|---|------|------|----------|------|---------|
| 1 | Users_Manage.sql | 45 | 🔴 Error | SQL001 | Missing SET NOCOUNT ON |
| 2 | UserService.cs | 12 | 🟡 Warning | CS8602 | Possible null reference |
| 3 | api.ts | 8 | 🟡 Warning | TS6133 | 'response' declared but never used |
**Result: ⌠1 Error, 2 Warnings — fix errors before proceeding**
```
---
## Layer 2 — Lint Check (ALL Languages)
**MANDATORY for every file.** Run the appropriate linter for each file type. Fix all errors; warnings should be fixed unless explicitly justified. This layer catches style violations, anti-patterns, and code quality issues that compilers don't flag.
### Installation Commands (run once per session if needed)
```bash
# ── TypeScript / React / JavaScript ──
npm install -D eslint @eslint/js typescript-eslint eslint-plugin-react eslint-plugin-react-hooks eslint-plugin-jsx-a11y 2>/dev/null
npm install -D prettier eslint-config-prettier eslint-plugin-prettier 2>/dev/null
# ── CSS / SCSS ──
npm install -D stylelint stylelint-config-standard stylelint-config-tailwindcss 2>/dev/null
# ── HTML ──
npm install -D htmlhint 2>/dev/null
# ── JSON ──
npm install -D jsonlint-mod 2>/dev/null
# ── Markdown ──
npm install -D markdownlint-cli 2>/dev/null
# ── SQL (T-SQL) ──
npm install -D sql-lint 2>/dev/null
pip install sqlfluff --break-system-packages 2>/dev/null
# ── C# / .NET (Roslyn analyzers — included in SDK 8+) ──
# These are built into dotnet build with <EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
# Additional: dotnet format for auto-fix
```
---
### 2.1 TypeScript / React — ESLint + Prettier
#### Rules (Error = 🔴, Warning = 🟡)
| Rule ID | Severity | What It Catches |
|---------|----------|-----------------|
| `@typescript-eslint/no-explicit-any` | 🔴 Error | Using `any` type — use `unknown` and narrow |
| `@typescript-eslint/no-unused-vars` | 🔴 Error | Variables/imports declared but never used |
| `@typescript-eslint/no-non-null-assertion` | 🟡 Warning | Using `!` non-null assertion — prefer optional chaining `?.` |
| `@typescript-eslint/explicit-function-return-type` | 🟡 Warning | Public functions missing return type annotation |
| `@typescript-eslint/no-floating-promises` | 🔴 Error | Async call without `await` or `.catch()` — fire-and-forget bug |
| `@typescript-eslint/no-misused-promises` | 🔴 Error | Passing async function where sync callback expected |
| `@typescript-eslint/strict-boolean-expressions` | 🟡 Warning | Truthy check on non-boolean: `if (str)` instead of `if (str !== '')` |
| `@typescript-eslint/consistent-type-imports` | 🟡 Warning | `import type { X }` for type-only imports |
| `@typescript-eslint/no-unnecessary-condition` | 🟡 Warning | Condition is always true/false — dead code |
| `@typescript-eslint/prefer-nullish-coalescing` | 🟡 Warning | Use `??` instead of `\|\|` for null/undefined checks |
| `@typescript-eslint/no-unsafe-assignment` | 🔴 Error | Assigning `any` typed value to typed variable |
| `@typescript-eslint/no-unsafe-member-access` | 🔴 Error | Accessing properties on `any` typed value |
| `@typescript-eslint/no-unsafe-call` | 🔴 Error | Calling `any` typed value as function |
| `@typescript-eslint/no-unsafe-return` | 🔴 Error | Returning `any` from typed function |
| `react/jsx-no-target-blank` | 🔴 Error | `<a target="_blank">` without `rel="noopener noreferrer"` |
| `react/no-array-index-key` | 🟡 Warning | Using array index as `key` prop — unstable on reorder |
| `react-hooks/rules-of-hooks` | 🔴 Error | Hooks called conditionally or inside loops |
| `react-hooks/exhaustive-deps` | 🟡 Warning | Missing dependencies in useEffect/useMemo/useCallback |
| `react/no-danger` | 🔴 Error | Using `dangerouslySetInnerHTML` — XSS risk |
| `react/jsx-no-constructed-context-values` | 🟡 Warning | Object literal in Context.Provider value — re-renders children |
| `react/no-unstable-nested-components` | 🟡 Warning | Component defined inside render — unmounts/remounts every render |
| `jsx-a11y/alt-text` | 🔴 Error | `<img>` without `alt` attribute |
| `jsx-a11y/click-events-have-key-events` | 🟡 Warning | `onClick` without `onKeyDown`/`onKeyUp` |
| `jsx-a11y/no-autofocus` | 🟡 Warning | `autoFocus` disrupts screen reader flow |
| `jsx-a11y/anchor-is-valid` | 🟡 Warning | `<a>` without valid `href` — use `<button>` instead |
| `no-console` | 🟡 Warning | `console.log` left in production code |
| `no-debugger` | 🔴 Error | `debugger` statement in production code |
| `no-var` | 🔴 Error | Using `var` — use `const` or `let` |
| `prefer-const` | 🟡 Warning | `let` when variable is never reassigned |
| `eqeqeq` | 🔴 Error | `==` / `!=` instead of `===` / `!==` |
| `no-eval` | 🔴 Error | `eval()` — code injection risk |
| `no-implied-eval` | 🔴 Error | `setTimeout("code")` — hidden eval |
| `curly` | 🟡 Warning | If/else/for/while without braces |
#### ESLint Config (eslint.config.mjs — flat config)
```javascript
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
import react from 'eslint-plugin-react';
import reactHooks from 'eslint-plugin-react-hooks';
import jsxA11y from 'eslint-plugin-jsx-a11y';
import prettier from 'eslint-config-prettier';
export default tseslint.config(
eslint.configs.recommended,
...tseslint.configs.strictTypeChecked,
...tseslint.configs.stylisticTypeChecked,
{
plugins: { react, 'react-hooks': reactHooks, 'jsx-a11y': jsxA11y },
rules: {
// ── TypeScript ──
'@typescript-eslint/no-explicit-any': 'error',
'@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/no-misused-promises': 'error',
'@typescript-eslint/consistent-type-imports': 'warn',
'@typescript-eslint/prefer-nullish-coalescing': 'warn',
'@typescript-eslint/strict-boolean-expressions': 'warn',
'@typescript-eslint/no-non-null-assertion': 'warn',
'@typescript-eslint/explicit-function-return-type': ['warn', { allowExpressions: true }],
'@typescript-eslint/no-unnecessary-condition': 'warn',
'@typescript-eslint/no-unsafe-assignment': 'error',
'@typescript-eslint/no-unsafe-member-access': 'error',
'@typescript-eslint/no-unsafe-call': 'error',
'@typescript-eslint/no-unsafe-return': 'error',
// ── React ──
'react/jsx-no-target-blank': 'error',
'react/no-array-index-key': 'warn',
'react/no-danger': 'error',
'react/jsx-no-constructed-context-values': 'warn',
'react/no-unstable-nested-components': 'warn',
'react-hooks/rules-of-hooks': 'error',
'react-hooks/exhaustive-deps': 'warn',
// ── Accessibility ──
'jsx-a11y/alt-text': 'error',
'jsx-a11y/click-events-have-key-events': 'warn',
'jsx-a11y/no-autofocus': 'warn',
'jsx-a11y/anchor-is-valid': 'warn',
// ── General JS ──
'no-console': 'warn',
'no-debugger': 'error',
'no-var': 'error',
'prefer-const': 'warn',
'eqeqeq': ['error', 'always'],
'no-eval': 'error',
'no-implied-eval': 'error',
'curly': ['warn', 'all'],
},
languageOptions: {
parserOptions: {
project: true,
ecmaFeatures: { jsx: true },
},
},
settings: { react: { version: 'detect' } },
},
prettier, // Must be last — disables formatting rules that conflict with Prettier
);
```
#### Prettier Config (.prettierrc)
```json
{
"semi": true,
"singleQuote": true,
"trailingComma": "all",
"printWidth": 100,
"tabWidth": 2,
"useTabs": false,
"bracketSpacing": true,
"jsxSingleQuote": false,
"arrowParens": "always",
"endOfLine": "lf"
}
```
#### Run Commands
```bash
# Lint check (report only)
npx eslint . --ext .ts,.tsx,.js,.jsx --format stylish 2>&1
# Lint auto-fix
npx eslint . --ext .ts,.tsx,.js,.jsx --fix 2>&1
# Prettier check
npx prettier --check "src/**/*.{ts,tsx,js,jsx,json,css,md}" 2>&1
# Prettier auto-fix
npx prettier --write "src/**/*.{ts,tsx,js,jsx,json,css,md}" 2>&1
# Combined: lint + format check
npx eslint . --ext .ts,.tsx && npx prettier --check "src/**/*.{ts,tsx}"
```
---
### 2.2 C# / .NET — Roslyn Analyzers + dotnet-format + EditorConfig
#### Rules (Error = 🔴, Warning = 🟡)
| Rule ID | Severity | What It Catches |
|---------|----------|-----------------|
| `CA1001` | 🔴 Error | Type owns disposable field but doesn't implement IDisposable |
| `CA1031` | 🟡 Warning | Catching general `Exception` — catch specific types |
| `CA1032` | 🟡 Warning | Custom exception missing standard constructors |
| `CA1054` | 🟡 Warning | URI parameter should be `System.Uri`, not `string` |
| `CA1062` | 🔴 Error | Validate public method arguments for null |
| `CA1063` | 🔴 Error | Implement IDisposable correctly (Dispose pattern) |
| `CA1303` | 🟡 Warning | String literal in exception/UI — consider resource file for i18n |
| `CA1304` | 🟡 Warning | Missing `CultureInfo` or `StringComparison` on string operations |
| `CA1305` | 🟡 Warning | Missing `IFormatProvider` — use `CultureInfo.InvariantCulture` |
| `CA1707` | 🟡 Warning | Identifier contains underscore (non-standard naming) |
| `CA1716` | 🟡 Warning | Identifier matches reserved language keyword |
| `CA1812` | 🟡 Warning | Internal class never instantiated — dead code? |
| `CA1822` | 🟡 Warning | Method doesn't access instance data — make `static` |
| `CA1848` | 🟡 Warning | Use `LoggerMessage.Define` for high-perf logging |
| `CA1860` | 🟡 Warning | Prefer `Length > 0` over `Any()` for collections |
| `CA2000` | 🔴 Error | Dispose objects before losing scope |
| `CA2007` | 🟡 Warning | Missing `ConfigureAwait(false)` in library code |
| `CA2016` | 🔴 Error | Forward `CancellationToken` to methods that accept it |
| `CA2100` | 🔴 Error | SQL command text from variable — SQL injection risk |
| `CA2213` | 🔴 Error | Disposable fields should be disposed |
| `CA2227` | 🟡 Warning | Collection property has setter — remove setter, use init or readonly |
| `CA2241` | 🔴 Error | Format string argument count mismatch |
| `CA2254` | 🟡 Warning | Log message template should not vary between calls |
| `IDE0003` | 🟡 Warning | `this.` qualification unnecessary — remove |
| `IDE0005` | 🟡 Warning | Unnecessary `using` directive — remove |
| `IDE0011` | 🟡 Warning | Add braces to `if`/`else`/`for`/`while` |
| `IDE0044` | 🟡 Warning | Private field can be `readonly` |
| `IDE0055` | 🟡 Warning | Formatting rule violation (indentation, spacing) |
| `IDE0058` | â„¹ï¸ Info | Expression value is never used |
| `IDE0060` | 🟡 Warning | Unused parameter — remove or prefix with `_` |
| `IDE0063` | 🟡 Warning | Use simple `using` declaration instead of `using` block |
| `IDE0066` | 🟡 Warning | Use switch expression instead of switch statement |
| `IDE0090` | 🟡 Warning | Use `new()` target-typed expression |
| `CS8600` | 🔴 Error | Converting null literal to non-nullable type |
| `CS8601` | 🔴 Error | Possible null reference assignment |
| `CS8602` | 🔴 Error | Dereference of possibly null reference |
| `CS8604` | 🔴 Error | Possible null reference argument for parameter |
| `CS8618` | 🔴 Error | Non-nullable property must contain non-null when exiting constructor |
| `CS8625` | 🔴 Error | Cannot convert null literal to non-nullable reference type |
| `ASP0014` | 🟡 Warning | Suggest using top-level route registrations |
| `ASP0019` | 🟡 Warning | Suggest using IHeaderDictionary.Append |
| **SP-ONLY MANDATE RULES** | | |
| `SP001` | 🔴 Error | **Inline SQL detected** — any SELECT/INSERT/UPDATE/DELETE string in C# code |
| `SP002` | 🔴 Error | **Entity Framework detected** — DbContext, DbSet, using EF namespace, EF NuGet package |
| `SP003` | 🔴 Error | **Raw SqlCommand** — new SqlCommand() or CommandType.Text found |
| `SP004` | 🔴 Error | **Direct Dapper outside SpHelper** — Dapper calls must go through SpHelper only |
| `SP005` | 🔴 Error | **EF NuGet reference** — EntityFrameworkCore in .csproj |
| `SP006` | 🔴 Error | **EF migration** — Migrations folder, dotnet ef command, Add-Migration |
| `SP007` | 🔴 Error | **EF Fluent API** — modelBuilder, HasKey, HasOne, OnModelCreating |
| `SP008` | 🔴 Error | **EF persistence** — SaveChanges, SaveChangesAsync, Add(), Update(), Remove() on context |
| `SP009` | 🔴 Error | **EF query operators** — Include(), ThenInclude(), AsNoTracking() on context |
| `SP010` | 🔴 Error | **FromSqlRaw / ExecuteSqlRaw** — raw SQL through EF methods |
| `SP011` | 🟡 Warning | **Missing SpHelper** — Repository class has no SpHelper dependency |
| `SP012` | 🟡 Warning | **Missing WithTracking** — SP call without CorrelationId/RequestId injection |
| `ASP0019` | 🟡 Warning | Suggest using IHeaderDictionary.Append |
#### .editorconfig (place in solution root)
```ini
root = true
# ── All files ──
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
# ── C# files ──
[*.cs]
# Formatting
csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_indent_case_contents = true
csharp_indent_switch_labels = true
csharp_space_after_cast = false
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
# Naming: private fields _camelCase
dotnet_naming_rule.private_fields_should_be_camel_case.symbols = private_fields
dotnet_naming_rule.private_fields_should_be_camel_case.style = camel_case_underscore
dotnet_naming_rule.private_fields_should_be_camel_case.severity = warning
dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
dotnet_naming_style.camel_case_underscore.required_prefix = _
dotnet_naming_style.camel_case_underscore.capitalization = camel_case
# Naming: interfaces I prefix
dotnet_naming_rule.interfaces_begin_with_i.symbols = interfaces
dotnet_naming_rule.interfaces_begin_with_i.style = begins_with_i
dotnet_naming_rule.interfaces_begin_with_i.severity = error
dotnet_naming_symbols.interfaces.applicable_kinds = interface
dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.capitalization = pascal_case
# Naming: async methods end with Async
dotnet_naming_rule.async_methods_end_with_async.symbols = async_methods
dotnet_naming_rule.async_methods_end_with_async.style = ends_with_async
dotnet_naming_rule.async_methods_end_with_async.severity = warning
dotnet_naming_symbols.async_methods.applicable_kinds = method
dotnet_naming_symbols.async_methods.required_modifiers = async
dotnet_naming_style.ends_with_async.required_suffix = Async
dotnet_naming_style.ends_with_async.capitalization = pascal_case
# Code quality
dotnet_diagnostic.CA1001.severity = error
dotnet_diagnostic.CA1062.severity = error
dotnet_diagnostic.CA1063.severity = error
dotnet_diagnostic.CA2000.severity = error
dotnet_diagnostic.CA2016.severity = error
dotnet_diagnostic.CA2100.severity = error
dotnet_diagnostic.CA2213.severity = error
dotnet_diagnostic.CA1031.severity = warning
dotnet_diagnostic.CA1822.severity = warning
dotnet_diagnostic.IDE0005.severity = warning
dotnet_diagnostic.IDE0044.severity = warning
dotnet_diagnostic.IDE0060.severity = warning
# Nullable reference types
dotnet_diagnostic.CS8600.severity = error
dotnet_diagnostic.CS8601.severity = error
dotnet_diagnostic.CS8602.severity = error
dotnet_diagnostic.CS8604.severity = error
dotnet_diagnostic.CS8618.severity = error
# ── SQL files ──
[*.sql]
indent_size = 4
indent_style = space
# ── TypeScript / JavaScript ──
[*.{ts,tsx,js,jsx}]
indent_size = 2
# ── JSON ──
[*.json]
indent_size = 2
# ── YAML ──
[*.{yml,yaml}]
indent_size = 2
# ── Markdown ──
[*.md]
trim_trailing_whitespace = false
```
#### .csproj Analyzer Configuration
```xml
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
<TreatWarningsAsErrors>false</TreatWarningsAsErrors>
<EnforceCodeStyleInBuild>true</EnforceCodeStyleInBuild>
<AnalysisLevel>latest-recommended</AnalysisLevel>
<EnableNETAnalyzers>true</EnableNETAnalyzers>
</PropertyGroup>
```
#### Run Commands
```bash
# Full build with analyzers (catches Roslyn + nullable + style)
dotnet build --no-restore -warnaserror 2>&1 | head -80
# Format check (dry run — reports violations)
dotnet format --verify-no-changes --verbosity diagnostic 2>&1 | head -50
# Format auto-fix
dotnet format 2>&1
# Specific analyzer check
dotnet build /p:EnforceCodeStyleInBuild=true /p:AnalysisLevel=latest-all 2>&1 | grep -E "(error|warning) (CA|CS|IDE|ASP)" | head -50
```
---
### 2.3 T-SQL — SQL Lint Rules
#### Rules (Error = 🔴, Warning = 🟡)
| Rule ID | Severity | What It Catches |
|---------|----------|-----------------|
| `SQL001` | 🔴 Error | Missing `SET NOCOUNT ON` in stored procedure |
| `SQL002` | 🔴 Error | Missing `SET XACT_ABORT ON` in write procedures (_Manage) |
| `SQL003` | 🔴 Error | `SELECT *` used in production query — list columns explicitly |
| `SQL004` | 🔴 Error | `= NULL` comparison — must use `IS NULL` / `IS NOT NULL` |
| `SQL005` | 🔴 Error | `GETDATE()` used — must use `SYSUTCDATETIME()` for UTC |
| `SQL006` | 🔴 Error | `DATETIME` data type used — must use `DATETIME2` |
| `SQL007` | 🔴 Error | Dynamic SQL with string concatenation — SQL injection risk |
| `SQL008` | 🟡 Warning | Missing `N''` prefix for NVARCHAR string literals |
| `SQL009` | 🟡 Warning | Missing explicit constraint names (PK_, FK_, UQ_, DF_, CK_) |
| `SQL010` | 🟡 Warning | Missing `GO` batch separator between DDL statements |
| `SQL011` | 🟡 Warning | Missing `IF NOT EXISTS` guard on CREATE TABLE/INDEX |
| `SQL012` | 🟡 Warning | Missing index on foreign key column |
| `SQL013` | 🟡 Warning | `NOLOCK` hint used — prefer RCSI at database level |
| `SQL014` | 🟡 Warning | Unqualified column names in multi-table query (missing table alias) |
| `SQL015` | 🟡 Warning | `TOP` without `ORDER BY` — non-deterministic results |
| `SQL016` | 🟡 Warning | `IN` subquery — prefer `EXISTS` for correlated subqueries |
| `SQL017` | 🟡 Warning | `MONEY` / `FLOAT` for currency — use `DECIMAL(19,4)` |
| `SQL018` | 🟡 Warning | `TEXT` / `IMAGE` deprecated types — use `NVARCHAR(MAX)` / `VARBINARY(MAX)` |
| `SQL019` | 🔴 Error | Missing `@CorrelationId` / `@RequestId` as first two SP parameters |
| `SQL020` | 🔴 Error | Missing `log.RequestLog` START/SUCCESS/ERROR logging in SP |
| `SQL021` | 🟡 Warning | Missing audit columns (`CreatedBy`, `CreatedAt`, `ModifiedBy`, `ModifiedAt`) |
| `SQL022` | 🟡 Warning | Missing `IsActive BIT` soft-delete column |
| `SQL023` | 🟡 Warning | Missing semicolon statement terminator |
| `SQL024` | 🟡 Warning | Non-SARGable WHERE clause (function on indexed column) |
| `SQL025` | 🟡 Warning | Implicit conversion risk (VARCHAR compared to NVARCHAR column) |
| `SQL026` | 🟡 Warning | Missing TRY/CATCH in stored procedure |
| `SQL027` | 🟡 Warning | Cursor used — prefer set-based operations |
| `SQL028` | 🟡 Warning | `WHILE` loop — consider set-based alternative |
| `SQL029` | 🟡 Warning | `VARCHAR(MAX)` used without justification — prefer sized `VARCHAR(n)` |
| `SQL030` | 🟡 Warning | Table/column name is a reserved keyword |
#### Run Commands (bash-based SQL linting)
```bash
# ── Critical checks (🔴 Errors) ──
echo "=== SQL LINT — CRITICAL ==="
# SQL003: SELECT *
grep -rn "SELECT \*" --include="*.sql" | grep -v "EXISTS\s*(SELECT" | grep -v "\-\-" && echo "🔴 SQL003: SELECT * found"
# SQL004: = NULL
grep -rn "[^!<>]= NULL" --include="*.sql" | grep -v "\-\-" && echo "🔴 SQL004: = NULL found (use IS NULL)"
# SQL005: GETDATE
grep -rn "GETDATE()" --include="*.sql" | grep -v "\-\-" && echo "🔴 SQL005: GETDATE() found (use SYSUTCDATETIME())"
# SQL006: DATETIME without 2
grep -rn "DATETIME[^2]" --include="*.sql" | grep -v "DATETIME2" | grep -v "\-\-" && echo "🔴 SQL006: DATETIME found (use DATETIME2)"
# SQL007: Dynamic SQL concatenation
grep -rn "EXEC\s*(" --include="*.sql" | grep "+" | grep -v "\-\-" && echo "🔴 SQL007: Dynamic SQL with concatenation"
# SQL019: Missing tracking params
for f in $(grep -rl "CREATE.*PROCEDURE\|ALTER.*PROCEDURE" --include="*.sql"); do
if ! grep -q "@CorrelationId.*UNIQUEIDENTIFIER" "$f"; then
echo "🔴 SQL019: $f — Missing @CorrelationId parameter"
fi
if ! grep -q "@RequestId.*UNIQUEIDENTIFIER" "$f"; then
echo "🔴 SQL019: $f — Missing @RequestId parameter"
fi
done
# SQL001: Missing SET NOCOUNT ON
for f in $(grep -rl "CREATE.*PROCEDURE\|ALTER.*PROCEDURE" --include="*.sql"); do
if ! grep -q "SET NOCOUNT ON" "$f"; then
echo "🔴 SQL001: $f — Missing SET NOCOUNT ON"
fi
done
# ── Warning checks (🟡) ──
echo "=== SQL LINT — WARNINGS ==="
# SQL009: Unnamed constraints
grep -rn "PRIMARY KEY\|FOREIGN KEY\|UNIQUE\|DEFAULT\|CHECK" --include="*.sql" | grep -v "CONSTRAINT [A-Z][A-Z]_" | grep -v "\-\-" | head -20
# SQL013: NOLOCK hints
grep -rn "NOLOCK\|WITH\s*(NOLOCK)" --include="*.sql" | grep -v "\-\-" && echo "🟡 SQL013: NOLOCK hint found"
# SQL015: TOP without ORDER BY
grep -rn "SELECT TOP" --include="*.sql" | while read -r line; do
linenum=$(echo "$line" | cut -d: -f2)
file=$(echo "$line" | cut -d: -f1)
if ! sed -n "$((linenum)),\$p" "$file" | head -10 | grep -q "ORDER BY"; then
echo "🟡 SQL015: $line — TOP without ORDER BY"
fi
done
# SQL023: Missing semicolons
grep -rn "^[[:space:]]*\(SELECT\|INSERT\|UPDATE\|DELETE\|EXEC\)" --include="*.sql" | head -20
echo "=== SQL LINT COMPLETE ==="
```
#### SQLFluff Config (.sqlfluff — when using sqlfluff)
```ini
[sqlfluff]
dialect = tsql
templater = raw
max_line_length = 120
[sqlfluff:rules:capitalisation.keywords]
capitalisation_policy = upper
[sqlfluff:rules:capitalisation.identifiers]
capitalisation_policy = pascal
[sqlfluff:rules:aliasing.table]
aliasing = explicit
[sqlfluff:rules:aliasing.column]
aliasing = explicit
[sqlfluff:rules:convention.terminator]
require_final_semicolon = true
```
```bash
# SQLFluff lint
sqlfluff lint --dialect tsql *.sql 2>&1 | head -50
# SQLFluff auto-fix
sqlfluff fix --dialect tsql *.sql 2>&1
```
---
### 2.4 HTML — HTMLHint
#### Rules
| Rule | Severity | What It Catches |
|------|----------|-----------------|
| `tagname-lowercase` | 🟡 Warning | Tag names should be lowercase |
| `attr-lowercase` | 🟡 Warning | Attribute names should be lowercase |
| `attr-value-double-quotes` | 🟡 Warning | Attribute values should use double quotes |
| `doctype-first` | 🔴 Error | DOCTYPE must be first line in HTML files |
| `tag-pair` | 🔴 Error | Tags must be paired (no unclosed tags) |
| `spec-char-escape` | 🟡 Warning | Special characters must be escaped (`&`, `<`) |
| `id-unique` | 🔴 Error | Duplicate `id` attributes on same page |
| `src-not-empty` | 🔴 Error | `src` / `href` attributes must not be empty |
| `alt-require` | 🔴 Error | `<img>` must have `alt` attribute |
| `title-require` | 🟡 Warning | `<html>` should have `<title>` in `<head>` |
| `style-disabled` | 🟡 Warning | Inline `style` attribute — use CSS classes |
| `inline-script-disabled` | 🟡 Warning | Inline `onclick` etc. — use event listeners |
| `head-script-disabled` | 🟡 Warning | Prefer scripts at bottom of `<body>` or `defer` |
| `input-requires-label` | 🔴 Error | `<input>` must have associated `<label>` |
#### HTMLHint Config (.htmlhintrc)
```json
{
"tagname-lowercase": true,
"attr-lowercase": true,
"attr-value-double-quotes": true,
"doctype-first": true,
"tag-pair": true,
"spec-char-escape": true,
"id-unique": true,
"src-not-empty": true,
"alt-require": true,
"title-require": true,
"style-disabled": true,
"inline-script-disabled": true,
"input-requires-label": true
}
```
```bash
npx htmlhint "**/*.html" 2>&1 | head -30
```
---
### 2.5 CSS / SCSS — Stylelint
#### Rules
| Rule | Severity | What It Catches |
|------|----------|-----------------|
| `color-no-invalid-hex` | 🔴 Error | Invalid hex color value |
| `font-family-no-duplicate-names` | 🟡 Warning | Same font listed twice |
| `declaration-no-important` | 🟡 Warning | `!important` — usually a specificity issue |
| `no-duplicate-selectors` | 🟡 Warning | Same selector appears twice in file |
| `no-descending-specificity` | 🟡 Warning | Lower specificity rule overrides higher one |
| `selector-no-qualifying-type` | 🟡 Warning | `div.class` — unnecessary type qualifier |
| `shorthand-property-no-redundant-values` | 🟡 Warning | `margin: 10px 10px 10px 10px` → `margin: 10px` |
| `property-no-unknown` | 🔴 Error | Unknown CSS property (typo) |
| `unit-no-unknown` | 🔴 Error | Unknown CSS unit (e.g., `10xp`) |
| `selector-max-id` | 🟡 Warning | Avoid ID selectors in stylesheets (specificity) |
| `max-nesting-depth` | 🟡 Warning | SCSS nesting > 3 levels deep |
| `no-empty-source` | 🟡 Warning | Empty CSS file |
#### Stylelint Config (.stylelintrc.json)
```json
{
"extends": ["stylelint-config-standard"],
"rules": {
"color-no-invalid-hex": true,
"font-family-no-duplicate-names": true,
"declaration-no-important": true,
"no-duplicate-selectors": true,
"no-descending-specificity": true,
"property-no-unknown": true,
"unit-no-unknown": true,
"selector-max-id": 0,
"max-nesting-depth": 3,
"no-empty-source": true
}
}
```
```bash
npx stylelint "**/*.css" "**/*.scss" 2>&1 | head -30
```
---
### 2.6 JSON — JSONLint + Schema Validation
#### Rules
| Rule | Severity | What It Catches |
|------|----------|-----------------|
| Syntax error | 🔴 Error | Invalid JSON (trailing comma, single quotes, comments) |
| Duplicate keys | 🔴 Error | Same key appears twice in same object |
| Schema mismatch | 🟡 Warning | `appsettings.json` missing required fields, wrong types |
| Trailing comma | 🔴 Error | `{ "a": 1, }` — invalid in standard JSON |
| Single quotes | 🔴 Error | `{'key': 'value'}` — JSON requires double quotes |
#### Run Commands
```bash
# Validate all JSON files
for f in $(find . -name "*.json" -not -path "*/node_modules/*"); do
python3 -c "import json; json.load(open('$f'))" 2>&1 && echo "✅ $f" || echo "🔴 $f — INVALID JSON"
done
# OR use jsonlint
npx jsonlint-mod --quiet *.json 2>&1
```
---
### 2.7 Markdown — markdownlint
#### Rules
| Rule | Severity | What It Catches |
|------|----------|-----------------|
| `MD001` | 🟡 Warning | Heading increment by more than one level (h1 → h3 skips h2) |
| `MD003` | 🟡 Warning | Inconsistent heading style (ATX vs setext) |
| `MD009` | 🟡 Warning | Trailing whitespace |
| `MD012` | 🟡 Warning | Multiple consecutive blank lines |
| `MD013` | â„¹ï¸ Info | Line length exceeds 120 chars |
| `MD022` | 🟡 Warning | Headings should be surrounded by blank lines |
| `MD032` | 🟡 Warning | Lists should be surrounded by blank lines |
| `MD033` | 🟡 Warning | Inline HTML in markdown (prefer markdown syntax) |
| `MD034` | 🟡 Warning | Bare URL (wrap in `<>` or `[text](url)`) |
| `MD041` | 🟡 Warning | First line should be a top-level heading |
```bash
npx markdownlint "**/*.md" --ignore node_modules 2>&1 | head -30
```
---
### 2.8 YAML — yamllint
```bash
pip install yamllint --break-system-packages 2>/dev/null
yamllint -s . 2>&1 | head -30
```
---
### 2.9 Dockerfile — hadolint
```bash
# If Docker files exist
if ls Dockerfile* 2>/dev/null; then
docker run --rm -i hadolint/hadolint < Dockerfile 2>&1 | head -20
fi
```
---
### Layer 2 Output Format
```
## Layer 2 — Lint Check
### TypeScript / React (ESLint + Prettier)
| # | File | Line | Rule | Severity | Message | Auto-Fix? |
|---|------|------|------|----------|---------|-----------|
| 1 | UserCard.tsx | 12 | @typescript-eslint/no-explicit-any | 🔴 Error | Unexpected `any`. Specify a type. | No |
| 2 | api.ts | 34 | @typescript-eslint/no-floating-promises | 🔴 Error | Promise returned but not awaited | No |
| 3 | App.tsx | 5 | prefer-const | 🟡 Warning | 'theme' is never reassigned. Use `const`. | ✅ Yes |
| 4 | index.tsx | 1 | @typescript-eslint/consistent-type-imports | 🟡 Warning | Use `import type` for type-only imports | ✅ Yes |
Prettier: 2 files need formatting (auto-fixable ✅)
### C# / .NET (Roslyn + dotnet-format)
| # | File | Line | Rule | Severity | Message | Auto-Fix? |
|---|------|------|------|----------|---------|-----------|
| 1 | UserService.cs | 45 | CA2016 | 🔴 Error | Forward CancellationToken to 'GetAsync' | No |
| 2 | SpHelper.cs | 12 | CS8602 | 🔴 Error | Dereference of possibly null reference | No |
| 3 | Program.cs | 8 | IDE0005 | 🟡 Warning | Remove unnecessary using | ✅ Yes |
dotnet-format: 3 files need formatting (auto-fixable ✅)
### T-SQL (SQL Lint)
| # | File | Line | Rule | Severity | Message | Auto-Fix? |
|---|------|------|------|----------|---------|-----------|
| 1 | Reports_Get.sql | 15 | SQL003 | 🔴 Error | SELECT * — list columns explicitly | No |
| 2 | Users_Manage.sql | 88 | SQL023 | 🟡 Warning | Missing semicolon terminator | ✅ Yes |
### JSON
All JSON files valid ✅
### Summary
| Language | 🔴 Errors | 🟡 Warnings | Auto-Fixable |
|----------|-----------|-------------|--------------|
| TypeScript/React | 2 | 2 | 2 |
| C# / .NET | 2 | 1 | 1 |
| T-SQL | 1 | 1 | 1 |
| JSON | 0 | 0 | 0 |
| **Total** | **5** | **4** | **4** |
**Result: ⌠5 Errors found — fix all errors before proceeding to Layer 3**
```
---
## Layer 3 — SonarQube-Lite Static Analysis
Simulate SonarQube's key rules for reliability, maintainability, and code smells.
### 3.1 Code Smells
| Smell | Severity | Detection |
|-------|----------|-----------|
| **Cognitive Complexity** > 15 | 🟠High | Nested ifs/loops/switches exceeding 3 levels; long CASE chains |
| **Method too long** > 40 lines | 🟡 Medium | Functions/methods/SP blocks exceeding 40 executable lines |
| **Too many parameters** > 7 | 🟡 Medium | Functions or SPs with more than 7 business parameters (tracking IDs excluded) |
| **Duplicate code blocks** | 🟡 Medium | 6+ lines duplicated across files; copy-pasted WHERE clauses |
| **Dead code** | 🟡 Medium | Commented-out code blocks, unreachable branches, unused functions |
| **Magic numbers/strings** | 🟡 Medium | Hardcoded values instead of constants: `if (status == 3)`, `"admin"` |
| **Long parameter list** | 🟡 Medium | Favor parameter objects over 5+ primitive parameters |
| **Deep nesting** > 3 levels | 🟡 Medium | Early return/guard clauses preferred over nested ifs |
| **Empty catch blocks** | 🟠High | `catch { }` or `catch (Exception) { }` with no logging/re-throw |
| **God class/file** > 300 lines | 🟡 Medium | Split into focused, single-responsibility modules |
### 3.2 Reliability
| Rule | Severity | Detection |
|------|----------|-----------|
| Null pointer dereference | 🔴 Critical | Accessing `.Property` on potentially null object |
| Resource leak | 🟠High | SqlConnection, HttpClient, Stream not disposed |
| Unchecked return value | 🟡 Medium | Ignoring return from async calls, .TryParse, etc. |
| Off-by-one errors | 🟠High | Array bounds, pagination OFFSET calculations |
| Race conditions | 🟠High | Shared mutable state without synchronization |
| Missing error handling | 🟠High | No try-catch around I/O operations |
| Infinite loop risk | 🔴 Critical | Loops with no guaranteed exit condition |
### 3.3 Maintainability Rating
Score each file A-E:
| Rating | Criteria |
|--------|----------|
| **A** | ≤ 5% of code needs refactoring; no smells above Medium |
| **B** | 6–10% needs refactoring; no more than 2 Medium smells |
| **C** | 11–20% needs refactoring; has High smells but no Critical |
| **D** | 21–50% needs refactoring; has Critical smells |
| **E** | > 50% needs refactoring; fundamental design issues |
### 3.4 Duplication Detection
Flag these patterns:
- **Exact duplicates**: 6+ identical lines across files
- **Structural duplicates**: Same logic with different variable names
- **SQL duplicates**: Repeated WHERE/JOIN patterns that should be a view or CTE
- **Config duplicates**: Same connection strings, URLs in multiple places
### Output Format
```
## Layer 3 — SonarQube-Lite Analysis
### Code Smells: 3 found
| # | File | Line | Rule | Severity | Message |
|---|------|------|------|----------|---------|
| 1 | OrderService.cs | 45-120 | S3776 | 🟠High | Cognitive complexity is 22 (max 15) |
| 2 | Users_Get.sql | 30 | S109 | 🟡 Medium | Magic number 200 — extract to named constant or parameter |
| 3 | UserList.tsx | 15-89 | S138 | 🟡 Medium | Function too long (74 lines, max 40) |
### Duplication: 1 block
| Files | Lines | Duplicate Lines |
|-------|-------|----------------|
| Orders_Get.sql ↔ Products_Get.sql | 20-35 ↔ 18-33 | 15 lines (pagination pattern) |
### Maintainability: B (92/100)
**Result: âš ï¸ 1 High, 2 Medium — fix High before proceeding**
```
---
## Layer 4 — Vulnerability Scan
Check for known vulnerability patterns in code and dependencies.
### 4.1 Injection Vulnerabilities
| Type | Language | What to Check |
|------|----------|---------------|
| **SQL Injection** | T-SQL | Dynamic SQL built with string concatenation: `EXEC('SELECT * FROM ' + @TableName)` |
| **SQL Injection** | C# | Raw string interpolation in queries: `$"SELECT * FROM Users WHERE Id = {id}"` |
| **XSS** | React/TS | `dangerouslySetInnerHTML`, unescaped user input in DOM |
| **Command Injection** | C# | `Process.Start()` with user-supplied arguments |
| **Path Traversal** | C#/Node | File operations with unsanitized user input: `File.ReadAllText(userPath)` |
| **LDAP Injection** | C# | Unsanitized input in LDAP queries |
| **NoSQL Injection** | TS/Node | Unvalidated objects passed to MongoDB queries |
| **Header Injection** | C# | User input in HTTP response headers |
### 4.2 Secrets & Credentials Exposure
```
🔴 CRITICAL — scan every file for:
✅ Hardcoded connection strings with passwords
✅ API keys in source code (regex: [A-Za-z0-9]{20,} near 'key', 'secret', 'token', 'password')
✅ Private keys or certificates in code
✅ Credentials in config files committed to source (appsettings.json with real passwords)
✅ JWT secrets hardcoded
✅ Cloud provider access keys (AWS, Azure, GCP patterns)
✅ Database passwords in plain text
```
**Detection regex patterns:**
```bash
# Secrets detection
grep -rn "password\s*[:=]\s*['\"]" --include="*.cs" --include="*.ts" --include="*.json" --include="*.sql"
grep -rn "connectionstring.*password" --include="*.json" --include="*.config" -i
grep -rn "Bearer [A-Za-z0-9\-._~+/]+" --include="*.cs" --include="*.ts"
grep -rn "sk-[A-Za-z0-9]{20,}" --include="*.cs" --include="*.ts" --include="*.json"
grep -rn "AKIA[A-Z0-9]{16}" --include="*.cs" --include="*.ts" --include="*.json"
```
### 4.3 Dependency Vulnerabilities
```bash
# .NET
dotnet list package --vulnerable 2>&1
# Node/React
npm audit 2>&1 | head -30
# Check for known vulnerable package versions
grep -n "System.Text.Json.*[0-7]\." *.csproj # Example: < v8 has known issues
```
### 4.4 Data Exposure
| Check | Severity | Details |
|-------|----------|---------|
| Stack traces in API responses | 🔴 Critical | GlobalExceptionMiddleware must catch ALL exceptions |
| Verbose error messages | 🟠High | Never expose column names, SP names, SQL errors to client |
| Sensitive data in logs | 🟠High | Don't log passwords, tokens, PII, full credit card numbers |
| Missing HTTPS enforcement | 🟠High | `app.UseHttpsRedirection()` must be present |
| PII in URL query parameters | 🟠High | Email, SSN, phone should be in POST body, not GET params |
| Sensitive data in localStorage | 🟠High | Tokens and PII should use httpOnly cookies or sessionStorage |
| Over-fetching from DB | 🟡 Medium | SELECT * returning columns with PII when not needed |
### Output Format
```
## Layer 4 — Vulnerability Scan
| # | File | Line | Type | Severity | Finding |
|---|------|------|------|----------|---------|
| 1 | appsettings.json | 5 | Secret | 🔴 Critical | Hardcoded DB password in connection string |
| 2 | SearchController.cs | 22 | SQLi | 🔴 Critical | String interpolation in raw SQL query |
| 3 | UserCard.tsx | 15 | XSS | 🟠High | dangerouslySetInnerHTML with user-supplied bio |
**Result: ⌠2 Critical, 1 High — MUST fix all before proceeding**
```
---
## Layer 5 — Security Hardening (OWASP Top 10)
Map every finding to OWASP 2021 Top 10 categories.
### OWASP Checklist per Language
#### A01: Broken Access Control
```
✅ Every API endpoint has [Authorize] or explicit [AllowAnonymous]
✅ Resource-level authorization (user can only access their own data)
✅ CORS configured for specific origins, never wildcard in production
✅ SQL SPs accept @UserId for audit — verify caller has permission
✅ No IDOR: user cannot pass another user's ID to access their data
✅ Anti-CSRF tokens on state-changing operations
✅ Directory listing disabled on web server
```
#### A02: Cryptographic Failures
```
✅ Passwords hashed with bcrypt/Argon2, never MD5/SHA1/plain
✅ Sensitive data encrypted at rest (column encryption, TDE)
✅ TLS 1.2+ enforced; no HTTP fallback
✅ Secrets in vault/environment variables, not in source
✅ No custom cryptography implementations
```
#### A03: Injection
```
✅ Parameterized queries / stored procedures — never string concatenation
✅ Input validated on both client AND server side
✅ HTML output encoded to prevent XSS
✅ File uploads validated (type, size, name sanitization)
✅ LIKE patterns escaped: user input with %, _, [ chars handled
```
#### A04: Insecure Design
```
✅ Rate limiting on authentication endpoints
✅ Account lockout after failed attempts
✅ Business logic validation server-side (not just UI)
✅ Proper error handling that doesn't reveal system internals
✅ Principle of least privilege in DB permissions
```
#### A05: Security Misconfiguration
```
✅ Debug/development mode disabled in production config
✅ Default credentials changed
✅ Unnecessary HTTP methods disabled
✅ Security headers set: X-Content-Type-Options, X-Frame-Options, CSP
✅ Stack traces never exposed in production responses
✅ Swagger/API docs disabled in production
```
#### A06: Vulnerable and Outdated Components
```
✅ No packages with known CVEs
✅ Frameworks at supported LTS versions
✅ No deprecated APIs used (TEXT, IMAGE, DATETIME in SQL Server)
```
#### A07: Identification and Authentication Failures
```
✅ JWT tokens have reasonable expiry
✅ Refresh token rotation implemented
✅ Password complexity enforced
✅ Session invalidation on logout
✅ Multi-factor authentication available for admin
```
#### A08: Software and Data Integrity Failures
```
✅ Input deserialization is validated (no insecure deserialization)
✅ Package integrity verified (lock files committed)
✅ No eval() or dynamic code execution with user input
```
#### A09: Security Logging and Monitoring Failures
```
✅ CorrelationId + RequestId logged on every operation
✅ Authentication failures logged
✅ Authorization failures logged
✅ Input validation failures logged (potential attack detection)
✅ Sensitive data masked in logs
✅ Log injection prevented (user input sanitized before logging)
```
#### A10: Server-Side Request Forgery (SSRF)
```
✅ URL validation on any server-side HTTP requests
✅ Allowlist for external API calls
✅ No user-controlled URLs passed to HttpClient without validation
```
### Output Format
```
## Layer 5 — Security Hardening (OWASP)
| # | OWASP | File | Line | Severity | Finding | Fix |
|---|-------|------|------|----------|---------|-----|
| 1 | A01 | UsersController.cs | 34 | 🔴 Critical | Missing [Authorize] on DELETE endpoint | Add [Authorize(Roles = "Admin")] |
| 2 | A03 | Reports_Get.sql | 22 | 🟠High | LIKE pattern not escaping user wildcards | Add ESCAPE clause or sanitize @SearchText |
| 3 | A05 | Program.cs | 48 | 🟡 Medium | Swagger enabled in all environments | Wrap in if (app.Environment.IsDevelopment()) |
**Result: ⌠1 Critical, 1 High, 1 Medium — fix Critical and High before proceeding**
```
---
## Layer 6 — Optimization & Standards Compliance
### 6.1 Performance Optimization
#### T-SQL Performance
```
✅ SARGable WHERE clauses — no functions on indexed columns
✅ Appropriate indexes exist for JOIN/WHERE/ORDER BY columns
✅ Foreign key columns indexed
✅ OFFSET/FETCH used for pagination (not TOP with subquery)
✅ ISNULL/COALESCE used correctly (ISNULL is faster for simple cases)
✅ Temp tables for large sets, table variables for < 100 rows
✅ No unnecessary DISTINCT (indicates a JOIN issue)
✅ EXISTS preferred over IN for correlated subqueries
✅ No implicit conversions in WHERE/JOIN (VARCHAR vs NVARCHAR)
✅ NOLOCK used sparingly; RCSI preferred
✅ No cursors — use set-based operations
✅ Computed columns considered for frequently derived values
✅ Statistics up to date on key columns
```
#### C# / .NET Performance
```
✅ async/await used throughout I/O paths — no sync-over-async
✅ CancellationToken forwarded through entire call chain
✅ IAsyncEnumerable for streaming large datasets from SPs
✅ StringBuilder for string concatenation in loops (> 3 concatenations)
✅ Span<T> / ReadOnlySpan<T> for parsing and slicing
✅ No Task.Result / .Wait() (deadlock risk in ASP.NET)
✅ HttpClient registered via IHttpClientFactory (not new HttpClient())
✅ SpHelper connection opened/closed per call (Dapper handles pooling)
✅ SP result sets return only needed columns — no SELECT * in SPs
✅ SP pagination uses OFFSET/FETCH with max PageSize cap (200)
✅ Dapper QueryMultipleAsync for SPs returning multiple result sets
✅ DynamicParameters reused efficiently — no unnecessary allocations
✅ Value types (struct/record struct) for small, immutable DTOs
🔴 NO EF Core — no AsNoTracking, no Select() projection, no compiled queries
🔴 NO inline SQL — all data access through SpHelper → Stored Procedures
```
#### React / TypeScript Performance
```
✅ Components don't re-render unnecessarily (check with React DevTools)
✅ useMemo/useCallback only where profiling shows benefit — not everywhere
✅ Large lists virtualized (@tanstack/react-virtual)
✅ Route-based code splitting with lazy() and Suspense
✅ Images optimized (WebP, lazy loading, appropriate dimensions)
✅ Bundle size checked — no unnecessary large dependencies
✅ Debounced search input (300ms minimum)
✅ AbortController used for cancellable fetch requests
✅ No inline object/array creation in JSX props (causes re-renders)
✅ TanStack Query caching configured (staleTime, gcTime)
```
### 6.2 Standards Compliance
#### Naming Conventions
| Element | T-SQL | C# | TypeScript/React |
|---------|-------|-----|-----------------|
| Tables | PascalCase plural (`app.Users`) | N/A | N/A |
| Columns | PascalCase (`FirstName`) | PascalCase properties | camelCase (`firstName`) |
| SPs | `{Table}_Manage` / `{Table}_Get` | N/A | N/A |
| Variables | `@CamelCase` | `_camelCase` (private) | `camelCase` |
| Constants | N/A | `PascalCase` | `SCREAMING_SNAKE` or `PascalCase` |
| Interfaces | N/A | `IUserRepository` | `UserCardProps` (no I prefix) |
| Files | `SP_{Name}.sql` | `UserService.cs` | `UserCard.tsx` |
| CSS classes | N/A | N/A | `kebab-case` or Tailwind utilities |
#### Team Convention Checks
```
✅ Consistent quote style (single quotes in TS, single in SQL strings)
✅ Consistent indentation (4 spaces for C#/SQL, 2 spaces for TS/React)
✅ Consistent import ordering (React → third-party → local → types)
✅ Consistent file organization (feature-based folders)
✅ Consistent error handling patterns (Result<T> or exception-based — pick one)
✅ No mixed patterns (don't use both Dapper and raw ADO.NET in same project)
✅ Comment quality — complex logic has WHY comments, not WHAT comments
✅ TODO/FIXME/HACK markers documented with ticket numbers
```
### 6.3 Documentation & Readability
```
✅ Public APIs have XML doc comments (C#) or JSDoc (TypeScript)
✅ Complex SQL has inline comments explaining business logic
✅ README updated when new features/tables/endpoints added
✅ Breaking changes documented
✅ API endpoint documentation (Swagger annotations) accurate
```
### Output Format
```
## Layer 6 — Optimization & Standards
| # | File | Line | Category | Severity | Finding | Recommendation |
|---|------|------|----------|----------|---------|----------------|
| 1 | Orders_Get.sql | 44 | Perf | 🟡 Medium | Non-SARGable: WHERE YEAR(OrderDate) = 2024 | Use date range: >= '2024-01-01' AND < '2025-01-01' |
| 2 | UserService.cs | 28 | Perf | 🟡 Medium | Missing CancellationToken forwarding | Add CancellationToken ct parameter |
| 3 | UserList.tsx | 12 | Perf | â„¹ï¸ Info | Search input not debounced | Add useDebounce(300ms) hook |
| 4 | api.ts | 5 | Standards | â„¹ï¸ Info | Inconsistent import ordering | Group: react → third-party → @/ local → types |
**Result: ✅ 0 Critical/High — 2 Medium, 2 Info (recommended fixes)**
```
---
## Final Gate Summary Template
After all 6 layers run, produce this summary:
```
â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•
CODE QUALITY GATE — FINAL REPORT
â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•â•
Files Checked: 5
Languages: T-SQL, C#, TypeScript/React
┌──────────────────────────────┬────────┬────────────â”
│ Check │ Status │ Issues │
├──────────────────────────────┼────────┼────────────┤
│ ðŸ›ï¸ SP-Only Mandate │ ✅ Pass │ No EF/Inline│
│ 1. VS Code Problems Tab │ ✅ Pass │ 0E 2W 0I │
│ 2. Lint Check (ALL langs) │ ✅ Pass │ 0E 3W 1I │
│ 3. SonarQube-Lite Analysis │ ✅ Pass │ 0C 1H 2M │
│ 4. Vulnerability Scan │ ✅ Pass │ 0C 0H 1M │
│ 5. Security (OWASP) │ ✅ Pass │ 0C 0H 2M │
│ 6. Optimization & Standards │ ✅ Pass │ 0C 0H 3M │
├──────────────────────────────┼────────┼────────────┤
│ OVERALL │ ✅ PASS │ 0C 1H 11M │
└──────────────────────────────┴────────┴────────────┘
Legend: C=Critical, H=High, M=Medium, E=Error, W=Warning, I=Info
SP-Only Mandate:
✅ No Entity Framework detected (no DbContext, DbSet, EF NuGet packages)
✅ No inline SQL detected (no raw SELECT/INSERT/UPDATE/DELETE in C#)
✅ All data access via SpHelper → Stored Procedures → Dapper
✅ @CorrelationId + @RequestId injected via WithTracking()
Gate Criteria:
✅ SP-Only Mandate passed
✅ Zero Critical findings across all layers
✅ Zero Errors in Layer 1 + Layer 2
âš ï¸ 1 High in Layer 3 — accepted (tracked in findings below)
Remaining Findings (Medium/Low — fix when practical):
1. [L2] App.tsx:5 — prefer-const: 'theme' never reassigned → use const
2. [L3] OrderService.cs:45 — Cognitive complexity 18 → refactor to extract methods
3. [L4] package.json — lodash 4.17.20 has prototype pollution fix in 4.17.21
4. ...
✅ GATE PASSED — files cleared for delivery to /mnt/user-data/outputs/
```
---
## Gate Decision Rules
| Findings | Decision |
|----------|----------|
| ðŸ›ï¸ SP-Only Mandate violated (EF or inline SQL found) | ⌠**BLOCKED** — rewrite to use SpHelper + SPs, no exceptions |
| 🔴 Any Critical (any layer) | ⌠**BLOCKED** — fix immediately, re-run gate |
| 🔴 Any Error in Layer 1 or Layer 2 | ⌠**BLOCKED** — code won't compile/run or fails lint |
| 🟠High findings only | âš ï¸ **CONDITIONAL** — fix if straightforward; document if accepted |
| 🟡 Medium and below only | ✅ **PASS** — deliver, note findings for future improvement |
| No findings | ✅ **CLEAN PASS** — deliver immediately |
---
## Integration with Existing Skills
This quality gate works alongside the existing tech-stack skills:
| After This Skill Runs... | This Gate Checks... |
|--------------------------|---------------------|
| **mssql** (T-SQL skill) | SP has @CorrelationId/@RequestId, SET NOCOUNT ON, idempotent DDL, proper indexing, no SELECT *, UTC dates, audit columns, soft delete |
| **dotnet** (.NET skill) | **ðŸ›ï¸ SP-Only Mandate** (no EF, no inline SQL, all access via SpHelper), TrackingContext injected, GlobalExceptionMiddleware present, no leaked stack traces, Serilog configured, CancellationToken forwarded, ApiResponse<T> wrapper used, Dapper + Microsoft.Data.SqlClient ONLY |
| **react** (React skill) | X-Correlation-Id sent, X-Request-Id read, ErrorBoundary wrapping routes, ErrorFallback shows requestId not stack trace, hooks follow rules, proper TypeScript strict mode |
### Cross-Stack Consistency Checks
```
✅ T-SQL SP parameter names match C# DynamicParameters.Add() names
✅ SP result set column names match C# DTO property names (case-insensitive via Dapper)
✅ API response shape matches TypeScript interface definitions
✅ API route naming matches React api.ts URL constants
✅ Error codes thrown in SP (50001, 50002...) handled in C# service layer
✅ Filter parameters (PageNumber, PageSize, SortColumn) consistent across all 3 layers
✅ CorrelationId + RequestId present in: SP params → C# SpHelper → API headers → React apiClient → ErrorFallback
✅ NO EF Core anywhere — no DbContext, no migrations, no EF NuGet packages
✅ ALL .cs repository files inject SpHelper, not DbContext
✅ ALL data operations: Repository → SpHelper.ManageAsync/GetByIdAsync/GetListAsync → SP
✅ NO inline SQL in any .cs file — zero tolerance
```
---
## Execution Workflow
When running this gate, follow this exact workflow:
```
1. IDENTIFY changed files
→ List all files created or modified in this session
2. RUN SP-ONLY MANDATE CHECK (before all layers — instant blocker)
→ For .cs files: scan for inline SQL, EF Core, raw SqlCommand
→ For .csproj files: scan for EntityFrameworkCore NuGet packages
→ If ANY violation found: ⌠BLOCKED — rewrite to use SpHelper + SPs
→ This check is NON-NEGOTIABLE — no exceptions, no workarounds
3. RUN Layer 1 (VS Code Problems)
→ For each file: syntax check, type check, reference check
→ Use bash tools where possible (tsc --noEmit, dotnet build)
→ If ANY 🔴 Error: STOP, fix, re-check
4. RUN Layer 2 (Lint Check — ALL languages)
→ TypeScript/React: npx eslint + npx prettier --check
→ C#/.NET: dotnet build (Roslyn analyzers) + dotnet format --verify-no-changes
→ C#/.NET: SP001-SP012 rules (inline SQL, EF detection, SpHelper verification)
→ T-SQL: bash grep checks for SQL001-SQL030 rules + sqlfluff lint
→ HTML: npx htmlhint
→ CSS: npx stylelint
→ JSON: python3 json.load validation / npx jsonlint-mod
→ Markdown: npx markdownlint
→ Auto-fix where possible (eslint --fix, prettier --write, dotnet format)
→ If ANY 🔴 Error after auto-fix: STOP, manual fix, re-check
5. RUN Layer 3 (SonarQube-Lite)
→ For each file: complexity, smells, duplication, maintainability rating
→ If ANY 🔴 Critical: STOP, fix, re-check
6. RUN Layer 4 (Vulnerability Scan)
→ For each file: injection patterns, secrets scan, dependency audit
→ If ANY 🔴 Critical: STOP, fix, re-check
7. RUN Layer 5 (Security / OWASP)
→ For each file: auth, input validation, data exposure, headers
→ If ANY 🔴 Critical: STOP, fix, re-check
8. RUN Layer 6 (Optimization & Standards)
→ For each file: performance, naming, conventions, documentation
→ Note findings but don't block on Medium/Low
9. PRODUCE Final Gate Summary
→ Table with all 6 layers + SP-only mandate status
→ List remaining Medium/Low findings
→ ✅ PASS / ⌠BLOCKED decision
9. IF PASSED: copy to /mnt/user-data/outputs/
IF BLOCKED: fix issues and re-run from the failed layer
```
---
## Quick-Reference Severity Guide
| Severity | Icon | Action | Examples |
|----------|------|--------|----------|
| 🔴 Critical | 🔴 | **Must fix now** — blocks delivery | SQL injection, hardcoded secrets, missing auth, syntax errors, null pointer crash |
| 🟠High | 🟠| **Should fix** — significant risk or smell | Empty catch blocks, resource leaks, cognitive complexity > 20, missing HTTPS |
| 🟡 Medium | 🟡 | **Fix when practical** — quality improvement | Unused variables, long methods, missing comments, non-optimal indexes |
| â„¹ï¸ Info | â„¹ï¸ | **Note for awareness** — nice-to-have | Import ordering, minor naming inconsistencies, potential micro-optimizations |
---
## Output Delivery
1. **This gate runs AFTER code is written** — it is the last step before delivery
2. **Run ALL 6 layers** — no skipping, no shortcuts
3. **Layer 2 (Lint) must auto-fix first** — run `eslint --fix`, `prettier --write`, `dotnet format` before reporting remaining issues
4. **Produce the Final Gate Summary** in every response where files are delivered
5. **Block delivery on Critical/Error findings** — fix first, then re-run
6. **Document accepted findings** — Medium/Low issues noted for future improvement
7. **Cross-reference with tech-stack skills** — ensure mssql/dotnet/react conventions followed
8. **Include lint config files** — when creating new projects, generate `.eslintrc`/`eslint.config.mjs`, `.prettierrc`, `.editorconfig`, `.stylelintrc.json`, `.htmlhintrc`, `.sqlfluff` alongside source code
9. **The gate report is shown inline in the chat** — not as a separate file (unless user requests it)
Files in this skill
- SKILL.md
- source.json
Attribution
Comments
Loading comments…
Newsletter
Get the weekly list of safe new skills, and the ones we pulled.