docs(adr-068): GW-15 body-limit layer + pre-extend cap in publish body handling

This commit is contained in:
2026-08-30 20:29:35 +00:00
parent 05ebbef43e
commit c8c7bd0910
@@ -72,8 +72,16 @@ stream; the operation's final `ResponseEnvelope` is the HTTP response.
The NDJSON body is **streamed, never fully buffered** (GW-06): axum's The NDJSON body is **streamed, never fully buffered** (GW-06): axum's
`Body` is framed into lines as bytes arrive, and each line is parsed and `Body` is framed into lines as bytes arrive, and each line is parsed and
pushed into the sink lazily — memory is bounded by the per-line cap (2 pushed into the sink lazily — memory is bounded by the per-line cap (2
MiB, matching axum's default whole-body limit), not by the unbounded MiB), not by the unbounded chunk count. The per-line cap is checked
chunk count. `publish_schema` validation is applied per chunk inside the **before** the unterminated byte buffer is extended (GW-15), so it holds
even when no `\n` ever arrives, and the trailing-EOF path re-checks it
before yielding. The gateway router also carries an explicit whole-body
limit layer (GW-15: 2 MiB + 64 KiB framing headroom, answering `413`) —
a raw-`Body` handler never consults axum's `DefaultBodyLimit` (that
limit is an extension extractors read), so the layer is the real
backstop; the layer deliberately sits above the per-line cap so a single
over-cap line still surfaces the route's semantic line-cap error rather
than the plain-text 413. `publish_schema` validation is applied per chunk inside the
sink-feeding stream (GW-01), so a Pub op registered with a sink-feeding stream (GW-01), so a Pub op registered with a
`publish_schema` enforces the same per-chunk contract over HTTP as over `publish_schema` enforces the same per-chunk contract over HTTP as over
the call protocol; a violation terminates the chunk stream with the call protocol; a violation terminates the chunk stream with
@@ -139,11 +147,13 @@ the doc does not preload operations.
the `/openapi.json` version bumps~~ — settled: first-line the `/openapi.json` version bumps~~ — settled: first-line
`{operation, chunk}` convention; terminal errors are plain HTTP `{operation, chunk}` convention; terminal errors are plain HTTP
status + JSON body (not an NDJSON line). status + JSON body (not an NDJSON line).
- The 2 MiB per-line cap (not a whole-body cap) bounds a single chunk; - The 2 MiB per-line cap bounds a single chunk (and, pre-newline, the
the total number of chunks is unbounded. Handlers that would receive unterminated buffer itself — GW-15); the total number of chunks is
unbounded streams over the wire get the same behavior over HTTP — unbounded but the whole request body is capped by the gateway
operators front the endpoint with the same body/timeout controls used body-limit layer (2 MiB + 64 KiB headroom → `413`, GW-15). Handlers
for any other streaming surface. that would receive unbounded streams over the wire get the same
behavior over HTTP — operators front the endpoint with the same
timeout controls used for any other streaming surface.
## References ## References