Skip to content

release: v0.6.0 — RFC 9457 default errors, security fixes - #19

Merged
kolkov merged 5 commits into
mainfrom
feat/rfc9457-default-errors
Sep 10, 2026
Merged

release: v0.6.0 — RFC 9457 default errors, security fixes#19
kolkov merged 5 commits into
mainfrom
feat/rfc9457-default-errors

Conversation

@kolkov

@kolkov kolkov commented Sep 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • RFC 9457 Problem Details is now the default error response for all auto-generated errors (404, 405, 413, 415, 400, 500, JWT 401, BasicAuth 401, RateLimit 429, CircuitBreaker 503)
  • CORS preflight echo bypass fixed — only filtered allowed headers returned
  • Example JWT alg confusion fixed — validates signing method
  • Form binding type errors return 400 (was 500)
  • RateLimiter exported with Stop() and NoHeaders options
  • Documentation cleanup — removed non-existent APIs from SECURITY.md, llms.md, plugin READMEs
  • Plugin deps updated — OTel v1.46, validator v10.30, sqlite v1.58

Breaking Changes

  • Error responses changed from text/plain to application/problem+json
  • Custom error handlers (SetErrorHandler, JWT ErrorHandler, etc.) are unaffected

Test plan

  • All tests pass (cached, 0 failures)
  • golangci-lint: 0 issues
  • gofmt: clean
  • TDD: failing tests written before each fix
  • Plugin deps updated and verified

Security:
- CORS preflight: write filtered allowedHeaders, not raw reqHeaders (echo bypass)
- Example JWT: validate signing method is HMAC before returning key (alg confusion)

Code fixes:
- Form binding type errors (age=abc) return DecodeError → 400, not 500
- Plugins updated: fursy v0.5.3→v0.5.4, stream v0.1.4→v0.1.5

Documentation (verified against actual code):
- SECURITY.md: remove non-existent CSRF/Timeout/BodyLimit/HTTPSRedirect, fix RateLimit sig, update versions 0.5.x
- llms.md: encoding/json/v2 → encoding/json, fix stale API examples
- Plugin READMEs: router.Run() → http.ListenAndServe()
- README.md: performance 256ns→53ns 0-alloc
- NewRateLimiter() returns *RateLimiter with Handler() and Stop() methods
- Stop() releases cleanup goroutine — prevents leak on limiter recreation
- NoHeaders: true disables X-RateLimit-* headers (was impossible before)
- Backward compatible: RateLimit() and RateLimitWithConfig() unchanged
…RS, Shutdown godoc

- PanicHandler: re-panic http.ErrAbortHandler (matches Recovery behavior)
- Problem.WithExtension/WithExtensions: deep-copy map to prevent aliasing
- CODEOWNERS: remove non-existent /internal/pool/, /handler.go, /Makefile; add actual files
- Shutdown godoc: fix order description (drain first, then callbacks)
All auto-generated error responses now return application/problem+json:
- Router: 404, 405, 413, 415, 400 (binding), 500
- JWT: 401 Unauthorized
- BasicAuth: 401 Unauthorized
- RateLimit: 429 Too Many Requests
- CircuitBreaker: 503 Service Unavailable
- Recovery/PanicHandler: 500 Internal Server Error

Breaking change: error responses are JSON instead of text/plain.
Custom error handlers (SetErrorHandler, JWT ErrorHandler, etc.) are
unaffected — only default handlers changed.
deps: OTel v1.38→v1.46, validator v10.24→v10.30, sqlite v1.40→v1.58
@codecov

codecov Bot commented Sep 10, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 92.68293% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
middleware/ratelimit.go 93.33% 1 Missing ⚠️
middleware/recovery.go 75.00% 1 Missing ⚠️
problem.go 90.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@kolkov
kolkov merged commit 32a0cfc into main Sep 10, 2026
12 checks passed
@kolkov
kolkov deleted the feat/rfc9457-default-errors branch September 10, 2026 22:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant