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.
- 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.