Skip to content

feat(server): bound HTTP request bodies and active responses - #2162

Open
AlexStocks wants to merge 3 commits into
masterfrom
codex/2084-http-resource-bounds
Open

AlexStocks wants to merge 3 commits into
masterfrom
codex/2084-http-resource-bounds

Conversation

@AlexStocks

@AlexStocks AlexStocks commented Oct 21, 2026 •

Copy link
Copy Markdown
Contributor

Which issue or RFC does this PR close?

Refs #2084 (R7). Preserve the mandatory stateless MCP transport introduced by merged #2134.

Rationale for this change

Incoming bodies could consume unbounded resources before domain validation, and active external requests had no process-wide admission bound. The Server now rejects excess work before downstream parsing and reserves capacity through the actual outward response send.

What changes are included in this PR?

  • POWERCONTEXT_SERVER_HTTP_MAX_REQUEST_BODY_BYTES, default 16 MiB: reject oversized declared or actual streamed bodies with 413/request_too_large, stopping at the first excess chunk.
  • POWERCONTEXT_SERVER_HTTP_MAX_CONCURRENT_REQUESTS, default 64 per process: return 503/server_overloaded and Retry-After: 1 immediately without reading rejected bodies.
  • Place admission outside the response-forwarding middleware so a blocked external send retains its slot. Release exactly once on final response completion, exception or cancellation.
  • Buffer accepted chunks within the byte cap. Trusted internal MCP-to-HTTP projections reuse their external admission; user headers cannot bypass it.
  • Keep master's mandatory stateless MCP transport and request-scoped authentication. No stateful configuration switch is introduced.
  • Correct the ZCode evidence collector to correlate JSON-RPC responses rather than count HTTP 307 redirects as executed tools, while retaining tool and protocol failures.
  • Document limits, costs and transport behavior in both locales.

Are there any user-facing changes?

Requests can receive 413 or 503 before reaching the route. Both limits must be positive. Lower body caps may reject otherwise valid domain input. The default admits the current 5 MiB Skill archive's 6,990,508-character base64 field plus bounded metadata.

Limits are per process. Sixty-four 16 MiB bodies already represent 1 GiB before parsing overhead; replay briefly copies each accepted body once. Long responses retain capacity until sent. Request-rate quotas, upload timeouts, connection limits and aggregate limits across processes remain deployment responsibilities.

MCP retains the existing stateless authentication behavior: no transport session ID or resumable cross-request SSE stream. Persisted Scope, Memory and Handoff data are unaffected.

How was this change tested?

  • Eleven original boundary regressions failed before implementation; focused original Server/MCP suites passed 87 tests.
  • Review regression through create_server_app(): block the outward /health/live body with concurrency one; before the fix subsequent requests return 200 instead of 503. After the fix all four are rejected without body reads, and capacity recovers after send completion. All 16 admission tests pass on Windows.
  • On Linux/Python 3.11, admission, real Uvicorn/HTTP/SQLite/FastMCP, request authentication, MCP and access suites: 40 passed. One-slot and two-slot real clients both work with the current stateless transport. Includes master's cross-user, identity update, revocation and reconnect regressions.
  • The original branch passed two pinned real ZCode CLI controlled acceptances, each covering nine core scenarios; inference was a protocol fixture. Collector corrections have RED/GREEN evidence and 26 related protocol/host/collection tests passed.
  • Changed-file pre-commit/Ruff, complete Linux/Python 3.11 Ty and whitespace checks pass.

Native Windows Ty has existing POSIX typing diagnostics; Linux typing is the reported full check. No real host UI or OceanBase multi-node acceptance is claimed.

AI usage statement

Codex assisted implementation, review and the reported validation.

Copilot AI balanced review requested due to automatic review settings October 21, 2026 08:32

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@hidb4ai hidb4ai left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

HTTP admission can release capacity before the outward response finishes; see the inline finding.

Comment thread src/powercontext/server/factory.py Outdated
configured_middleware.insert(
0,
Middleware(
HttpResourceLimitsMiddleware,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] Hold admission through the outer response send

create_app() subsequently prepends the attach_request_id and negotiate_dream_contract BaseHTTPMiddleware layers, so this limiter observes completion on their internal response channel before the response has finished sending. With max_concurrent_requests=1, blocking the external ASGI send on the /health/live response body still lets four subsequent requests return 200; they should return 503 while that response is blocked. Placing the same limiter outside those response-forwarding layers makes all four return 503. Slow clients can therefore retain unfinished responses beyond the configured cap. Keep admission held through the final outward response send, and add a blocked-send regression through create_server_app().

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 26ea7ba. Admission now wraps the response-forwarding middleware and retains capacity while the outward ASGI send is blocked. A create_server_app() regression reproduces 200 before the fix, then verifies four 503 responses without body reads and recovery after the first send finishes. The existing cleanup test now waits for outward completion rather than its inner send. Current master was merged while retaining its mandatory stateless MCP authentication; related Linux admission/MCP/authentication suites passed 40 tests.

Merge current master, retain its mandatory stateless MCP authentication,
and place HTTP admission outside response-forwarding middleware. A blocked
external send now keeps the only slot reserved. Wait for actual outward
completion in the existing cleanup regression instead of an inner send.
Remove the superseded stateful opt-in and document the current transport.

Constraint: Do not restore cross-request authentication context retention.
Scope-risk: Limits remain process-local and long responses retain capacity.
Tested: Blocked-send RED returned 200 instead of 503; all 16 admission tests passed after repair; Linux HTTP/MCP/authentication suites 40 passed; complete Linux Python 3.11 Ty; changed-file pre-commit.
Copilot AI balanced review requested due to automatic review settings October 21, 2026 12:51

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

An organization owner can choose the repository organization as the billing source for reviews requested by members with a paid Copilot license. Learn about Copilot code review billing.

@AlexStocks AlexStocks changed the title feat(server): bound HTTP admission and expose stateless MCP feat(server): bound HTTP request bodies and active responses Oct 21, 2026
@AlexStocks AlexStocks added the 1.4.1 v1.4.1 release tracking label Oct 21, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

1.4.1 v1.4.1 release tracking

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants