Commit Graph
2 Commits
Author SHA1 Message Date
developer 48d37db15b Add the first internal/api test suite
build / build-push (push) Failing after 19s
internal/api is the admin REST + SSE surface and had no test file at all,
so nothing pinned the auth modes, the X-Forwarded-For trust boundary, the
rate limiter or the fact that a read route must not mutate anything. This
adds a local harness (a Server over fake hooks on an httptest listener,
with a real config file on disk) and three test files.

What it pins:

* Routing. A table over every route in Server.routes: each one answers 200
  and reaches the hook it is supposed to, so a new route without a case
  here is a route nothing tests. Plus method-not-allowed / 404 / outside
  the base path, a base path other than /api, and a read-route sweep that
  asserts no mutating hook was reached, the config generation did not move
  and the file on disk is byte-identical afterwards. A panicking component
  becomes a 500 and the server keeps serving, because the admin API is the
  only way to fix a broken instance.
* Auth. All three modes. apikey: the right key always works, and a prefix,
  a suffix, a case-folded key, a wrong basic password, an unknown bearer
  token, an unsupported scheme and a malformed Authorization header never
  do; curl -u any:KEY is accepted because that is what clients send.
  basic: bad username and bad password refused, a successful login issues a
  bearer token, the token works for the whole API, basic auth also works
  per request, an API key is not a credential in this mode, logout revokes
  the token, and a token past its session_ttl stops working. none: nothing
  is required and the caller runs as a writable loopback principal. trust
  _loopback: a local client with no credentials is let through, and a
  forwarded non-loopback client is not. Every mutating route refuses a
  read-only key with 403 without reaching its hook or touching the file
  (and the same request with a read-write key succeeds, so the 403 is about
  the key and not the payload), and allow_config_write: false refuses the
  settings editor with a valid key while the other mutations still work.
  The hashing is pinned on the state, not on timing: the authenticator's
  maps are keyed on the SHA-256 of the credential and hold no plaintext key
  or password, so a copied server struct cannot leak one.
* Product code is untouched; the suite is `package api` with its own setup.
2026-09-27 15:54:50 +00:00
developer 85453852d5 initial commit 2026-09-27 11:20:34 +00:00