Snapshot: 2026-05-30. Existing framework already provides Laravel-grade DX
(web.App, web.Router, web.Context, ORM, migrations, factories,
seeders, Artisan CLI). This TODO lists the real gaps to close.
-
web/security.go:SecurityHeaders()— CSP, X-Frame-Options, X-Content-Type-Options, Referrer-Policy, HSTS, Permissions-Policy -
web/security.go:CSRF()— double-submit cookie, constant-time compare, safe-method skip (GET/HEAD/OPTIONS) -
web/security.go:RateLimit(n, window)— fixed-window per IP,429 Too Many RequestswithRetry-After -
web/security.go:BodyLimit(n bytes)— wrapr.Bodywithhttp.MaxBytesReaderto prevent DoS via huge payloads -
web/security.go:RequestID()— generate/forwardX-Request-IDfor tracing & log correlation
-
web/validate.go: nativeValidationError+ tag-basedValidate() -
web/context.go:c.BindAndValidate(dst)— wires Bind+Validate, auto-422 with{"errors": {field: msg}} - Extra rules:
numeric,integer,ip,gt=N,lt=N
-
web/app.go: setReadTimeout,WriteTimeout,IdleTimeout,MaxHeaderBytes -
web/context.go:Bind()appliesMaxBytesReader(default 1 MiB) andDisallowUnknownFields() -
web/context.go: production-safeInternalError—APP_ENV=productionhides rawerr.Error()
- Double-body write:
Bind()400 +respond()500 wrote payload twice. Tracked withbodyWrittenflag. -
Created(): status flushed before Content-Type could be set, leaving 201 responses astext/plain. Replaced withpendingStatusthat defersWriteHeader.
-
web/cookies.go:c.Cookie(name)/c.SetCookie(...)with Secure / HttpOnly / SameSite=Lax default-on -
web/middleware.go:Throttle(...)alias forRateLimit -
web/router.go: route names +Route(name) (Route, ok)lookup -
web/router.go:Middleware(...)chain helper for per-route mw (currently achievable viaGroupof one) -
web/middleware.go:CORSWithConfig— credentials,Access-Control-Max-Age, echo requested headers - CORS rejects wildcard + credentials at init (panic)
-
SECURITY.md: catalogue all defenses + recommended config -
README.md: link new middleware -
examples/secure: a runnable example demonstrating every guard
- Session cookies / signed cookies (need a kv abstraction first)
- WebSocket / SSE
- gRPC adapter
- Sanctum/Passport equivalent
If git push -u origin laravel-style fails (no remote / auth), commits
stay local — manual push by the maintainer.