R3: gateway edge hardening — body cap, h2c sizing, rate-limit observability

- GATEWAY_MAX_BODY_BYTES (1 MiB): connect WithReadMaxBytes + http.MaxBytesReader
  on the public mux; explicit http2.Server MaxConcurrentStreams/IdleTimeout and
  an http.Server ReadHeaderTimeout (R2 report follow-up).
- gateway_rate_limited_total{class} counter, Debug per rejection, a rejection
  tracker drained every 30 s into a Warn summary per key and a report POST to
  /api/v1/internal/ratelimit/report (feeds the admin view + auto-flag).
- The dead AdminPerMinute/AdminBurst policy now guards the /_gm mount (429),
  ahead of its Basic-Auth.
- resolve() logs the cause of infra session-resolve failures at Warn (the
  transient unauthenticated dips from the R2 run); unknown tokens stay silent.
This commit is contained in:
Ilia Denisov
2026-06-10 01:58:48 +02:00
parent c23ac94c4e
commit 8878711cf3
12 changed files with 549 additions and 35 deletions
+13
View File
@@ -18,6 +18,7 @@ import (
"google.golang.org/grpc"
"google.golang.org/grpc/credentials/insecure"
"scrabble/gateway/internal/ratelimit"
pushv1 "scrabble/pkg/proto/push/v1"
)
@@ -124,3 +125,15 @@ func parseAPIError(status int, data []byte) *APIError {
func (c *Client) SubscribePush(ctx context.Context, gatewayID string) (grpc.ServerStreamingClient[pushv1.Event], error) {
return c.push.Subscribe(ctx, &pushv1.SubscribeRequest{GatewayId: gatewayID})
}
// ReportRateLimited posts the gateway's periodic rate-limiter rejection summary
// to the backend, which feeds the admin console's throttled view and the
// high-rate auto-flag. The endpoint carries no user identity: like
// sessions/resolve it rides the trusted internal segment (R3).
func (c *Client) ReportRateLimited(ctx context.Context, windowSeconds int, entries []ratelimit.Rejection) error {
body := struct {
WindowSeconds int `json:"window_seconds"`
Entries []ratelimit.Rejection `json:"entries"`
}{WindowSeconds: windowSeconds, Entries: entries}
return c.do(ctx, http.MethodPost, "/api/v1/internal/ratelimit/report", "", "", body, nil)
}