apomesh-rest-api
apomesh-rest-api is a transport crate: the REST/JSON external API and
the Server-Sent Events (SSE) event tail. It is the human-facing parallel to
the gRPC programmatic wire — an axum + tower-http server whose handlers are
thin adapters that extract HTTP inputs, call a substrate workflow, and
serialize the typed outcome back to JSON. It runs no business logic; the same
workflows the gRPC surface calls live in
apomesh-orchestrator and
apomesh-substrate. This is transport
parity, not a second API: a session started over REST and one started over
gRPC take the identical substrate path. Touch this crate for the HTTP surface
— route families, the generated OpenAPI document, the SSE projection, and the
HTTP auth middleware.
Position in the workspace
Section titled “Position in the workspace”- Layer: transports. See
The dispatch lifecycle
for how every transport converges on one session workflow, and
Identity & authorization for the
SessionAuthbackend both transports share. - Depends on: apomesh-protocol
(the wire types the JSON shapes mirror),
apomesh-substrate (the domain types
and primitives the handlers call), and
apomesh-orchestrator (the
transport-blind
create_session_workflowthe session routes delegate to). - Consumed by:
apomesh-orchestrator-bin— the daemon binary constructs theRestAppState, callsbuild_router, andserves the listener beside the gRPC service. It is the crate’s only consumer; the transport is wired, not depended on by the substrate layers.
What it owns
Section titled “What it owns”- The router assembly —
build_routermounts every route family under/api/v1/, layers the auth middleware onto the protected sub-router, and attaches the standard tower-http stack (CORS, compression, request-id, body-limit, timeout, trace). - The route families — thin translate-and-delegate handlers grouped by resource (sessions, tenants, quotas, published agents and skills, strategy configs, tokens, audit, HITL, provider config, the memory reads, assets).
- OpenAPI 3.x generation — the
ApiDocaggregator drives compile-time derivation from each handler’s#[utoipa::path]annotation and serves the document as the contract artifact. - The SSE event projection —
routes::eventsadapts the substrate’sEventBus::tail_fromsubscription (the same primitive the gRPCTailEventsRPC uses) into atext/event-streamresponse, one SSE frame per envelope. - HTTP authentication — the
oauth_extractmiddleware bridges the HTTP bearer token to the substrate’sSessionAuth, installing the resolvedTenantContextfor downstream handlers. No business logic — auth and shape translation only.
Public surface
Section titled “Public surface”build_router—build_router(state: RestAppState, http: HttpConfig) -> axum::Router; the entry point that mounts every family, the middleware, and the OpenAPI document into one router.serve—serve(router, config: RestServerConfig); binds the listener (plaintext, or TLS from the sameConfig::auth.tlsblock the gRPC listener reads) and runs forever, returning the closed-enumRestServerErroron failure.RestAppState— the aggregated substrate handles (OrchestratorRuntime,OrchestratorDaemon, registries,SessionAuth); every field is anArc, so axum’sStateextractor clones it per request cheaply.RestServerConfig/HttpConfig— the listener config (address + optional TLS) and the operator HTTP-surface policy (CORS origins, max body bytes).ApiDoc/OPENAPI_JSON_PATH— the utoipa aggregator and the/api/v1/openapi.jsonpath the served document is exposed at.routes::*::router()— each resource family exposes arouter()returning anOpenApiRouter;build_routermerges them.routes::events(SSE tail) —GET /api/v1/events?session=<id>; the live event-bus stream withLast-Event-IDresume.auth::oauth_extract— the middleware that runsSessionAuth.authenticateand installs theTenantContext.
The route families are deliberately not enumerated here. The served
OpenAPI document at GET /api/v1/openapi.json is generated from the handlers
and is the exhaustive, always-current surface — consult it for exact request
and response shapes.
The daemon binary owns the wiring: it builds one RestAppState from the same
Arc-shared substrate handles the gRPC service holds, then mounts and serves
the router. The shape (from apomesh-orchestrator-bin):
use apomesh_rest_api::{build_router, serve, HttpConfig, RestServerConfig};
// `rest_state: RestAppState` and `rest_cfg: RestServerConfig` are built from// the daemon's shared handles + `Config::auth.tls`.let router = build_router(rest_state, HttpConfig::default());serve(router, rest_cfg).await?;For driving the running surface — starting a session, tailing events, and cancelling over HTTP — see the REST + SSE how-to, which walks the curl calls against the local stack.
Related
Section titled “Related”- How-to: REST + SSE — start, tail, and cancel over HTTP.
- Concepts: Control & execution planes
(the transports beside the substrate),
Identity & authorization (the shared
SessionAuthbackend). - Reference: apomesh-orchestrator (the workflows it delegates to), apomesh-protocol (the wire it mirrors in JSON).