Skip to content

Migrate from Trillium [part 7C]: admin routes and Trillium router removal#2247

Merged
jcjones merged 2 commits intomainfrom
jcj/axum-migration-part7c
May 8, 2026
Merged

Migrate from Trillium [part 7C]: admin routes and Trillium router removal#2247
jcjones merged 2 commits intomainfrom
jcj/axum-migration-part7c

Conversation

@jcjones
Copy link
Copy Markdown
Contributor

@jcjones jcjones commented May 7, 2026

  • Move the admin queue routes (index, show, delete) to Axum handlers gated by the new AdminPermissionsActor extractor, which centralizes the admin-only check (returning 404 for non-admins to hide endpoint existence). This is enforced by using a nested router, which has a route_layer that layers admin::require_admin on top of everything in that router, so we don't forget anything.

  • Wire ReplaceMimeTypesLayer on the Axum /api sub-router now that all API routes are served by Axum. Removed the Trillium routes() and api_routes() functions, the api() handler chain, handler/misc.rs (actor_required, admin_required), and all FromConn impls from route files. Then I realized this is supposed to be in Part 8 and I stopped.

  • Add #[serde(alias)]es to JobStatus so query-param deserialization accepts lowercase values (matching the previous QueryStrong behavior).

  • Add #[cfg(all(assets)...] to a couple of telemetry things so we don't commit compilation crimes. These'll get cleaned up when we drop trillium_opentelemetry, I think.

Note that there is still cleanup to do in Part 8, even though the migration is mostly done here. I wasn't super disciplined with what I deleted and what I marked dead, for which I request grace. Just, one thing at a time.

@jcjones jcjones marked this pull request as ready for review May 7, 2026 18:10
@jcjones jcjones requested a review from a team as a code owner May 7, 2026 18:10
Base automatically changed from jcj/axum-migration-part7b to main May 7, 2026 23:53
…oval

- Move the admin queue routes (index, show, delete) to Axum handlers
gated by the new AdminPermissionsActor extractor, which centralizes
the admin-only check (returning 404 for non-admins to hide endpoint
existence). This is enforced by using a nested router, which has a
`route_layer` that layers `admin::require_admin` on top of everything
in that router, so we don't forget anything.

- Wire ReplaceMimeTypesLayer on the Axum /api sub-router now that all
API routes are served by Axum. Removed the Trillium routes() and
api_routes() functions, the api() handler chain, handler/misc.rs
(actor_required, admin_required), and all FromConn impls from route
files. Then I realized this is supposed to be in Part 8 and I stopped.

- Add #[serde(alias)]es to JobStatus so query-param
deserialization accepts lowercase values (matching the previous
QueryStrong behavior).

- Add #[cfg(all(assets)...] to a couple of telemetry things so we
don't commit compilation crimes. These'll get cleaned up when we
drop trillium_opentelemetry, I think.

Note that there is still cleanup to do in Part 8, even though the
migration is mostly done here. I wasn't super disciplined with what
I deleted and what I marked dead, for which I request grace. Just,
one thing at a time.
@jcjones jcjones force-pushed the jcj/axum-migration-part7c branch from 71e32ec to 6f819cf Compare May 8, 2026 00:06
@jcjones
Copy link
Copy Markdown
Contributor Author

jcjones commented May 8, 2026

unexpected http status POST http://localhost:8080/api/aggregators 403 Forbidden

The pair_aggregator CLI gets a 403 when trying to create an aggregator. Oops.

@divergentdave
Copy link
Copy Markdown
Collaborator

The pair_aggregator CLI gets a 403 when trying to create an aggregator. Oops.

We might need an Axum replacement for #[cfg(feature = "integration-testing")] state(crate::User::for_integration_testing()).

@jcjones
Copy link
Copy Markdown
Contributor Author

jcjones commented May 8, 2026

The pair_aggregator CLI gets a 403 when trying to create an aggregator. Oops.

We might need an Axum replacement for #[cfg(feature = "integration-testing")] state(crate::User::for_integration_testing()).

I came back to this window to say basically the same thing, and found you solved the problem before me! I stripped this out too early, basically. For good reasons.

The Trillium `api()` handler chain had `state(User::for_integration_testing())`
gated on `#[cfg(feature = "integration-testing")]`, which injected an admin
user into every request. When 7C removed the Trillium router, this injection
was lost, causing the `pair_aggregator` container in compose.dev.yaml to get
403 Forbidden on `POST /api/aggregators` (n.b. the CLI uses `--token=""` and
relies on the integration-testing user for auth).

So, let's fix it. This is a new Axum middleware that unconditionally injects the
`integration-testing` user into request extensions when the feature is enabled.

While I'm at it, I also rename the existing `test-header-injection` middleware to
`inject_test_header_user` in order to distinguish it from the unconditional injection.
@jcjones jcjones merged commit 14cf57a into main May 8, 2026
9 of 11 checks passed
@jcjones jcjones deleted the jcj/axum-migration-part7c branch May 8, 2026 16:51
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.

3 participants