2 Commits
Author SHA1 Message Date
Latte 7bb99d94bf feat(serve): /healthz, fail-closed bind, and OAuth resource-server mode
Extend the HTTP transport (from the remote-MCP work) so it's production-ready.

- /healthz: an unauthenticated GET liveness route that returns only
  {status, server, version} — no account data, no token state. For Docker and
  reverse-proxy probes; on stdio the route is never served.
- Fail-closed bind: refuse to start without authentication, and make the
  message distinguish a loopback bind from a public (0.0.0.0) one. The only
  override is the explicit FAMILIAR_ALLOW_INSECURE_BIND=true escape hatch, which
  permits an unauthenticated bind (with a loud warning).
- FAMILIAR_AUTH_MODE=oauth: run as an OAuth 2.1 resource server. A JWTVerifier
  validates external-issuer JWTs (JWKS from FAMILIAR_OAUTH_JWKS_URI, else
  discovered from FAMILIAR_OAUTH_ISSUER's OIDC metadata) against issuer +
  audience, wrapped in a RemoteAuthProvider that serves
  /.well-known/oauth-protected-resource so OAuth-only clients (Claude web) can
  discover the authorization server. familiar is a resource server only — no
  authorization server, no DCR. bearer mode is unchanged and stays the default.

Tests cover healthz (200, no leak), fail-closed vs escape hatch, and oauth
(valid JWT 200; missing/expired/wrong-audience 401 + WWW-Authenticate; the
protected-resource metadata), plus the new config readers.
2026-07-04 19:25:52 +02:00
Latte 44b2dbac0c test(serve): cover HTTP bearer auth, start refusal, config, write default, headless login
- 401 without/with a bad token (incl. WWW-Authenticate: Bearer), 200 with a
  valid one, driven through the ASGI app in-process.
- configure_http refuses to start when the token is unset or blank.
- FAMILIAR_HTTP_* config defaults and overrides; http_token() strip/empty.
- HTTP write default disabled by default, env still wins, stdio stays enabled.
- parse_callback (URL / bare code / empty) and the manual_login exchange flow.
2026-07-04 18:22:01 +02:00