원클릭으로
go-review-service
Audit a GOB Go microservice against all project conventions and patterns
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
메뉴
Audit a GOB Go microservice against all project conventions and patterns
Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
SOC 직업 분류 기준
Internal POSIX runtime helpers for agente-00c/feature-00c orchestrators (state, lock, validation, hashes, secrets filter). NOT user-invocable.
Task status / backlog progress report; identifies tasks ready to start. Triggers: "revisar tarefas", "status das tarefas", "progresso do projeto", "review tasks". Skip for executing (execute-task) or creating tasks (create-tasks).
GLOBAL feature portfolio dashboard — compare progress, suggest archive/abandon/prioritize. Triggers: "status global", "portfolio de features", "dashboard de features", "comparar features". Cross-feature; for single feature deep-dive use review-task.
Convert a natural-language feature description into SDD spec (user stories, FRs, success criteria). Triggers: "specify", "criar spec", "nova feature", "feature spec". Skip for refining an existing spec (clarify).
Requirements quality gate ("unit tests for English") by domain (ux/api/security/performance/a11y). Triggers: "checklist", "validar requisitos", "quality gate". Validates REQUIREMENT quality, not code.
Refine an existing spec via structured Q&A (max 5). Triggers: "clarify", "clarificar spec", "resolver ambiguidades", "refinar spec". Operates on existing spec.md; use specify to create one.
| name | go-review-service |
| description | Audit a GOB Go microservice against all project conventions and patterns |
| allowed-tools | ["Read","Glob","Grep","Bash"] |
Perform a comprehensive read-only audit of a GOB Go microservice, checking 17 conventions. Outputs a structured PASS/FAIL/WARNING report with line references.
"review service", "audit service", "validar servico", "check service", "verificar servico", "checar servico"
$ARGUMENTS should specify:
gob-member-service) — requiredDetermine the service root:
services/{service-name}/
Read these files first (in parallel where possible):
cmd/api/main.go — middleware order, wiring, shutdowninternal/factory/factory.go — repository factoryinternal/repository/repository.go — interfacesinternal/handler/*.go — route registrationgo.mod — module path, dependenciesmigrations/ — list files for schema referenceFor each check, output one of:
Expected order (top to bottom in main.go):
recover.New()requestid.New()apmfiber.Middleware(apmfiber.WithTracer(tracer)) — after requestid, before logging (unconditional/nil-safe; rollout-window dual-accept detailed in Check 3)middleware.LoggingWithLogger(log) or middleware.Logging()cors.New(...) — with AllowOrigins, AllowHeaders, AllowMethods, AllowCredentialsmiddleware.DryRun(...) — if service supports dry-runmiddleware.DryRunFinalizer() — if dry-run presentmiddleware.AuditPublisher(...) — after cors/dryrun, before endpointsSearch: Look for app.Use( calls in main.go. Verify order matches.
rabbitmq.NewFromURL)middleware.AuditExchange constantif rmqURL != "" with warning on failuredefer auditRMQ.Close() presentSearch: AuditPublisher in main.go.
observability.ElasticAPMTracer(cfg, log) called, returns (tracer, err) (non-fatal on error — Resilience Class A: degraded/non-recording, not a boot failure)apmfiber.Middleware(apmfiber.WithTracer(tracer)) present, unconditional — WithTracer(nil) is nil-safe (falls back to apm.DefaultTracer()), no != nil guard neededdefer observability.ShutdownElasticAPM(tracer) presentrequestid and before logging middlewareRollout-window dual-accept (FR-007): while the platform-wide code migration to Elastic APM is in progress across the 20 repositories (commons + 19 services), this check PASSes if the service shows the Elastic signals above OR the legacy signals below in isolation — it FAILs only when neither is present. This is a documented, temporary exception to the zero-New-Relic-references goal (spec.md SC-001), ratified to close once code migration completes (spec.md Clarifications — "aperto final").
observability.NewRelicApp(serviceName, cfg, log) called; nrfiber.Middleware(nrApp) present (historically conditional on nrApp != nil); defer observability.ShutdownNewRelic(nrApp) present.Search: Elastic — ElasticAPMTracer, apmfiber, ShutdownElasticAPM in main.go.
Legacy (rollout window only) — NewRelicApp, nrfiber, ShutdownNewRelic in main.go.
Aperto final (runbook task 6.5): once the operator confirms code migration is complete across all 20 repositories, DELETE the "Legacy signals" bullet and the second half of the Search line above — this check then requires the Elastic signals exclusively and FAILs any service still showing New Relic wiring.
For each handler's RegisterRoutes() method:
/types, /counts, /search) MUST come BEFORE parameterized routes (/:id)/groups) MUST be registered BEFORE /:id catch-allFAIL if: Any /:id or /:param route appears before a static route at the same level.
Search: All RegisterRoutes methods in internal/handler/.
context.Context is the first parameter in every methodFindByID returns (*domain.X, error) — nil/nil when not foundinternal/repository/repository.goSearch: repository.go file, look for interface definitions.
GetContext (single row) and SelectContext (multiple rows)sql.ErrNoRows returns nil, nil (not wrapped as error)member.members)$1, $2, ... positional parameters (not ?)db:"" tags separate from domain structstoDomain() converter methods on row structsSearch: internal/repository/postgres/*.go files.
var ErrXxxNotFound = errors.New("...")Search: internal/service/*.go files, look for var Err and return types.
errors.Is() for sentinel error matchingdto.ErrorResponse with appropriate HTTP status codesmiddleware.GetUserID(c), middleware.GetClaims(c)c.Status(xxx).JSON(dto.ErrorResponse{...}) patternSearch: internal/handler/*.go for errors.Is and ErrorResponse.
Repositories struct holds all repo instancesNewRepositories(db) constructor creates all reposNewDryRunRepositories(db) for dry-run mode (if applicable)RepositoryFactory with isDryRun flag (if dry-run supported)Search: internal/factory/factory.go.
snake_case (e.g., json:"lodge_id")snake_case matching column names (e.g., db:"lodge_id")omitempty on optional/nullable fieldsdb:"-" on computed/relation fieldsjson:"-" on fields that should be visible in APISearch: Domain structs in internal/domain/*.go, check tags.
All three must be present:
GET /health — returns 200 OKGET /ready — pings DB (db.PingContext) and returns health statusGET /version — returns service version infoSearch: /health, /ready, /version in main.go.
EnableTrustedProxyCheck: trueTrustedProxies configured (e.g., private network ranges)ProxyHeader: "X-Real-Ip" or "X-Forwarded-For"fiber.Config{} in main.goSearch: fiber.New( or fiber.Config in main.go.
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)consumer.Stop()) if RabbitMQ consumer existsapp.ShutdownWithContext(ctx) or app.Shutdown()Search: signal.Notify, Shutdown, defer in main.go.
github.com/gob/gob-{service-name}github.com/gob/gob-process-serviceSearch: First line of go.mod.
storage.Storage interface from gob-go-commons/pkg/storage/storage.NewFromConfig(cfg) (auto-selects S3 or local)Upload(ctx, key, reader, size, contentType) — NOT PutPresignedGetURL(ctx, key, expiry) — NOT GetPresignedURL{service}/{category}/{entityID}/{uuid}-{filename}.extstorage.ValidateFileType() and storage.ValidateFileSize()storage.Storage parameterSearch: storage.Storage in handler/service files.
N/A if service doesn't handle file uploads.
AMQPPublisher + NoopPublisher (graceful degradation when RabbitMQ unavailable)SetPublisher() method or accepts publisher in constructortopic and durableSearch: Publisher, AMQPPublisher, NoopPublisher in service and messaging files.
N/A if service doesn't publish events.
Verify logging follows the project standards (see CLAUDE.md "Structured Logging Standards"):
15a. Repository layer has logger injected:
log *logger.Logger field*logger.Logger parameter15b. Repository methods have entry/exit/duration logging:
entity, operationduration_msWithError(err) before returningFindByID not-found path must log Debug (not Error)duration_ms15c. Service layer has logging:
log *logger.Logger fieldentity_idWithError(err)15d. Handler layer has logging:
WithRequestID(requestID), WithError(err)entity, operation fields15e. No anti-patterns:
fmt.Println or log.Println (standard library) — must use logger.Loggerlogger.Default() in production code (inject via constructor)fmt.Println or log.Println found in non-test codeSearch: All .go files in internal/, look for log., logger., fmt.Print, log.Print.
# Service Audit: {service-name}
Date: {current date}
## Summary
PASS: X/17 | FAIL: Y/17 | WARNING: Z/17 | N/A: W/17
## Results
### 1. Middleware Order
**PASS** — Correct order: recover → requestid → apmfiber → logging → cors → dryrun → audit
(main.go:45-82)
### 2. Audit Middleware
**FAIL** — Missing separate RabbitMQ connection. Audit reuses existing connection.
(main.go:95)
### 3. Elastic APM
**PASS** — Elastic signals present: `apmfiber.Middleware(apmfiber.WithTracer(tracer))` unconditional/nil-safe, `ElasticAPMTracer`/`ShutdownElasticAPM` wired
(main.go:104-108, 375)
... (continue for all 17 checks)
## Recommendations
1. [Highest priority fixes]
2. [Medium priority improvements]
3. [Low priority suggestions]