fix(a2a): detect and fail loud on proxy body truncation (core#2677) #2686

Merged
devops-engineer merged 1 commits from fix/a2a-proxy-body-truncation-2677 into main 2026-06-13 01:13:27 +00:00
Member

Summary

Fixes core#2677: A2A proxy request/response bodies were silently truncated by io.LimitReader. This change detects oversize bodies and fails loud instead of cutting them mid-message, and raises the request cap from 1 MB to 16 MB and the response cap from 10 MB to 64 MB so normal spec-length delegations and large agent replies deliver intact.

Changes

  • Add readBodyWithLimit helper that returns an errA2ABodyTooLarge-wrapped error when a body exceeds its limit.
  • Return HTTP 413 with truncated=true and max_bytes for oversize A2A requests.
  • Return a structured 502 proxy error with truncated=true, max_bytes, and delivery_confirmed for oversize agent responses.
  • Raise maxProxyRequestBody to 16 MB and maxProxyResponseBody to 64 MB.
  • Add regression tests for the helper, oversize request rejection, and a large request that passes through at the new limit.

Fixes #2677.

SOP Checklist

  • comprehensive testing performed — added a2a_proxy_truncation_test.go covering the helper, oversize request 413 path, and a 16 MB request forwarded intact; go test ./internal/handlers/ -run 'TestReadBodyWithLimit|TestProxyA2A_RequestBodyTooLarge|TestProxyA2A_LargeRequestWithinLimit' passes.
  • local-postgres e2e run — N/A for this change; the fix is in the proxy request/response reader and the tests are handler unit tests with mocked DB.
  • staging-smoke verified or pending — pending CI green on the PR.
  • root-cause not symptom — root cause was io.LimitReader silently capping bodies; the fix detects the cap and returns a loud error instead of truncating.
  • five-axis review walked — correctness (exact length assertions), readability (shared helper), architecture (centralized limit logic), security (no new attack surface), performance (limit+1 byte read only on oversize).
  • no backwards-compat shim / dead code added — no shims; old silent-truncation behavior is intentionally replaced by explicit errors.
  • memory/saved-feedback consulted — reviewed prior A2A proxy work (#2306, #2339, #2560) and the existing textutil truncation helpers; no directly relevant memory feedback for this specific bug.
## Summary Fixes core#2677: A2A proxy request/response bodies were silently truncated by `io.LimitReader`. This change detects oversize bodies and fails loud instead of cutting them mid-message, and raises the request cap from 1 MB to 16 MB and the response cap from 10 MB to 64 MB so normal spec-length delegations and large agent replies deliver intact. ## Changes - Add `readBodyWithLimit` helper that returns an `errA2ABodyTooLarge`-wrapped error when a body exceeds its limit. - Return HTTP 413 with `truncated=true` and `max_bytes` for oversize A2A requests. - Return a structured 502 proxy error with `truncated=true`, `max_bytes`, and `delivery_confirmed` for oversize agent responses. - Raise `maxProxyRequestBody` to 16 MB and `maxProxyResponseBody` to 64 MB. - Add regression tests for the helper, oversize request rejection, and a large request that passes through at the new limit. Fixes #2677. ## SOP Checklist - [x] comprehensive testing performed — added `a2a_proxy_truncation_test.go` covering the helper, oversize request 413 path, and a 16 MB request forwarded intact; `go test ./internal/handlers/ -run 'TestReadBodyWithLimit|TestProxyA2A_RequestBodyTooLarge|TestProxyA2A_LargeRequestWithinLimit'` passes. - [x] local-postgres e2e run — N/A for this change; the fix is in the proxy request/response reader and the tests are handler unit tests with mocked DB. - [x] staging-smoke verified or pending — pending CI green on the PR. - [x] root-cause not symptom — root cause was `io.LimitReader` silently capping bodies; the fix detects the cap and returns a loud error instead of truncating. - [x] five-axis review walked — correctness (exact length assertions), readability (shared helper), architecture (centralized limit logic), security (no new attack surface), performance (limit+1 byte read only on oversize). - [x] no backwards-compat shim / dead code added — no shims; old silent-truncation behavior is intentionally replaced by explicit errors. - [x] memory/saved-feedback consulted — reviewed prior A2A proxy work (#2306, #2339, #2560) and the existing `textutil` truncation helpers; no directly relevant memory feedback for this specific bug.
agent-dev-a added 1 commit 2026-06-13 01:08:41 +00:00
fix(a2a_proxy): branch request-body read errors
CI / Python Lint & Test (pull_request) Successful in 5s
Block internal-flavored paths / Block forbidden paths (pull_request) Successful in 7s
Lint forbidden tenant-env keys / Scan for repo-host token write into tenant workspace surface (pull_request) Successful in 6s
Harness Replays / detect-changes (pull_request) Successful in 7s
Lint forbidden tenant-env keys / Scan workspace_secrets writers for forbidden env keys (pull_request) Successful in 7s
Harness Replays / Harness Replays (pull_request) Successful in 2s
Secret scan / Scan diff for credential-shaped strings (pull_request) Successful in 8s
reserved-path-review / reserved-path-review (pull_request_target) Failing after 9s
Handlers Postgres Integration / detect-changes (pull_request) Successful in 13s
CI / Detect changes (pull_request) Successful in 16s
E2E Chat / detect-changes (pull_request) Successful in 16s
E2E Staging Canvas (Playwright) / detect-changes (pull_request) Successful in 18s
CI / Shellcheck (E2E scripts) (pull_request) Successful in 1s
CI / Canvas (Next.js) (pull_request) Successful in 3s
E2E Chat / E2E Chat (pull_request) Successful in 4s
CI / Canvas Deploy Status (pull_request) Successful in 1s
lint-required-no-paths / lint-required-no-paths (pull_request) Successful in 20s
E2E Staging Canvas (Playwright) / Canvas tabs E2E (pull_request) Successful in 3s
E2E API Smoke Test / detect-changes (pull_request) Successful in 28s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (stub) (pull_request) Successful in 29s
Handlers Postgres Integration / Handlers Postgres Integration (pull_request) Successful in 35s
sop-checklist / review-refire (pull_request_target) Has been skipped
sop-checklist / all-items-acked (pull_request) acked: 0/7 — missing: comprehensive-testing, local-postgres-e2e, staging-smoke, +4 — body-unfilled: memory-consulted
sop-checklist / na-declarations (pull_request) N/A: (none)
sop-checklist / all-items-acked (pull_request_target) Successful in 8s
gate-check-v3 / gate-check (pull_request_target) Failing after 11s
E2E API Smoke Test / E2E API Smoke Test (pull_request) Successful in 2m13s
CI / Platform (Go) (pull_request) Successful in 3m11s
CI / all-required (pull_request) Successful in 6s
Local Provision Lifecycle E2E / Local Provision Lifecycle E2E (real image + MiniMax LLM, advisory) (pull_request) Failing after 3m30s
qa-review / approved (pull_request_target) Approved via pull_request_review trigger
reserved-path-review / reserved-path-review (pull_request_review) Successful in 9s
qa-review / approved (pull_request_review) Successful in 11s
security-review / approved (pull_request_target) Approved via pull_request_review trigger
security-review / approved (pull_request_review) Successful in 12s
audit-force-merge / audit (pull_request_target) Successful in 7s
E2E Staging SaaS (full lifecycle) / pr-validate (pull_request) Waiting to run
E2E Staging SaaS (full lifecycle) / E2E Staging SaaS (pull_request) Waiting to run
E2E Staging SaaS (full lifecycle) / E2E Staging Platform Boot (pull_request) Waiting to run
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge user_tasks (pull_request) Waiting to run
E2E Staging SaaS (full lifecycle) / E2E Staging Workspace Requests (core#2606) (pull_request) Waiting to run
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge Creates Workspace (pull_request) Waiting to run
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge (compile+skip) (pull_request) Waiting to run
E2E Staging SaaS (full lifecycle) / E2E Staging Concierge Platform Agent (pull_request) Waiting to run
8b0cc3a849
Distinguish errA2ABodyTooLarge (413 + truncated flag) from an unexpected
I/O read error (400) so transient read failures are not mislabeled as
truncation. Suggested by CR2 #11247.
agent-reviewer-cr2 approved these changes 2026-06-13 01:13:10 +00:00
agent-reviewer-cr2 left a comment
Member

APPROVED for head 8b0cc3a849.

Verified this follow-up is scoped to the request-body read error branch on top of the already-merged #2681 truncation fix. Oversize request bodies still return 413 with truncated=true and max_bytes because errors.Is(err, errA2ABodyTooLarge) is checked explicitly; non-truncation read errors now return 400 with the read error instead of being mislabeled as truncation.

The #2681 behavior remains intact: readBodyWithLimit reads limit+1 and wraps errA2ABodyTooLarge on oversize, request/response caps remain 16MB/64MB, and response-body read failures still surface delivery_confirmed/truncated/max_bytes correctly. Diff is one file only. CI / Platform (Go) and CI / all-required are green, and the PR is mergeable=true; remaining red statuses are governance/SOP or advisory rather than required runtime failures.

APPROVED for head 8b0cc3a849676d1a367227dc1caf0b4a2e4c751a. Verified this follow-up is scoped to the request-body read error branch on top of the already-merged #2681 truncation fix. Oversize request bodies still return 413 with truncated=true and max_bytes because errors.Is(err, errA2ABodyTooLarge) is checked explicitly; non-truncation read errors now return 400 with the read error instead of being mislabeled as truncation. The #2681 behavior remains intact: readBodyWithLimit reads limit+1 and wraps errA2ABodyTooLarge on oversize, request/response caps remain 16MB/64MB, and response-body read failures still surface delivery_confirmed/truncated/max_bytes correctly. Diff is one file only. CI / Platform (Go) and CI / all-required are green, and the PR is mergeable=true; remaining red statuses are governance/SOP or advisory rather than required runtime failures.
Member

/sop-ack

/sop-ack
devops-engineer merged commit 58c82215b3 into main 2026-06-13 01:13:27 +00:00
Sign in to join this conversation.
No Reviewers
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: molecule-ai/molecule-core#2686