| name | marsai:production-readiness-audit |
| description | Comprehensive MarsAI-standards-aligned 44-dimension production readiness audit. Detects project stack, loads MarsAI standards via WebFetch, and runs in batches of 10 explorers appending incrementally to a single report file. Categories - Structure (pagination, errors, routes, bootstrap, runtime, core deps, naming, domain modeling, nil-safety, api-versioning, resource-leaks), Security (auth, IDOR, SQL, validation, secret-scanning, data-encryption, multi-tenant, rate-limiting, cors), Operations (telemetry, health, config, connections, logging, resilience, graceful-degradation), Quality (idempotency, docs, debt, testing, dependencies, performance, concurrency, migrations, linting, caching), Infrastructure (containers, hardening, cicd, async, makefile, license). Produces scored report (0-430, max 440 with multi-tenant) with severity ratings and standards cross-reference. |
| trigger | - Preparing a service for production deployment
- Conducting periodic security or quality review of a codebase
- Onboarding to assess codebase health and maturity
- Evaluating technical debt before a major release
- Validating compliance with MarsAI engineering standards
|
| skip_when | - Project is a prototype or throwaway proof-of-concept not heading to production
- Codebase is a library or SDK with no deployable service component
- User only needs a single-dimension check (use targeted review instead)
|
Production Readiness Audit
Modularization Note
⚠️ CANDIDATE FOR MODULARIZATION: This skill file exceeds 6,000 lines and is a candidate for splitting into sub-skills. Future work MUST consider:
- Category-based sub-skills: Split into 5 category-specific skills (Structure, Security, Operations, Quality, Infrastructure)
- Explorer templates extraction: Move the 44 dimension-specific explorer prompts to separate template files
- Scoring logic separation: Extract scoring and weighting logic to a dedicated calculation module
- Report generation: Separate report templating from audit logic
MUST NOT add new dimensions without first implementing modularization to prevent further bloat.
A comprehensive, multi-agent audit system that evaluates codebase production readiness across 44 dimensions in 5 categories, aligned with MarsAI development standards as the source of truth. This skill detects the project stack, loads relevant standards via WebFetch, and runs explorer agents in batches of 10, appending results incrementally to a single report file to prevent context bloat while maintaining thorough coverage.
When This Skill Activates
Use this skill when:
- Preparing for production deployment
- Conducting periodic security/quality reviews
- Onboarding to understand codebase health
- Evaluating technical debt before major releases
- Validating compliance with MarsAI engineering standards
- Assessing a codebase's maturity level against MarsAI standards
Audit Dimensions
Category A: Code Structure & Patterns (11 dimensions)
| # | Dimension | Focus Area |
|---|
| 1 | Pagination Standards | Cursor vs offset pagination, limit validation, response structure |
| 2 | Error Framework | Domain errors, error codes convention, error handling, error propagation |
| 3 | Route Organization | Hexagonal structure, handler construction, route registration |
| 4 | Bootstrap & Initialization | Staged startup, cleanup handlers, graceful shutdown |
| 5 | Runtime Safety | Panic recovery, production mode handling |
| 28 | Core Dependencies & Frameworks | Framework version minimums, no custom utility duplication |
| 29 | Naming Conventions | snake_case DB, camelCase JSON body, snake_case query params |
| 30 | Domain Modeling | ToEntity/FromEntity, always-valid constructors, private fields + getters |
| 35 | Nil/Null Safety | Type assertions, nil map/pointer/channel, null guards, API response consistency |
| 38 | API Versioning | Versioning strategy, backward compatibility, deprecation, sunset headers |
| 42 | Resource Leak Prevention | Unclosed handles, connection leaks, context propagation, cleanup ordering |
Category B: Security & Access Control (9 base + 1 conditional)
| # | Dimension | Focus Area |
|---|
| 6 | Auth Protection | Route protection, JWT validation, tenant extraction, Access Manager |
| 7 | IDOR & Access Control | Ownership verification, tenant isolation, resource authorization |
| 8 | SQL Safety | Parameterized queries, identifier escaping, injection prevention |
| 9 | Input Validation | Request body validation, query params, VO validation |
| 37 | Secret Scanning | Hardcoded credentials, API keys, private keys, connection strings |
| 41 | Data Encryption at Rest | Field-level encryption, key management, password hashing, encrypted backups |
| 43 | Rate Limiting | Three-tier strategy (Global/Export/Dispatch), Redis-backed storage, key generation, production safety |
| 44 | CORS Configuration | Origin validation, middleware ordering, production wildcard prohibition, Helmet integration |
| 33 | Multi-Tenant Patterns (CONDITIONAL) | Tenant Manager, TenantMiddleware with WithPG/WithMB, JWT tenantId, module-specific connections |
Category C: Operational Readiness (7 dimensions)
| # | Dimension | Focus Area |
|---|
| 11 | Telemetry & Observability | OpenTelemetry integration, tracing, metrics |
| 12 | Health Checks | Liveness/readiness probes, dependency health, degraded status |
| 13 | Configuration Management | Env var validation, production constraints, secrets handling |
| 14 | Connection Management | DB/Redis pool settings, timeouts, replica support |
| 15 | Logging & PII Safety | Structured logging, sensitive data protection, log levels |
| 36 | Resilience Patterns | Circuit breakers, retry with backoff, timeout cascading, bulkhead isolation |
| 39 | Graceful Degradation | Fallback behavior, cached responses, feature flags, partial responses |
Category D: Quality & Maintainability (10 dimensions)
| # | Dimension | Focus Area |
|---|
| 16 | Idempotency | Idempotency keys, retry safety, duplicate prevention |
| 17 | API Documentation | Swaggo/OpenAPI annotations, response schemas, examples |
| 18 | Technical Debt | TODOs, FIXMEs, deprecated code, incomplete implementations |
| 19 | Testing Coverage | Co-located tests, mocking, parameterized tests, integration tests |
| 20 | Dependency Management | Pinned versions, CVE scanning, deprecated packages |
| 21 | Performance Patterns | N+1 queries, SELECT *, slice pre-allocation, batching |
| 22 | Concurrency Safety | Race conditions, async leaks, unbounded concurrency, worker pools |
| 23 | Migration Safety | Up/down pairs, CONCURRENTLY indexes, NOT NULL defaults |
| 31 | Linting & Code Quality | Import ordering, magic numbers, linter config |
| 40 | Caching Patterns | Cache invalidation, TTL management, stampede prevention, tenant-scoped keys |
Category E: Infrastructure & Hardening (6 dimensions)
| # | Dimension | Focus Area |
|---|
| 24 | Container Security | Dockerfile best practices, non-root user, multi-stage, image pinning |
| 25 | HTTP Hardening | Security headers (HSTS, CSP), cookie attributes, server banner |
| 26 | CI/CD Pipeline | Pipeline definitions, automated tests, security scanning |
| 27 | Async Reliability | DLQs, retry policies, consumer group usage, message durability |
| 32 | Makefile & Dev Tooling | 17+ required Makefile commands, dev workflow automation |
| 34 | License Headers | Copyright headers on all source files |
Execution Protocol
This skill runs up to 44 explorer agents in 5 batches of up to 10, writing results incrementally to a single report file. Before dispatch, it detects the project stack and loads MarsAI standards as the source of truth.
Output File
All results are appended to: docs/audits/production-readiness-{YYYY-MM-DDTHH:MM:SS}.md
Timestamp format: YYYY-MM-DDTHH:MM:SS using local time (e.g., 2026-02-07T20:45:30). MUST use local time from system clock, not UTC.
Batch Execution Schedule
| Batch | Agents | Category Focus |
|---|
| 1 | 1-10 | Structure (Pagination, Errors, Routes, Bootstrap, Runtime) + Security (Auth, IDOR, SQL, Input) + Operations (Telemetry) |
| 2 | 12-20 | Operations (Health, Config, Connections, Logging) + Quality (Idempotency, API Docs, Tech Debt, Testing, Dependencies) |
| 3 | 21-30 | Quality (Performance, Concurrency, Migrations) + Infrastructure (Containers, Hardening, CI/CD, Async) + Structure (Core Deps, Naming, Domain Modeling) |
| 4 | 31-42 | Quality (Linting, Caching) + Infrastructure (Makefile, Multi-Tenant*, License) + New Dimensions (Resilience, Secret Scanning, API Versioning, Graceful Degradation, Data Encryption, Resource Leaks) |
| 5 | 43-44 + Summary | Security (Rate Limiting, CORS Configuration) + Final Summary (43 base + 1 conditional) |
Step 0: Stack Detection
Before running any explorers, detect the project stack to determine which MarsAI standards to load.
Detection via Glob:
| Check | Flag | Standards to Load |
|---|
**/package.json + React/Next.js deps | FRONTEND=true | Language-specific standards |
**/package.json + Express/Fastify/NestJS deps | TS_BACKEND=true | Language-specific standards |
**/Dockerfile* exists | DOCKER=true | devops.md |
**/Makefile exists | MAKEFILE=true | devops.md → Makefile Standards |
**/LICENSE* exists | LICENSE=true | Activates dimension 34 |
MULTI_TENANT env var in config/env files (.env*, docker-compose*, config files) | MULTI_TENANT=true | multi-tenant.md |
Detection Logic:
Glob("**/package.json") → Read for React/Next.js → if found: FRONTEND=true
Glob("**/package.json") → Read for Express/Fastify/NestJS → if found: TS_BACKEND=true
Glob("**/Dockerfile*") → if found: DOCKER=true
Glob("**/Makefile") → if found: MAKEFILE=true
Glob("**/LICENSE*") → if found: LICENSE=true
Grep("MULTI_TENANT") → if found in env/config files: MULTI_TENANT=true
Stack determines which standards are loaded in Step 0.5.
Step 0.5: Load MarsAI Standards
Based on detected stack, load MarsAI development standards via WebFetch from the canonical source of truth. Store fetched content for injection into explorer prompts.
WebFetch URL Map:
Based on detected stack, WebFetch the relevant standards modules from dev-team/docs/standards/. The exact modules depend on the project's language and framework.
Stack-specific standards loading: Load the appropriate standards modules based on the detected stack flags (GO, TS_BACKEND, FRONTEND, etc.). The standards files are located in the dev-team/docs/standards/ directory of the MarsAI repository.
Always WebFetch (stack-independent):
| Module | Variable | URL |
|---|
| devops.md | standards_devops | https://raw.githubusercontent.com/V4-Company/marsai/main/dev-team/docs/standards/devops.md |
| sre.md | standards_sre | https://raw.githubusercontent.com/V4-Company/marsai/main/dev-team/docs/standards/sre.md |
Fallback: If any WebFetch fails, note the failure in the audit report and proceed with existing generic patterns for that dimension. Do not abort the audit.
Standards Injection Pattern:
Each explorer prompt receives relevant standards content between ---BEGIN STANDARDS--- and ---END STANDARDS--- markers. The explorer uses these as the authoritative reference for its audit dimension.
Step 1: Initialize Report File
Write to docs/audits/production-readiness-{YYYY-MM-DDTHH:MM:SS}.md:
# Production Readiness Audit Report
**Date:** {YYYY-MM-DDTHH:MM:SS}
**Codebase:** {project-name}
**Auditor:** Claude Code (Production Readiness Skill v3.0)
**Status:** In Progress...
## Audit Configuration
| Property | Value |
|----------|-------|
| **Detected Stack** | {TypeScript / Frontend / Mixed} |
| **Standards Loaded** | {list of loaded standards files} |
| **Active Dimensions** | {43 base + 1 conditional (max 44)} |
| **Max Possible Score** | {dynamic_max: 430 or 440} |
| **Conditional: Multi-Tenant** | {Active / Inactive} |
---
Step 2: Execute Batch 1 (Agents 1-10)
Launch 10 explorers in parallel:
Task(subagent_type="Explore", prompt="<Agent 1: Pagination Standards>")
Task(subagent_type="Explore", prompt="<Agent 2: Error Framework>")
Task(subagent_type="Explore", prompt="<Agent 3: Route Organization>")
Task(subagent_type="Explore", prompt="<Agent 4: Bootstrap & Init>")
Task(subagent_type="Explore", prompt="<Agent 5: Runtime Safety>")
Task(subagent_type="Explore", prompt="<Agent 6: Auth Protection>")
Task(subagent_type="Explore", prompt="<Agent 7: IDOR Protection>")
Task(subagent_type="Explore", prompt="<Agent 8: SQL Safety>")
Task(subagent_type="Explore", prompt="<Agent 9: Input Validation>")
Task(subagent_type="Explore", prompt="<Agent 10: Telemetry & Observability>")
After completion: Append results to the report file.
Step 3: Execute Batch 2 (Agents 12-20)
Launch 9 explorers in parallel:
Task(subagent_type="Explore", prompt="<Agent 12: Health Checks>")
Task(subagent_type="Explore", prompt="<Agent 13: Configuration Management>")
Task(subagent_type="Explore", prompt="<Agent 14: Connection Management>")
Task(subagent_type="Explore", prompt="<Agent 15: Logging & PII Safety>")
Task(subagent_type="Explore", prompt="<Agent 16: Idempotency>")
Task(subagent_type="Explore", prompt="<Agent 17: API Documentation>")
Task(subagent_type="Explore", prompt="<Agent 18: Technical Debt>")
Task(subagent_type="Explore", prompt="<Agent 19: Testing Coverage>")
Task(subagent_type="Explore", prompt="<Agent 20: Dependency Management>")
After completion: Append results to the report file.
Step 4: Execute Batch 3 (Agents 21-30)
Launch 10 explorers in parallel:
Task(subagent_type="Explore", prompt="<Agent 21: Performance Patterns>")
Task(subagent_type="Explore", prompt="<Agent 22: Concurrency Safety>")
Task(subagent_type="Explore", prompt="<Agent 23: Migration Safety>")
Task(subagent_type="Explore", prompt="<Agent 24: Container Security>")
Task(subagent_type="Explore", prompt="<Agent 25: HTTP Hardening>")
Task(subagent_type="Explore", prompt="<Agent 26: CI/CD Pipeline>")
Task(subagent_type="Explore", prompt="<Agent 27: Async Reliability>")
Task(subagent_type="Explore", prompt="<Agent 28: Core Dependencies & Frameworks>")
Task(subagent_type="Explore", prompt="<Agent 29: Naming Conventions>")
Task(subagent_type="Explore", prompt="<Agent 30: Domain Modeling>")
After completion: Append results to the report file.
Step 5: Execute Batch 4 (Agents 31-42)
Launch remaining explorers:
Task(subagent_type="Explore", prompt="<Agent 31: Linting & Code Quality>")
Task(subagent_type="Explore", prompt="<Agent 32: Makefile & Dev Tooling>")
# CONDITIONAL: Only if MULTI_TENANT=true
Task(subagent_type="Explore", prompt="<Agent 33: Multi-Tenant Patterns>")
Task(subagent_type="Explore", prompt="<Agent 34: License Headers>")
Task(subagent_type="Explore", prompt="<Agent 35: Nil/Null Safety>")
Task(subagent_type="Explore", prompt="<Agent 36: Resilience Patterns>")
Task(subagent_type="Explore", prompt="<Agent 37: Secret Scanning>")
Task(subagent_type="Explore", prompt="<Agent 38: API Versioning>")
Task(subagent_type="Explore", prompt="<Agent 39: Graceful Degradation>")
Task(subagent_type="Explore", prompt="<Agent 40: Caching Patterns>")
Task(subagent_type="Explore", prompt="<Agent 41: Data Encryption at Rest>")
Task(subagent_type="Explore", prompt="<Agent 42: Resource Leak Prevention>")
After completion: Append results to the report file.
Step 6: Execute Batch 5 (Agents 43-44 + Summary)
Launch security middleware explorers:
Task(subagent_type="Explore", prompt="<Agent 43: Rate Limiting>")
Task(subagent_type="Explore", prompt="<Agent 44: CORS Configuration>")
After completion: Append results to the report file.
Step 7: Finalize Report
- Read the complete report file
- Calculate scores for each dimension
- Generate Executive Summary with totals
- Prepend Executive Summary to the report
- Add remediation priorities
- Add Standards Compliance Cross-Reference table
- Present verbal summary to user
Explorer Agent Prompts
Agent 1: Pagination Standards Auditor
Audit pagination implementation across the codebase for production readiness.
**Detected Stack:** {DETECTED_STACK}
**MarsAI Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Pagination Patterns" section from api-patterns.md}
---END STANDARDS---
**Key Concept: TWO valid pagination strategies:**
- **Offset** for low-volume admin entities
- **Cursor** for high-volume transaction entities
**Search Patterns:**
- Files: `**/pagination*.ts`, `**/handlers.ts`, `**/dto.ts`, `**/httputils.ts`, `**/cursor.ts`
- Keywords: `limit`, `offset`, `cursor`, `page`, `nextCursor`, `prevCursor`, `setCursor`, `setItems`
- Standards-specific: `CursorPagination`, `Pagination`, `validateParameters`, `QueryHeader`, `MAX_PAGINATION_LIMIT`
**Reference Implementations (GOOD):**
Offset mode (admin entities):
```typescript
// Handler sets page field — indicates offset mode
const pagination = new Pagination({
limit: headerParams.limit,
page: headerParams.page,
sortOrder: headerParams.sortOrder,
});
const items = await this.query.getAllOrganizations(ctx, headerParams);
pagination.setItems(items);
return res.status(200).json(pagination);
// Repository uses OFFSET = (page - 1) * limit
query.limit(filter.limit).offset((filter.page - 1) * filter.limit);
Cursor mode (transaction entities):
const pagination = new Pagination({
limit: headerParams.limit,
sortOrder: headerParams.sortOrder,
});
const { items, cursor } = await this.query.getAllTransactions(ctx, orgID, ledgerID, headerParams);
pagination.setItems(items);
pagination.setCursor(cursor.next, cursor.prev);
return res.status(200).json(pagination);
Check Against MarsAI Standards For:
- (HARD GATE) Consistent pagination response structure matching MarsAI standards across all list endpoints
- (HARD GATE) Maximum limit enforcement via
ValidateParameters (MAX_PAGINATION_LIMIT, default 100)
- Correct strategy per entity type: offset for admin entities, cursor for transaction entities
- No mixing of both strategies in the same endpoint (page + cursor in same response is FORBIDDEN)
- Proper error handling for invalid pagination params
- Default values when params missing
- Response field names match MarsAI API conventions (camelCase JSON)
Severity Ratings:
- CRITICAL: No limit validation (allows unlimited queries)
- CRITICAL: HARD GATE violation per MarsAI standards — pagination response structure missing entirely
- HIGH: Inconsistent pagination structures across endpoints
- HIGH: Missing
ValidateParameters call on list endpoints
- MEDIUM: Using offset pagination on high-volume transaction tables
- MEDIUM: Mixing both strategies in the same endpoint
- LOW: Using cursor where offset would suffice for admin entities
Output Format:
## Pagination Audit Findings
### Summary
- Total list endpoints: X
- Using cursor pagination: Y
- Using offset pagination: Z
- Missing pagination entirely: W
- Missing limit validation: N
### Strategy Mapping
| Endpoint | Entity Type | Expected Strategy | Actual Strategy | Match |
|----------|-------------|-------------------|-----------------|-------|
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 2: Error Framework Auditor
```prompt
Audit error handling framework usage for production readiness.
**Detected Stack:** {DETECTED_STACK}
**MarsAI Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Error Codes Convention" and "Error Handling" sections from domain.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/error*.ts`, `**/handlers.ts`, `**/exceptions/*.ts`
- Keywords: `throw`, `catch`, `Error`, `HttpException`, `NotFoundException`
- Also search: `process.exit`, `unhandledRejection`
- Standards-specific: `DomainError`, `ErrorResponse`, `HttpException`
**Reference Implementation (GOOD):**
```typescript
// Validate with explicit checks and throw typed errors (no process.exit)
if (!config) {
throw new ValidationError('config is required');
}
// Domain error types
class NotFoundError extends Error {
constructor(message = 'resource not found') { super(message); this.name = 'NotFoundError'; }
}
class InvalidInputError extends Error {
constructor(message = 'invalid input') { super(message); this.name = 'InvalidInputError'; }
}
// Error mapping in handlers
if (err instanceof NotFoundError) {
return res.status(404).json({ error: 'resource not found' });
}
Reference Implementation (BAD):
if (!config) {
process.exit(1);
}
const result = await doSomething().catch(() => null);
throw new Error('error');
Reference Implementation (GOOD — RFC 7807 Error Responses):
interface ProblemDetails {
type: string;
title: string;
status: number;
detail: string;
instance?: string;
code: string;
}
function newProblemResponse(res: Response, status: number, errCode: string, detail: string) {
return res.status(status).json({
type: `https://api.example.com/errors/${errCode}`,
title: getStatusText(status),
status,
detail,
instance: res.req.path,
code: errCode,
});
}
async function create(req: Request, res: Response) {
try {
} catch (err) {
if (err instanceof NotFoundError) {
return newProblemResponse(res, 404, 'RESOURCE_NOT_FOUND', 'The requested resource does not exist');
}
if (err instanceof InvalidInputError) {
return newProblemResponse(res, 422, 'VALIDATION_FAILED', err.message);
}
return newProblemResponse(res, 500, 'INTERNAL_ERROR', 'An unexpected error occurred');
}
}
Reference Implementation (BAD — Inconsistent Error Responses):
return res.status(400).json({ error: 'invalid input' });
return res.status(400).json({ message: 'invalid input', code: 400 });
return res.status(400).json({ errors: ['field X is required'] });
return res.status(422).json({ error: 'The email field is required and must be valid' });
Check Against MarsAI Standards For:
- (HARD GATE) Explicit nil checks with error returns instead of panic for validation per MarsAI standards
- (HARD GATE) Named error variables (sentinel errors) per module following MarsAI error codes convention
- (HARD GATE) No process.exit() or unhandled exceptions in production code
- Proper error wrapping with %w
- errors.Is/errors.As for error matching
- No swallowed errors (_, err := ignored)
- HTTP error responses follow MarsAI ErrorResponse structure from domain.md
- RFC 7807 Problem Details format compliance — error responses MUST include:
type, title, status, detail, instance fields
- Consistent error response schema across all endpoints — every endpoint MUST return the same JSON error structure (no mixed formats)
- Machine-readable error codes for programmatic client consumption — every error response MUST include a stable, enumerated
code field (not free-text messages)
- Error response examples documented in API annotations (Swaggo
@Failure tags with response schema)
Severity Ratings:
- CRITICAL: process.exit() or unhandled exceptions in production code paths (HARD GATE violation per MarsAI standards)
- CRITICAL: Swallowed errors in critical paths
- HIGH: Generic error messages without context
- HIGH: Error response format does not match MarsAI standards
- HIGH: Inconsistent error response format across endpoints (some return
{"error": "msg"}, others {"message": "msg", "code": "X"})
- MEDIUM: No RFC 7807 Problem Details compliance (error responses lack
type, title, status, detail, instance structure)
- MEDIUM: Error codes not machine-readable (free-text error messages only, no stable enumerated codes for programmatic consumption)
- MEDIUM: Inconsistent error types across modules
- LOW: Missing error wrapping context
- LOW: Missing error response examples in API documentation (Swaggo
@Failure annotations lack response body schema)
Output Format:
## Error Framework Audit Findings
### Summary
- Nil checks with error returns: X
- Panic calls in production: Y
- Swallowed errors: Z
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 3: Route Organization Auditor
```prompt
Audit route organization and handler structure for production readiness.
**Detected Stack:** {DETECTED_STACK}
**MarsAI Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Architecture Patterns" and "Directory Structure" sections from architecture.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/routes.ts`, `**/handlers.ts`, `**/controllers/*.ts`, `**/modules/*.ts`
- Keywords: `Router`, `Controller`, `@Get`, `@Post`, `app.use`, `router.get`
- Standards-specific: `modules/{module}/`, `hexagonal`, `ports`, `adapters`
**Reference Implementation (GOOD):**
```typescript
// Centralized route registration
function registerRoutes(router: Router, handler: Handler): void {
if (!handler) {
throw new Error('handler is required');
}
router.post('/v1/resources', authMiddleware('resource', 'create'), handler.create);
router.get('/v1/resources', authMiddleware('resource', 'read'), handler.list);
router.get('/v1/resources/:id', authMiddleware('resource', 'read'), handler.get);
}
// Handler constructor with validation
class Handler {
constructor(private readonly deps: Dependencies) {
if (!deps.repository) {
throw new Error('repository dependency is required');
}
}
}
Check Against MarsAI Standards For:
- (HARD GATE) Hexagonal structure:
modules/{module}/adapters/http/ per architecture.md
- (HARD GATE) Centralized route registration per module
- Handler constructors validate all dependencies
- Consistent URL patterns (v1, kebab-case, plural resources) per MarsAI conventions
- All routes use auth middleware (no public endpoints without explicit exemption)
- Clear separation: routes.ts vs handlers.ts per MarsAI directory structure
Severity Ratings:
- CRITICAL: Unprotected routes (missing auth middleware)
- CRITICAL: HARD GATE violation — project does not follow hexagonal architecture per MarsAI standards
- HIGH: Scattered route definitions
- MEDIUM: Handler accepts nil dependencies
- LOW: Inconsistent URL naming conventions
Output Format:
## Route Organization Audit Findings
### Summary
- Modules following hexagonal: X/Y
- Routes with protection: X/Y
- Handlers validating deps: X/Y
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 4: Bootstrap & Initialization Auditor
```prompt
Audit application bootstrap and initialization for production readiness.
**Detected Stack:** {DETECTED_STACK}
**MarsAI Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Bootstrap" section from bootstrap.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/main.ts`, `**/index.ts`, `**/bootstrap/*.ts`, `**/app.module.ts`
- Keywords: `bootstrap`, `NestFactory`, `listen`, `shutdown`, `cleanup`, `graceful`
- Standards-specific: `bootstrapApplication`, `staged initialization`
**Reference Implementation (GOOD):**
```typescript
// Staged initialization with cleanup
async function bootstrap(): Promise<void> {
let startupSucceeded = false;
const cleanupFns: Array<() => Promise<void>> = [];
try {
// 1. Load config
const cfg = loadConfig();
// 2. Initialize logger
const logger = initLogger(cfg);
cleanupFns.push(() => logger.flush());
// 3. Initialize telemetry
const telemetry = initTelemetry(cfg, logger);
cleanupFns.push(() => telemetry.shutdown());
// 4. Connect infrastructure (DB, Redis, MQ)
const db = await connectDB(cfg);
cleanupFns.push(() => db.destroy());
// 5. Initialize modules in dependency order
// ...
startupSucceeded = true;
} finally {
if (!startupSucceeded) {
// Cleanup on failure — reverse order
for (const fn of cleanupFns.reverse()) {
await fn().catch(() => {});
}
}
}
}
Check Against MarsAI Standards For:
- (HARD GATE) Staged initialization order per bootstrap.md (config -> logger -> telemetry -> infra)
- (HARD GATE) Cleanup handlers for failed startup
- (HARD GATE) Graceful shutdown support
- Module initialization in dependency order per MarsAI bootstrap pattern
- Error propagation (not just logging and continuing)
- Production vs development mode handling
Severity Ratings:
- CRITICAL: No graceful shutdown (HARD GATE violation per MarsAI standards)
- CRITICAL: HARD GATE violation — bootstrap does not follow MarsAI staged initialization pattern
- HIGH: Resources not cleaned up on startup failure
- HIGH: Errors logged but not returned
- MEDIUM: Initialization order issues
- LOW: Missing development mode toggles
Output Format:
## Bootstrap Audit Findings
### Summary
- Graceful shutdown: Yes/No
- Cleanup on failure: Yes/No
- Staged initialization: Yes/No
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 5: Runtime Safety Auditor
```prompt
Audit pkg/runtime usage and panic handling for production readiness.
**Detected Stack:** {DETECTED_STACK}
**Search Patterns:**
- Files: `**/error-handler*.ts`, `**/middleware/*.ts`, `**/*.ts`
- Keywords: `uncaughtException`, `unhandledRejection`, `process.on`, `ErrorHandler`
- Also search: `process.exit(`, `throw` (unhandled)
**Reference Implementation (GOOD):**
```typescript
// Bootstrap initialization — global error handlers
process.on('uncaughtException', (err) => {
logger.error('Uncaught exception', { error: err.message, stack: err.stack });
metrics.increment('uncaught_exceptions');
if (cfg.envName === 'production') {
process.exit(1); // Crash and let orchestrator restart
}
});
process.on('unhandledRejection', (reason) => {
logger.error('Unhandled rejection', { reason });
metrics.increment('unhandled_rejections');
});
// In HTTP handlers — error middleware
app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
logger.error('Handler error', { error: err.message, path: req.path });
res.status(500).json({ error: 'Internal server error' });
});
// In background workers — try/catch with recovery policy
async function processJob(job: Job): Promise<void> {
try {
await handleJob(job);
} catch (err) {
logger.error('Job failed', { jobId: job.id, error: err });
// Log and continue — do not crash worker
}
}
Check For:
- pkg/runtime initialized at startup
- Production mode set based on environment
- All async operations have error handling
- Appropriate error recovery policies per context
- Error metrics enabled for alerting
- Global error handlers configured (uncaughtException, unhandledRejection)
Severity Ratings:
- CRITICAL: Async operations without error handling
- HIGH: Missing production mode setting
- HIGH: No global error handlers (uncaughtException/unhandledRejection)
- MEDIUM: Inconsistent error recovery policies
- LOW: Missing error metrics
Output Format:
## Runtime Safety Audit Findings
### Summary
- Runtime initialized: Yes/No
- Handlers with recovery: X/Y
- Goroutines with recovery: X/Y
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 6: Auth Protection Auditor
```prompt
Audit authentication and authorization implementation for production readiness.
**Detected Stack:** {DETECTED_STACK}
**MarsAI Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Access Manager Integration" section from security.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/auth/*.ts`, `**/middleware/*.ts`, `**/guards/*.ts`, `**/routes.ts`
- Keywords: `Authorize`, `Guard`, `JWT`, `tenant`, `extractToken`, `passport`
- Standards-specific: `AccessManager`, `auth-library`, `AuthGuard`
**Reference Implementation (GOOD):**
```typescript
// Protected route group with auth middleware
const authMiddleware = (resource: string, action: string) =>
[verifyJwt, authorize(resource, action)];
// All routes use auth middleware
router.post('/v1/config/contexts', ...authMiddleware('contexts', 'create'), handler.create);
// JWT validation
function parseTokenClaims(tokenString: string, secret: string): JwtPayload {
try {
const decoded = jwt.verify(tokenString, secret, { algorithms: ['RS256'] });
if (typeof decoded === 'string') throw new InvalidTokenError();
return decoded as JwtPayload;
} catch (err) {
if (err instanceof jwt.TokenExpiredError) throw new TokenExpiredError();
throw new InvalidTokenError();
}
}
Check Against MarsAI Standards For:
- (HARD GATE) All routes protected via Access Manager integration per security.md
- (HARD GATE) Auth library used for JWT validation (not custom JWT parsing)
- Resource/action authorization granularity per MarsAI access control model
- Token expiration enforcement
- Tenant extraction from JWT claims
- Auth bypass for health/ready endpoints only
Severity Ratings:
- CRITICAL: Unprotected data endpoints (HARD GATE violation per MarsAI standards)
- CRITICAL: JWT parsed but not validated
- CRITICAL: HARD GATE violation — not using auth library for access management
- HIGH: Missing token expiration check
- HIGH: Tenant claims not enforced
- MEDIUM: Overly broad permissions
- LOW: Missing fine-grained actions
Output Format:
## Auth Protection Audit Findings
### Summary
- Protected routes: X/Y
- JWT validation: Complete/Partial/Missing
- Tenant enforcement: Yes/No
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 7: IDOR & Access Control Auditor
```prompt
Audit IDOR (Insecure Direct Object Reference) protection for production readiness.
**Detected Stack:** {DETECTED_STACK}
**Search Patterns:**
- Files: `**/verifier*.ts`, `**/handlers.ts`, `**/guards/*.ts`, `**/context.ts`
- Keywords: `verifyOwnership`, `tenantId`, `contextId`, `parseAndVerify`
**Reference Implementation (GOOD):**
```typescript
// 4-layer IDOR protection
async function parseAndVerifyContextParam(
req: Request,
verifier: ContextOwnershipVerifier
): Promise<{ contextId: string; tenantId: string }> {
// 1. UUID format validation
const contextId = req.params.contextId;
if (!isValidUUID(contextId)) throw new InvalidIdError();
// 2. Extract tenant from auth context (cannot be spoofed)
const tenantId = req.user.tenantId;
// 3. Database query filtered by tenant
// 4. Post-query ownership verification
await verifier.verifyOwnership(tenantId, contextId);
return { contextId, tenantId };
}
// Verifier implementation
class OwnershipVerifier {
async verifyOwnership(tenantId: string, resourceId: string): Promise<void> {
const resource = await this.query.get(tenantId, resourceId); // Query WITH tenant filter
if (!resource) throw new NotFoundError();
if (resource.tenantId !== tenantId) throw new NotOwnedError(); // Double-check ownership
}
}
Reference Implementation (BAD):
async function getResource(req: Request, res: Response) {
const id = req.params.id;
const resource = await repo.findById(id);
return res.json(resource);
}
Check For:
- All resource access verifies ownership
- Tenant ID from JWT context (not request params)
- Database queries include tenant filter
- Post-query ownership double-check
- UUID validation before database lookup
- Consistent verifier pattern across modules
Severity Ratings:
- CRITICAL: Resource access without ownership check
- CRITICAL: Tenant ID from user input (not JWT)
- HIGH: Missing post-query ownership verification
- MEDIUM: Inconsistent verifier implementation
- LOW: Missing UUID format validation
Output Format:
## IDOR Protection Audit Findings
### Summary
- Modules with verifiers: X/Y
- Multi-tenant filtered queries: X/Y
- Post-query verification: X/Y
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 8: SQL Safety Auditor
```prompt
Audit SQL injection prevention for production readiness.
**Detected Stack:** {DETECTED_STACK}
**Search Patterns:**
- Files: `**/repository/*.ts`, `**/*_repo.ts`, `**/database/*.ts`
- Keywords: `query`, `execute`, `$1`, `$2`, `knex`, `prisma`, `typeorm`
- Also search for: String concatenation in SQL: `` `SELECT.*${` ``, template literal interpolation in queries
**Reference Implementation (GOOD):**
```typescript
// Parameterized queries
const query = 'INSERT INTO resources (id, name, tenant_id) VALUES ($1, $2, $3)';
await client.query(query, [id, name, tenantId]);
// SQL identifier escaping for dynamic schemas
function quoteIdentifier(identifier: string): string {
return '"' + identifier.replace(/"/g, '""') + '"';
}
await client.query(`SET LOCAL search_path TO ${quoteIdentifier(tenantId)}`);
// Query builder (Knex)
const result = await knex('resources').select('*').where({ tenant_id: tenantId });
Reference Implementation (BAD):
const query = "SELECT * FROM users WHERE name = '" + name + "'";
const query = `SELECT * FROM users WHERE id = '${id}'`;
const query = `SET search_path TO ${tenantId}`;
Check For:
- All queries use parameterized statements ($1, $2, ...)
- No string concatenation in SQL queries
- Dynamic identifiers properly escaped (QuoteIdentifier)
- Query builders used for complex WHERE clauses
- No raw SQL with user input
Severity Ratings:
- CRITICAL: String concatenation with user input
- CRITICAL: Template literal interpolation with user values
- HIGH: Unescaped dynamic identifiers
- MEDIUM: Raw SQL where builder would be safer
- LOW: Inconsistent query patterns
Output Format:
## SQL Safety Audit Findings
### Summary
- Parameterized queries: X/Y
- String concatenation risks: Z
- Identifier escaping: Yes/No
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 9: Input Validation Auditor
```prompt
Audit input validation patterns for production readiness.
**Detected Stack:** {DETECTED_STACK}
**MarsAI Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Frameworks & Libraries" section from core.md — specifically validation library reference}
---END STANDARDS---
**Search Patterns:**
- Files: `**/dto.ts`, `**/handlers.ts`, `**/value-objects/*.ts`, `**/schemas/*.ts`
- Keywords: `class-validator`, `zod`, `joi`, `@IsString`, `z.object`, `schema.validate`
- Standards-specific: `class-validator`, `class-transformer`, `zod`
**Reference Implementation (GOOD):**
```typescript
// DTO with validation decorators (class-validator)
class CreateRequest {
@IsString()
@MinLength(1)
@MaxLength(255)
name: string;
@IsEnum(ResourceType)
type: string;
@IsInt()
@Min(0)
@Max(1000000)
amount: number;
}
// Handler with body parsing and validation
async function create(req: Request, res: Response) {
const payload = plainToInstance(CreateRequest, req.body);
const errors = await validate(payload);
if (errors.length > 0) {
return res.status(400).json({ error: 'Validation failed', details: errors });
}
// ...
}
// Value object with domain validation
class ValueObject {
private constructor(private readonly value: string) {}
static create(value: string): ValueObject {
if (!value || value.length > MAX_LENGTH) throw new InvalidInputError();
if (!VALID_PATTERN.test(value)) throw new InvalidInputError();
return new ValueObject(value);
}
}
Reference Implementation (BAD):
interface Request {
name: string;
}
const payload = req.body as CreateRequest;
const amount = parseInt(req.query.amount as string);
Check Against MarsAI Standards For:
- (HARD GATE) Validation library (class-validator/zod/joi) used for DTO validation per MarsAI core.md
- (HARD GATE) All DTOs have validation decorators/schemas on required fields
- Body parsing errors are handled (not ignored)
- Query/path params validated before use
- Numeric bounds enforced (min/max)
- String length limits enforced
- Enum values constrained
- Value objects have factory methods with validation
- File upload size/type validation
Severity Ratings:
- CRITICAL: Body parsing errors ignored
- CRITICAL: HARD GATE violation — not using validation library per MarsAI standards
- HIGH: No validation on user input DTOs
- HIGH: Unbounded numeric inputs
- MEDIUM: Missing string length limits
- LOW: Value objects without IsValid()
Output Format:
## Input Validation Audit Findings
### Summary
- DTOs with validation tags: X/Y
- BodyParser error handling: X/Y
- Value objects with IsValid: X/Y
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 10: Telemetry & Observability Auditor
```prompt
Audit telemetry and observability implementation for production readiness.
**Detected Stack:** {DETECTED_STACK}
**MarsAI Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Observability" section from bootstrap.md and "OpenTelemetry" section from sre.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/observability*.ts`, `**/telemetry*.ts`, `**/tracing*.ts`, `**/handlers.ts`
- Keywords: `tracer.startSpan`, `span`, `logger`, `metrics`, `opentelemetry`
- Standards-specific: `@opentelemetry/sdk-node`, `otel`, `OpenTelemetry`
**Reference Implementation (GOOD):**
```typescript
// Handler with proper telemetry
async function doSomething(req: Request, res: Response) {
const span = tracer.startSpan('handler.doSomething');
const ctx = trace.setSpan(context.active(), span);
span.setAttribute('request_id', req.headers['x-request-id'] ?? '');
try {
// ... business logic
} catch (err) {
span.recordException(err as Error);
span.setStatus({ code: SpanStatusCode.ERROR, message: (err as Error).message });
logger.error('operation failed', { error: err });
throw err;
} finally {
span.end();
}
}
Reference Implementation (GOOD — Trace Propagation & Sampling):
import { propagation, context } from '@opentelemetry/api';
async function doRequest(url: string, options: RequestInit = {}): Promise<Response> {
const headers: Record<string, string> = {};
propagation.inject(context.active(), headers);
return fetch(url, { ...options, headers: { ...options.headers, ...headers } });
}
import { propagation, baggage } from '@opentelemetry/api';
function injectBusinessContext(tenantId: string, userId: string) {
const bag = propagation.createBaggage({
tenantId: { value: tenantId },
userId: { value: userId },
});
return propagation.setBaggage(context.active(), bag);
}
async function handleMessage(msg: Message) {
const producerCtx = propagation.extract(context.active(), msg.headers);
const producerSpanCtx = trace.getSpanContext(producerCtx);
const span = tracer.startSpan(`consume.${msg.type}`, {
links: producerSpanCtx ? [{ context: producerSpanCtx }] : [],
});
try {
await processMessage(msg);
} finally {
span.end();
}
}
function initTracer(env: string) {
const sampler = env === 'production'
? new ParentBasedSampler({ root: new TraceIdRatioBasedSampler(0.1) })
: env === 'staging'
? new ParentBasedSampler({ root: new TraceIdRatioBasedSampler(0.5) })
: new AlwaysOnSampler();
return new NodeTracerProvider({ sampler });
}
async function createOrder(req: Request, res: Response) {
const span = tracer.startSpan('handler.createOrder');
span.setAttributes({
'order.id': order.id,
'tenant.id': tenantId,
'order.amount': order.totalAmount,
});
span.end();
}
Reference Implementation (BAD — Trace Propagation):
async function doRequest(url: string): Promise<Response> {
return fetch(url);
}
async function handleMessage(msg: Message) {
const span = tracer.startSpan('consume.event');
await processMessage(msg);
span.end();
}
const provider = new NodeTracerProvider();
Check Against MarsAI Standards For:
- (HARD GATE) OpenTelemetry SDK used for telemetry initialization per MarsAI standards
- (HARD GATE) OpenTelemetry integration (not custom tracing) per sre.md
- All handlers start spans with descriptive names
- Errors recorded to spans before returning
- Request IDs propagated through context
- Metrics initialized at startup per bootstrap.md observability section
- Structured logging with context (not console.log)
- Graceful telemetry shutdown
- Cross-service trace context propagation — outgoing HTTP requests MUST inject W3C Trace Context headers (
traceparent, tracestate) using OpenTelemetry propagators
- Baggage propagation across service boundaries — business context (e.g.,
tenantId, userId, correlationId) MUST be propagated via OpenTelemetry Baggage for cross-service observability
- Span linking for async flows — message producer spans MUST be linked to consumer spans via
trace.WithLinks() so async flows appear connected in distributed traces
- Trace sampling configuration — production environments MUST configure sampling rate (not 100% sampling) to control cost; development environments may use
AlwaysSample
- Custom span attributes for business-relevant data — spans MUST include domain-specific attributes (e.g.,
order.id, tenant.id, transaction.amount) for meaningful trace filtering
Severity Ratings:
- CRITICAL: No tracing in handlers (HARD GATE violation per MarsAI standards)
- CRITICAL: HARD GATE violation — not using OpenTelemetry SDK for telemetry
- HIGH: Errors not recorded to spans
- HIGH: No trace context propagation in outgoing HTTP requests (downstream services cannot correlate traces — breaks distributed tracing)
- HIGH: Async message flows break trace continuity (no span links between producer and consumer — message processing appears as disconnected traces)
- MEDIUM: Missing request ID propagation
- MEDIUM: No trace sampling configuration (100% sampling in production = storage cost explosion and performance overhead)
- MEDIUM: Missing baggage propagation for cross-service business context (cannot filter/correlate traces by tenant, user, or business entity)
- LOW: Inconsistent span naming conventions
- LOW: No custom span attributes for business metrics (traces lack domain context for meaningful filtering and alerting)
Output Format:
## Telemetry Audit Findings
### Summary
- Handlers with tracing: X/Y
- Handlers with error recording: X/Y
- Metrics initialization: Yes/No
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 12: Health Checks Auditor
```prompt
Audit health check endpoints for production readiness.
**Detected Stack:** {DETECTED_STACK}
**MarsAI Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Health Checks" section from sre.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/health*.ts`, `**/routes.ts`, `**/app.ts`, `**/server.ts`
- Keywords: `/health`, `/ready`, `/live`, `healthHandler`, `readinessHandler`
- Standards-specific: `liveness`, `readiness`, `degraded`
**Reference Implementation (GOOD):**
```typescript
// Liveness probe - always returns healthy if process is running
function healthHandler(req: Request, res: Response) {
return res.send('healthy');
}
// Readiness probe - checks all dependencies
function readinessHandler(deps: HealthDependencies) {
return async (req: Request, res: Response) => {
const checks: Record<string, string> = {};
let status = 200;
// Required dependency - fails readiness if down
try {
await deps.db.raw('SELECT 1');
checks.database = 'healthy';
} catch {
checks.database = 'unhealthy';
status = 503;
}
// Optional dependency - reports degraded but doesn't fail
if (deps.redis) {
try {
await deps.redis.ping();
checks.redis = 'healthy';
} catch {
checks.redis = 'degraded';
}
}
return res.status(status).json({
status: status === 200 ? 'healthy' : 'unhealthy',
checks,
});
};
}
// Register without auth middleware
app.get('/health', healthHandler);
app.get('/ready', readinessHandler(deps));
Check Against MarsAI Standards For:
- (HARD GATE) /health endpoint exists (liveness) per sre.md
- (HARD GATE) /ready endpoint exists (readiness) per sre.md
- Health endpoints bypass auth middleware
- Database connectivity checked in readiness
- Message queue connectivity checked
- Optional deps don't fail readiness (just report degraded) per MarsAI health check pattern
- Response includes individual check status
- Appropriate HTTP status codes (200 vs 503)
Severity Ratings:
- CRITICAL: No health endpoints at all (HARD GATE violation per MarsAI standards)
- HIGH: No readiness probe (only liveness)
- HIGH: Health endpoints require auth
- MEDIUM: Missing dependency checks in readiness
- LOW: No degraded status for optional deps
Output Format:
## Health Checks Audit Findings
### Summary
- Liveness endpoint: Yes/No (/path)
- Readiness endpoint: Yes/No (/path)
- Dependencies checked: [list]
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 13: Configuration Management Auditor
```prompt
Audit configuration management for production readiness.
**Detected Stack:** {DETECTED_STACK}
**MarsAI Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Configuration" section from core.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/config.ts`, `**/bootstrap/*.ts`, `**/.env*`
- Keywords: `process.env`, `dotenv`, `@nestjs/config`, `Joi.object`, `z.object`
- Standards-specific: `dotenv`, `@nestjs/config`, `convict`
**Reference Implementation (GOOD):**
```typescript
// Config with validation (using zod)
const configSchema = z.object({
envName: z.string().default('development'),
dbPassword: z.string().optional(),
authEnabled: z.coerce.boolean().default(false),
postgresSSLMode: z.string().default('disable'),
});
// Production validation
function validateProductionConfig(cfg: Config): void {
if (cfg.envName === 'production') {
if (!cfg.authEnabled) {
throw new Error('AUTH_ENABLED must be true in production');
}
if (!cfg.dbPassword) {
throw new Error('POSTGRES_PASSWORD required in production');
}
if (cfg.postgresSSLMode === 'disable') {
throw new Error('POSTGRES_SSLMODE cannot be disable in production');
}
}
}
// Load with validation
function loadConfig(): Config {
const raw = {
envName: process.env.ENV_NAME,
dbPassword: process.env.POSTGRES_PASSWORD,
authEnabled: process.env.AUTH_ENABLED,
postgresSSLMode: process.env.POSTGRES_SSLMODE,
};
const cfg = configSchema.parse(raw);
validateProductionConfig(cfg);
return cfg;
}
Check Against MarsAI Standards For:
- (HARD GATE) All config loaded from env vars (not hardcoded) per MarsAI core.md configuration section
- (HARD GATE) Production-specific validation exists
- Sensible defaults for non-production
- Auth required in production
- TLS/SSL required in production
- Default credentials rejected in production
- Secrets not logged during startup
- Config validation fails fast (at startup)
Severity Ratings:
- CRITICAL: Hardcoded secrets in code (HARD GATE violation per MarsAI standards)
- CRITICAL: No production validation
- HIGH: Auth can be disabled in production
- HIGH: TLS not enforced in production
- MEDIUM: Missing sensible defaults
- LOW: Config not validated at startup
Output Format:
## Configuration Management Audit Findings
### Summary
- Env vars used: X fields
- Production validation: Yes/No
- Constraints enforced: [list]
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 14: Connection Management Auditor
```prompt
Audit database and cache connection management for production readiness.
**Detected Stack:** {DETECTED_STACK}
**MarsAI Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Core Dependencies" section from core.md — specifically connection packages}
---END STANDARDS---
**Search Patterns:**
- Files: `**/config.ts`, `**/database*.ts`, `**/redis*.ts`, `**/postgres*.ts`
- Keywords: `pool`, `max`, `min`, `idleTimeoutMillis`, `connectionTimeoutMillis`, `ioredis`
- Standards-specific: `knex`, `typeorm`, `prisma`, `ioredis`, `pg`
**Reference Implementation (GOOD):**
```typescript
// Database pool configuration
const dbConfig = {
pool: {
max: parseInt(process.env.POSTGRES_MAX_OPEN_CONNS ?? '25'),
min: parseInt(process.env.POSTGRES_MIN_IDLE_CONNS ?? '5'),
idleTimeoutMillis: parseInt(process.env.POSTGRES_IDLE_TIMEOUT_MS ?? '30000'),
acquireTimeoutMillis: parseInt(process.env.POSTGRES_ACQUIRE_TIMEOUT_MS ?? '10000'),
},
};
// Redis pool configuration
const redisConfig = {
maxRetriesPerRequest: 3,
connectTimeout: parseInt(process.env.REDIS_CONNECT_TIMEOUT_MS ?? '5000'),
commandTimeout: parseInt(process.env.REDIS_COMMAND_TIMEOUT_MS ?? '3000'),
lazyConnect: true,
};
// Primary + Replica support
interface DatabaseConnections {
primary: Knex;
replica: Knex; // Falls back to primary if not configured
}
Check Against MarsAI Standards For:
- (HARD GATE) Project connection libraries used per core.md
- DB connection pool limits configured
- Redis pool settings configured
- Connection timeouts set (not infinite)
- Connection max lifetime set (prevents stale connections)
- Idle connection limits reasonable
- Read replica support (for scaling reads)
- Connection health checks (ping on checkout)
- Graceful connection shutdown
Severity Ratings:
- CRITICAL: No connection pool limits (unbounded connections)
- CRITICAL: HARD GATE violation — not using project connection libraries
- HIGH: No connection timeouts (hang forever)
- HIGH: No max lifetime (stale connections)
- MEDIUM: Missing read replica support
- LOW: Pool sizes not tuned
Output Format:
## Connection Management Audit Findings
### Summary
- DB pool configured: Yes/No (max: X, idle: Y)
- Redis pool configured: Yes/No (size: X)
- Timeouts configured: Yes/No
- Replica support: Yes/No
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 15: Logging & PII Safety Auditor
```prompt
Audit logging practices and PII protection for production readiness.
**Detected Stack:** {DETECTED_STACK}
**MarsAI Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Logging" section from quality.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/*.ts`
- Keywords: `logger.`, `log.`, `error`, `info`, `warn`, `password`, `token`, `secret`
- Also search: `console.log`, `console.error` (should not be used for logging in production)
- Standards-specific: `winston`, `pino`, `bunyan`, structured logging library references
**Reference Implementation (GOOD):**
```typescript
// Structured logging with context
logger.info('resource created', {
requestId,
userId,
action: 'create_resource',
});
// Production-safe error logging
if (isProduction) {
// Don't include error details that might leak PII
logger.error('operation failed', { status: code, path });
} else {
// Development can have full details
logger.error('operation failed', { error: err.message, stack: err.stack });
}
// Config DSN without password
function getDSN(config: Config): string {
// Returns connection string without logging password
return `host=${config.host} port=${config.port} user=${config.user} dbname=${config.dbName}`;
}
Reference Implementation (BAD):
console.log('User logged in:', userEmail);
logger.info(`Login attempt: email=${email} password=${password}`);
logger.debug('Request body:', requestBody);
console.error('Error:', err);
Check Against MarsAI Standards For:
- (HARD GATE) Structured logging used (not console.log or console.error) per quality.md logging section
- Logger obtained from context (request tracking)
- No passwords/tokens logged
- Production mode sanitizes error details
- Request/response bodies not logged raw
- Log levels appropriate (not everything at INFO)
- Request IDs included for tracing
- No PII in log messages (emails, names, etc.)
Severity Ratings:
- CRITICAL: Passwords/tokens logged
- CRITICAL: PII logged in production
- HIGH: console.log used instead of logger (HARD GATE violation per MarsAI standards)
- HIGH: Full error details in production
- MEDIUM: Missing request ID in logs
- LOW: Inappropriate log levels
Output Format:
## Logging & PII Safety Audit Findings
### Summary
- Structured logging: Yes/No
- PII protection: Yes/No
- Production mode: Yes/No
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 16: Idempotency Auditor
```prompt
Audit idempotency implementation for production readiness.
**Detected Stack:** {DETECTED_STACK}
**MarsAI Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: Full module content from idempotency.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/idempotency*.ts`, `**/value-objects/*.ts`, `**/redis/*.ts`
- Keywords: `idempotencyKey`, `tryAcquire`, `markComplete`, `setNX`, `idempotent`
- Standards-specific: `IdempotencyRepository`, `idempotency middleware`
**Reference Implementation (GOOD):**
```typescript
// Idempotency key value object
const IDEMPOTENCY_KEY_MAX_LENGTH = 128;
const IDEMPOTENCY_KEY_PATTERN = /^[A-Za-z0-9:_-]+$/;
class IdempotencyKey {
private constructor(private readonly value: string) {}
static create(value: string): IdempotencyKey {
if (!value || value.length > IDEMPOTENCY_KEY_MAX_LENGTH) {
throw new InvalidIdempotencyKeyError();
}
if (!IDEMPOTENCY_KEY_PATTERN.test(value)) {
throw new InvalidIdempotencyKeyError();
}
return new IdempotencyKey(value);
}
toString(): string { return this.value; }
}
// Redis-backed idempotency
class IdempotencyRepository {
constructor(private readonly redis: Redis, private readonly ttlSeconds: number = 604800) {} // 7 days
async tryAcquire(key: IdempotencyKey): Promise<boolean> {
// SetNX is atomic - only first caller wins
const result = await this.redis.set(this.keyName(key), 'acquired', 'EX', this.ttlSeconds, 'NX');
return result === 'OK';
}
async markComplete(key: IdempotencyKey): Promise<void> {
await this.redis.set(this.keyName(key), 'complete', 'EX', this.ttlSeconds);
}
}
// Usage in handler
async function processCallback(req: Request, res: Response) {
const key = IdempotencyKey.create(req.headers['idempotency-key'] as string);
const acquired = await idempotency.tryAcquire(key);
if (!acquired) {
return res.status(200).json({ status: 'already_processed' });
}
// Process...
await idempotency.markComplete(key);
return res.json(result);
}
Check Against MarsAI Standards For:
- (HARD GATE) Idempotency keys for financial/critical operations per idempotency.md
- (HARD GATE) Atomic acquire mechanism (SetNX or similar)
- TTL to prevent unbounded storage
- Key validation (format, length) per MarsAI idempotency patterns
- Proper state transitions (acquired -> complete/failed)
- Retry-safe (failed operations can be retried)
- Idempotency for webhook callbacks
- Idempotency for payment operations
Severity Ratings:
- CRITICAL: No idempotency for financial operations (HARD GATE violation per MarsAI standards)
- HIGH: Non-atomic acquire (race conditions)
- HIGH: No TTL (memory leak)
- MEDIUM: Missing key validation
- LOW: No failed state handling
Output Format:
## Idempotency Audit Findings
### Summary
- Idempotency implemented: Yes/No
- Operations covered: [list]
- Storage backend: Redis/DB/Memory
- TTL configured: X days
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 17: API Documentation Auditor
```prompt
Audit API documentation (Swagger/OpenAPI) for production readiness.
**Detected Stack:** {DETECTED_STACK}
**MarsAI Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: Swaggo/OpenAPI subsection from "Pagination Patterns" in api-patterns.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/main.ts`, `**/controllers/*.ts`, `**/dto.ts`, `**/swagger/*`, `**/openapi*.yaml`
- Keywords: `@ApiOperation`, `@ApiResponse`, `@ApiProperty`, `@ApiTags`, `@swagger-jsdoc`
- Standards-specific: `@nestjs/swagger`, `swagger-jsdoc`, `openapi`, `docs/swagger.json`
**Reference Implementation (GOOD):**
```typescript
// NestJS controller with full OpenAPI documentation
@ApiTags('resources')
@ApiBearerAuth()
@Controller('v1/resources')
export class ResourcesController {
@Post()
@ApiOperation({ summary: 'Create a resource', description: 'Creates a new resource with the given parameters' })
@ApiResponse({ status: 201, type: ResourceResponse })
@ApiResponse({ status: 400, type: ErrorResponse, description: 'Invalid input' })
@ApiResponse({ status: 401, type: ErrorResponse, description: 'Unauthorized' })
@ApiResponse({ status: 403, type: ErrorResponse, description: 'Forbidden' })
@ApiResponse({ status: 500, type: ErrorResponse, description: 'Internal error' })
async create(@Body() dto: CreateRequest): Promise<ResourceResponse> { ... }
}
// DTO with documentation
class CreateRequest {
@ApiProperty({ example: 'my-resource' })
@IsString()
name: string;
@ApiProperty({ example: 'TYPE_A', enum: ['TYPE_A', 'TYPE_B'] })
@IsEnum(ResourceType)
type: string;
@ApiProperty({ example: 100, minimum: 0, maximum: 1000000 })
@IsInt()
@Min(0)
@Max(1000000)
amount: number;
}
Check Against MarsAI Standards For:
- (HARD GATE) OpenAPI/Swagger annotations present per MarsAI api-patterns.md
- API title, version, description in OpenAPI config
- Security definitions (Bearer token)
- All endpoints have @Router annotation
- Request/response types documented
- All error codes documented (@Failure)
- Examples in DTOs (example: tag)
- Enums documented (enums: tag)
- Parameter constraints documented (minimum, maximum)
- Tags organize endpoints logically
- Swagger UI accessible
Severity Ratings:
- HIGH: No Swagger annotations at all (HARD GATE violation per MarsAI standards)
- HIGH: Missing security definitions
- MEDIUM: Endpoints without documentation
- MEDIUM: Error responses not documented
- LOW: Missing examples in DTOs
- LOW: Inconsistent tag usage
Output Format:
## API Documentation Audit Findings
### Summary
- Swagger annotations: Yes/No
- Documented endpoints: X/Y
- Security definitions: Yes/No
- Error responses documented: X/Y
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 18: Technical Debt Auditor
```prompt
Audit technical debt indicators for production readiness.
**Detected Stack:** {DETECTED_STACK}
**Search Patterns (with context):**
- `TODO` - Planned work
- `FIXME` - Known bugs
- `HACK` - Workarounds
- `XXX` - Danger zones
- `deprecated` (case-insensitive)
- `"in a real implementation"` or `"real implementation"`
- `"temporary"` or `"temp fix"`
- `"workaround"`
- `throw new Error("not implemented")`
**Risk Assessment Criteria:**
**Implement Now (High Risk):**
- Security-related TODOs (auth, validation, encryption)
- Error handling TODOs in critical paths
- Data integrity issues
- "FIXME" in production code paths
**Monitor (Medium Risk):**
- Performance optimization TODOs
- Incomplete logging
- "deprecated" usage without migration plan
**Acceptable Debt (Low Risk):**
- Future feature ideas
- Code style improvements
- Test coverage expansion
- Documentation improvements
**Output Format:**
Technical Debt Audit Findings
Summary
- Total TODOs: X
- Total FIXMEs: Y
- Deprecated usage: Z
- "Real implementation" markers: N
HIGH RISK - Implement Now
| File:Line | Type | Description | Risk |
|---|
| path:123 | TODO | Auth bypass for testing | Security |
MEDIUM RISK - Monitor
| File:Line | Type | Description | Risk |
|---|
LOW RISK - Acceptable Debt
| File:Line | Type | Description | Risk |
|---|
Recommendations
- ...
Agent 19: Testing Coverage Auditor
Audit test coverage and testing patterns for production readiness.
**Detected Stack:** {DETECTED_STACK}
**MarsAI Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Testing" section from quality.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/*.spec.ts`, `**/*.test.ts`, `**/mocks/**/*.ts`, `**/__tests__/**/*.ts`
- Keywords: `describe`, `it(`, `test(`, `expect(`, `jest.mock`, `vi.mock`
- Standards-specific: `jest`, `vitest`, `supertest`, `testcontainers`
**Reference Implementation (GOOD):**
```typescript
// Co-located test file
// file: handler.spec.ts (next to handler.ts)
describe('Handler.create', () => {
it('should create a resource successfully', async () => {
// Arrange
const mockRepo = { save: jest.fn().mockResolvedValue(undefined) };
const handler = new Handler(mockRepo);
// Act
const result = await handler.create(ctx, input);
// Assert
expect(result).toEqual(expected);
expect(mockRepo.save).toHaveBeenCalledWith(expect.any(Object));
});
});
// Parameterized tests for multiple cases
describe('Validation', () => {
const cases = [
{ name: 'valid input', input: 'test', shouldThrow: false },
{ name: 'empty input', input: '', shouldThrow: true },
{ name: 'too long', input: 'a'.repeat(300), shouldThrow: true },
];
it.each(cases)('$name', async ({ input, shouldThrow }) => {
if (shouldThrow) {
await expect(validate(input)).rejects.toThrow();
} else {
await expect(validate(input)).resolves.not.toThrow();
}
});
});
// Integration test with testcontainers
describe('Integration: CreateResource', () => {
if (process.env.SKIP_INTEGRATION) return;
// Setup container...
});
Check Against MarsAI Standards For:
- (HARD GATE) Test files co-located with source (*.spec.ts / *.test.ts) per quality.md testing section
- (HARD GATE) Mocks use jest.mock/vi.mock (not hand-written implementations) per MarsAI standards
- (HARD GATE) Assertions use jest/vitest expect() per MarsAI standards
- Parameterized tests (it.each / test.each) for multiple cases
- Integration tests in separate directory or with configuration flags
- Test helpers/fixtures organized
- Concurrent test execution where appropriate
- Test cleanup with afterEach/afterAll hooks
Severity Ratings:
- HIGH: Critical paths without tests (HARD GATE violation per MarsAI standards)
- HIGH: Hand-written mocks (should use jest.mock per MarsAI standards)
- MEDIUM: Missing table-driven tests for validators
- MEDIUM: No integration tests
- LOW: Tests not running in parallel
- LOW: Missing edge case coverage
Output Format:
## Testing Coverage Audit Findings
### Summary
- Test files found: X
- Modules with tests: X/Y
- Mock generation: jest.mock / hand-written
- Integration tests: Yes/No
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 20: Dependency Management Auditor
```prompt
Audit dependency management for production readiness.
**Detected Stack:** {DETECTED_STACK}
**MarsAI Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Frameworks & Libraries" section from core.md — specifically the version table}
---END STANDARDS---
**Search Patterns:**
- Files: `package.json`, `package-lock.json`, `yarn.lock`, `pnpm-lock.yaml`
- Commands: Run `npm audit` mentally based on package.json
- Standards-specific: Check for required MarsAI dependencies in package.json
**Reference Implementation (GOOD):**
```json
// package.json with pinned versions
{
"name": "@company/project",
"dependencies": {
"@nestjs/core": "^10.3.0",
"ioredis": "^5.3.0",
"@opentelemetry/sdk-node": "^0.48.0"
},
"devDependencies": {
"jest": "^29.7.0",
"typescript": "^5.3.0"
}
}
Reference Implementation (BAD):
{ "some-lib": "file:../local-lib" }
{ "some-lib": "*" }
{ "jsonwebtoken": "^7.0.0" }
Check Against MarsAI Standards For:
- (HARD GATE) Required MarsAI framework dependencies present in package.json per core.md version table
- All dependencies pinned (no "*" or unranged)
- No local file: protocol in production dependencies
- Known vulnerable packages identified (npm audit)
- Unused dependencies (not imported anywhere)
- Major version mismatches
- Deprecated packages flagged by npm
- Lock file exists and is committed
- Framework versions meet MarsAI minimum requirements (Node.js 20+, TypeScript 5+, etc.)
Known Vulnerable Packages to Flag:
- jsonwebtoken < 9.0.0 (multiple CVEs)
- axios < 1.6.0 (SSRF vulnerability)
- lodash < 4.17.21 (prototype pollution)
- express < 4.19.0 (path traversal)
Severity Ratings:
- CRITICAL: Known CVE in dependency (npm audit critical)
- CRITICAL: HARD GATE violation — required MarsAI framework dependency missing from package.json
- HIGH: Local replace directive
- HIGH: Deprecated package with security issues
- MEDIUM: Significantly outdated dependencies
- MEDIUM: Framework versions below MarsAI minimum requirements
- LOW: Minor version behind
Output Format:
## Dependency Audit Findings
### Summary
- Total dependencies: X
- Direct dependencies: Y
- Potentially outdated: Z
- Known vulnerabilities: N
### Critical Issues
[package] - Description
### Recommendations
1. ...
### Agent 21: Performance Patterns Auditor
```prompt
Audit performance patterns for production readiness.
**Detected Stack:** {DETECTED_STACK}
**Search Patterns:**
- Files: `**/*.ts`
- Keywords: `for`, `map(`, `push(`, `SELECT *`, `N+1`, `Promise.all`
**Reference Implementation (GOOD):**
```typescript
// Batch database operations
async function createBatch(items: Item[]): Promise<void> {
const batchSize = 100;
for (let i = 0; i < items.length; i += batchSize) {
const batch = items.slice(i, i + batchSize);
await knex('items').insert(batch);
}
}
// Select only needed columns
async function list(): Promise<Item[]> {
return knex('items').select('id', 'name', 'status'); // Not SELECT *
}
// Avoid N+1 with eager loading
async function getWithRelations(id: string): Promise<Item> {
return knex('items')
.where('items.id', id)
.join('children', 'children.parent_id', 'items.id')
.select('items.*', 'children.*');
}
// Bounded concurrent requests
import pLimit from 'p-limit';
const limit = pLimit(10);
const results = await Promise.all(
urls.map(url => limit(() => fetch(url)))
);
Reference Implementation (BAD):
const items = await knex('items').select('*');
for (const item of items) {
const children = await knex('children').where('parent_id', item.id);
}
const results = await Promise.all(
urls.map(url => fetch(url))
);
function handleRequest() {
const buf = Buffer.alloc(1 << 20);
}
Check For:
- SELECT * avoided (explicit column selection)
- N+1 queries prevented (use Preload/joins)
- Slice pre-allocation when size known
- Object pooling for frequent allocations
- Batch operations for bulk inserts/updates
- Indexes exist for filtered/sorted columns
- Connection pooling configured
- Context timeouts on DB operations
Severity Ratings:
- HIGH: N+1 query pattern in production code
- HIGH: SELECT * on large tables
- MEDIUM: Missing slice pre-allocation
- MEDIUM: No batch operations for bulk data
- LOW: Missing object pooling optimization
- LOW: Minor inefficiencies
Output Format:
## Performance Audit Findings
### Summary
- N+1 patterns found: X
- SELECT * usage: Y
- Missing pre-allocations: Z
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 22: Concurrency Safety Auditor
```prompt
Audit concurrency patterns for production readiness.
**Detected Stack:** {DETECTED_STACK}
**MarsAI Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Concurrency Patterns" section from architecture.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/*.ts`
- Keywords: `Promise.all`, `Promise.race`, `Worker`, `setInterval`, `async`, `concurrency`
- Standards-specific: `p-limit`, `p-queue`, `worker_threads`, `bull`
**Reference Implementation (GOOD):**
```typescript
// Bounded concurrent processing
import pLimit from 'p-limit';
const limit = pLimit(10); // Max 10 concurrent
async function processAll(items: Item[]): Promise<void> {
const results = await Promise.allSettled(
items.map(item => limit(() => process(item)))
);
const errors = results.filter(r => r.status === 'rejected');
if (errors.length > 0) {
throw new AggregateError(errors.map(e => (e as PromiseRejectedResult).reason));
}
}
// Worker with AbortController for cancellation
async function worker(signal: AbortSignal): Promise<void> {
while (!signal.aborted) {
const item = await getNextItem();
if (item) await process(item);
await new Promise(resolve => setTimeout(resolve, 100));
}
}
// Thread-safe cache with Map (single-threaded JS, but consistent patterns)
class Cache<T> {
private items = new Map<string, T>();
get(key: string): T | undefined {
return this.items.get(key);
}
set(key: string, item: T): void {
this.items.set(key, item);
}
}
Reference Implementation (BAD):
const results = await Promise.all(
millionItems.map(item => process(item))
);
setInterval(() => {
process();
}, 1000);
items.forEach(item => {
process(item);
});
await Promise.all(items.map(item => process(item)));
Check Against MarsAI Standards For:
- (HARD GATE) Maps protected by mutex when shared per architecture.md concurrency patterns
- Loop variables not captured in closures
- Goroutines have cancellation (context)
- WaitGroup used for coordination
- Bounded concurrency (worker pools) per MarsAI patterns
- Channels closed by sender
- Select with default for non-blocking
- No async leaks (all operations complete or are cancelled)
Severity Ratings:
- CRITICAL: Unbounded concurrent operations (HARD GATE violation per MarsAI standards)
- CRITICAL: Async leak (no cleanup path)
- HIGH: Fire-and-forget async operations without error handling
- HIGH: Unbounded Promise.all without concurrency limit
- MEDIUM: Missing context cancellation
- LOW: Inefficient locking patterns
Output Format:
## Concurrency Audit Findings
### Summary
- Goroutine spawns: X locations
- Mutex usage: Y locations
- Potential race conditions: Z
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 23: Migration Safety Auditor
```prompt
Audit database migration safety for production readiness.
**Detected Stack:** {DETECTED_STACK}
**MarsAI Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Core Dependencies" section from core.md — database migration patterns}
---END STANDARDS---
**Search Patterns:**
- Files: `migrations/*.sql`, `migrations/*.ts`, `**/migration*.ts`
- Keywords: `DROP`, `ALTER`, `RENAME`, `NOT NULL`, `CREATE INDEX`
- Standards-specific: migration tool (knex migrations, prisma migrate, typeorm migrations)
**Reference Implementation (GOOD):**
```sql
-- 000001_create_users.up.sql
CREATE TABLE IF NOT EXISTS users (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
email VARCHAR(255) NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
);
CREATE INDEX CONCURRENTLY IF NOT EXISTS idx_users_email ON users(email);
-- 000001_create_users.down.sql
DROP INDEX IF EXISTS idx_users_email;
DROP TABLE IF EXISTS users;
-- Adding nullable column (safe)
ALTER TABLE users ADD COLUMN IF NOT EXISTS phone VARCHAR(50);
-- Adding NOT NULL with default (safe)
ALTER TABLE users ADD COLUMN IF NOT EXISTS status VARCHAR(20) NOT NULL DEFAULT 'active';
Reference Implementation (BAD):
ALTER TABLE users ADD COLUMN role VARCHAR(50) NOT NULL;
CREATE INDEX idx_users_email ON users(email);
DROP TABLE users;
DROP COLUMN email;
ALTER TABLE users RENAME COLUMN email TO user_email;
Reference Implementation (GOOD — Constraints & Data Migrations):
ALTER TABLE orders ADD COLUMN IF NOT EXISTS status VARCHAR(20) NOT NULL DEFAULT 'pending';
ALTER TABLE orders ADD CONSTRAINT chk_order_status
CHECK (status IN ('pending', 'processing', 'completed', 'cancelled', 'refunded'));
ALTER TABLE order_items ADD CONSTRAINT fk_order_items_order
FOREIGN KEY (order_id) REFERENCES orders(id)
ON DELETE CASCADE
ON UPDATE CASCADE;
CREATE TYPE account_status AS ENUM ('active', 'inactive', 'suspended', 'deleted');
ALTER TABLE accounts ADD COLUMN IF NOT EXISTS status account_status NOT NULL DEFAULT 'active';
UPDATE orders SET status = 'completed' WHERE legacy_status = 1 AND status IS NULL;
UPDATE orders SET status = 'cancelled' WHERE legacy_status = 2 AND status IS NULL;