Skip to main content

HTTP API and live streaming

The HTTP API is the shared contract between bhtune-server, the browser frontend, and external HTTP clients. Route handlers and their request and response types define one OpenAPI 3.1 document. Full mode serves it at GET /api/openapi.json and provides interactive Scalar documentation at GET /api/docs. Demo omits both routes and exposes only its restricted simulator surface.

The generated document is checked in as the repository-root openapi.json. CI regenerates it from the server definitions and checks for a diff. The frontend's TypeScript API types are generated from that same file and have their own regenerate-and-diff check. This keeps the runtime routes, published contract, and browser client aligned. See the HTTP API reference.

Adapter and runtime boundary​

The HTTP adapter projects database records into explicit response types rather than exposing storage rows as the wire contract. CLI and HTTP projections describe the same run without making either adapter depend on the other.

StartRunRequest and CLI TuneArgs become a runtime-owned ValidatedTuneRequest. The runtime resolves common defaults, validates inputs, prepares provenance, and drives the tune; the server owns HTTP extraction, response mapping, and task registration. A successful POST /api/runs returns 201 after preparation and runs the tune asynchronously. Cancellation signals that task and waits for a terminal result; leaving a browser page is not cancellation.

Full mode's POST /api/runs/preflight uses the same request shape but calls only read-only preflight, with a read-only template pool and ReadOnlyDriver. It does not call preparation, insert history, start background tuning, write tags, or refresh a namespace.

Post-run write/revert operations use the shared runtime's pre-read, per-constant verification, rollback where applicable, and audit services. Their in-memory HTTP reservation complements, but does not replace, the durable live-operation guard. They use the run's recorded connection. Controller-ready result text and numeric write targets come from the same snapshotted precision policy; reverting recorded previous values does not apply that rounding.

Request/setup errors use typed HTTP error responses. A processed PID write can instead return 200 with writes[].success = false and an error_message: HTTP success alone is not physical write success. Clients must inspect the returned audit and restore/result evidence.

Live run stream​

GET /api/runs/{id}/stream sends run progress as Server-Sent Events (SSE). It emits the persisted initial-readings snapshot, then persisted samples in tick order, and a final done event when the run reaches a terminal outcome. Each connection can reconstruct the run from its stored samples rather than depending on a client-specific in-memory history.

The stream reads the same SQLite records used by run history and the REST API. It does not drive a second tuning loop or create another sample store. SSE is server-to-browser progress; starting, cancelling, and reviewing a run remain ordinary HTTP API operations.

The browser closes its EventSource on done and refreshes the run-detail query so final results, write audits, and restoration status come from the authoritative record. Reconnection replays persisted evidence; it does not require a second broadcast store or a special in-memory history for each visitor.

Browser assets and fallback rules​

Release builds embed frontend/dist/ in bhtune-server; debug builds read those assets from disk. Frontend assets must be built before compiling a standalone release server, and the server must be rebuilt after asset changes.

RequestResponse
index.html or a client-side routeSPA shell with Cache-Control: no-cache.
A built static assetIts MIME type and immutable asset caching.
A missing path with a dotted final component404, not an HTML response masquerading as an asset.
An unknown /api/* pathJSON 404, not the SPA shell.
A UI request when no frontend is builtActionable 503; API routes remain independent.

The server build script creates the asset directory before rust-embed expands its path guard. An existing empty directory prevents a bad compile-time canonical path from rejecting assets that are built later during debug development; it is not a substitute for building the frontend before release embedding. The frontend architecture describes client state and live/history rendering.

See the Web GUI quickstart to inspect the API and its OpenAPI contract.