You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Commit e2354ee
Browse filesBrowse the repository at this point in the historyBrowse files
Copy file name to clipboardExpand all lines: CHANGELOG.md
+6Lines changed: 6 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -15,6 +15,7 @@ Format inspired by [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
15
15
- The worker pool now also refuses a dispatch when the chosen slot already has enough work ahead of it that the projected wait, measured as the slot's pending count times the per-task deadline, would exceed a configurable ceiling. A task that would otherwise sit behind a long backlog is turned away fast instead of waiting indefinitely, and the refusal records whether it was the overall depth or the projected wait that triggered it
16
16
- The template engine now carries a cumulative budget across a single render, counting every `#each` body execution and every output character produced anywhere in that render, including inside nested loops and pulled-in includes. When the total loop executions cross one ceiling or the total output length crosses another, the render stops with a clear data error instead of being allowed to spin or grow without bound, and the same budget guards both the buffered render path and the streaming one
17
17
- Static file serving now understands a single byte-range request. Every static response advertises that ranges are accepted, and a request asking for one contiguous range is answered with a partial-content response carrying the matched byte window and a stream bounded to exactly those bytes, releasing the file handle when the window is fully sent, errors, or is cancelled. A range that names a window the file cannot satisfy is refused with a clear range-not-satisfiable response stating the true size, while an absent, multi-part, or malformed range simply falls back to the full file as before, and only the bytes inside the requested window are ever read off disk
18
+
- Two middleware lifecycle events now stream through the observability bus. A session cookie that fails to decode surfaces as `session:invalid` carrying the cookie name and a reason that says whether the value was tampered with, has aged past its limit, or was simply malformed, while the request still proceeds with no session attached. A custom CSRF rule that throws surfaces as `csrf:rule-error` carrying which rule broke, so a faulty validator is visible rather than swallowed
18
19
19
20
### Changed
20
21
@@ -26,6 +27,9 @@ Format inspired by [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
26
27
- A WebSocket handshake that arrives with no `Origin` header used to always be waved through, so a request with the header simply omitted slipped past even a configured allowlist or wildcard policy. A missing `Origin` is now accepted only when no policy is configured at all and the same-origin default applies. The moment an explicit allowlist or wildcard is set, an absent `Origin` fails closed and the upgrade is refused
27
28
- A HEAD response used to read the entire GET body into memory just to count its bytes and fill in `Content-Length`, so answering a HEAD for a large representation pulled the whole payload through anyway. The body is now cancelled without being buffered, an existing `Content-Length` is preserved as-is, and none is computed, so a HEAD stays cheap and headers-only
28
29
- A top-level template render that failed while resolving or rendering used to throw straight out with no lifecycle signal, so a watcher saw the successful `view:rendered` for a good render but nothing at all when one broke. A render that throws now emits a `view:error` carrying the template path and the cause before the error propagates onward, so a broken render is just as observable as a good one, while an included template still leaves all emission to the top-level render that pulled it in
30
+
- The per-request context now carries the router event emitter, handed down from the request layer and exposed only through the internal framework surface, so built-in middleware can raise a lifecycle event without reaching for a global. When no emitter is wired the call is a quiet no-op
31
+
- Decoding a signed session cookie used to collapse every kind of failure into a bare empty result, so a tampered signature, an aged-out token, and a plain unparseable value all looked the same and none of them left a trace. The decoder now returns either the recovered data or a single reason naming what went wrong, the middleware reports that reason as a `session:invalid` event, and the request still continues with no session attached just as before
32
+
- A custom CSRF rule that threw used to be silently treated as a failed check with nothing recorded, so a buggy validator looked indistinguishable from an honestly rejected request. A throwing rule still fails its own check and falls safe to a refusal, but now it also emits a `csrf:rule-error` naming which of the two rules broke, so the fault surfaces instead of hiding
29
33
30
34
### Fixed
31
35
@@ -39,6 +43,8 @@ Format inspired by [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
39
43
-`worker:timeout`, `worker:crash`, `worker:respawn`, and `worker:rejected` added to the observability `Event` union, the first two carrying the raw `Error` alongside the slot index and the timeout duration where relevant, and the last carrying a `reason` of either depth or projected wait alongside the current and maximum queue depth
40
44
-`EngineOptions` and `HandlerOptions` gain optional `maxRenderIterations` and `maxOutputSize` fields capping the total `#each` body executions and the total output characters allowed in a single render, each defaulting to a fixed ceiling when left unset, while the existing `maxIterations` is now documented as the per-`#each`-block limit
41
45
-`RenderBudget` exported as a public interface describing the per-render cumulative tally of total `#each` body executions and total output characters that a render threads through its loops and includes
46
+
-`session:invalid` and `csrf:rule-error` added to the observability `Event` union, the first carrying the cookie name and a `reason` of tampered, expired, or malformed, and the second carrying the raw `Error` alongside the `rule` that threw, either origin or secFetchSite
47
+
-`SessionDecodeResult` exported as a public discriminated type describing a session decode as either the recovered data or a single failure reason of tampered, expired, or malformed
0 commit comments