Chirp 0.7.0

Production safety defaults, Kida 0.9 contract diagnostics, request URL scopes, deferred cache reuse, Chirp UI 0.9, and SSE/markdown hardening.

Focus: tighten production trust boundaries and startup diagnostics while adding the URL-scope and deferred-cache primitives needed by larger hypermedia apps.

This release requireskida-templates>=0.9.0 and chirp-ui>=0.9.0 for the optional UI layer, documents the bengal-pounce>=0.7.0 production boundary, adds security-sensitive defaults for cache, auth rate limiting, CORS, SSE, markdown, and freeze output, and expands app.check()so more template, route, reactive, and fragment mistakes are caught before deployment.


Highlights

Kida 0.9 contract diagnostics

Chirp now surfaces Kida 0.9 component-call, dotted context-contract, literal-attribute, escape-audit, and privacy-lint diagnostics throughapp.check(). Missing-block behavior remains compatible with Chirp's BlockNotFoundErrorcontract even when Kida reports missing blocks with its typed runtime error.

Production safety defaults

Several defaults now fail safer:

  • CacheMiddleware skips reads and writes for GET requests with Cookie or Authorizationheaders.
  • Auth rate limiting keys by socket client address unless the app explicitly configures a trusted header.
  • Credentialed wildcard CORS is rejected.
  • app.check() flags wildcard allowed_hostsoutside development.
  • chirp freeze rejects expanded URLs containing . or ..path segments before writing files.

SSE and markdown hardening

SSEEvent rejects event names and IDs containing CR, LF, or NUL characters, rejects negative retry values, and normalizes carriage returns in data frames. Markdown rendering and register_markdown_filter()sanitize unsafe HTML, event attributes, and unsafe link/image URLs by default.

Request URL scopes

RequestUrlScope, request.with_url_scope(...), request.scoped_url(path), and request.url_for(...) let middleware generate tenant or base-path public URLs without changing app.url_for(...) or rewriting rendered HTML. Auth redirects preserve that scope in generated ?next=values.

Deferred cache and reactive checks

The provisionalDeferredCache enables explicit server-side reuse of Suspense deferred values with TTL expiry and same-key in-flight deduplication. Reactive apps can now feed emitted paths, audience scopes, connection scopes, and dependency indexes into app.check()so missing subscribers and dependency drift are visible at startup.

Fragment and form contract coverage

app.check() warns when fragment blocks rely on imports or bindings declared only inside ancestor blocks. chirp.testing adds RouteSmokeCase and assert_route_smoke for full-page and fragment route smoke checks. When CSRFMiddlewareis active, static mutating forms without an obvious CSRF field now produce contract warnings.

Chirp UI 0.9 floor and dev reload polish

The optionalui extra, development example dependency, and new scaffolded projects now use chirp-ui>=0.9.0, so fresh apps pick up the current companion UI layer. Debug browser reload now boots idempotently, skips htmx swaps, honors reload_include=()as an opt-out, and avoids passing browser asset suffixes to Pounce as process-reload extensions.


Migration Notes

Apps behind a trusted proxy that intentionally key auth rate limits byX-Forwarded-For must pass AuthRateLimitConfig(key_header="x-forwarded-for").

Credentialed CORS must list explicit origins instead of using a wildcard.

Trusted markdown that intentionally preserves raw HTML can passsanitize=False.

Apps constructingSSEEvent(event=...) or SSEEvent(id=...)must pass single-line field values.

Untargeted yieldedFragment values in EventStream now emit on the documented htmx SSE messagechannel. Targeted fragments still use their target as the event name.

Dependencies

  • kida-templates>=0.9.0
  • bengal-pounce>=0.7.0
  • chirp-ui>=0.9.0

Upgrading

uv pip install --upgrade "bengal-chirp>=0.7.0"
pip install --upgrade "bengal-chirp>=0.7.0"