Expand description
Always-on local HTTP API for image generation (127.0.0.1 only).
Synchronous: POST /image blocks until the engine finishes and returns the
image bytes. Models come from the local Catalog, which the operator can
extend at runtime via POST /models — the same ModelSource shape the
studio uses. Every job is recorded into the in-app local queue.
§Security model
Binding loopback alone is not enough:
- Browsers happily fire cross-site
text/plainPOSTs at127.0.0.1without a CORS preflight, and this API parses bodies as JSON regardless of content type — so without a guard any web page could inject catalog models (with attacker-controlled download URLs) or burn the GPU. DNS rebinding additionally lets a page read responses. - Any other local OS user can reach the port.
Defence, checked in order on every route except GET /healthz:
- Host allow-list — must be loopback (DNS-rebinding guard).
- Origin allow-list — when present, must be a loopback origin (CSRF guard; absent means a non-browser client and is allowed).
- Bearer token —
Authorization: Bearer <token>, compared in constant time. The token is generated per install, persisted inconfig.toml, and published to local clients via the owner-onlylocal-api.jsondiscovery file in the worker’s config dir.
Structs§
- Local
Api - The local image API server, bound but not yet serving.
- Model
Services - What the local API offers besides one-off jobs: the model host, and the tokens that open streaming sessions on the LAN listener.
Constants§
- MAX_
BODY_ BYTES - Maximum accepted request-body size.
read_bodyused to read to string unbounded, so a single request could OOM the worker.
Functions§
- remove_
discovery_ file - Best-effort removal of the discovery file on shutdown. A missing file is the desired end state; any other failure is warn-logged so a stale token file never vanishes silently and never lingers silently.
- write_
discovery_ file - Publish the bound URL + bearer token for local clients, atomically
and owner-only (the file carries the token). Written on every
successful bind; removed again by
remove_discovery_fileon clean shutdown so stale files can’t point at a dead port.