Part of the Admin UI epic #156 — stage 2 of 5.
Sablier has no authentication anywhere today — a grep for auth middleware across internal/ returns nothing. That is defensible while the API only serves reverse-proxy strategy calls on an internal port. It stops being defensible the moment /api/config exists (stage 1) and /api/instances/{name}/start exists (stage 5): that combination is a remote control plane for the whole cluster on an unauthenticated port.
Scope
A shared-token middleware, opt-in:
--server.auth.token / SABLIER_SERVER_AUTH_TOKEN
- Compared with
crypto/subtle.ConstantTimeCompare, never ==.
- Accepted as
Authorization: Bearer <token>.
- Applied to the new introspection routes from stage 1 and the mutating routes from stage 5.
- Not applied to
/health, and not applied to the two strategy endpoints — reverse-proxy integrations (Traefik, nginx, Caddy, the plugins) call those unauthenticated today and must keep working. Breaking them would be a silent outage for every existing user.
/metrics follows the same rule as the strategy endpoints: unauthenticated, since it is already opt-in and typically scraped from inside the network.
Enforcement rule
When no token is configured:
- introspection routes stay available (they are read-only, and this is the current default posture for a local Sablier)
- mutating routes are not registered at all — not 401, absent
This makes the safe configuration the default one and means a user cannot accidentally expose start/stop control by enabling the UI.
Startup logging should state plainly which posture is active, so it shows up in a support thread.
Definition of done
Part of the Admin UI epic #156 — stage 2 of 5.
Sablier has no authentication anywhere today — a grep for auth middleware across
internal/returns nothing. That is defensible while the API only serves reverse-proxy strategy calls on an internal port. It stops being defensible the moment/api/configexists (stage 1) and/api/instances/{name}/startexists (stage 5): that combination is a remote control plane for the whole cluster on an unauthenticated port.Scope
A shared-token middleware, opt-in:
crypto/subtle.ConstantTimeCompare, never==.Authorization: Bearer <token>./health, and not applied to the two strategy endpoints — reverse-proxy integrations (Traefik, nginx, Caddy, the plugins) call those unauthenticated today and must keep working. Breaking them would be a silent outage for every existing user./metricsfollows the same rule as the strategy endpoints: unauthenticated, since it is already opt-in and typically scraped from inside the network.Enforcement rule
When no token is configured:
This makes the safe configuration the default one and means a user cannot accidentally expose start/stop control by enabling the UI.
Startup logging should state plainly which posture is active, so it shows up in a support thread.
Definition of done
/healthverified unauthenticated by testEnv:/CLI:/Default:/Since:annotations the rest ofpkg/configuses, so it flows into the generated docs