Changelog / Release Notes
This page records public release notes for Quater.
Prerequisites
Read Stability before upgrading Quater versions.
0.1.0
Fixed
- Fixed
:intpath parameters so only ASCII digit segments match integer routes. Signed values, underscore grouping, Unicode digits, and surrounding whitespace now fall through as non-matching paths instead of resolving to the same handler. - Fixed MCP and CLI action calls for
:intpath parameters so they reject the same non-canonical values as HTTP instead of accepting Pythonint()aliases. - Fixed RSGI request body limits so chunked uploads without
Content-Lengthreturn413 Payload Too Largeas soon as the stream crossesmax_body_size. - Fixed remote CLI action calls so handler
ValueErrors and streaming response failures return500 action_failedinstead of being mistaken forresponse_too_large. (#97) - Fixed route compilation so path parameter annotations must match route converters, preventing
{id}handlers annotated asintfrom receiving strings at runtime. (#89)
0.1.0b1
This started Quater's beta release train for 0.1. It marked the HTTP/MCP/CLI surface model, per-surface auth, resource lifecycle, and testing helpers as ready for broader evaluation before the final 0.1.0 release.
Added
- Added support for declaring a
Resourcein a parameter'sAnnotated[...]type metadata (for examplesession: Annotated[Session, db_session]) as an alternative to the decoratorinject={...}map. This allows reusableAnnotatedaliases shared across handlers, type-checks with no cast, and produces the same binding — excluded from caller-facing schemas — asinject. Declaring a parameter's resource in both places, or as a parameter default, is rejected during route compilation. (#48) - Added support for resources that depend on other resources. A
Resourceprovider can now declare parameters annotated withAnnotated[T, other], the same way a handler does; Quater resolves each dependency first, once, from the request's shared scope, and passes it in. Dependencies stay private to the provider — they never appear in OpenAPI, MCP, or CLI schemas. The dependency graph is validated when routes compile: dependency cycles and provider parameters that are neither the request nor a resource fail at startup. (#53) - Added
scope="function"forResourceproviders that need to finish before the response is sent, such as transaction/unit-of-work providers that commit afteryield. The defaultscope="request"remains streaming-safe, and request-scoped resources cannot depend on function-scoped resources. (#83) - Added real-database integration tests for the resource lifecycle — async and sync sessions, transaction commit and rollback, and one session shared per request — across HTTP, MCP, and CLI, on a reusable SQLAlchemy/SQLite test harness. (#57)
- Added a
CliTestClient, reachable asclient.clion the in-processTestClient, withcall()andmanifest()helpers for the CLI action surface. HTTP, MCP (client.mcp), and CLI now each have a first-class test helper. (#57) - Added security regression coverage proving callers cannot spoof
request.context.sourceorrequest.context.entrypointthrough HTTP headers, request bodies, MCP metadata, or remote CLI action payloads. HTTP remainsapi/server, MCP remainsmcp/server, remote CLI remainscli/server, and local CLI remainscli/local. (#70) - Added a cross-surface parity test matrix that calls the same handler through HTTP, MCP
tools/call, local CLI, and remote CLI, then checks declared inputs, defaults, optional values, validation failures, handler errors, and the documented unknown-extra argument policy. (#68) - Added contributor documentation, GitHub issue and PR templates, and a required pre-commit setup so new contributors can follow the same basic checks used by CI.
Changed
- Changed request handling to resolve every injected
Resourcethrough a single per-request scope. The sameResourcenow opens once per request — one database session serves the whole request — and is torn down once, in reverse order, even when a resource fails to open partway through. The scope is lazy: a request that injects nothing never allocates one, and nothing opened for one request is ever visible to another. The MCP and CLI paths now share that one scope between authentication and the handler instead of building separate request objects. (#52) - Reworked authentication into per-surface
AuthConfigobjects. An app is configured withQuater(auth=[AuthConfig(fn, surfaces=["api", "mcp", "cli"])]), and exactly one authenticator runs per request, chosen byrequest.context.source. The authenticator receives the realRequest; after cheap header/token checks it can callawait request.resolve(resource)to open the same request-scoped resource that the handler injects through anAnnotated[T, resource]alias. That resource shares the handler's scope, so a session auth opens to verify the caller is the same session the handler injects.AuthContextgained a typedpayloadslot to carry the loaded object (for example theUser) so a handler reads it back through a resource with no second query. A surface covered byAuthConfigprotects its exposed routes by default; routes opt out withpublic=True(every exposed surface) orpublic=["mcp", ...](named surfaces). Remote CLI now reads the action name before auth, matching MCP. (#54) - Changed global middleware and exception handlers to wrap the real route handler on HTTP, MCP tools, and CLI actions. MCP
tools/calland CLI action calls now run globalbefore,around,after, and exception handlers around the handler response before Quater creates the JSON-RPC or action RPC envelope. Remote CLI no longer runs global middleware on the outer RPC wrapper, avoiding double execution. Migration note: HTTP-shaped global middleware such as cookies, redirects, HTML pages, or browser-only headers should checkrequest.context.sourceand skip"mcp"/"cli"when needed. (#55) - Changed empty required JSON body binding to fail as request validation with
Missing required body parameter: ...across HTTP, MCP tools, local CLI, and remote CLI. Directawait request.json()still reports malformed JSON for an empty or invalid body. (#68)
Fixed
- Fixed yield resource cleanup so handler/authentication errors are thrown into generator providers. Rollback branches now run on request failure, and cleanup failures during an existing error no longer hide the primary response. (#83)
- Fixed HTTP path parameter parity across RSGI, ASGI, and WSGI. ASGI now percent-decodes
raw_pathbefore route matching, so encoded slashes split path segments the same way they do on Quater's primary Granian/RSGI path; WSGI also recovers UTF-8 path bytes before dispatch. (#78) - Fixed RSGI response cleanup to await response finalizers before the adapter returns, matching ASGI and WSGI cleanup behavior for regular and streaming responses. (#77)
- Fixed protected action approval hashes to use the bound and validated handler arguments, including defaults and normalized scalar values, instead of the raw caller payload. Request and resource values stay out of the hash, so approval tokens now map to the operation Quater will actually run. (#72)
- Isolated synthetic MCP and CLI action requests from the outer transport request. Route handlers now only receive
Header()andCookie()values that were passed as action arguments, plus framework-generated headers needed for the synthetic body. Transport auth, cookies, protocol headers, request ids, and content length stay on the MCP/CLI surface instead of leaking into handler binding. (#64) - Fixed HTTP JSON body binding so an empty optional or defaulted
Bodyis treated like missing input, matching MCP and CLI action calls. Required empty bodies still return400 Missing required body parameter; non-empty malformed JSON and typed JSONnullare still rejected normally. (#66)
Removed
- Breaking: removed the
mcp_auth=andcli_auth=constructor hooks, the per-route and per-groupauth=argument, theAuthRequesttype, and theAuthenticatealias. Migrate by moving each authenticator into the matching surface'sAuthConfigand switching authenticators to take the realRequest; routes that were public dropauth=and addpublic=only where anAuthConfignow covers their surface. See Auth Model.
0.1.0a2
This alpha tightens fail-fast validation around auth headers, CORS, production-facing config, and adapter response safety.
Fixed
- Added duplicate
AuthorizationandProxy-Authorizationheader validation before auth hooks run. - Added CORS
allowed_methodsvalidation during configuration and includedHEADin the default CORS method set. - Added validation for single-string, bytes, mapping, and non-string values in CORS list-like config fields before app startup.
- Changed ASGI path extraction to preserve encoded path segments from
raw_pathwhen servers provide it. - Added validation for single-string and non-string values in list-like config fields before app startup.
- Added validation for non-string optional config fields and boolean or non-numeric limit settings before app startup.
- Added malformed
Cookieheader handling that returns400 Bad Request. - Added malformed bracketed
Hostheader validation before surface auth runs. - Added response value validation before adapters write HTTP responses, so bad response bodies, status codes, and stream chunks fail safely.
- Changed ASGI request body reads to reject client disconnects instead of passing partial request bodies to handlers.
- Changed surface auth to run even when a request already has an auth context.
- Changed request body reads to cache read and size-limit failures instead of invoking the body reader again.
- Changed shutdown hook failures to mark lifespan as failed instead of started.
- Changed tool and action registry access to compile dirty routes once and keep the HTTP router current.
- Removed duplicate request security-context resolution from the HTTP hot path.
- Changed size-string parsing to reject whitespace between the number and unit.
- Changed remote CLI config to store only connection details and fetch action discovery on demand instead of persisting remote manifests.
0.1.0a1
This is the first alpha release shape for evaluation.
Added
Quaterapplication object with RSGI, ASGI, and WSGI adapters.- Typed route decorators for
GET,POST,PUT,PATCH,DELETE, and custom methods. - Path, query, header, cookie, and JSON body binding.
msgspecJSON serialization and validation.- Route-level auth with
auth=. - MCP tools with
tool=True,mcp_auth,tools/list, andtools/call. - Human-readable MCP docs at
/mcp/docs. - CLI actions with
cli=True, local execution, remote execution, dry-run, and approval hooks. - Generated OpenAPI JSON and Swagger UI.
Resourceinjection andapp.state.- Route groups that flatten at startup.
- In-process
TestClientandMCPTestClient. - CORS, allowed-host checks, body limits, security headers, request IDs, signed cookies, and production safety checks.
Breaking
No previous public release exists, so there are no migration steps.
Fixed
No previous public release exists.
Deprecated
No public API is deprecated in this alpha.
What Can Go Wrong
No matching distribution found for quater==0.1.0a1 : Check whether you are installing from the intended package index. Early alpha testing may use TestPyPI before the package is published to PyPI.
Also See
- Known Limitations: current gaps.
- Stability: version pinning and upgrade expectations.
- Quickstart: first working app.