Repository navigation
Make the Axum adapter production-ready for self-hosted deployments #391
Description
Goal
Make the Axum adapter a supported self-hosted runtime for applications such as Trusted Server. EdgeZero delivers the runtime contract, Docker scaffolding, multi-platform container validation, application publishing guidance, and generic deployment recipes. Application repositories own the deployable images and releases.
Current state
Axum already provides native routing, request conversion, store injection, local persistent KV, environment-backed secrets, and a reqwest proxy client. Generated application entrypoints call dev_server::run_app; this is also the container deployment path documented today.
The quick audit at 98930917d96cb665c7255f36ca8bbd61fc7539e1 found unbounded JSON buffering, fully collected response and proxy bodies, an outbound client created per incoming request, Ctrl-C-only graceful shutdown, permissive local configuration loading, and no tracked application Dockerfile or image-publishing workflow. See the linked sub-issues for exact source references.
Before issue creation, cargo test -p edgezero-adapter-axum --all-targets --all-features passed all 149 tests. This establishes a functional baseline, not production certification. Overload, cancellation, container shutdown, streaming backpressure, and architecture support still need targeted proof.
Prerequisite HTTP foundation
PR #275, portable outbound HTTP and request lifecycle contracts, is the primary implementation dependency. The initial audit covered main at 9893091 and missed this open draft PR. Its inspected head is c84996a45610efea02e7ca812417b7804a6414f7; this update is source review, not a rerun of its test or deployment evidence.
The PR already replaces much of the HTTP behavior targeted by #393, #394, #395, and the error/completion portions of #397: route-aware admission, bounded/deadline-aware ingress, streaming and response completion, shared outbound transport, typed wire policies, safe public errors, and owned Axum HTTP/1 connections. It also changes fallible app construction/configuration, relevant to #392 and #396.
Runtime implementation/integration should depend on the accepted #275 contracts rather than change interfaces that it retires. Re-audit the merged implementation and narrow or close sub-issues where existing tests and production acceptance evidence already satisfy the criteria. Remaining work includes production policy/overload proof, SIGTERM/readiness/draining, explicit storage/config mounts, trusted incoming proxies, operator diagnostics, and container/release validation.
Packaging and release-workflow preparation can proceed in parallel, but #398/#399's final runtime validation depends on this HTTP foundation. Preserve the PR's Unsupported/BestEffort capability distinctions. Its completion reports do not prove end-client receipt, and its admission hooks do not by themselves establish safe deployment limits or process shutdown.
PR #389 is secondary related timing work, not a substitute for this prerequisite.
Initial support scope
- Linux amd64 and arm64 application-container validation; each deployment target must separately support the selected architecture.
- Release-built native apps behind an operator-managed TLS reverse proxy/load balancer.
- Production Docker recipes and disposable CI application images, not a public EdgeZero application image or a custom runtime base image.
- Bounded buffered JSON handling, process shutdown/readiness, explicit configuration/storage, incremental streaming, safe outbound semantics, and diagnostics using accepted PR feat: implement portable outbound HTTP and request lifecycle contracts #275 contracts.
- No invented workload-independent concurrency or handler/stream deadline defaults. Axum: enforce configurable buffered request-body limits #393 is limited to buffered-body protection; broader policies need measured workload requirements and separate scope.
- Explicit single-writer embedded storage restrictions; do not infer multi-replica app safety from framework portability.
- Generic Docker, Kubernetes, and one selected managed-container deployment guide. Application-specific manifests, feature policy, bootstrap, secrets, and publication remain downstream.
Proposed approach
- Reconcile Axum: enforce configurable buffered request-body limits #393/Axum: preserve incremental streaming with bounded backpressure #394 to the narrowed buffered-body scope. Adopt accepted PR feat: implement portable outbound HTTP and request lifecycle contracts #275 contracts and re-audit what is already implemented; do not build duplicate ingress, transport, or response-completion frameworks.
- Start Axum: scaffold hardened production application Dockerfiles #398 with Trusted Server-derived portable dependency, committed lockfile, and pinned toolchain assumptions. Build/test a generated app in a constrained container. Document application-owned JS/assets build steps without requiring Node for all framework consumers.
- Add Axum: validate multi-platform containers and provide an application publishing workflow #399 native amd64/arm64, read-only PR container CI and a tested trusted-publisher recipe. Packaging/architecture preparation may land while runtime work is in progress; it is not production certification.
- Prioritize Axum: define a production server lifecycle with bounded graceful shutdown #392 signals/readiness/draining and Axum: make production configuration and local storage explicit #396 paths/required-startup/store behavior for runtime integration. Then run remaining Axum: enforce configurable buffered request-body limits #393/Axum: preserve incremental streaming with bounded backpressure #394/Axum: reuse outbound clients and preserve proxy HTTP semantics #395/Axum: add safe production diagnostics and trusted-proxy handling #397 acceptance checks against the integrated image and record any unresolved evidence gaps.
- Deliver Axum: document Docker, Kubernetes, and managed-cloud deployments #400 generic deployment guidance using the proven contract. Trusted Server #897 owns its image release and installer, with #840 coordinating relevant migration work.
flowchart TD
A[Portable Docker recipe and read-only architecture CI] --> D[Integrated container acceptance]
B[Accepted PR 275 HTTP contracts] --> C[Lifecycle and config first, then residual HTTP checks]
C --> D
D --> E[Generic deployment and app publishing recipes]
E --> F[Downstream Trusted Server image and deployment]
Keep native mechanics in Axum and preserve portable non-Send/WASM contracts. Do not block packaging preparation on the entire historical application backlog.
Done when
- PR feat: implement portable outbound HTTP and request lifecycle contracts #275 integration is complete and runtime issues implement only residual work, with unsupported/BestEffort guarantees preserved.
- All linked sub-issues meet their scoped acceptance criteria.
- A generated application uses portable dependencies and its own committed lockfile and declared toolchain, then builds/runs outside the source checkout in a non-root read-only-root container.
- The container recipe passes native amd64/arm64 CI; publication guidance preserves tested artifact identity and keeps privileged release operations separate from untrusted PR builds.
- Required-config failure, mounted state restart, readiness, SIGTERM/draining, buffered-body limits, incremental streaming, relevant outbound semantics, and safe diagnostics are exercised through the integrated runtime.
- Deferred workload-specific admission/deadline/overload policy is explicitly documented rather than silently assigned to Axum: enforce configurable buffered request-body limits #393 or claimed as proven process memory safety.
- Axum: document Docker, Kubernetes, and managed-cloud deployments #400 documents and verifies the agreed Docker/Kubernetes/managed-container scope, including storage, TLS/proxy, probes, shutdown, upgrades, and rollback.
- EdgeZero publishes no application image as a completion requirement; downstream image/config/signing/release ownership is clear.
- Existing workspace tests, lint/format checks, and WASM compatibility gates still pass.
Related work and exclusions
Coordinate with #79, #81, #82, and #85 for backend policy; #92 for client metadata; #107 and #110 for portable streaming helpers; and #118 through #122 for shared observability. Existing issues retain their current parents.
Generated workflows overlap with #161. Config semantics and local provisioning relate to #324 and #288. The deployment/build-tool container plan in docs/superpowers/plans/2026-08-20-build-cache-container.md is separate from an Axum application runtime image.
Direct TLS termination, Kubernetes operators, cloud-specific provisioning/deploy commands, new distributed KV providers, native macOS/Windows release binaries, and changes to build-tool container architecture are not required for this Epic. They can become follow-up issues after this scope is proven.
Affected areas
Adapter -- Axum; Core (routing, extractors, middleware); CLI (new, build, deploy, dev); CI / Tooling; Documentation.
Sub-issues
- Axum: define a production server lifecycle with bounded graceful shutdown #392 Axum: define a production server lifecycle with bounded graceful shutdown
- Axum: enforce configurable buffered request-body limits #393 Axum: enforce configurable buffered request-body limits
- Axum: preserve incremental streaming with bounded backpressure #394 Axum: preserve incremental streaming with bounded backpressure
- Axum: reuse outbound clients and preserve proxy HTTP semantics #395 Axum: reuse outbound clients and preserve proxy HTTP semantics
- Axum: make production configuration and local storage explicit #396 Axum: make production configuration and local storage explicit
- Axum: add safe production diagnostics and trusted-proxy handling #397 Axum: add safe production diagnostics and trusted-proxy handling
- Axum: scaffold hardened production application Dockerfiles #398 Axum: scaffold hardened production application Dockerfiles
- Axum: validate multi-platform containers and provide an application publishing workflow #399 Axum: validate multi-platform containers and provide an application publishing workflow
- Axum: document Docker, Kubernetes, and managed-cloud deployments #400 Axum: document Docker, Kubernetes, and managed-cloud deployments
- Add AWS configuration and secret-store providers for self-hosted applications #410 Add AWS configuration and secret-store providers for self-hosted applications
Downstream connections
Trusted Server owns its runnable image and ts up under #897. Relevant application prerequisites are #1141 config handoff, #1142 health/startup, #1139 stores, #1134 consent/geo, #843 secrets, and #1204 Node/build setup. These are coordination links, not a reparenting of downstream work or a claim every open migration issue blocks packaging.
GitHub implementation map
Runtime PRs belong to GitHub stack #408, visible from PR #409, in bottom-to-top order: #275 → #406 → #407 → #409. Their base branches follow that same order. All remain draft; stack membership is not accepted-prerequisite or final-image evidence.
| Issue | Implementation PR | Branch / relationship |
|---|---|---|
| #392 and #396 | #406 | issue-392-396-production-hosting-spec, based on #275's docs/outbound-http-spec |
| #393 | #407 | issue-393-buffered-body-limit-spec, based on #406 |
| #394 and #395 | No published PR yet | Acceptance/residual work on the #275 contracts; #395 depends on #394 for bounded transport |
| #397 | #409 | issue-397-diagnostics-proxy-trust-spec, based on #407; optional #389 stays separate |
| #398 | #401 | issue-398-docker-spec, based on main; independent packaging slice A, not part of runtime stack #408 |
| #399 | No published PR yet | Depends on #398's buildable recipe |
| #400 | No published PR yet | Depends on #398 packaging and #399 architecture evidence |
All ten tasks are native GitHub sub-issues of this Epic. Native blocker links mirror the explicit issue dependencies: #394 blocks #395; #398 blocks #399 and #400; #399 blocks #400. Preparation slices may proceed while completion/acceptance prerequisites remain open. Runtime acceptance dependencies on PR #275 stay explicit PR links, not fabricated issue dependencies. Mapped implementation PRs now have native GitHub Development closing links: #406 closes #392 and #396, #407 closes #393, #409 closes #397, and #401 closes #398. Their descriptions include explicit Closes statements. Issues remain open now and PRs remain draft; remaining integration and acceptance gates are still required before merge.
PR #275 has advanced beyond the parent revision used by #406. The branch-base chain is correct, but integration/re-audit and affected acceptance reruns remain outstanding. Updating metadata does not rebase or certify the child branches.
Activity