# Pattern: Handler ## Responsibility HTTP only: bind JSON/query → validate → call service interface → map errors to envelope. ## Shape ```go type ReportService interface { Decode(ctx context.Context, in DecodeInput) (*DecodeOutput, error) } type ReportHandler struct { svc ReportService } func (h *ReportHandler) Decode(c *gin.Context) { var req DecodeRequest if err := c.ShouldBindJSON(&req); err != nil { response.Fail(c, 400, 10000, "invalid request") return } out, err := h.svc.Decode(c.Request.Context(), toInput(req)) if err != nil { // map domain errors → codes response.Fail(c, 400, 30001, err.Error()) return } response.OK(c, out) } ``` ## Never - SQL here - Business unlock math here (belongs service)