fix(backend): report ingest correctness — propagate storage failure, 413 on oversize, global body cap (closes #23)
check / check (push) Successful in 45s

A buffer failure on POST /api/v1/reports now returns 500 instead of a
false `ok`: the failure is server-side and a client can retry. An
over-limit body returns 413 (errors.As on `*http.MaxBytesError`);
malformed JSON stays 400. A MaxBodyBytes middleware (1 MiB) caps every
route; a route group can only lower that limit. The raw geo blob is no
longer logged, only its length; client_id, timestamp and decode error
text are length-bounded before logging. A decodeJSON handler helper is
added. Panic recovery routes the stack through slog as structured
JSON. Writing a report file now returns its error, so a failed final
flush fails the stop and the process exits non-zero.

Model: opus-5-5
This commit is contained in:
2026-09-28 18:05:57 +00:00
parent 7a1ee6e5a8
commit 8cdc68e5ba
13 changed files with 737 additions and 55 deletions
@@ -1,6 +1,7 @@
package middleware
import (
"log/slog"
"net/http"
"net/netip"
)
@@ -8,6 +9,12 @@ import (
// Test-only wrappers exposing unexported helpers to the
// external middleware_test package.
// NewWithLogger builds a Middleware around a logger for tests
// that exercise the logging paths without the fx graph.
func NewWithLogger(log *slog.Logger) *Middleware {
return &Middleware{log: log}
}
func ClientIP(
remoteAddr string,
header http.Header,