name: production-readiness-audit description: Comprehensive Ring-standards-aligned 44-dimension production readiness audit. Detects project stack, loads Ring 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. allowed-tools: Task, Read, Glob, Grep, Write, TodoWrite, WebFetch
Production Readiness Audit
A comprehensive, multi-agent audit system that evaluates codebase production readiness across 44 dimensions in 5 categories, aligned with Ring 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 Ring engineering standards
- Assessing a codebase's maturity level against Ring 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 | lib-commons v2, 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, defer 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, DualPoolMiddleware, JWT tenantId, module-specific connections |
Category C: Operational Readiness (7 dimensions)
| # | Dimension | Focus Area |
|---|---|---|
| 11 | Telemetry & Observability | OpenTelemetry integration, tracing, metrics, lib-commons tracking |
| 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, mockgen, table-driven 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, goroutine leaks, mutex usage, worker pools |
| 23 | Migration Safety | Up/down pairs, CONCURRENTLY indexes, NOT NULL defaults |
| 31 | Linting & Code Quality | Import ordering (3 groups), magic numbers, golangci-lint 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 .go 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 Ring 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 Ring standards to load.
Detection via Glob:
| Check | Flag | Standards to Load |
|---|---|---|
**/go.mod exists |
GO=true | All golang/*.md modules |
**/package.json + React/Next.js deps |
FRONTEND=true | (future enrichment) |
**/package.json + Express/Fastify deps |
TS_BACKEND=true | (future enrichment) |
**/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*.go) |
MULTI_TENANT=true | multi-tenant.md |
Detection Logic:
Glob("**/go.mod") → if found: GO=true
Glob("**/package.json") → Read for React/Next.js → if found: FRONTEND=true
Glob("**/package.json") → Read for Express/Fastify → 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 Ring Standards
Based on detected stack, load Ring development standards via WebFetch from the canonical source of truth. Store fetched content for injection into explorer prompts.
WebFetch URL Map (from dev-team/docs/standards/golang/index.md):
If GO=true, WebFetch these and store content:
| Module | Variable | URL |
|---|---|---|
| core.md | standards_core |
https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/core.md |
| bootstrap.md | standards_bootstrap |
https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/bootstrap.md |
| security.md | standards_security |
https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/security.md |
| domain.md | standards_domain |
https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/domain.md |
| api-patterns.md | standards_api |
https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/api-patterns.md |
| quality.md | standards_quality |
https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/quality.md |
| architecture.md | standards_arch |
https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/architecture.md |
| messaging.md | standards_messaging |
https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/messaging.md |
| domain-modeling.md | standards_dm |
https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/domain-modeling.md |
| idempotency.md | standards_idempotency |
https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/idempotency.md |
If MULTI_TENANT=true, also WebFetch:
| Module | Variable | URL |
|---|---|---|
| multi-tenant.md | standards_multitenant |
https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/golang/multi-tenant.md |
Always WebFetch (stack-independent):
| Module | Variable | URL |
|---|---|---|
| devops.md | standards_devops |
https://raw.githubusercontent.com/LerianStudio/ring/main/dev-team/docs/standards/devops.md |
| sre.md | standards_sre |
https://raw.githubusercontent.com/LerianStudio/ring/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** | {Go / 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}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Pagination Patterns" section from api-patterns.md}
---END STANDARDS---
**Key Concept: Midaz uses TWO valid pagination strategies:**
- **Offset** for low-volume admin entities (organizations, ledgers, accounts, assets, portfolios, products, segments)
- **Cursor** for high-volume transaction entities (transactions, operations, balances, audit logs, events)
**Search Patterns:**
- Files: `**/pagination*.go`, `**/handlers.go`, `**/dto.go`, `**/httputils.go`, `**/cursor.go`
- 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):
```go
// Handler sets Page field — indicates offset mode
pagination := libPostgres.Pagination{
Limit: headerParams.Limit,
Page: headerParams.Page,
SortOrder: headerParams.SortOrder,
}
items, err := h.Query.GetAllOrganizations(ctx, *headerParams)
pagination.SetItems(items)
return libHTTP.OK(c, pagination)
// Repository uses OFFSET = (Page - 1) * Limit
query.Limit(filter.Limit).Offset((filter.Page - 1) * filter.Limit)
Cursor mode (transaction entities):
// Handler does NOT set Page — indicates cursor mode
pagination := libPostgres.Pagination{
Limit: headerParams.Limit,
SortOrder: headerParams.SortOrder,
}
items, cursor, err := h.Query.GetAllTransactions(ctx, orgID, ledgerID, *headerParams)
pagination.SetItems(items)
pagination.SetCursor(cursor.Next, cursor.Prev)
return libHTTP.OK(c, pagination)
Check Against Ring Standards For:
- (HARD GATE) Consistent pagination response structure matching Ring 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 Ring API conventions (camelCase JSON)
Severity Ratings:
- CRITICAL: No limit validation (allows unlimited queries)
- CRITICAL: HARD GATE violation per Ring standards — pagination response structure missing entirely
- HIGH: Inconsistent pagination structures across endpoints
- HIGH: Missing
ValidateParameterscall 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}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Error Codes Convention" and "Error Handling" sections from domain.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/error*.go`, `**/handlers.go`
- Keywords: `ErrRepo`, `errors.Is`, `errors.As`, `errors.New`
- Also search: `panic(`, `log.Fatal`
- Standards-specific: `ErrCode`, `DomainError`, `ErrorResponse`
**Reference Implementation (GOOD):**
```go
// Validate with explicit checks and return errors (no panic)
if config == nil {
return fmt.Errorf("validation: config required")
}
// Domain error types
var (
ErrNotFound = errors.New("resource not found")
ErrInvalidInput = errors.New("invalid input")
)
// Error mapping in handlers
if errors.Is(err, domain.ErrNotFound) {
return httputil.NotFoundError(c, span, logger, "resource not found", err)
}
Reference Implementation (BAD):
// Direct panic in production code
if config == nil {
panic("config is nil") // BAD: Return error instead
}
// Swallowing errors
result, _ := doSomething() // BAD: Ignoring error
// Generic error messages
return errors.New("error") // BAD: Not descriptive
Reference Implementation (GOOD — RFC 7807 Error Responses):
// RFC 7807 Problem Details compliant error response
type ProblemDetails struct {
Type string `json:"type"` // URI reference identifying the problem type
Title string `json:"title"` // Short human-readable summary
Status int `json:"status"` // HTTP status code
Detail string `json:"detail"` // Human-readable explanation specific to this occurrence
Instance string `json:"instance,omitempty"` // URI reference for the specific occurrence
Code string `json:"code"` // Machine-readable error code for programmatic handling
}
// Consistent error response factory
func NewProblemResponse(c *fiber.Ctx, status int, errCode string, detail string) error {
return c.Status(status).JSON(ProblemDetails{
Type: "https://api.example.com/errors/" + errCode,
Title: http.StatusText(status),
Status: status,
Detail: detail,
Instance: c.Path(),
Code: errCode,
})
}
// Handler usage — consistent across ALL endpoints
func (h *Handler) Create(c *fiber.Ctx) error {
// ...
if errors.Is(err, domain.ErrNotFound) {
return NewProblemResponse(c, 404, "RESOURCE_NOT_FOUND", "The requested resource does not exist")
}
if errors.Is(err, domain.ErrInvalidInput) {
return NewProblemResponse(c, 422, "VALIDATION_FAILED", err.Error())
}
return NewProblemResponse(c, 500, "INTERNAL_ERROR", "An unexpected error occurred")
}
// Swaggo annotation with error response schema documented
// @Failure 404 {object} ProblemDetails "Resource not found"
// @Failure 422 {object} ProblemDetails "Validation failed"
// @Failure 500 {object} ProblemDetails "Internal server error"
Reference Implementation (BAD — Inconsistent Error Responses):
// BAD: Inconsistent error response formats across endpoints
// Handler A returns:
return c.Status(400).JSON(fiber.Map{"error": "invalid input"})
// Handler B returns a different structure:
return c.Status(400).JSON(fiber.Map{"message": "invalid input", "code": 400})
// Handler C returns yet another structure:
return c.Status(400).JSON(fiber.Map{"errors": []string{"field X is required"}})
// BAD: Free-text error messages only (no machine-readable codes)
return c.Status(422).JSON(fiber.Map{"error": "The email field is required and must be valid"})
// Client cannot programmatically distinguish error types — must parse human text
// BAD: No error response schema in Swaggo annotations
// @Failure 400 "Bad request" // No response body schema defined
Check Against Ring Standards For:
- (HARD GATE) Explicit nil checks with error returns instead of panic for validation per Ring standards
- (HARD GATE) Named error variables (sentinel errors) per module following Ring error codes convention
- (HARD GATE) No panic() in non-test production code
- Proper error wrapping with %w
- errors.Is/errors.As for error matching
- No swallowed errors (_, err := ignored)
- HTTP error responses follow Ring ErrorResponse structure from domain.md
- RFC 7807 Problem Details format compliance — error responses MUST include:
type,title,status,detail,instancefields - 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
codefield (not free-text messages) - Error response examples documented in API annotations (Swaggo
@Failuretags with response schema)
Severity Ratings:
- CRITICAL: panic() in production code paths (HARD GATE violation per Ring standards)
- CRITICAL: Swallowed errors in critical paths
- HIGH: Generic error messages without context
- HIGH: Error response format does not match Ring 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,instancestructure) - 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
@Failureannotations 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}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Architecture Patterns" and "Directory Structure" sections from architecture.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/routes.go`, `**/handlers.go`, `internal/**/adapters/http/*.go`
- Keywords: `RegisterRoutes`, `protected(`, `fiber.Router`, `NewHandler`
- Standards-specific: `internal/{module}/adapters/`, `hexagonal`, `ports`
**Reference Implementation (GOOD):**
```go
// Centralized route registration
func RegisterRoutes(protected func(resource, action string) fiber.Router, handler *Handler) error {
if handler == nil {
return errors.New("handler is nil")
}
protected("resource", "create").Post("/v1/resources", handler.Create)
protected("resource", "read").Get("/v1/resources", handler.List)
protected("resource", "read").Get("/v1/resources/:id", handler.Get)
return nil
}
// Handler constructor with validation
func NewHandler(deps ...interface{}) (*Handler, error) {
if dep == nil {
return nil, ErrNilDependency
}
return &Handler{...}, nil
}
Check Against Ring Standards For:
- (HARD GATE) Hexagonal structure:
internal/{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 Ring conventions
- All routes use protected() wrapper (no public endpoints without explicit exemption)
- Clear separation: routes.go vs handlers.go per Ring directory structure
Severity Ratings:
- CRITICAL: Unprotected routes (missing auth middleware)
- CRITICAL: HARD GATE violation — project does not follow hexagonal architecture per Ring 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}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Bootstrap" section from bootstrap.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/main.go`, `**/init.go`, `**/bootstrap/*.go`
- Keywords: `InitServers`, `startupSucceeded`, `defer`, `cleanup`, `graceful`
- Standards-specific: `NewServiceBootstrap`, `staged initialization`
**Reference Implementation (GOOD):**
```go
// Staged initialization with cleanup
func InitServers(opts *Options) (*Service, error) {
startupSucceeded := false
defer func() {
if !startupSucceeded {
cleanupConnections(...) // Only cleanup on failure
}
}()
// 1. Load config
cfg, err := loadConfig()
if err != nil {
return nil, fmt.Errorf("config: %w", err)
}
// 2. Initialize logger
logger := initLogger(cfg)
// 3. Initialize telemetry
telemetry := initTelemetry(cfg, logger)
// 4. Connect infrastructure (DB, Redis, MQ)
db, err := connectDB(cfg)
if err != nil {
return nil, fmt.Errorf("database: %w", err)
}
// 5. Initialize modules in dependency order
...
startupSucceeded = true
return &Service{...}, nil
}
Check Against Ring 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 Ring bootstrap pattern
- Error propagation (not just logging and continuing)
- Production vs development mode handling
Severity Ratings:
- CRITICAL: No graceful shutdown (HARD GATE violation per Ring standards)
- CRITICAL: HARD GATE violation — bootstrap does not follow Ring 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: `**/runtime/*.go`, `**/recover*.go`, `**/*.go`
- Keywords: `RecoverAndLog`, `RecoverWithPolicy`, `InitPanicMetrics`, `SetProductionMode`
- Also search: `panic(`, `recover()` (manual usage)
**Reference Implementation (GOOD):**
```go
// Bootstrap initialization
runtime.InitPanicMetrics(telemetry.MetricsFactory)
if cfg.EnvName == "production" {
runtime.SetProductionMode(true)
}
// In HTTP handlers
defer runtime.RecoverAndLogWithContext(ctx, logger, "module", "handler_name")
// In worker goroutines
defer runtime.RecoverWithPolicyAndContext(ctx, logger, "module", "worker", runtime.CrashProcess)
// In background jobs (should retry, not crash)
defer runtime.RecoverWithPolicyAndContext(ctx, logger, "module", "job", runtime.LogAndContinue)
Check For:
- pkg/runtime initialized at startup
- Production mode set based on environment
- All goroutines have panic recovery
- Appropriate recovery policies per context
- Panic metrics enabled for alerting
- No raw recover() without pkg/runtime
Severity Ratings:
- CRITICAL: Goroutines without panic recovery
- HIGH: Missing production mode setting
- HIGH: Raw recover() without proper handling
- MEDIUM: Inconsistent recovery policies
- LOW: Missing panic 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}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Access Manager Integration" section from security.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/auth/*.go`, `**/middleware*.go`, `**/routes.go`
- Keywords: `Authorize`, `protected`, `JWT`, `tenant`, `ExtractToken`
- Standards-specific: `AccessManager`, `lib-auth`, `ProtectedGroup`
**Reference Implementation (GOOD):**
```go
// Protected route group
protected := func(resource, action string) fiber.Router {
return auth.ProtectedGroup(api, authClient, tenantExtractor, resource, action)
}
// All routes use protected
protected("contexts", "create").Post("/v1/config/contexts", handler.Create)
// JWT validation
func parseTokenClaims(tokenString string, secret []byte) (jwt.MapClaims, error) {
parser := jwt.NewParser(jwt.WithValidMethods(validSigningMethods))
token, err := parser.ParseWithClaims(...)
if err != nil || !token.Valid {
return nil, ErrInvalidToken
}
// Check expiration
if exp, ok := claims["exp"].(float64); ok {
if time.Now().Unix() > int64(exp) {
return nil, ErrTokenExpired
}
}
return claims, nil
}
Check Against Ring Standards For:
- (HARD GATE) All routes protected via Access Manager integration per security.md
- (HARD GATE) lib-auth used for JWT validation (not custom JWT parsing)
- Resource/action authorization granularity per Ring 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 Ring standards)
- CRITICAL: JWT parsed but not validated
- CRITICAL: HARD GATE violation — not using lib-auth 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*.go`, `**/handlers.go`, `**/context.go`
- Keywords: `VerifyOwnership`, `tenantID`, `contextID`, `ParseAndVerify`
**Reference Implementation (GOOD):**
```go
// 4-layer IDOR protection
func ParseAndVerifyContextParam(fiberCtx *fiber.Ctx, verifier ContextOwnershipVerifier) (uuid.UUID, uuid.UUID, error) {
// 1. UUID format validation
contextID, err := uuid.Parse(fiberCtx.Params("contextId"))
if err != nil {
return uuid.Nil, uuid.Nil, ErrInvalidID
}
// 2. Extract tenant from auth context (cannot be spoofed)
tenantID := auth.GetTenantID(ctx)
// 3. Database query filtered by tenant
// 4. Post-query ownership verification
if err := verifier.VerifyOwnership(ctx, tenantID, contextID); err != nil {
return uuid.Nil, uuid.Nil, err
}
return contextID, tenantID, nil
}
// Verifier implementation
func (v *verifier) VerifyOwnership(ctx context.Context, tenantID, resourceID uuid.UUID) error {
resource, err := v.query.Get(ctx, tenantID, resourceID) // Query WITH tenant filter
if errors.Is(err, sql.ErrNoRows) {
return ErrNotFound
}
if resource.TenantID != tenantID { // Double-check ownership
return ErrNotOwned
}
return nil
}
Reference Implementation (BAD):
// BAD: No ownership verification
func GetResource(c *fiber.Ctx) error {
id := c.Params("id")
resource, err := repo.FindByID(ctx, id) // No tenant filter!
return c.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: `**/*.postgresql.go`, `**/repository/*.go`, `**/*_repo.go`
- Keywords: `ExecContext`, `QueryContext`, `Exec(`, `Query(`, `$1`, `$2`
- Also search for: String concatenation in SQL: `"SELECT.*" +`, `fmt.Sprintf.*SELECT`
**Reference Implementation (GOOD):**
```go
// Parameterized queries
query := `INSERT INTO resources (id, name, tenant_id) VALUES ($1, $2, $3)`
_, err = tx.ExecContext(ctx, query, id, name, tenantID)
// SQL identifier escaping for dynamic schemas
func QuoteIdentifier(identifier string) string {
return "\"" + strings.ReplaceAll(identifier, "\"", "\"\"") + "\""
}
schemaQuery := "SET LOCAL search_path TO " + QuoteIdentifier(tenantID)
// Query builder (Squirrel)
query := sq.Select("*").From("resources").Where(sq.Eq{"tenant_id": tenantID})
Reference Implementation (BAD):
// BAD: String concatenation
query := "SELECT * FROM users WHERE name = '" + name + "'"
// BAD: fmt.Sprintf for values
query := fmt.Sprintf("SELECT * FROM users WHERE id = '%s'", id)
// BAD: Unescaped identifier
query := "SET search_path TO " + tenantID // SQL injection via tenant
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: fmt.Sprintf 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}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Frameworks & Libraries" section from core.md — specifically go-playground/validator/v10 reference}
---END STANDARDS---
**Search Patterns:**
- Files: `**/dto.go`, `**/handlers.go`, `**/value_objects/*.go`
- Keywords: `validate:`, `BodyParser`, `IsValid()`, `Parse`, `required`
- Standards-specific: `validator/v10`, `go-playground/validator`
**Reference Implementation (GOOD):**
```go
// DTO with validation tags
type CreateRequest struct {
Name string `json:"name" validate:"required,min=1,max=255"`
Type string `json:"type" validate:"required,oneof=TYPE_A TYPE_B"`
Amount int `json:"amount" validate:"gte=0,lte=1000000"`
}
// Handler with body parsing error handling
func (h *Handler) Create(c *fiber.Ctx) error {
var payload CreateRequest
if err := c.BodyParser(&payload); err != nil {
return badRequest(c, span, logger, "invalid request body", err)
}
// Validate struct
if err := h.validator.Struct(payload); err != nil {
return badRequest(c, span, logger, "validation failed", err)
}
...
}
// Value object with domain validation
func (vo ValueObject) IsValid() bool {
if vo.value == "" || len(vo.value) > maxLength {
return false
}
return validPattern.MatchString(vo.value)
}
Reference Implementation (BAD):
// BAD: No validation tags
type Request struct {
Name string `json:"name"` // No validation!
}
// BAD: Ignoring body parse error
payload := Request{}
c.BodyParser(&payload) // Error ignored!
// BAD: No bounds checking
amount := c.QueryInt("amount") // Could be negative or huge
Check Against Ring Standards For:
- (HARD GATE) go-playground/validator/v10 used for struct validation per Ring core.md
- (HARD GATE) All DTOs have validate: tags on required fields
- BodyParser errors are handled (not ignored)
- Query/path params validated before use
- Numeric bounds enforced (min/max)
- String length limits enforced
- Enum values constrained (oneof=)
- Value objects have IsValid() methods
- File upload size/type validation
Severity Ratings:
- CRITICAL: BodyParser errors ignored
- CRITICAL: HARD GATE violation — not using go-playground/validator/v10 per Ring 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}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Observability" section from bootstrap.md and "OpenTelemetry with lib-commons" section from sre.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/observability*.go`, `**/telemetry*.go`, `**/handlers.go`
- Keywords: `NewTrackingFromContext`, `tracer.Start`, `span`, `logger`, `metrics`
- Standards-specific: `libCommons.NewTrackingFromContext`, `otel`, `OpenTelemetry`
**Reference Implementation (GOOD):**
```go
// Handler with proper telemetry
func (h *Handler) DoSomething(c *fiber.Ctx) error {
ctx := c.UserContext()
logger, tracer, headerID, _ := libCommons.NewTrackingFromContext(ctx)
ctx, span := tracer.Start(ctx, "handler.DoSomething")
defer span.End()
span.SetAttributes(attribute.String("request_id", headerID))
// On error
span.RecordError(err)
span.SetStatus(codes.Error, err.Error())
logger.Errorf("operation failed: %v", err)
return nil
}
Reference Implementation (GOOD — Trace Propagation & Sampling):
// W3C Trace Context propagation in outgoing HTTP requests
import (
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/propagation"
)
func (c *HTTPClient) Do(ctx context.Context, req *http.Request) (*http.Response, error) {
// Inject trace context into outgoing request headers
otel.GetTextMapPropagator().Inject(ctx, propagation.HeaderCarrier(req.Header))
return c.client.Do(req.WithContext(ctx))
}
// Baggage propagation for business context
import "go.opentelemetry.io/otel/baggage"
func InjectBusinessContext(ctx context.Context, tenantID, userID string) context.Context {
tenantMember, _ := baggage.NewMember("tenantId", tenantID)
userMember, _ := baggage.NewMember("userId", userID)
bag, _ := baggage.New(tenantMember, userMember)
return baggage.ContextWithBaggage(ctx, bag)
}
// Span linking for async flows — consumer side
func (c *Consumer) Handle(msg *Message) error {
producerCtx := otel.GetTextMapPropagator().Extract(context.Background(), propagation.MapCarrier(msg.Headers))
producerSpanCtx := trace.SpanContextFromContext(producerCtx)
ctx, span := c.tracer.Start(context.Background(), "consume."+msg.Type,
trace.WithLinks(trace.Link{SpanContext: producerSpanCtx}),
)
defer span.End()
return c.process(ctx, msg)
}
// Trace sampling configuration
func initTracer(env string) *trace.TracerProvider {
var sampler trace.Sampler
switch env {
case "production":
sampler = trace.ParentBased(trace.TraceIDRatioBased(0.1))
case "staging":
sampler = trace.ParentBased(trace.TraceIDRatioBased(0.5))
default:
sampler = trace.AlwaysSample()
}
return trace.NewTracerProvider(trace.WithSampler(sampler))
}
// Custom span attributes for business context
func (h *Handler) CreateOrder(c *fiber.Ctx) error {
ctx, span := h.tracer.Start(c.UserContext(), "handler.CreateOrder")
defer span.End()
span.SetAttributes(
attribute.String("order.id", order.ID.String()),
attribute.String("tenant.id", tenantID.String()),
attribute.Float64("order.amount", order.TotalAmount),
)
// ...
}
Reference Implementation (BAD — Trace Propagation):
// BAD: Outgoing HTTP request without trace context propagation
func (c *HTTPClient) Do(ctx context.Context, req *http.Request) (*http.Response, error) {
return c.client.Do(req) // No propagation — downstream sees a new disconnected trace
}
// BAD: Async message consumer starts fresh trace without linking to producer
func (c *Consumer) Handle(msg *Message) error {
ctx, span := c.tracer.Start(context.Background(), "consume.event")
defer span.End()
return c.process(ctx, msg) // No link to producer span — trace is disconnected
}
// BAD: No sampling configuration (AlwaysSample in production)
func initTracer() *trace.TracerProvider {
return trace.NewTracerProvider() // Default: AlwaysSample — 100% of traces stored
}
Check Against Ring Standards For:
- (HARD GATE) lib-commons NewTrackingFromContext used for telemetry initialization per Ring 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 fmt.Println)
- 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 Ring standards)
- CRITICAL: HARD GATE violation — not using lib-commons 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}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Health Checks" section from sre.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/fiber_server.go`, `**/health*.go`, `**/routes.go`
- Keywords: `/health`, `/ready`, `/live`, `healthHandler`, `readinessHandler`
- Standards-specific: `liveness`, `readiness`, `degraded`
**Reference Implementation (GOOD):**
```go
// Liveness probe - always returns healthy if process is running
func healthHandler(c *fiber.Ctx) error {
return c.SendString("healthy")
}
// Readiness probe - checks all dependencies
func readinessHandler(deps *HealthDependencies) fiber.Handler {
return func(c *fiber.Ctx) error {
checks := fiber.Map{}
status := fiber.StatusOK
// Required dependency - fails readiness if down
if err := deps.DB.Ping(c.Context()); err != nil {
checks["database"] = "unhealthy"
status = fiber.StatusServiceUnavailable
} else {
checks["database"] = "healthy"
}
// Optional dependency - reports degraded but doesn't fail
if deps.Redis != nil {
if err := deps.Redis.Ping(c.Context()).Err(); err != nil {
checks["redis"] = "degraded"
} else {
checks["redis"] = "healthy"
}
}
return c.Status(status).JSON(fiber.Map{
"status": statusString(status),
"checks": checks,
})
}
}
// Register without auth middleware
app.Get("/health", healthHandler)
app.Get("/ready", readinessHandler(deps))
Check Against Ring 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 Ring 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 Ring 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}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Configuration" section from core.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/config.go`, `**/bootstrap/*.go`, `**/.env*`
- Keywords: `env:`, `envDefault:`, `Validate()`, `LoadConfig`, `production`
- Standards-specific: `envconfig`, `caarlos0/env`
**Reference Implementation (GOOD):**
```go
// Config with validation
type Config struct {
EnvName string `env:"ENV_NAME" envDefault:"development"`
DBPassword string `env:"POSTGRES_PASSWORD"`
AuthEnabled bool `env:"AUTH_ENABLED" envDefault:"false"`
}
// Production validation
func (c *Config) Validate() error {
if c.EnvName == "production" {
// Require auth in production
if !c.AuthEnabled {
return errors.New("AUTH_ENABLED must be true in production")
}
// Require DB password in production
if c.DBPassword == "" {
return errors.New("POSTGRES_PASSWORD required in production")
}
// Require TLS for databases
if c.PostgresSSLMode == "disable" {
return errors.New("POSTGRES_SSLMODE cannot be disable in production")
}
}
return nil
}
// Load with validation
func LoadConfig() (*Config, error) {
cfg := &Config{}
if err := envconfig.Process("", cfg); err != nil {
return nil, fmt.Errorf("load env: %w", err)
}
if err := cfg.Validate(); err != nil {
return nil, fmt.Errorf("validate: %w", err)
}
return cfg, nil
}
Check Against Ring Standards For:
- (HARD GATE) All config loaded from env vars (not hardcoded) per Ring 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 Ring 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}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Core Dependency: lib-commons" section from core.md — specifically connection packages}
---END STANDARDS---
**Search Patterns:**
- Files: `**/config.go`, `**/database*.go`, `**/redis*.go`, `**/postgres*.go`
- Keywords: `MaxOpenConns`, `MaxIdleConns`, `PoolSize`, `Timeout`, `SetConnMaxLifetime`
- Standards-specific: `lib-commons`, `mpostgres`, `mredis`, `mmongo`
**Reference Implementation (GOOD):**
```go
// Database pool configuration
type DBConfig struct {
MaxOpenConnections int `env:"POSTGRES_MAX_OPEN_CONNS" envDefault:"25"`
MaxIdleConnections int `env:"POSTGRES_MAX_IDLE_CONNS" envDefault:"5"`
ConnMaxLifetime int `env:"POSTGRES_CONN_MAX_LIFETIME_MINS" envDefault:"30"`
}
// Apply pool settings
func ConfigurePool(db *sql.DB, cfg *DBConfig) {
db.SetMaxOpenConns(cfg.MaxOpenConnections)
db.SetMaxIdleConns(cfg.MaxIdleConnections)
db.SetConnMaxLifetime(time.Duration(cfg.ConnMaxLifetime) * time.Minute)
}
// Redis pool configuration
type RedisConfig struct {
PoolSize int `env:"REDIS_POOL_SIZE" envDefault:"10"`
MinIdleConns int `env:"REDIS_MIN_IDLE_CONNS" envDefault:"2"`
ReadTimeoutMs int `env:"REDIS_READ_TIMEOUT_MS" envDefault:"3000"`
WriteTimeoutMs int `env:"REDIS_WRITE_TIMEOUT_MS" envDefault:"3000"`
DialTimeoutMs int `env:"REDIS_DIAL_TIMEOUT_MS" envDefault:"5000"`
}
// Primary + Replica support
type DatabaseConnections struct {
Primary *sql.DB
Replica *sql.DB // Falls back to primary if not configured
}
Check Against Ring Standards For:
- (HARD GATE) lib-commons connection packages used (mpostgres, mredis, mmongo) 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 lib-commons connection packages
- 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}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Logging" section from quality.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/*.go`
- Keywords: `logger.`, `log.`, `Errorf`, `Infof`, `WithFields`, `password`, `token`, `secret`
- Also search: `fmt.Print`, `fmt.Println` (should not be used for logging)
- Standards-specific: `zap`, `zerolog`, structured logging library references
**Reference Implementation (GOOD):**
```go
// Structured logging with context
logger, tracer, requestID, _ := libCommons.NewTrackingFromContext(ctx)
logger.WithFields(
"request_id", requestID,
"user_id", userID,
"action", "create_resource",
).Info("resource created")
// Production-safe error logging
if isProduction {
// Don't include error details that might leak PII
logger.Errorf("operation failed: status=%d path=%s", code, path)
} else {
// Development can have full details
logger.Errorf("operation failed: error=%v", err)
}
// Config DSN without password
func (c *Config) DSN() string {
// Returns connection string without logging password
return fmt.Sprintf("host=%s port=%d user=%s dbname=%s",
c.Host, c.Port, c.User, c.DBName)
}
Reference Implementation (BAD):
// BAD: fmt.Println for logging
fmt.Println("User logged in:", userEmail)
// BAD: Logging sensitive data
logger.Infof("Login attempt: email=%s password=%s", email, password)
// BAD: Logging full request body (might contain PII)
logger.Debugf("Request body: %+v", requestBody)
// BAD: Not using structured logging
log.Printf("Error: %v", err)
Check Against Ring Standards For:
- (HARD GATE) Structured logging used (not fmt.Print or log.Printf) 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: fmt.Print used instead of logger (HARD GATE violation per Ring 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}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: Full module content from idempotency.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/idempotency*.go`, `**/value_objects/*.go`, `**/redis/*.go`
- Keywords: `IdempotencyKey`, `TryAcquire`, `MarkComplete`, `SetNX`, `idempotent`
- Standards-specific: `IdempotencyRepository`, `idempotency middleware`
**Reference Implementation (GOOD):**
```go
// Idempotency key value object
type IdempotencyKey string
const (
idempotencyKeyMaxLength = 128
idempotencyKeyPattern = `^[A-Za-z0-9:_-]+$`
)
func (key IdempotencyKey) IsValid() bool {
s := string(key)
if s == "" || len(s) > idempotencyKeyMaxLength {
return false
}
return regexp.MustCompile(idempotencyKeyPattern).MatchString(s)
}
// Redis-backed idempotency
type IdempotencyRepository struct {
client *redis.Client
ttl time.Duration // e.g., 7 days
}
func (r *IdempotencyRepository) TryAcquire(ctx context.Context, key IdempotencyKey) (bool, error) {
// SetNX is atomic - only first caller wins
result, err := r.client.SetNX(ctx, r.keyName(key), "acquired", r.ttl).Result()
return result, err
}
func (r *IdempotencyRepository) MarkComplete(ctx context.Context, key IdempotencyKey) error {
return r.client.Set(ctx, r.keyName(key), "complete", r.ttl).Err()
}
// Usage in handler
func (h *Handler) ProcessCallback(c *fiber.Ctx) error {
key := extractIdempotencyKey(c)
acquired, err := h.idempotency.TryAcquire(ctx, key)
if err != nil {
return internalError(c, "idempotency check failed", err)
}
if !acquired {
return c.Status(200).JSON(fiber.Map{"status": "already_processed"})
}
// Process...
h.idempotency.MarkComplete(ctx, key)
return c.JSON(result)
}
Check Against Ring 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 Ring 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 Ring 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}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: Swaggo/OpenAPI subsection from "Pagination Patterns" in api-patterns.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/main.go`, `**/handlers.go`, `**/dto.go`, `**/swagger/*`
- Keywords: `@Summary`, `@Router`, `@Param`, `@Success`, `@Failure`, `@Security`
- Standards-specific: `swaggo`, `swag init`, `docs/swagger.json`
**Reference Implementation (GOOD):**
```go
// Main entry with API metadata
// @title My API
// @version v1.0.0
// @description API description
// @BasePath /
// @securityDefinitions.apikey BearerAuth
// @in header
// @name Authorization
// Handler with full documentation
// @Summary Create a resource
// @Description Creates a new resource with the given parameters
// @Tags resources
// @Accept json
// @Produce json
// @Param request body CreateRequest true "Resource to create"
// @Success 201 {object} ResourceResponse
// @Failure 400 {object} ErrorResponse "Invalid input"
// @Failure 401 {object} ErrorResponse "Unauthorized"
// @Failure 403 {object} ErrorResponse "Forbidden"
// @Failure 500 {object} ErrorResponse "Internal error"
// @Security BearerAuth
// @Router /v1/resources [post]
func (h *Handler) Create(c *fiber.Ctx) error { ... }
// DTO with documentation
type CreateRequest struct {
Name string `json:"name" example:"my-resource" validate:"required"`
Type string `json:"type" example:"TYPE_A" enums:"TYPE_A,TYPE_B"`
Amount int `json:"amount" example:"100" minimum:"0" maximum:"1000000"`
}
Check Against Ring Standards For:
- (HARD GATE) Swaggo annotations present per Ring api-patterns.md
- API title, version, description in main.go
- 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 Ring 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"`
- `panic("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}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Testing" section from quality.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/*_test.go`, `**/mocks/**/*.go`, `tests/**/*.go`
- Keywords: `func Test`, `t.Run`, `mock.Mock`, `assert.`, `require.`
- Standards-specific: `mockgen`, `testify`, `testcontainers`
**Reference Implementation (GOOD):**
```go
// Co-located test file
// file: handler_test.go (next to handler.go)
func TestHandler_Create(t *testing.T) {
// Arrange
ctrl := gomock.NewController(t)
defer ctrl.Finish()
mockRepo := mocks.NewMockRepository(ctrl)
mockRepo.EXPECT().Save(gomock.Any(), gomock.Any()).Return(nil)
handler := NewHandler(mockRepo)
// Act
result, err := handler.Create(ctx, input)
// Assert
require.NoError(t, err)
assert.Equal(t, expected, result)
}
// Table-driven tests for multiple cases
func TestValidation(t *testing.T) {
tests := []struct {
name string
input string
wantErr bool
}{
{"valid input", "test", false},
{"empty input", "", true},
{"too long", strings.Repeat("a", 300), true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
err := Validate(tt.input)
if tt.wantErr {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
// Integration test with testcontainers
func TestIntegration_CreateResource(t *testing.T) {
if testing.Short() {
t.Skip("skipping integration test")
}
// Setup container...
}
Check Against Ring Standards For:
- (HARD GATE) Test files co-located with source (*_test.go) per quality.md testing section
- (HARD GATE) Mocks generated via mockgen (not hand-written) per Ring standards
- (HARD GATE) Assertions use testify (assert/require) per Ring standards
- Table-driven tests for multiple cases
- Integration tests in separate directory or with build tags
- Test helpers/fixtures organized
- Parallel tests where appropriate (t.Parallel())
- Test cleanup with t.Cleanup() or defer
Severity Ratings:
- HIGH: Critical paths without tests (HARD GATE violation per Ring standards)
- HIGH: Hand-written mocks (should use mockgen per Ring 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: mockgen / 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}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Frameworks & Libraries" section from core.md — specifically the version table}
---END STANDARDS---
**Search Patterns:**
- Files: `go.mod`, `go.sum`, `**/vendor/**`
- Commands: Run `go list -m -u all` mentally based on go.mod
- Standards-specific: Check for required Ring dependencies in go.mod
**Reference Implementation (GOOD):**
```go
// go.mod with pinned versions
module github.com/company/project
go 1.24
require (
github.com/gofiber/fiber/v2 v2.52.10 // Pinned, not "latest"
github.com/lib/pq v1.10.9
go.opentelemetry.io/otel v1.39.0
)
// Indirect deps managed automatically
require (
github.com/valyala/fasthttp v1.52.0 // indirect
)
Reference Implementation (BAD):
// BAD: Using replace for production
replace github.com/some/lib => ../local-lib
// BAD: Unpinned versions
require github.com/some/lib latest
// BAD: Very old versions with known CVEs
require github.com/dgrijalva/jwt-go v3.2.0 // Has CVE, use golang-jwt
Check Against Ring Standards For:
- (HARD GATE) Required Ring framework dependencies present in go.mod per core.md version table
- All dependencies pinned (no "latest")
- No local replace directives in production
- Known vulnerable packages identified
- Unused dependencies (not imported anywhere)
- Major version mismatches
- Deprecated packages (e.g., dgrijalva/jwt-go -> golang-jwt)
- go.sum exists and is committed
- Framework versions meet Ring minimum requirements (Go 1.24+, Fiber v2, etc.)
Known Vulnerable Packages to Flag:
- github.com/dgrijalva/jwt-go (use golang-jwt/jwt)
- github.com/pkg/sftp < v1.13.5
- golang.org/x/crypto < recent
- golang.org/x/net < recent
Severity Ratings:
- CRITICAL: Known CVE in dependency
- CRITICAL: HARD GATE violation — required Ring framework dependency missing from go.mod
- HIGH: Local replace directive
- HIGH: Deprecated package with security issues
- MEDIUM: Significantly outdated dependencies
- MEDIUM: Framework versions below Ring 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: `**/*.go`
- Keywords: `for.*range`, `append(`, `make(`, `sync.Pool`, `SELECT *`, `N+1`
**Reference Implementation (GOOD):**
```go
// Pre-allocate slices when size is known
items := make([]Item, 0, len(input)) // Capacity hint
// Use sync.Pool for frequently allocated objects
var bufferPool = sync.Pool{
New: func() interface{} {
return new(bytes.Buffer)
},
}
// Batch database operations
func (r *Repo) CreateBatch(ctx context.Context, items []Item) error {
return r.db.WithContext(ctx).CreateInBatches(items, 100).Error
}
// Select only needed columns
func (r *Repo) List(ctx context.Context) ([]Item, error) {
return r.db.WithContext(ctx).
Select("id", "name", "status"). // Not SELECT *
Find(&items).Error
}
// Avoid N+1 with preloading
func (r *Repo) GetWithRelations(ctx context.Context, id uuid.UUID) (*Item, error) {
return r.db.WithContext(ctx).
Preload("Children").
First(&item, id).Error
}
Reference Implementation (BAD):
// BAD: SELECT * fetches unnecessary data
db.Find(&items)
// BAD: N+1 query pattern
for _, item := range items {
db.Where("parent_id = ?", item.ID).Find(&children) // Query per item!
}
// BAD: Growing slice without capacity
var items []Item
for _, input := range inputs {
items = append(items, transform(input)) // Reallocates repeatedly
}
// BAD: Large allocations in hot path without pooling
func handleRequest() {
buf := make([]byte, 1<<20) // 1MB allocation per request
}
Check For:
- SELECT * avoided (explicit column selection)
- N+1 queries prevented (use Preload/joins)
- Slice pre-allocation when size known
- sync.Pool 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 sync.Pool 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}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Concurrency Patterns" section from architecture.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/*.go`
- Keywords: `go func`, `sync.Mutex`, `sync.RWMutex`, `chan`, `select {`, `sync.WaitGroup`
- Standards-specific: `errgroup`, `semaphore`, `worker pool`
**Reference Implementation (GOOD):**
```go
// Mutex protecting shared state
type Cache struct {
mu sync.RWMutex
items map[string]Item
}
func (c *Cache) Get(key string) (Item, bool) {
c.mu.RLock()
defer c.mu.RUnlock()
item, ok := c.items[key]
return item, ok
}
func (c *Cache) Set(key string, item Item) {
c.mu.Lock()
defer c.mu.Unlock()
c.items[key] = item
}
// WaitGroup for goroutine coordination
func processAll(items []Item) error {
var wg sync.WaitGroup
errCh := make(chan error, len(items))
for _, item := range items {
wg.Add(1)
go func(i Item) {
defer wg.Done()
if err := process(i); err != nil {
errCh <- err
}
}(item) // Pass item to avoid closure capture
}
wg.Wait()
close(errCh)
// Collect errors
for err := range errCh {
return err
}
return nil
}
// Context for cancellation
func worker(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
case item := <-workCh:
process(item)
}
}
}
Reference Implementation (BAD):
// BAD: Race condition - map access without lock
var cache = make(map[string]Item)
func Get(key string) Item { return cache[key] } // Concurrent read/write!
// BAD: Goroutine leak - no way to stop
go func() {
for {
process() // Runs forever, no context check
}
}()
// BAD: Closure captures loop variable
for _, item := range items {
go func() {
process(item) // All goroutines see last item!
}()
}
// BAD: Unbounded goroutine spawning
for _, item := range millionItems {
go process(item) // 1M goroutines!
}
Check Against Ring 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 Ring patterns
- Channels closed by sender
- Select with default for non-blocking
- No goroutine leaks (all paths exit)
Severity Ratings:
- CRITICAL: Race condition on shared map (HARD GATE violation per Ring standards)
- CRITICAL: Goroutine leak (no exit path)
- HIGH: Loop variable capture bug
- HIGH: Unbounded goroutine spawning
- 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}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Core Dependency: lib-commons" section from core.md — database migration patterns}
---END STANDARDS---
**Search Patterns:**
- Files: `migrations/*.sql`, `migrations/*.go`
- Keywords: `DROP`, `ALTER`, `RENAME`, `NOT NULL`, `CREATE INDEX`
- Standards-specific: `golang-migrate`, `lib-commons migration`
**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):
-- BAD: Adding NOT NULL without default (locks table, fails if data exists)
ALTER TABLE users ADD COLUMN role VARCHAR(50) NOT NULL;
-- BAD: Non-concurrent index (locks table)
CREATE INDEX idx_users_email ON users(email);
-- BAD: Destructive without IF EXISTS
DROP TABLE users;
DROP COLUMN email;
-- BAD: Renaming column (breaks application)
ALTER TABLE users RENAME COLUMN email TO user_email;
Reference Implementation (GOOD — Constraints & Data Migrations):
-- GOOD: NOT NULL ADD COLUMN with DEFAULT (no table rewrite lock)
ALTER TABLE orders ADD COLUMN IF NOT EXISTS status VARCHAR(20) NOT NULL DEFAULT 'pending';
-- GOOD: CHECK constraint for domain validation at DB level
ALTER TABLE orders ADD CONSTRAINT chk_order_status
CHECK (status IN ('pending', 'processing', 'completed', 'cancelled', 'refunded'));
-- GOOD: Foreign key with explicit cascading behavior and matching types
ALTER TABLE order_items ADD CONSTRAINT fk_order_items_order
FOREIGN KEY (order_id) REFERENCES orders(id)
ON DELETE CASCADE
ON UPDATE CASCADE;
-- GOOD: Enum type at database level
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';
-- GOOD: Separate data migration file (000005_backfill_status.up.sql)
-- This is a DATA migration, separate from schema changes
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;
Reference Implementation (BAD — Constraints & Data Migrations):
-- BAD: NOT NULL ADD COLUMN without DEFAULT (full table rewrite — locks table)
ALTER TABLE orders ADD COLUMN priority INTEGER NOT NULL;
-- On a table with 10M rows, this locks the table for minutes
-- BAD: No CHECK constraint — application validates but DB accepts anything
ALTER TABLE orders ADD COLUMN status VARCHAR(20);
-- Application code checks status in ('pending', 'completed') but DB allows 'banana'
-- BAD: Foreign key with mismatched types
ALTER TABLE order_items ADD CONSTRAINT fk_order
FOREIGN KEY (order_id) REFERENCES orders(id);
-- BAD: Foreign key without cascading behavior
ALTER TABLE order_items ADD CONSTRAINT fk_order
FOREIGN KEY (order_id) REFERENCES orders(id);
-- Default NO ACTION — DELETE FROM orders fails if order_items exist (unexpected 500s)
-- BAD: Data migration mixed with schema migration in same file
ALTER TABLE orders ADD COLUMN status VARCHAR(20) NOT NULL DEFAULT 'pending';
UPDATE orders SET status = 'completed' WHERE completed_at IS NOT NULL;
CREATE INDEX CONCURRENTLY idx_orders_status ON orders(status);
-- CONCURRENTLY cannot run inside a transaction — this file cannot execute atomically
Check Against Ring Standards For:
- (HARD GATE) All migrations have up AND down files per Ring migration patterns
- (HARD GATE) CREATE INDEX uses CONCURRENTLY
- New NOT NULL columns have DEFAULT
- DROP/ALTER use IF EXISTS
- No column renames (add new, migrate data, drop old)
- No destructive operations in up migrations
- Migrations are additive (safe rollback)
- Sequential numbering (no gaps)
- Migration tool matches Ring standard (golang-migrate or lib-commons)
- NOT NULL columns MUST have DEFAULT values in ADD COLUMN migrations — adding a NOT NULL column without DEFAULT requires a full table rewrite lock on existing data, causing downtime on large tables
- CHECK constraints for domain-specific validation at database level — values validated only in application code MUST also have database-level CHECK constraints as a safety net
- Foreign key consistency — foreign keys MUST have matching column types and MUST define explicit cascading behavior (ON DELETE/ON UPDATE) rather than relying on database defaults
- Enum validation at database level — domain enums MUST be enforced via CHECK constraint or PostgreSQL enum type, not just application-level validation
- Data migration scripts MUST be separate from schema migrations — mixing data transformations with schema changes in the same migration file makes rollback unsafe
Severity Ratings:
- CRITICAL: NOT NULL without default (HARD GATE violation per Ring standards)
- CRITICAL: Missing down migration (HARD GATE violation)
- CRITICAL: NOT NULL ADD COLUMN without DEFAULT (locks entire table for rewrite on large datasets — causes production downtime)
- HIGH: Non-concurrent index creation
- HIGH: Column rename (breaking change)
- HIGH: No CHECK constraints for domain values validated only in application code (database accepts any value — data corruption if application validation is bypassed)
- MEDIUM: DROP without IF EXISTS
- MEDIUM: Foreign keys without explicit cascading behavior (relies on database default
NO ACTION— may cause unexpected constraint violations on DELETE) - MEDIUM: Enum values validated only in application code (database allows invalid values — data integrity depends entirely on application correctness)
- LOW: Migration naming inconsistency
- LOW: Data migrations mixed with schema migrations in same file (harder to rollback, debug, and review independently)
Output Format:
## Migration Safety Audit Findings
### Summary
- Total migrations: X
- Up migrations: Y
- Down migrations: Z
- Potentially unsafe: N
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 24: Container Security Auditor
```prompt
Audit container security and Dockerfile best practices for production readiness.
**Detected Stack:** {DETECTED_STACK}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Containers" section from devops.md}
---END STANDARDS---
**Search Patterns:**
- Files: `Dockerfile*`, `docker-compose*.yml`, `Makefile`
- Keywords: `FROM`, `USER`, `COPY`, `ADD`, `HEALTHCHECK`
- Standards-specific: `distroless`, `nonroot`, `multi-stage`
**Reference Implementation (GOOD):**
```dockerfile
# Multi-stage build
FROM golang:1.24-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build -o /main cmd/app/main.go
# Distroless or minimal runtime image
FROM gcr.io/distroless/static-debian12:nonroot
WORKDIR /
COPY --from=builder /main .
# Non-root user
USER nonroot:nonroot
# Healthcheck defined
HEALTHCHECK --interval=30s --timeout=3s CMD ["/main", "-health"]
ENTRYPOINT ["/main"]
Check Against Ring Standards For:
- (HARD GATE) Multi-stage builds (builder vs runtime) per devops.md containers section
- (HARD GATE) Non-root user execution (
USER nonrootor numeric ID) per Ring standards - Minimal/Distroless runtime images per Ring container patterns
- Pinned base image versions (not
latest) COPYused instead ofADD(unless extracting tar)- .dockerignore file exists and excludes secrets/git
- Sensitive args not passed as build-args (secrets)
Severity Ratings:
- CRITICAL: Running as root in production image (HARD GATE violation per Ring standards)
- CRITICAL: HARD GATE violation — no multi-stage build per devops.md
- HIGH: Secrets in Dockerfile/history
- MEDIUM: Using
latesttag - LOW: Missing HEALTHCHECK in Dockerfile
Output Format:
## Container Security Audit Findings
### Summary
- Multi-stage build: Yes/No
- Non-root user: Yes/No
- Base image pinned: Yes/No
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 25: HTTP Hardening Auditor
```prompt
Audit HTTP security headers and hardening configuration for production readiness.
**Detected Stack:** {DETECTED_STACK}
**Search Patterns:**
- Files: `**/fiber_server.go`, `**/middleware*.go`
- Keywords: `Helmet`, `CSRF`, `Secure`, `HttpOnly`, `SameSite`
**Reference Implementation (GOOD):**
```go
// Security headers
app.Use(helmet.New(helmet.Config{
XSSProtection: "1; mode=block",
ContentTypeNosniff: "nosniff",
XFrameOptions: "DENY",
HSTSMaxAge: 31536000,
HSTSExcludeSubdomains: false,
HSTSPreloadEnabled: true,
ContentSecurityPolicy: "default-src 'self'",
}))
Check For:
- HSTS enabled (Strict-Transport-Security)
- CSP configured (Content-Security-Policy)
- X-Frame-Options set to DENY or SAMEORIGIN
- Secure cookies (Secure, HttpOnly, SameSite=Strict/Lax)
- Server banner suppressed (Server: value removed)
Severity Ratings:
- HIGH: Missing HSTS
- MEDIUM: Missing CSP or overly permissive
- LOW: Server banner exposed
Output Format:
## HTTP Hardening Audit Findings
### Summary
- HSTS enabled: Yes/No
- CSP configured: Yes/No
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 26: CI/CD Pipeline Auditor
```prompt
Audit CI/CD pipelines for production readiness.
**Detected Stack:** {DETECTED_STACK}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: CI section from devops.md}
---END STANDARDS---
**Search Patterns:**
- Files: `.github/workflows/*.yml`, `.gitlab-ci.yml`, `Makefile`
- Keywords: `test`, `lint`, `build`, `docker`, `sign`
- Standards-specific: `golangci-lint`, `gosec`, `trivy`, `cosign`
**Reference Implementation (GOOD):**
```yaml
# .github/workflows/ci.yml
name: CI
on: [push, pull_request]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-go@v5
- run: go test -race -v ./...
- run: golangci-lint run
security:
runs-on: ubuntu-latest
steps:
- uses: securego/gosec@master
with:
args: ./...
Check Against Ring Standards For:
- (HARD GATE) CI pipeline exists (GitHub Actions/GitLab CI) per devops.md
- (HARD GATE) Tests run on PRs per Ring CI requirements
- Linting runs on PRs (golangci-lint)
- Security scanning (gosec, trivy) integrated
- Artifact signing (cosign/sigstore)
- Docker image build and push stages
- Automated deployment stages (if applicable)
Severity Ratings:
- CRITICAL: No CI pipeline (HARD GATE violation per Ring standards)
- CRITICAL: Tests not running on PR (HARD GATE violation)
- HIGH: Missing linting in CI
- MEDIUM: Missing security scanning
- LOW: Artifacts not signed
Output Format:
## CI/CD Pipeline Audit Findings
### Summary
- CI Pipeline: Active/Missing
- Tests on PR: Yes/No
- Linting: Yes/No
- Security Scans: Yes/No
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 27: Async Reliability Auditor
```prompt
Audit asynchronous processing reliability for production readiness.
**Detected Stack:** {DETECTED_STACK}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "RabbitMQ Worker Pattern" section from messaging.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/worker/*.go`, `**/queue/*.go`, `**/kafka/*.go`, `**/rabbitmq/*.go`
- Keywords: `Ack`, `Nack`, `Retry`, `DeadLetter`, `DLQ`, `ConsumerGroup`
- Standards-specific: `amqp`, `RabbitMQ`, `lib-commons messaging`
**Reference Implementation (GOOD):**
```go
// Reliable consumer with DLQ strategy
func (c *Consumer) Handle(msg *Message) error {
if err := c.process(msg); err != nil {
if msg.RetryCount >= maxRetries {
// Move to Dead Letter Queue
return c.dlq.Publish(msg)
}
// Retry with backoff
return c.RetryLater(msg, backoff(msg.RetryCount))
}
return msg.Ack()
}
Reference Implementation (GOOD — Outbox, Idempotency & Poison Messages):
// Transactional outbox pattern — event published within same DB transaction
func (s *Service) CreateOrder(ctx context.Context, order *Order) error {
return s.db.WithContext(ctx).Transaction(func(tx *gorm.DB) error {
if err := tx.Create(order).Error; err != nil {
return err
}
outboxEvent := OutboxEvent{
AggregateID: order.ID,
AggregateType: "Order",
EventType: "OrderCreated",
Payload: mustMarshal(order),
Status: "pending",
}
return tx.Create(&outboxEvent).Error
})
}
// Outbound webhook with retry and delivery tracking
func (w *WebhookDelivery) Deliver(ctx context.Context, endpoint string, payload []byte) error {
var lastErr error
for attempt := 0; attempt < w.maxRetries; attempt++ {
resp, err := w.httpClient.Post(endpoint, "application/json", bytes.NewReader(payload))
if err == nil && resp.StatusCode >= 200 && resp.StatusCode < 300 {
w.trackDelivery(ctx, endpoint, "delivered", attempt+1)
return nil
}
lastErr = fmt.Errorf("attempt %d: status=%d err=%w", attempt+1, resp.StatusCode, err)
w.trackDelivery(ctx, endpoint, "retrying", attempt+1)
time.Sleep(exponentialBackoff(attempt))
}
w.trackDelivery(ctx, endpoint, "failed", w.maxRetries)
return fmt.Errorf("webhook delivery failed after %d attempts: %w", w.maxRetries, lastErr)
}
// Idempotent message consumer with deduplication
func (c *Consumer) HandleIdempotent(ctx context.Context, msg *Message) error {
if processed, _ := c.dedup.IsProcessed(ctx, msg.ID); processed {
logger.Info("duplicate message skipped", "msg_id", msg.ID)
return msg.Ack()
}
if err := c.process(ctx, msg); err != nil {
return err
}
c.dedup.MarkProcessed(ctx, msg.ID, 24*time.Hour)
return msg.Ack()
}
// Event ordering via partition key
func (p *Producer) PublishOrderEvent(ctx context.Context, orderID string, event interface{}) error {
return p.channel.Publish(ctx, PublishOptions{
Exchange: "orders",
RoutingKey: "order.events",
PartitionKey: orderID,
Body: mustMarshal(event),
Headers: map[string]interface{}{
"sequence": event.SequenceNumber,
},
})
}
// Poison message isolation (separate from DLQ)
func (c *Consumer) HandleWithPoisonDetection(msg *Message) error {
var event DomainEvent
if err := json.Unmarshal(msg.Body, &event); err != nil {
c.poisonQueue.Publish(msg, fmt.Sprintf("deserialization failed: %v", err))
return msg.Ack()
}
if err := c.process(event); err != nil {
if msg.RetryCount >= maxRetries {
return c.dlq.Publish(msg)
}
return c.RetryLater(msg, backoff(msg.RetryCount))
}
return msg.Ack()
}
Reference Implementation (BAD — Outbox, Idempotency & Poison Messages):
// BAD: Fire-and-forget webhook — no retry, no delivery tracking
func (s *Service) NotifyWebhook(endpoint string, payload []byte) {
go func() {
http.Post(endpoint, "application/json", bytes.NewReader(payload))
}()
}
// BAD: Event published OUTSIDE transaction — lost events on rollback
func (s *Service) CreateOrder(ctx context.Context, order *Order) error {
if err := s.db.Create(order).Error; err != nil {
return err
}
return s.publisher.Publish("OrderCreated", order)
}
// BAD: Consumer without idempotency — processes duplicates
func (c *Consumer) Handle(msg *Message) error {
return c.process(msg)
}
// BAD: Poison messages treated same as processing failures
func (c *Consumer) Handle(msg *Message) error {
var event DomainEvent
if err := json.Unmarshal(msg.Body, &event); err != nil {
return msg.Nack(true) // Requeue — malformed message retried forever
}
return c.process(event)
}
Check Against Ring Standards For:
- (HARD GATE) Dead Letter Queues (DLQ) configured for failed messages per messaging.md
- (HARD GATE) Explicit Ack/Nack handling (no auto-ack) per Ring RabbitMQ worker pattern
- Retry policies with exponential backoff
- Consumer groups for parallel processing
- Graceful shutdown of consumers (wait for processing to finish)
- Message durability settings (persistent queues)
- lib-commons messaging integration where applicable
- Outbound webhook delivery guarantees — webhook publishing MUST implement retry with exponential backoff and delivery status tracking (not fire-and-forget HTTP calls)
- At-least-once delivery patterns for event publishing — events MUST be published within the same transaction as the state change (transactional outbox pattern) to prevent lost events on rollback
- Idempotent message receivers — consumers MUST implement deduplication checks (idempotency keys, message ID tracking) before processing to handle at-least-once delivery without duplicate side effects
- Event ordering guarantees where required — order-dependent workflows MUST use partition keys or sequence numbers to guarantee processing order within a partition
- Poison message handling — messages that repeatedly fail deserialization or schema validation MUST be isolated separately from DLQ, preventing bad messages from blocking queue consumers
Severity Ratings:
- CRITICAL: Messages auto-acked before processing (HARD GATE violation per Ring standards)
- HIGH: No DLQ for poison messages (infinite loops) — HARD GATE violation
- HIGH: No retry backoff strategy
- HIGH: Outbound webhooks with no retry mechanism (fire-and-forget HTTP call — delivery failures are silently lost)
- HIGH: Event publishing outside transaction boundary (state change commits but event publish fails — lost events, inconsistent downstream state)
- HIGH: Message consumers without idempotency checks (at-least-once delivery causes duplicate processing — double charges, duplicate records)
- MEDIUM: Missing graceful shutdown for workers
- MEDIUM: No event ordering strategy for order-dependent workflows (e.g., "order cancelled" processed before "order created")
- MEDIUM: No poison message isolation (malformed messages that fail deserialization block the queue or get retried infinitely)
- LOW: No webhook delivery status tracking/dashboard (cannot audit delivery success rates)
Output Format:
## Async Reliability Audit Findings
### Summary
- Async processing detected: Yes/No
- DLQ configured: Yes/No
- Retry strategy: Yes/No
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 28: Core Dependencies & Frameworks Auditor
```prompt
Audit core dependency usage and framework compliance for production readiness.
**Detected Stack:** {DETECTED_STACK}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: Sections 2 and 3 from core.md — "Core Dependency: lib-commons" and "Frameworks & Libraries"}
---END STANDARDS---
**Search Patterns:**
- Files: `go.mod`, `go.sum`, `**/utils/*.go`, `**/helpers/*.go`, `**/common/*.go`
- Keywords: `lib-commons`, `github.com/LerianStudio`, `go 1.`, `fiber`, `gorm`, `validator`
- Also search: Custom utility packages that may duplicate lib-commons functionality
**Reference Implementation (GOOD):**
```go
// go.mod with lib-commons v2 and required frameworks
module github.com/company/project
go 1.24
require (
github.com/LerianStudio/lib-commons/v2 v2.x.x // lib-commons present
github.com/gofiber/fiber/v2 v2.52.x // Fiber v2
gorm.io/gorm v1.25.x // GORM
github.com/go-playground/validator/v10 v10.x.x // Validator
github.com/stretchr/testify v1.9.x // Testify
)
Reference Implementation (BAD):
// BAD: Custom utilities that duplicate lib-commons
// internal/utils/database.go
func ConnectDB(dsn string) (*sql.DB, error) {
// Custom connection logic duplicating lib-commons/mpostgres
}
// BAD: Custom telemetry wrapper duplicating lib-commons
// internal/common/tracing.go
func StartSpan(ctx context.Context, name string) (context.Context, trace.Span) {
// Custom wrapper duplicating lib-commons/NewTrackingFromContext
}
// BAD: Missing lib-commons entirely
// go.mod without github.com/LerianStudio/lib-commons
Check Against Ring Standards For:
- (HARD GATE) lib-commons v2 present in go.mod — this is mandatory per Ring standards
- (HARD GATE) No custom utility packages that duplicate lib-commons functionality (check utils/, helpers/, common/)
- Go version 1.24+ in go.mod
- Fiber v2 framework present
- GORM ORM present
- go-playground/validator/v10 present
- testify present for testing
- No alternative libraries used for functionality already covered by lib-commons
Severity Ratings:
- CRITICAL: lib-commons not in go.mod (HARD GATE violation per Ring standards)
- CRITICAL: Custom utilities duplicating lib-commons functionality (HARD GATE violation)
- HIGH: Framework versions below Ring minimum requirements
- MEDIUM: Using alternative libraries for functionality covered by Ring stack
- LOW: Minor version discrepancies
Output Format:
## Core Dependencies & Frameworks Audit Findings
### Summary
- lib-commons v2 present: Yes/No
- Go version: X (minimum 1.24)
- Required frameworks present: X/Y
- Custom utility packages found: [list]
- lib-commons duplication detected: Yes/No
### Critical Issues
[file:line or go.mod] - Description
### Recommendations
1. ...
### Agent 29: Naming Conventions Auditor
```prompt
Audit naming conventions across the codebase for production readiness.
**Detected Stack:** {DETECTED_STACK}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: Naming conventions from core.md section 5 (if exists) and JSON naming subsection from api-patterns.md section 1}
---END STANDARDS---
**Search Patterns:**
- Files: `**/*.go` for struct tags, `**/migrations/*.sql` for column names
- Keywords: `json:"`, `db:"`, `gorm:"`, `column:`, `CREATE TABLE`
- Also search: Query parameter handling for naming consistency
**Reference Implementation (GOOD):**
```go
// Go struct with correct naming conventions
type Account struct {
ID uuid.UUID `json:"id" gorm:"column:id"`
DisplayName string `json:"display_name" gorm:"column:display_name"` // camelCase JSON, snake_case DB
AccountType string `json:"account_type" gorm:"column:account_type"`
CreatedAt time.Time `json:"created_at" gorm:"column:created_at"`
}
// Query parameters use snake_case
// GET /v1/accounts?account_type=savings&created_after=2024-01-01
// SQL migration with snake_case columns
// CREATE TABLE accounts (
// id UUID PRIMARY KEY,
// display_name VARCHAR(255),
// account_type VARCHAR(50),
// created_at TIMESTAMP WITH TIME ZONE
// );
Reference Implementation (BAD):
// BAD: Inconsistent JSON naming
type Account struct {
ID uuid.UUID `json:"id"`
DisplayName string `json:"displayName"` // camelCase instead of snake_case
AccountType string `json:"account_type"` // snake_case — inconsistent with above!
CreatedAt time.Time `json:"CreatedAt"` // PascalCase — wrong!
}
// BAD: Mixed naming in query params
// GET /v1/accounts?accountType=savings&created_after=2024-01-01
Check Against Ring Standards For:
- snake_case for database column names in migrations and GORM tags
- snake_case for JSON response body fields (json:"field_name")
- snake_case for query parameters
- PascalCase for Go exported types and functions
- camelCase for Go unexported fields and variables
- Consistent naming convention within each context (no mixing)
Severity Ratings:
- HIGH: Inconsistent JSON field naming across response DTOs (mix of conventions)
- MEDIUM: Query params not using snake_case
- MEDIUM: Database columns not using snake_case
- LOW: Minor naming inconsistencies within a single file
Output Format:
## Naming Conventions Audit Findings
### Summary
- JSON fields audited: X
- Using snake_case JSON: Y/X
- DB columns using snake_case: Y/Z
- Query params using snake_case: Y/Z
- Naming convention violations: N
### Issues by Convention
#### JSON Naming
[file:line] - Field "displayName" should be "display_name"
#### Database Naming
[file:line] - Column "displayName" should be "display_name"
#### Query Parameter Naming
[file:line] - Param "accountType" should be "account_type"
### Recommendations
1. ...
### Agent 30: Domain Modeling Auditor
```prompt
Audit domain modeling patterns for production readiness.
**Detected Stack:** {DETECTED_STACK}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "ToEntity/FromEntity" section 9 from domain.md and "Always-Valid Domain Model" section 21 from domain-modeling.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/domain/*.go`, `**/entity/*.go`, `**/model/*.go`, `**/value_objects/*.go`
- Keywords: `ToEntity`, `FromEntity`, `NewXxx`, `IsValid()`, `private fields`
- Also search: `**/adapters/**/*.go` for mapping patterns
**Reference Implementation (GOOD):**
```go
// Always-valid domain model with private fields and constructor
type Account struct {
id uuid.UUID // Private fields
name string
accountType AccountType
status Status
createdAt time.Time
}
// Constructor enforces invariants
func NewAccount(name string, accountType AccountType) (*Account, error) {
if name == "" {
return nil, ErrNameRequired
}
if !accountType.IsValid() {
return nil, ErrInvalidAccountType
}
return &Account{
id: uuid.New(),
name: name,
accountType: accountType,
status: StatusActive,
createdAt: time.Now(),
}, nil
}
// Exported getters (no setters for immutable fields)
func (a *Account) ID() uuid.UUID { return a.id }
func (a *Account) Name() string { return a.name }
func (a *Account) Status() Status { return a.status }
// ToEntity/FromEntity mapping in adapters
func (dto *CreateAccountDTO) ToEntity() (*domain.Account, error) {
return domain.NewAccount(dto.Name, domain.AccountType(dto.Type))
}
func FromEntity(account *domain.Account) *AccountResponse {
return &AccountResponse{
ID: account.ID().String(),
Name: account.Name(),
Status: string(account.Status()),
}
}
Reference Implementation (BAD):
// BAD: Domain model with exported mutable fields and no constructor
type Account struct {
ID uuid.UUID `json:"id"` // Exported + mutable!
Name string `json:"name"` // Can be set to "" directly
AccountType string `json:"account_type"` // No type safety
Status string `json:"status"` // No validation
}
// BAD: Direct field access without validation
account := &Account{Name: ""} // Invalid state allowed!
// BAD: No ToEntity/FromEntity — DTOs used directly as domain models
func (h *Handler) Create(c *fiber.Ctx) error {
var account Account
c.BodyParser(&account)
repo.Save(ctx, &account) // DTO goes straight to persistence!
}
Check Against Ring Standards For:
- (HARD GATE) Domain models use private fields with exported getters per domain-modeling.md always-valid pattern
- (HARD GATE) Constructors (NewXxx) enforce invariants — no invalid domain objects can be created
- (HARD GATE) ToEntity/FromEntity mapping patterns in adapters per domain.md section 9
- Value objects have IsValid() methods
- No direct field access on domain models from outside the package
- DTOs are separate from domain models (not the same struct)
- Consistent domain modeling across all bounded contexts
Severity Ratings:
- CRITICAL: Domain models with exported mutable fields and no constructor (HARD GATE violation per Ring standards)
- CRITICAL: DTOs used directly as domain models (no ToEntity/FromEntity)
- HIGH: Missing ToEntity/FromEntity in adapters (HARD GATE violation)
- MEDIUM: Inconsistent domain modeling across modules
- MEDIUM: Value objects without IsValid()
- LOW: Minor modeling inconsistencies
Output Format:
## Domain Modeling Audit Findings
### Summary
- Domain models found: X
- Using always-valid pattern: Y/X
- With constructors (NewXxx): Y/X
- ToEntity/FromEntity present: Y/Z adapters
- Value objects with IsValid: Y/Z
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 31: Linting & Code Quality Auditor
```prompt
Audit linting configuration and code quality patterns for production readiness.
**Detected Stack:** {DETECTED_STACK}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Linting" section 16 from quality.md}
---END STANDARDS---
**Search Patterns:**
- Files: `.golangci.yml`, `.golangci.yaml`, `**/*.go`
- Keywords: `//nolint`, `golangci-lint`, import grouping patterns
- Also search: Magic numbers in business logic code
**Reference Implementation (GOOD):**
```go
// Import ordering: 3 groups (stdlib, external, internal)
import (
"context"
"fmt"
"time"
"github.com/gofiber/fiber/v2"
"github.com/google/uuid"
"go.opentelemetry.io/otel"
"github.com/company/project/internal/domain"
)
// Named constants instead of magic numbers
const (
maxRetries = 3
defaultTimeout = 30 * time.Second
maxPageSize = 100
minPasswordLen = 8
)
// Using named constants in logic
if retryCount >= maxRetries {
return ErrMaxRetriesExceeded
}
Reference Implementation (BAD):
// BAD: Import ordering not following convention
import (
"github.com/company/project/internal/domain"
"fmt"
"github.com/gofiber/fiber/v2"
"context"
)
// BAD: Magic numbers in business logic
if retryCount >= 3 { // What is 3?
time.Sleep(30 * time.Second) // What is 30?
}
if len(password) < 8 { // What is 8?
return errors.New("too short")
}
if pageSize > 100 { // What is 100?
pageSize = 100
}
Check Against Ring Standards For:
- (HARD GATE) golangci-lint configuration exists per quality.md linting section
- Import ordering follows 3-group convention (stdlib, external, internal)
- Magic numbers replaced with named constants in business logic
- Required linters enabled in golangci-lint config
- No blanket //nolint without specific linter name
- Consistent code formatting (gofmt/goimports applied)
Severity Ratings:
- HIGH: No golangci-lint configuration (HARD GATE violation per Ring standards)
- MEDIUM: Magic numbers in business logic
- MEDIUM: Import ordering not following 3-group convention
- MEDIUM: Blanket //nolint without justification
- LOW: Minor style inconsistencies
Output Format:
## Linting & Code Quality Audit Findings
### Summary
- golangci-lint config: Yes/No
- Import ordering violations: X files
- Magic numbers found: Y locations
- Blanket //nolint usage: Z locations
### Issues
#### golangci-lint Configuration
[config status and missing linters]
#### Import Ordering
[file:line] - Imports not following 3-group convention
#### Magic Numbers
[file:line] - Magic number N used (suggest: named constant)
### Recommendations
1. ...
### Agent 32: Makefile & Dev Tooling Auditor
```prompt
Audit Makefile and development tooling for production readiness.
**Detected Stack:** {DETECTED_STACK}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: "Makefile Standards" section 7 from devops.md}
---END STANDARDS---
**Search Patterns:**
- Files: `Makefile`, `makefile`, `GNUmakefile`
- Keywords: `.PHONY`, `build`, `test`, `lint`, `help`, `docker`
- Also search: `scripts/*.sh` for development scripts
**Reference Implementation (GOOD):**
```makefile
.PHONY: build test lint cover up down logs setup migrate seed generate swagger docker-build docker-push clean help check
build: ## Build the application binary
go build -o bin/app cmd/app/main.go
test: ## Run all unit tests
go test -race -v ./...
lint: ## Run linters
golangci-lint run
cover: ## Run tests with coverage
go test -race -coverprofile=coverage.out ./...
go tool cover -html=coverage.out -o coverage.html
up: ## Start local dependencies (docker-compose)
docker compose up -d
down: ## Stop local dependencies
docker compose down
logs: ## Tail local dependency logs
docker compose logs -f
setup: ## Initial project setup
go mod download
go install github.com/swaggo/swag/cmd/swag@latest
migrate: ## Run database migrations
migrate -path migrations -database "$$DATABASE_URL" up
seed: ## Seed database with test data
go run cmd/seed/main.go
generate: ## Run code generators (mockgen, etc.)
go generate ./...
swagger: ## Generate Swagger documentation
swag init -g cmd/app/main.go
docker-build: ## Build Docker image
docker build -t app:latest .
docker-push: ## Push Docker image
docker push app:latest
clean: ## Clean build artifacts
rm -rf bin/ coverage.out coverage.html
help: ## Show this help message
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
check: ## Run all checks (lint + test + cover)
$(MAKE) lint
$(MAKE) test
$(MAKE) cover
Check Against Ring Standards For:
- (HARD GATE) Makefile exists in project root per devops.md
- Required targets present: build, lint, test, cover, up, down, logs, setup, migrate, seed, generate, swagger, docker-build, docker-push, clean, help, check
- All targets have help descriptions (## comments)
- .PHONY declarations for non-file targets
helptarget shows available commandschecktarget runs full validation pipeline
Severity Ratings:
- HIGH: No Makefile in project (HARD GATE violation per Ring standards)
- MEDIUM: Missing required Makefile targets (list which ones are missing)
- MEDIUM: Targets without help descriptions
- LOW: Missing .PHONY declarations
- LOW: Targets without error handling
Output Format:
## Makefile & Dev Tooling Audit Findings
### Summary
- Makefile present: Yes/No
- Required targets present: X/17
- Missing targets: [list]
- Targets with help: X/Y
### Required Targets Checklist
| Target | Present | Has Help |
|--------|---------|----------|
| build | Yes/No | Yes/No |
| test | Yes/No | Yes/No |
| lint | Yes/No | Yes/No |
| cover | Yes/No | Yes/No |
| up | Yes/No | Yes/No |
| down | Yes/No | Yes/No |
| logs | Yes/No | Yes/No |
| setup | Yes/No | Yes/No |
| migrate | Yes/No | Yes/No |
| seed | Yes/No | Yes/No |
| generate | Yes/No | Yes/No |
| swagger | Yes/No | Yes/No |
| docker-build | Yes/No | Yes/No |
| docker-push | Yes/No | Yes/No |
| clean | Yes/No | Yes/No |
| help | Yes/No | Yes/No |
| check | Yes/No | Yes/No |
### Recommendations
1. ...
### Agent 33: Multi-Tenant Patterns Auditor *(CONDITIONAL)*
```prompt
CONDITIONAL: Only run this agent if MULTI_TENANT=true was detected during stack detection. If the project does not use multi-tenancy (no tenant config, no pool manager, no tenant middleware), SKIP this agent entirely and report: "Dimension 33 skipped — single-tenant project (no multi-tenant indicators detected)."
If multi-tenant IS detected, audit multi-tenant architecture patterns for production readiness.
**Detected Stack:** {DETECTED_STACK}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: Section 23 from multi-tenant.md}
---END STANDARDS---
**Search Patterns:**
- Files: `**/tenant*.go`, `**/pool*.go`, `**/middleware*.go`, `**/context*.go`
- Keywords: `tenantID`, `TenantManager`, `TenantContext`, `schema`, `search_path`
- Also search: `**/jwt*.go`, `**/auth*.go` for tenant extraction
**Reference Implementation (GOOD):**
```go
// DualPoolMiddleware routes to correct tenant connection pool per module
type DualPoolMiddleware struct {
onboardingPool *tenantmanager.TenantConnectionManager
transactionPool *tenantmanager.TenantConnectionManager
onboardingMongoPool *tenantmanager.MongoManager
transactionMongoPool *tenantmanager.MongoManager
}
// Path-based pool selection
func (m *DualPoolMiddleware) selectPool(path string) *tenantmanager.TenantConnectionManager {
if m.isTransactionPath(path) {
return m.transactionPool
}
return m.onboardingPool
}
// Module-specific connection from context
db, err := tenantmanager.GetModulePostgresForTenant(ctx, constant.ModuleOnboarding)
// Entity-scoped query — ALWAYS filter by organization_id + ledger_id
func (r *Repo) Find(ctx context.Context, orgID, ledgerID, id uuid.UUID) (*Entity, error) {
db, err := tenantmanager.GetModulePostgresForTenant(ctx, constant.ModuleTransaction)
if err != nil {
return nil, err
}
find := squirrel.Select(columnList...).
From(r.tableName).
Where(squirrel.Expr("organization_id = ?", orgID)).
Where(squirrel.Expr("ledger_id = ?", ledgerID)).
Where(squirrel.Expr("id = ?", id)).
PlaceholderFormat(squirrel.Dollar)
// ...
}
Reference Implementation (BAD):
// BAD: Query without entity scoping — intra-tenant IDOR!
func (r *Repo) FindByID(ctx context.Context, id uuid.UUID) (*Entity, error) {
db, _ := tenantmanager.GetModulePostgresForTenant(ctx, constant.ModuleTransaction)
return db.QueryRowContext(ctx, "SELECT * FROM entities WHERE id = $1", id)
}
// BAD: Tenant ID from request header (can be spoofed)
func GetTenantID(c *fiber.Ctx) string {
return c.Get("X-Tenant-ID") // User-controlled!
}
// BAD: Non-module-specific connection getter
db, err := tenantmanager.GetPostgresForTenant(ctx) // WRONG: missing module parameter
Check Against Ring Standards For:
- (HARD GATE) Tenant ID extracted from JWT claims (not user-controlled headers/params) per multi-tenant.md
- (HARD GATE) All database queries include entity scoping (organization_id + ledger_id)
- (HARD GATE) DualPoolMiddleware injects tenant into request context with module-specific connections
- TenantConnectionManager with dual-pool (onboarding + transaction) architecture
- Database-per-tenant isolation (separate databases per tenant via TenantConnectionManager)
- Tenant-scoped cache keys (Redis keys include tenant prefix via GetKeyFromContext)
- No cross-tenant data leakage in list/search operations
- Cross-module connection injection (both modules in context)
- ErrManagerClosed handling (503 SERVICE_UNAVAILABLE)
Severity Ratings:
- CRITICAL: Queries without entity scoping — intra-tenant IDOR (HARD GATE violation per Ring standards)
- CRITICAL: Tenant ID from user-controlled input (HARD GATE violation)
- CRITICAL: Missing DualPoolMiddleware (HARD GATE violation)
- HIGH: No TenantConnectionManager for connection management
- HIGH: Cache keys not tenant-scoped
- HIGH: Missing cross-module connection injection
- MEDIUM: Inconsistent tenant extraction across modules
- MEDIUM: Missing ErrManagerClosed handling
- LOW: Missing tenant validation in non-critical paths
Output Format:
## Multi-Tenant Patterns Audit Findings
### Summary
- Multi-tenant detection: Yes/No/N/A
- Tenant extraction: JWT / Header / Missing
- DualPoolMiddleware: Yes/No
- Tenant Manager: Yes/No
- Dual-pool architecture: Yes/No
- Module-specific connections: Yes/No
- Queries with entity scoping: X/Y
### Critical Issues
[file:line] - Description
### Recommendations
1. ...
### Agent 34: License Headers Auditor
```prompt
Audit license/copyright headers on source files for production readiness. If no LICENSE file exists in the project root, report all items as "N/A — No LICENSE file detected" with evidence.
**Detected Stack:** {DETECTED_STACK}
**Ring Standards (Source of Truth):**
---BEGIN STANDARDS---
{INJECTED: License header section from core.md section 7 (if exists), otherwise use organizational defaults}
---END STANDARDS---
**Search Patterns:**
- Files: `**/*.go` (check first 5 lines for copyright/license header)
- Also check: `LICENSE`, `LICENSE.md`, `NOTICE` files in project root
- Keywords: `Copyright`, `Licensed under`, `SPDX-License-Identifier`
**Reference Implementation (GOOD):**
```go
// Copyright 2025 LerianStudio. All rights reserved.
// Use of this source code is governed by the Apache License 2.0
// that can be found in the LICENSE file.
// SPDX-License-Identifier: Apache-2.0
package domain
import (
...
)
Reference Implementation (BAD):
// BAD: No license header at all
package domain
import (
...
)
// BAD: Outdated year
// Copyr
> Content truncated for page performance. Open the source repository for the full SKILL.md file.