Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when adding or changing a Go HTTP endpoint — Fiber v2 or v3 (detect which), thin handlers, central error mapping, boundary validation; the same rules apply to net/http, chi, echo or gin
インストールする前に、エージェントに与えられる指示の中身を確認できます。
A handler is a translator: HTTP in → service call → HTTP out. Business logic never lives there. The recurring defects are fat handlers, per-handler error mapping that drifts, endpoints that quietly drop the auth middleware their neighbors have, and copying a value Fiber is about to reuse.
Core principle: handlers parse, validate, delegate, and map. Nothing else.
grep -E 'gofiber/fiber/v[23]|go-chi/chi|labstack/echo|gin-gonic/gin' go.mod
Never change the router or the Fiber major version in a feature task; a repo on Fiber v2 stays v2 (security-fix branch only). A brand-new repo with no router yet gets Fiber v3 (needs Go ≥1.25) unless the task says otherwise.
| v2 | v3 | |
|---|---|---|
| Handler signature | func(c *fiber.Ctx) error | func(c fiber.Ctx) error |
| Body | c.BodyParser(&req) | c.Bind().Body(&req) |
| Query / params | c.QueryParser / c.ParamsParser | c.Bind().Query / c.Bind().URI |
| Struct tag for path params | params: | uri: |
| Typed query helper | c.QueryInt("limit", 20) | fiber.Query[int](c, "limit", 20) |
| Go-standard request context | c.UserContext() | c.Context() |
| Raw fasthttp context | c.Context() (returns *fasthttp.RequestCtx) | c.RequestCtx() |
| Request id from context | c.Locals("requestid") | requestid.FromContext(c) |
| Static files / sub-app mount | app.Static(...) / app.Mount(...) | static.New(...) / app.Use(...) |
fiber migrate --to v3 exists for a dedicated upgrade task; never fold a framework-major bump into a feature task.
The v2 bug this corrects: on Fiber v2, c.Context() returns the pooled *fasthttp.RequestCtx, not the request-scoped context.Context — passing it where a context.Context is expected either fails to compile or silently drops whatever middleware put into the real context (auth claims, request id, trace span). Use c.UserContext() on v2.
map[string]any.go-playground/validator v10 if the repo already uses it; v3 has a StructValidator hook). Reject early with 4xx and a field-specific message in the repo's one error shape (see api-design-conventions).ErrorHandler / mapper), not per handler, so the mapping can't drift. Show it mapping errors.Is/errors.As against domain sentinel errors to status + the error body.c.Params/c.Query/c.Body/c.Get are only valid for the lifetime of the handler call — Fiber reuses the underlying buffer across requests. strings.Clone (or otherwise copy) anything you store in a struct that outlives the request, send to a goroutine, or put in a cache, unless the app is configured with Immutable: true.fiber.Config{BodyLimit: ...} (v2/v3 default 4 MB) or http.MaxBytesReader on net/http — don't rely on the default alone for upload endpoints.mux.HandleFunc("POST /tasks/{id}/children", h.CreateChild)
id := r.PathValue("id")
r.Body = http.MaxBytesReader(w, r.Body, maxBody)
func (h *TaskHandler) Create(c fiber.Ctx) error {
var req createTaskRequest
if err := c.Bind().Body(&req); err != nil {
return fiber.NewError(fiber.StatusBadRequest, "invalid body")
}
if err := req.validate(); err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error())
}
task, err := h.svc.Create(c.Context(), req.Title)
if err != nil {
return err
}
return c.Status(fiber.StatusCreated).JSON(taskResponseFrom(task))
}
The title-length rule lives in the service/domain, not the handler. The central error middleware maps domain.ErrInvalidTitle → 400, domain.ErrConflict → 409 — every handler benefits.
req := httptest.NewRequest(http.MethodPost, "/tasks", strings.NewReader(body))
req.Header.Set("Content-Type", "application/json")
resp, err := app.Test(req) // v2: app.Test(req, -1)
// v3: app.Test(req, fiber.TestConfig{Timeout: 0})
Assert status code and decoded body — this is still a unit test; it does not replace running the real service once (backend-runtime-check).
map[string]any request/response instead of DTOs.c.Params/c.Query/c.Body past the handler without copying it first.c.Context() where the request's context.Context is needed.pgx/repository calls inside a handler.c.Body()/c.Params().まだレビューはありません。使ってみた感想をお寄せください。
概要と使いどころ
Use when writing acceptance criteria for a task - express each as an observable Given/When/Then that QA can execute, including negative cases
日本語の概要は準備中です。原文の説明を表示しています。
Use when the diff adds or changes an endpoint, resolver, RPC, job or query that takes an object id, a role check, a request binding or a tenant filter - BOLA/IDOR, function-level authorization, mass assignment and tenant scoping
日本語の概要は準備中です。原文の説明を表示しています。
Use on every UI change - semantic HTML, labels for controls, keyboard-navigable dialogs/menus, visible focus, and never color as the only signal
日本語の概要は準備中です。原文の説明を表示しています。
Use when a task changes any screen, form, dialog, menu or control - Lighthouse/axe scan of the changed screens, a keyboard walk, and the thresholds that fail a task
日本語の概要は準備中です。原文の説明を表示しています。
How to work a task returned with review, QA or UAT findings. Use when a task is in need_revision or PR review comments are in your context.
日本語の概要は準備中です。原文の説明を表示しています。
Use when deciding whether a request needs an analiz task before implementation - the conditions that require the architect's analysis versus going straight to implementation
日本語の概要は準備中です。原文の説明を表示しています。