From c8c7bd0910f72013fe758a435985981b1f9c5d4a Mon Sep 17 00:00:00 2001 From: "glm-5.3-flash" Date: Sun, 30 Aug 2026 20:29:35 +0000 Subject: [PATCH] docs(adr-068): GW-15 body-limit layer + pre-extend cap in publish body handling --- .../decisions/068-gateway-publish-endpoint.md | 24 +++++++++++++------ 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/docs/architecture/decisions/068-gateway-publish-endpoint.md b/docs/architecture/decisions/068-gateway-publish-endpoint.md index 1d2748e..4ad3cf8 100644 --- a/docs/architecture/decisions/068-gateway-publish-endpoint.md +++ b/docs/architecture/decisions/068-gateway-publish-endpoint.md @@ -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 `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 -MiB, matching axum's default whole-body limit), not by the unbounded -chunk count. `publish_schema` validation is applied per chunk inside the +MiB), not by the unbounded chunk count. The per-line cap is checked +**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 `publish_schema` enforces the same per-chunk contract over HTTP as over 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 `{operation, chunk}` convention; terminal errors are plain HTTP status + JSON body (not an NDJSON line). -- The 2 MiB per-line cap (not a whole-body cap) bounds a single chunk; - the total number of chunks is unbounded. Handlers that would receive - unbounded streams over the wire get the same behavior over HTTP — - operators front the endpoint with the same body/timeout controls used - for any other streaming surface. +- The 2 MiB per-line cap bounds a single chunk (and, pre-newline, the + unterminated buffer itself — GW-15); the total number of chunks is + unbounded but the whole request body is capped by the gateway + body-limit layer (2 MiB + 64 KiB headroom → `413`, GW-15). Handlers + 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