docs: missing_docs sweep — 0 warnings + deny gate + publish-prep decisions (HY-02, HY-04, HY-11)
- document every public-API item across 18 files (openapi_spec model, HttpAuthScheme/HttpServiceConfig, HttpClientBuildError + SharedHttpClient accessors, RetryAfterMiddleware, GatewayDispatch, gateway error mapping, CallRequest/SchemaQuery/SubscribeStream, HttpAdapter + ALPNs + builders, decoy/healthz/state, WsSessions/WsPumps, from_openapi/from_jsonschema/from_mcp/from_wss/to_mcp, lib.rs module docs) - enforcement: #![deny(missing_docs)] at crate root — stronger than CI rustdocflags (every build incl. cfg(test), where rustdoc misses the test-support module docs) - HY-10 (opportunistic): all 8 docs.rs/alkhttp placeholder ADR links + the one relative ../docs link converted to plain text; the 10 pre-existing private/redundant intra-doc-link warnings fixed — RUSTDOCFLAGS="-D warnings" cargo doc is fully clean - HY-11 decision: docs/ + tasks/ excluded from the published package (contributor-facing design/process material; ADR references degrade to plain text uniformly). cargo publish --dry-run: 38 files, ~889 KiB, zero docs/ or tasks/ entries - HY-04 decision: keep + document — frame_channel0_chunk's unwrap is on serializing the acyclic EventEnvelope (unreachable failure); # Panics on it and the adjacent WsClient senders state the contract Verified: cargo test (299 + 5 TLS), --all-features (370 + suites), --no-default-features (299), clippy --all-targets -D warnings (default + all-features), fmt --check, cargo doc -D warnings clean, cargo publish --dry-run --allow-dirty clean. Tasks: review-001-missing-docs-sweep (final pending task; 42/42)
This commit is contained in:
+19
-2
@@ -23,9 +23,9 @@
|
||||
//!
|
||||
//! ## Connection knobs and boundaries
|
||||
//!
|
||||
//! [`HttpAdapter::serve_io`] configures the hyper auto builder with a
|
||||
//! The accept-loop side (`serve_io`, crate-private) configures the hyper auto builder with a
|
||||
//! tokio timer and timeouts (values in the method doc). The **concurrency
|
||||
//! cap is not a knob of this crate**: [`ProtocolHandler::handle`] serves
|
||||
//! cap is not a knob of this crate**: the `ProtocolHandler::handle` trait method serves
|
||||
//! exactly one accepted bidirectional stream per call, and the accept
|
||||
//! loop — how many streams are handled concurrently, on which tasks —
|
||||
//! belongs to the consumer that owns the `Connection` (or the
|
||||
@@ -53,7 +53,9 @@ use super::decoy::{decoy_fallback, decoy_method_not_allowed};
|
||||
use super::healthz::healthz;
|
||||
use super::state::{DecoyConfig, RouterState};
|
||||
|
||||
/// The HTTP/1.1 ALPN (`http/1.1`) `HttpAdapter` registers on (ADR-001).
|
||||
pub const ALPN_HTTP1: &[u8] = b"http/1.1";
|
||||
/// The HTTP/2 ALPN (`h2`) `HttpAdapter` registers on (ADR-001).
|
||||
pub const ALPN_H2: &[u8] = b"h2";
|
||||
|
||||
/// The WS upgrade path (ADR-067). Reserved in the default surface; the
|
||||
@@ -79,6 +81,11 @@ pub const RESERVED_PATHS: &[&str] = &[
|
||||
WS_UPGRADE_PATH,
|
||||
];
|
||||
|
||||
/// The HTTP server host (ADR-001, ADR-002, ADR-039): an axum
|
||||
/// `Router` serving the gateway, `/healthz`, `/openapi.json`, the MCP
|
||||
/// route, the WS upgrade path, and assembly-registered custom routes,
|
||||
/// behind the bearer-auth middleware — served over one ALPN depending
|
||||
/// on the constructor.
|
||||
pub struct HttpAdapter {
|
||||
identity_provider: Arc<dyn alkcall::core::auth::IdentityProvider>,
|
||||
registry: Arc<OperationRegistry>,
|
||||
@@ -94,6 +101,7 @@ pub struct HttpAdapter {
|
||||
}
|
||||
|
||||
impl HttpAdapter {
|
||||
/// An HTTP/1.1 adapter (registers on `http/1.1` ALPN).
|
||||
pub fn new(
|
||||
identity_provider: Arc<dyn alkcall::core::auth::IdentityProvider>,
|
||||
registry: Arc<OperationRegistry>,
|
||||
@@ -101,6 +109,7 @@ impl HttpAdapter {
|
||||
Self::for_alpn(identity_provider, registry, ALPN_HTTP1)
|
||||
}
|
||||
|
||||
/// An HTTP/2 adapter (registers on `h2` ALPN).
|
||||
pub fn h2(
|
||||
identity_provider: Arc<dyn alkcall::core::auth::IdentityProvider>,
|
||||
registry: Arc<OperationRegistry>,
|
||||
@@ -145,6 +154,8 @@ impl HttpAdapter {
|
||||
}
|
||||
}
|
||||
|
||||
/// Set the decoy surface for unregistered paths and rebuild the
|
||||
/// router (custom routes are preserved — SRV-05).
|
||||
pub fn with_decoy(mut self, decoy: DecoyConfig) -> Self {
|
||||
self.decoy = decoy.clone();
|
||||
let state = RouterState {
|
||||
@@ -165,6 +176,9 @@ impl HttpAdapter {
|
||||
self
|
||||
}
|
||||
|
||||
/// Mount assembly-provided custom routes under the bearer-auth
|
||||
/// middleware (ADR-046) and rebuild the router. Reserved paths
|
||||
/// (`RESERVED_PATHS`) are rejected before the merge.
|
||||
pub fn with_extra_routes(mut self, routes: Router) -> Self {
|
||||
let state = RouterState {
|
||||
registry: Arc::clone(&self.registry),
|
||||
@@ -241,14 +255,17 @@ impl HttpAdapter {
|
||||
Arc::new(tokio::sync::Semaphore::new(max_sessions))
|
||||
}
|
||||
|
||||
/// The configured decoy surface (assembly introspection).
|
||||
pub fn decoy(&self) -> &DecoyConfig {
|
||||
&self.decoy
|
||||
}
|
||||
|
||||
/// The ALPN this adapter registers on (`http/1.1` or `h2`).
|
||||
pub fn alpn(&self) -> &'static [u8] {
|
||||
self.alpn
|
||||
}
|
||||
|
||||
/// The assembled router (for the accept loop the consumer owns).
|
||||
pub fn router(&self) -> &Router {
|
||||
&self.router
|
||||
}
|
||||
|
||||
@@ -24,6 +24,9 @@ use axum::response::Response;
|
||||
|
||||
use super::DecoyConfig;
|
||||
|
||||
/// The fallback handler for unregistered paths (stealth mode, ADR-010):
|
||||
/// resolves the configured [`DecoyConfig`] variant — a fake nginx 404,
|
||||
/// a static site, or a redirect.
|
||||
pub async fn decoy_fallback(State(decoy): State<DecoyConfig>, request: Request) -> Response {
|
||||
match decoy {
|
||||
DecoyConfig::NotFound => fake_nginx_404(),
|
||||
@@ -32,6 +35,8 @@ pub async fn decoy_fallback(State(decoy): State<DecoyConfig>, request: Request)
|
||||
}
|
||||
}
|
||||
|
||||
/// A fake nginx-format 404 body with a 404 status — the stealth
|
||||
/// "nothing is here" response that does not disclose the gateway.
|
||||
pub fn fake_nginx_404() -> Response {
|
||||
let body = nginx_error_body("404 Not Found");
|
||||
let mut resp = Response::new(Body::from(body));
|
||||
@@ -62,10 +67,13 @@ fn nginx_405_response() -> Response {
|
||||
/// `Router::method_not_allowed_fallback` — applies to every
|
||||
/// previously registered `MethodRouter` (default surface + extra
|
||||
/// routes).
|
||||
/// A plain nginx-format 405 body — the decoy method-not-allowed
|
||||
/// response for reserved paths hit with unsupported methods.
|
||||
pub async fn decoy_method_not_allowed() -> Response {
|
||||
nginx_405_response()
|
||||
}
|
||||
|
||||
/// A 302 redirect to `to` (the `DecoyConfig::Redirect` surface).
|
||||
pub fn redirect(to: &str) -> Response {
|
||||
let mut resp = Response::new(Body::empty());
|
||||
*resp.status_mut() = StatusCode::FOUND;
|
||||
@@ -75,6 +83,9 @@ pub fn redirect(to: &str) -> Response {
|
||||
resp
|
||||
}
|
||||
|
||||
/// Serve a static site from `root` for unregistered paths (the
|
||||
/// `DecoyConfig::StaticSite` surface); paths escaping the root get the
|
||||
/// fake 404.
|
||||
pub async fn serve_static(root: &Path, request: Request) -> Response {
|
||||
let path = request.uri().path();
|
||||
let resolved = match resolve_static_path(root, path).await {
|
||||
|
||||
@@ -10,6 +10,9 @@ use axum::response::IntoResponse;
|
||||
|
||||
const HEALTHZ_BODY: &str = "ok";
|
||||
|
||||
/// `GET /healthz` — the operational liveness probe. Always answers
|
||||
/// `200 ok` (text/plain), independent of registry contents; the
|
||||
/// response is deliberately uninformative (stealth):
|
||||
pub async fn healthz() -> impl IntoResponse {
|
||||
(
|
||||
StatusCode::OK,
|
||||
|
||||
+10
-4
@@ -17,10 +17,16 @@ pub enum DecoyConfig {
|
||||
/// Serve a fake `404 Not Found` (the default — a fake nginx 404).
|
||||
#[default]
|
||||
NotFound,
|
||||
/// Serve a static site from a configured directory.
|
||||
StaticSite { root: PathBuf },
|
||||
/// Redirect to a configured URL.
|
||||
Redirect { to: String },
|
||||
/// Serve a static site from the given directory root.
|
||||
StaticSite {
|
||||
/// The directory tree served for unregistered paths.
|
||||
root: PathBuf,
|
||||
},
|
||||
/// Redirect unregistered paths to the given URL.
|
||||
Redirect {
|
||||
/// The redirect target URL.
|
||||
to: String,
|
||||
},
|
||||
}
|
||||
|
||||
/// State embedded in the axum `Router`: the registry and identity
|
||||
|
||||
Reference in New Issue
Block a user