A security and scalability pass over the API, following an external review. Authorization now fails closed, defaults are stricter, and run and connection caps are shared across workers when Redis is configured.
This release has breaking changes. Read "Before you upgrade" first.
pip install -U "10xgraph-api==0.8.0"- Authorization defaults to
ownershipwhenever auth is on, in every mode.- Before, it was
allow_allunlessMODE=production. - To keep the old development behaviour, set
"authorization": "allow_all".
- Before, it was
- Ownership checks fail closed.
- With auth on, the server refuses to start if your checkpointer cannot resolve thread owners (
aget_thread_ownernot implemented). - Implement it, or choose
allow_allor a custom backend.
- With auth on, the server refuses to start if your checkpointer cannot resolve thread owners (
- Unowned threads only allow creating actions.
- Reading, deleting, stopping or fixing a thread that doesn't exist now answers 403.
- Before, these returned an empty result.
gunicornis no longer a dependency.- Images built with
10xgraph buildinstall it themselves. - If you run gunicorn yourself, install it alongside the API:
pip install gunicorn uvicorn-worker. - The worker class is now
uvicorn_worker.UvicornWorker. Regenerate with10xgraph build --force, or update-k.
- Images built with
POST /v1/graph/fixreturnsstateas a JSON object, not a JSON-encoded string. Drop anyJSON.parse/json.loadson that field./v1/graph/invokeno longer returnsmeta.thread_name. The name is generated in the background and appears on the thread (GET /v1/threads).- Realtime init frames can no longer replace the system prompt unless you add
"system_prompt"towebsocket.realtime_client_overrides. trusted_proxy_headers: truenow trusts only loopback and private networks. List your proxies intrusted_proxies.- Production defaults are stricter:
MEDIA_REQUIRE_OWNERis on.graph_introspectionisscoped, so the graph structure, tools and state schema need thegraph:readscope.IS_DEBUGis forced off.
- Production 4xx responses keep their message; only 5xx responses are made generic.
- Generated Dockerfiles install only the dependencies you list.
10xgraph buildwarns if your requirements file orpyproject.tomldoes not list10xgraph-api.
- Log injection: values a client controls (ids, paths, rate-limit keys, run config, messages) are logged through
log_safe(), so a request can't forge log lines. - ReDoS fix: the JWT detection pattern in the log sanitizer now runs in linear time on crafted input.
- Token revocation: the new
token_revocationkey refuses revoked tokens before they expire, on HTTP and on every WebSocket run. - Size limit for WebSocket frames: JSON frames over
MAX_REQUEST_SIZEare refused. - Strict production checks:
STRICT_PRODUCTION_CHECKS=truerefuses to start on wildcardALLOWED_HOST/ORIGINSor enabled API docs. - Example fixes:
examples/security/no longer prints key or secret fragments, and API keys are hashed with HMAC-SHA-256 andAPI_KEY_PEPPER.
runskey:thread_ids(client|server).config_keysandstate_keysallow-lists.max_concurrent_per_user, default 10.timeout.
- Readiness probe:
GET /health/readychecks the checkpointer, Redis and the store. The k8s manifest uses it. - Shared caps: run and WebSocket connection caps are shared across workers through Redis when it is configured.
- Lighter images: Dockerfiles are built in two stages, so the runtime image ships only your code and a virtualenv: no compiler, no curl.
- Dependency changes:
- JSON responses are serialized by pydantic-core.
orjsonandplatformdirsare dropped.- The
uvicornfloor is 0.36.
See CHANGELOG.md for the full list.