feat(http): implement /healthz raw route and stealth decoy fallback

GET /healthz: raw route, no auth, no OperationContext, returns 200 OK
with plain-text 'ok' (ADR-036). Decoy fallback for unknown paths via
DecoyConfig: fake nginx 404 (default), static site serving, or redirect.
Decoy does not leak alknet presence (no alknet headers/format). Custom
routes take precedence over decoy (decoy is fallback only). Wire real
handlers into HttpAdapter router replacing placeholder 501s.
This commit is contained in:
2026-07-01 18:40:01 +00:00
parent a65afb0dfb
commit 3702da1aee
6 changed files with 473 additions and 7 deletions

View File

@@ -0,0 +1,62 @@
//! `GET /healthz` — the one raw HTTP route (ADR-036).
//!
//! No auth, no call protocol, no `OperationContext`. Returns `200 OK` with a
//! plain-text body (`"ok"`) if the endpoint is healthy. This is the
//! infrastructure endpoint load balancers and orchestrators call; it must
//! work before identity is resolvable. See
//! `docs/architecture/crates/http/http-server.md` §"/healthz (raw route)".
use axum::http::{header, HeaderValue, StatusCode};
use axum::response::IntoResponse;
const HEALTHZ_BODY: &str = "ok";
pub async fn healthz() -> impl IntoResponse {
(
StatusCode::OK,
[(header::CONTENT_TYPE, HeaderValue::from_static("text/plain"))],
HEALTHZ_BODY,
)
}
#[cfg(test)]
mod tests {
use super::*;
use axum::body::Body;
use axum::http::Request;
use http_body_util::BodyExt;
async fn call_healthz(req: Request<Body>) -> axum::response::Response {
let app = axum::Router::new().route("/healthz", axum::routing::get(healthz));
tower::ServiceExt::<Request<Body>>::oneshot(app, req)
.await
.unwrap()
}
#[tokio::test]
async fn healthz_handler_returns_200_with_plain_text_ok() {
let req = Request::builder()
.uri("/healthz")
.body(Body::empty())
.unwrap();
let resp = call_healthz(req).await;
assert_eq!(resp.status(), StatusCode::OK);
let ctype = resp
.headers()
.get(header::CONTENT_TYPE)
.map(|v| v.to_str().unwrap().to_string());
assert_eq!(ctype.as_deref(), Some("text/plain"));
let bytes = resp.into_body().collect().await.unwrap().to_bytes();
assert_eq!(&bytes[..], b"ok");
}
#[tokio::test]
async fn healthz_works_with_no_authorization_header() {
let req = Request::builder()
.uri("/healthz")
.body(Body::empty())
.unwrap();
let resp = call_healthz(req).await;
assert_eq!(resp.status(), StatusCode::OK);
}
}