Skip to content

refactor: admit routes through Hono middleware - #1721

Merged
ColeMurray merged 2 commits into
mainfrom
refactor/hono-pr1-admit-middleware
Sep 2, 2026
Merged

refactor: admit routes through Hono middleware#1721
ColeMurray merged 2 commits into
mainfrom
refactor/hono-pr1-admit-middleware

Conversation

@ColeMurray

@ColeMurray ColeMurray commented Sep 2, 2026

Copy link
Copy Markdown
Owner

Summary

Second step of the series retiring the routing adapter left by #1716 (guardrails landed in #1720). This PR replaces the mechanism around every route while leaving all 171 route handlers untouched; after it, the remaining shim is one legacy() adapter function that later PRs delete module by module.

Admission is Hono middleware. admit(policy) (src/routing/admit.ts) evaluates the route's declarative policy through the unchanged admitRoute() pipeline and sets c.var.admission. Denials answer from the middleware, with an authorization denial audited before anything is logged, as before. A principal-less policy that requires authorization is refused when the middleware is built.

The lifecycle is one app.use("*") (src/routing/hono-app.ts) that owns what dispatchMatchedRoute and the outer handler used to: the DB guard (undecorated 503), the HEAD guard (404, never Hono's implicit GET), the request context and start time, the request log, the audit of allowed decisions after the handler including the 500 path, and the common response headers with the route's Cache-Control. app.onError maps HttpError to the { error } envelope and logs anything else as the sanitized 500; a non-Error throw takes the same path.

Default deny. If a handler answers without admit() having run ahead of it, the lifecycle replaces the response with a sanitized 500, drops the handler's headers, and logs router.unadmitted_response. Every policy, including public, sets the admission variable, so a route registered without admit() fails closed on its first request; the matrix suite drives every route in CI. This is the request-time check chosen in review of #1720 over the build-time registry.

Host-injected entrypoint. createControlPlaneApp(catalog, host) takes a host whose one job is to build the BackgroundTasks port from whatever the platform passed as the execution context. cloudflareHost wraps waitUntil; the unit-test host hands the port straight through, which deletes the fake ExecutionContext in router.test-support.ts. handleControlPlaneHttp and createControlPlaneHttpHandler keep their signatures, so index.ts is unchanged.

Deleted: Route.pattern, parsePattern, the raw-path re-match and its router.match_mismatch branch, route-dispatch.ts, the start-time WeakMap. Admission now takes params: RouteParams (raw segments read back from the pathname by position, src/routing/route-params.ts) instead of a RegExpMatchArray, and legacyMatch() rebuilds the array handlers still read from those params.

Test changes. Unit tests that selected routes by route.pattern use matchRoute() / routePathPattern() from test support instead; no assertions changed. The conformance snapshot drops the pattern field from each of its 171 rows (identities, groups, policies, and order verified identical before and after). New hono-app.test.ts covers the default deny (including header non-leakage), preflight and 404 exemptions, HEAD, HttpError mapping, unexpected and non-Error throws, and both build-time refusals.

Behavior notes

  • No status, body, header, or log-ordering change on any route. The four route-matrix snapshots are byte-identical.
  • The request-duration clock now starts in the lifecycle middleware, after Hono selects the route, rather than before app.fetch. The difference is the router lookup.
  • Parameter values handlers see are still raw. Decoding by default arrives with the module conversions.

Verification

  • Unit: 232 files, 3,464 passed.
  • Integration (workerd, real D1): 96 files, 1,128 passed.
  • Typecheck (src, tsconfig.test.json, test/integration), ESLint, and Prettier clean.

https://claude.ai/code/session_01KdDpTgGEjXpBA9SaGQVUH1

Summary by CodeRabbit

  • Improvements
    • Updated request routing and authorization handling for more consistent policy enforcement.
    • Improved handling of denied requests, unexpected errors, unsupported methods, and route-related failures.
    • Strengthened route validation, including authorization requirements and duplicate parameter detection.
    • Improved request lifecycle behavior, including logging, trace identifiers, response finalization, and CORS preflight handling.
  • Bug Fixes
    • Improved extraction and handling of route parameters, including sandbox session-related requests.
    • Ensured unexpected handler failures return a consistent server error response with the appropriate headers and response policy.

Route admission runs as admit(policy) middleware ahead of each catalog
handler, and a lifecycle middleware owns the guards, request context,
request log, authorization audit, and common headers. A handler that
answers without admission running ahead of it is refused with a 500.

The raw-path regex re-match, Route.pattern, parsePattern, the dispatch
chain, and the start-time WeakMap are gone. Admission reads raw path
parameters by position from the pathname, and a legacy adapter rebuilds
the match array handlers still take, so no route module changes. The
app takes a host for its background-task port instead of a Cloudflare
ExecutionContext.

Claude-Session: https://claude.ai/code/session_01KdDpTgGEjXpBA9SaGQVUH1
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Terraform Validation Results

Step Status
Format
Init
Validate
Tests

Note: Terraform plan was skipped because secrets are not configured. This is expected for external contributors. See docs/GETTING_STARTED.md for setup instructions.

Pushed by: @ColeMurray, Action: pull_request

@coderabbitai

coderabbitai Bot commented Sep 2, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Team

Run ID: feac72af-c99c-4555-9ab1-54ec9ddbaaf5

📥 Commits

Reviewing files that changed from the base of the PR and between 6f41f6e and 62e9356.

📒 Files selected for processing (8)
  • packages/control-plane/src/router.policy.test.ts
  • packages/control-plane/src/router.test-support.ts
  • packages/control-plane/src/routing/admit.ts
  • packages/control-plane/src/routing/hono-app.test.ts
  • packages/control-plane/src/routing/hono-app.ts
  • packages/control-plane/src/routing/hono-env.ts
  • packages/control-plane/src/routing/route-params.test.ts
  • packages/control-plane/src/routing/route-params.ts

Included review availability: Your plan provides up to 8 included reviews per hour; 6 remain after this review.


📝 Walkthrough

Walkthrough

The control-plane router now uses path-based route definitions, structured parameters, admission middleware, and a host-based Hono lifecycle. Tests use shared route matching and validate admission, errors, CORS, logging, and route contracts.

Changes

Control-plane routing

Layer / File(s) Summary
Route contracts and structured parameters
packages/control-plane/src/routes/shared.ts, packages/control-plane/src/routing/route-params.ts, packages/control-plane/src/routing/route-admission.ts, packages/control-plane/src/routing/request-lifecycle.ts
Routes no longer expose compiled patterns. Authorization and sandbox binding use named RouteParams.
Admission middleware and host contracts
packages/control-plane/src/routing/admit.ts, packages/control-plane/src/routing/hono-env.ts
Admission middleware evaluates policies, stores admission state, audits denials, and uses a platform host for background tasks.
Hono application lifecycle
packages/control-plane/src/routing/hono-app.ts, packages/control-plane/src/routing/hono-app.test.ts
The application validates routes, maps failures, finalizes responses, handles execution contexts, and tests lifecycle behavior.
Router test adapter
packages/control-plane/src/router.test-support.ts
Tests use a platform-neutral Hono host with shared path-pattern and catalog-matching helpers.
Route test migration
packages/control-plane/src/router.*.test.ts, packages/control-plane/src/routes/*.test.ts, packages/control-plane/test/integration/hono-route-catalog-conformance.test.ts
Tests use route paths and shared matching helpers instead of compiled route patterns.

Estimated code review effort: 4 (Complex) | ~60 minutes

Merge Risk: 🔵 Low · up to 62e93

The refactor centralizes route admission and error handling, but an unadmitted handler could still execute before its response is rejected, and an early host-setup failure may bypass the intended sanitized error path. Current in-repository composition limits both cases, so the PR is mergeable with explicit owner awareness or follow-up.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant ControlPlaneApp
  participant admit
  participant admitRoute
  participant RouteHandler
  Client->>ControlPlaneApp: Send request
  ControlPlaneApp->>admit: Evaluate route policy
  admit->>admitRoute: Pass named RouteParams
  admitRoute-->>admit: Return admission result
  admit->>RouteHandler: Invoke admitted route
  RouteHandler-->>ControlPlaneApp: Return response
  ControlPlaneApp-->>Client: Finalize response
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 32.61% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 46 functions across 26 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: refactoring route admission to use Hono middleware.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch refactor/hono-pr1-admit-middleware

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@open-inspect open-inspect Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The middleware migration has a promising direction, but it currently introduces three structural boundary problems that should be resolved before merging. Most importantly, fallible admission work occurs before route state is recorded, so one entire failure class bypasses the lifecycle finalizer. The new raw-parameter extractor also accepts route declarations that violate its own RouteParams contract, and the host abstraction removes a faithful adapter only by replacing it with unknown and reciprocal casts. These are not cosmetic concerns: they create hidden response modes and make the central routing boundary less type-safe. No changed file crosses the 1k-line threshold, and the focused routing suites plus all current CI checks pass, but the missing cases were confirmed with temporary regression probes.

Comment thread packages/control-plane/src/routing/admit.ts
Comment thread packages/control-plane/src/routing/route-params.ts Outdated
Comment thread packages/control-plane/src/routing/hono-env.ts Outdated

@open-inspect open-inspect Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Summary

PR #1721, refactor: admit routes through Hono middleware, by @ColeMurray moves route admission and request lifecycle behavior into Hono middleware while preserving the legacy handler interface. The overall structure is well tested, but an exception during admission bypasses the new response-finalization guarantees and should be fixed before merge.

Files changed: 27, with 716 additions and 498 deletions.

Critical Issues

  • [Error handling / observability] packages/control-plane/src/routing/hono-app.ts:149 - If admission throws before c.set("admission", ...), Hono creates the sanitized 500 and this branch returns it without CORS, correlation headers, or the selected route's cache policy. A service-auth identity lookup failure is one concrete path to this state. Preserve enough route policy before awaiting admission, finalize this response, and cover the case with a test.

Suggestions

  • [Route contract] packages/control-plane/src/routing/hono-app.ts:40 - Reject duplicate parameter names during route validation. The removed named-capture regex rejected these at construction, while rawRouteParams() now silently overwrites an earlier value.
  • [Testing] packages/control-plane/src/router.policy.test.ts:85 - Check parameter names as complete path segments rather than substrings so :id cannot be satisfied by :identity.

Nitpicks

None.

Positive Feedback

  • The default-deny behavior correctly clears prior response headers, preventing an unadmitted handler from leaking cookies or other metadata.
  • The conformance fixture exercises all 171 routes with encoded slashes, which gives strong coverage for the raw-parameter compatibility requirement.
  • HEAD, OPTIONS, unknown-route, HttpError, ordinary Error, and non-Error throw behavior are covered directly.

Questions

None.

Verdict

Request Changes: address the admission-exception response finalization gap. The duplicate-parameter and segment-exact checks are recommended hardening.

Verification: 147 focused unit tests passed, the 171-route integration conformance test passed, and control-plane typecheck, lint, and diff checks passed.

Comment thread packages/control-plane/src/routing/hono-app.ts Outdated
Comment thread packages/control-plane/src/routing/hono-app.ts
Comment thread packages/control-plane/src/router.policy.test.ts Outdated
An error thrown inside admission now carries the selected route's
response policy and the common headers. The host port is typed against
the platform execution context with a faithful test adapter, raw
parameters use a null-prototype dictionary and refuse a segment
mismatch, duplicate parameter names are rejected at build, and the
policy test matches parameter names as whole segments.

Claude-Session: https://claude.ai/code/session_01KdDpTgGEjXpBA9SaGQVUH1
@github-actions

github-actions Bot commented Sep 2, 2026

Copy link
Copy Markdown

Terraform Validation Results

Step Status
Format
Init
Validate
Tests

Note: Terraform plan was skipped because secrets are not configured. This is expected for external contributors. See docs/GETTING_STARTED.md for setup instructions.

Pushed by: @ColeMurray, Action: pull_request

@ColeMurray
ColeMurray merged commit 372fad2 into main Sep 2, 2026
13 checks passed
@ColeMurray
ColeMurray deleted the refactor/hono-pr1-admit-middleware branch September 2, 2026 21:55
ColeMurray added a commit that referenced this pull request Sep 3, 2026
## Summary

Third step of the series retiring the routing adapter (#1720 guardrails,
#1721 mechanism). This PR converts the first six route modules to native
Hono sub-apps and establishes the pattern the remaining module PRs
follow. 12 routes convert; the other 159 still go through the catalog
adapter.

**A converted module** is a `Hono` sub-app whose routes register with
`admit(policy)` as their first middleware and a native handler behind
it:

```ts
export const keyboardShortcutRoutes = new Hono<ControlPlaneHonoEnv>();

keyboardShortcutRoutes.get(
  "/keyboard-shortcuts",
  admit({ ...SCM_AGNOSTIC_HUMAN_USER_ROUTE, authorization: ACTIVE_SELF }),
  async (c) => {
    const { ctx } = c.var.admitted;   // ctx.principal is typed UserPrincipal by the policy
    ...
  }
);
```

`admit()` is now generic over its policy and sets `c.var.admitted` as `{
request, ctx }`, where `request` is the request as authentication
returned it (sig1 verification consumes the original body) and `ctx` is
the request context narrowed by the policy's authentication kind,
exactly as `RouteContext<Authentication>` narrowed the legacy handler's
fourth argument. Handlers use `c.req.param()` for path parameters; none
of the six modules has one, so no decoding question arises in this PR.

**The catalog mounts modules in place.** `catalog` (renamed from
`routes`) is an ordered list of `Route | RouteModule`.
`createControlPlaneApp` mounts a sub-app with `app.route("/", module)`
where it appears and registers a legacy route through the adapter where
it appears, so registration order, and therefore precedence, is
unchanged. The path grammar and duplicate-parameter checks run for
module routes too.

**Route contracts come from Hono's own route list.**
`listRouteContracts(app)` walks `app.routes` and yields `{ method, path,
...policy }` for every entry whose handler is the `admit()` middleware,
which carries the policy it enforces. The policy tests, the
route-admission matrix, its sentinel suite, and the conformance suite
iterate that list instead of the catalog array, so they cover converted
and legacy routes alike. Both integration snapshots are byte-identical
to `main`.

**Handler-level tests become request-level.** `analytics.test.ts` went
through `createTestRequestHandler([analyticsRoutes])` with
`authenticate` mocked to return a user and
`ownerAuthorizationDatabase()` answering the effective-authorization
lookup, which is the pattern `router.authorization-audit.test.ts`
already used. Same assertions, plus a denial case that proves no store
is touched. The remaining 26 handler-level test files convert with their
modules.

Converted: `health` (moved out of `catalog.ts` into its own module),
`keyboard-shortcuts`, `model-preferences`, `sign-in-providers`,
`audit-events`, `analytics`.

## Verification

- Unit: 234 files, 3,474 passed.
- Integration (workerd, real D1): 96 files, 1,128 passed. Route-matrix
and conformance snapshots unchanged.
- Typecheck (`src`, `tsconfig.test.json`, `test/integration`), ESLint,
and Prettier clean.

https://claude.ai/code/session_01KdDpTgGEjXpBA9SaGQVUH1


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
  - Added a health check endpoint reporting service availability.
- Expanded support for modular route handling while preserving existing
endpoint access policies.
- Added route contract reporting for endpoint methods, paths, and access
requirements.

- **Bug Fixes**
- Preserved authentication, authorization, caching, and request-context
behavior across updated endpoints.
- Improved validation for unsupported route patterns and improperly
configured routes.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
ColeMurray added a commit that referenced this pull request Sep 3, 2026
## Summary

Fourth step of the series retiring the routing adapter (#1720, #1721,
#1723). This PR converts the sessions cluster, the largest and most
policy-diverse group, to native Hono sub-apps: 42 routes across 13
session modules plus the Slack notification route. It is the design
proof for path parameters and for the sandbox-fallback and exact-sandbox
policies.

**Modules.** Each session module is a `Hono` sub-app registering
`admit(policy)` first, and `sessions.ts` nests them under one sub-app in
the old precedence order (`/sessions/inbox` still registers before
`/sessions/:id`). The catalog mounts that sub-app and the Slack
notification module where the spread and the inline route used to sit.

**Handlers** keep their bodies and take a typed params object in place
of the match array:

```ts
export async function handleGetChild(
  request: Request,
  env: Env,
  params: { id: string; childId: string },
  ctx: SessionRouteContext
): Promise<Response>
```

Registration passes `c.req.param()`, which Hono types from the path
literal, so a handler declaring `childId` cannot be wired to a route
without one. `withSessionRuntime(env, ctx)` replaces the
`sessionRoute()` wrapper: it attaches the runtime client at the call
site, and the handler-level tests use the same function to build their
context.

**Runtime proxy.** The three factories (`simpleProxy`,
`legacyTokenRefresh`, `lifecycleProxy`) now build handlers rather than
catalog entries, collected in `sessionRuntimeProxyHandlers` and
registered one route each. The tests select handlers from that map by
the production contract instead of scanning a route array.

**Decode once, in Hono.** Admission now reads `c.req.param()`, so the
session id the sandbox binding verifies, the automation id the ownership
check loads, and any actorless-grant path parameter are Hono's decoded
values, and admission's own `decodeURIComponent` calls are removed.
`rawRouteParams` survives only inside the legacy adapter, for the
modules not yet converted, and goes with them.

## Behavior change

An encoded session id now resolves the same session as its plain form:
`GET /sessions/%74est-…` returns the session rather than 404, and a
sandbox token on `/sessions/%74est-…/tunnel-urls` verifies rather than
401. The guardrail tests from #1720 record this as their new
expectation. No other route observed a different status: both
integration snapshots are byte-identical to `main`.

## Tests

Handler-level tests pass params objects and get their session runtime
from `withSessionRuntime`; assertions are unchanged.
`router.create-session.test.ts` calls the exported `handleCreateSession`
directly. No test lost coverage; the route-matrix suite covers every
converted route per credential class as before.

## Verification

- Unit: 234 files, 3,476 passed.
- Integration (workerd, real D1): 96 files, 1,128 passed. Route-matrix
and conformance snapshots unchanged.
- Typecheck (`src`, `tsconfig.test.json`, `test/integration`), ESLint,
and Prettier clean.

## Review follow-up (71224c4)

- **Malformed path segments are refused at admission.** Hono leaves a
segment it cannot decode as it arrived, so the automation-id
requirement's 400 had become a 404. `admit()` now checks every raw
`:param` segment once and answers `400 { error: "Invalid path encoding"
}` on every route before any lookup. This replaces the three
route-specific messages `main` produced for this input (`Invalid
automation route`, `Invalid user ID` on malformed member ids, and the
session routes' 404); the two RBAC integration expectations and the
routing-compatibility probe record the uniform envelope. Both matrix
snapshots are still byte-identical.
- **One call-site adapter.** `dispatch(c, handler)` in
`routing/admit.ts` is the only place a Hono context is unpacked for a
handler; `dispatchSession(c, handler)` adds the runtime client. A route
reads `admit(policy), (c) => dispatchSession(c, handleX)`. The context
type is checked against the policy, so a user-only handler behind a
user-or-service policy fails to compile (a curried `handle(handler)`
form was tried and rejected because Hono infers the environment from the
returned function and that check disappears).
- **Proxy tests dispatch through the production sub-app.** The test-only
handler map is gone; the runtime proxy registers its handlers directly,
and `session-runtime-proxy.test.ts` sends real requests through
`sessionRuntimeProxyRoutes`, with a 17-row wiring table that fails if a
route is bound to the wrong proxy.

https://claude.ai/code/session_01KdDpTgGEjXpBA9SaGQVUH1


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

* **Improvements**
* Standardized routing and authorization across session, attachment,
media, child-session, prompt, pull-request, skills, WebSocket token, and
notification endpoints.
* Preserved existing endpoint paths, permissions, upload validation,
streaming, and error handling.
* Improved handling of percent-encoded path values so valid requests
resolve correctly.

* **Bug Fixes**
* Malformed percent-encoded path segments now return a clear 400 error
before processing.

* **Tests**
* Expanded coverage for routing, authorization, encoded paths, and
request dispatch.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
ColeMurray added a commit that referenced this pull request Sep 3, 2026
Last PR of the Hono series (#1720, #1721, #1723, #1724, #1726, #1727,
#1728, #1729). Every route module is a Hono sub-app, so the adapter that
carried catalog routes through admission has nothing left to serve.

## Removed

- `legacy()` and `legacyMatch()` in `routing/hono-app.ts`;
`createControlPlaneApp(modules, host)` mounts modules only.
- `RouteDefinition`, `Route`, `defineRoute()`, `defineRoutes()`, and
`extractRepoParams()` in `routes/shared.ts`. `RouteAdmissionPolicy` is
now an interface over `RoutePolicy` plus `authorization` and
`serviceActorClaims`; `cacheControl` lives on `AdmissionPolicy` in
`routing/admit.ts`.
- `RouteCatalogEntry`; the catalog is `readonly RouteModule[]`.
- `legacyRoutes()` in test support; `matchRoute()` no longer fabricates
a `RegExpMatchArray`.
- `routes/shared.test.ts`, replaced by
`routes/repository-params.test.ts` over the decoded pair.

## Kept on purpose

- `RouteParams`: admission's decoded-parameter dictionary. Hono exports
no such type.
- `rawRouteParams()`: the malformed-encoding guard's raw read-back
(added in #1724).

## Tests

Fixtures that need synthetic routes build a `Hono` module and pass it to
`createTestRequestHandler([module])`: the lifecycle suite, the contract
lister's suite, and the authorization-audit suite's eleven routes. The
two Worker-boundary suites build their shadow catalogs the same way:
conformance echoes the raw read-back through `rawRouteParams()`, and the
matrix's "raw path segments" probe from #1720 is now the decode-once
assertion on what handlers receive (`abc%2Fdef` arrives as `abc/def`,
`web%252Fapp` as `web%2Fapp`).

## Verification

| Check | Result |
|---|---|
| Typecheck (src, test, integration) | clean |
| ESLint, Prettier | clean |
| Unit | 234 files, 3,512 passed |
| Integration (workerd, real D1) | 96 files, 1,129 passed |
| Matrix and conformance snapshots | byte-identical |

https://claude.ai/code/session_01KdDpTgGEjXpBA9SaGQVUH1


<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Bug Fixes**
- Repository paths now support nested owner namespaces, such as
`group/subgroup`.
- Repository names containing slash characters are rejected with a clear
validation message.
- URL path parameters are decoded consistently, improving handling of
encoded repository and member identifiers.

- **Refactor**
- Control-plane routing now uses the current route-module system,
providing consistent admission, route matching, and request handling
behavior.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant