"""Liveness / version endpoint. The ``/healthz`` endpoint is intentionally minimal: it must be safe to expose unauthenticated (Caddy + uptime checks will hit it), so it leaks only the app version and the build's git commit SHA — no hostnames, paths, config values, or environment details. """ from __future__ import annotations from typing import Literal from fastapi import APIRouter, Depends from pydantic import BaseModel, Field from app import __version__ from app.config import Settings, get_settings class HealthResponse(BaseModel): """Response schema for ``GET /healthz``. Kept as an explicit :class:`pydantic.BaseModel` so FastAPI publishes the shape in the OpenAPI schema and so any drift is caught at typing time rather than via a loose ``dict``. """ status: Literal["ok"] = Field( default="ok", description="Liveness indicator; this endpoint only returns 'ok'.", ) version: str = Field(description="Application semantic version.") commit_sha: str = Field( description="Git commit SHA of the running build ('unknown' in dev).", ) # Module-level router; mounted by `app.main.create_app`. No prefix and no # auth dependencies — /healthz is intentionally public. router: APIRouter = APIRouter(tags=["health"]) @router.get( "/healthz", response_model=HealthResponse, summary="Liveness + version probe", ) def healthz(settings: Settings = Depends(get_settings)) -> HealthResponse: """Return a minimal liveness envelope. Parameters ---------- settings: Injected via FastAPI's dependency system so tests can override configuration cleanly. Returns ------- HealthResponse ``status`` is always ``"ok"``; ``version`` and ``commit_sha`` identify the running build. """ # Intentionally does not touch the DB, filesystem, or any external # service. This is liveness, not readiness — a readiness probe with # deeper checks can be added in a later phase behind a different path. return HealthResponse( version=__version__, commit_sha=settings.git_commit_sha, )