Serve with gunicorn (1 worker) and raise the OHTTP request cap to 20 MiB#134
Merged
Conversation
The Image Studio sends reference images inline (base64) and allows up to 10 attachments, so multi-image edit requests can legitimately exceed the old cap sized for a single ~10 MiB image. 20 MiB covers a ~14 MiB raw payload after base64/JSON overhead while still bounding enclave memory use. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Pr2LKM6cnW5wbGo6DeRCZp
adambalogh
marked this pull request as ready for review
July 22, 2026 12:16
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two gateway-side fixes for the intermittent failures reported in OpenGradient/chat-app#704 (opaque 502s / CORS-blocked errors on the OHTTP chat path).
1. Serve with gunicorn instead of the werkzeug dev server
start.shranpython3 -m tee_gateway, which serves production traffic through Flask's development server (application.run()), whose fragile connection handling under concurrent load surfaces to clients as opaque connection resets — a 502 at the relay, CORS-blocked in the browser. Gunicorn was already pinned inpyproject.toml/uv.lockbut nothing invoked it (the app factory even has a comment anticipating it).Behavior-preservation constraints, encoded in the config:
/v1/keysprovider-key injection and the x402 middleware it installs, and the price-feed/heartbeat background threads. Clients (including the OHTTP relay) always hit the same process, so any request-to-request affinity (e.g. polling flows) is preserved by construction.threaded=Truebehavior.--timeout 0— no worker watchdog, so long-lived requests (image generation up to 120s, streamed completions) aren't killed mid-flight; duration is already bounded by the app's own httpx timeouts, and the dev server had no watchdog either.--max-requests— recycling the worker would regenerate the TEE keys mid-life.--preload— the price feed thread starts at import time and must live in the worker process.python3 -m tee_gateway(make test-local) still runs the dev server for local development. The deploy pipeline needs no changes — the entrypoint is baked into the image (CMD /bin/start.sh).2. Raise
_MAX_ENCAPSULATED_REQUEST_BYTESfrom 16 MiB to 20 MiBThe Image Studio sends reference images inline (base64) and allows up to 10 attachments, so multi-image edit requests could legitimately exceed the old cap sized for a single ~10 MiB image (surfacing as a flaky 413). Both enforcement points use the constant. The chat-app now also downscales references at attach time (OpenGradient/chat-app#710), so this is headroom, not an invitation for bigger payloads.
Testing
uv run pytest tee_gateway/test— 194 passed, 3 skipped (includes the oversized-body test, which derives its payload from the constant).start.shlocally:/health200 (live price feed),/v1/ohttp/config200, and garbage to/v1/ohttpreturns the proper{"error": "malformed encapsulated request"}.Note: both changes alter the enclave image, so PCR measurements move on the next deploy.
🤖 Generated with Claude Code
https://claude.ai/code/session_01Pr2LKM6cnW5wbGo6DeRCZp