You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The application currently exposes only GET /health. It is a process-only liveness check that returns {"status":"up"} without querying PostgreSQL or another dependency. There is no distinct readiness endpoint, Actuator-style index/info contract, or build-provenance endpoint.
This issue defines the complete initial operational endpoint contract. It complements, but is broader than, #18 (health split) and #19 (observability strategy).
Endpoint contract
Endpoint name
Description
What it should do
Success response
Failure response
GET /actuator/health/liveness
Process liveness probe.
Return successfully only when the FastAPI process can serve an HTTP request. Do not call PostgreSQL, Keycloak/JWKS, Logfire, or any network dependency. It is intended for a container orchestrator restart decision.
HTTP 200 {"status":"UP"}
HTTP 503 {"status":"DOWN"}
A hung process will normally fail by probe timeout or connection failure rather than returning JSON.
GET /actuator/health/readiness
Traffic-admission probe.
Check PostgreSQL with SELECT 1. Check the resolved OIDC JWKS URI with a short timeout and require a valid JSON document with a non-empty keys array. Do not check Redis, migrations, or Logfire: Redis is not used, migrations are an external pre-start task, and Logfire export is optional.
Use stable non-sensitive reason codes only: unavailable, timeout, or invalid_response. Never expose raw exceptions, URLs, credentials, or connection details.
No endpoint-specific failure. An unexpected error uses the existing HTTP 500application/problem+json response.
GET /actuator/info
Immutable deployed-service and build identity.
Return the application distribution name and version from installed Python package metadata. Return CI-injected build revision and creation time. Do not return runtime health, environment variables, credentials, or host data.
No endpoint-specific failure. An unexpected error uses the existing HTTP 500application/problem+json response.
Metadata sources of truth
Value
Source of truth
Delivery to the running application
Service name
[project].name in pyproject.toml
Installed distribution metadata via importlib.metadata
Application version
[project].version in pyproject.toml
Installed distribution metadata via importlib.metadata
Build revision
Exact Git SHA checked out by CI
OCI org.opencontainers.image.revision label and an image ENV mirror for the endpoint
Build creation time
CI-generated UTC timestamp at image build
OCI org.opencontainers.image.created label and an image ENV mirror for the endpoint
requires-python = ">=3.13" is an interpreter compatibility constraint, not the application version. The runtime currently cannot read package metadata because this project is not installed as a distribution with discoverable dist-info; add an explicit build backend and install the application into the image before using importlib.metadata.
Out of scope
Do not implement GET /actuator/health; readiness is the single aggregate availability decision for this template.
Do not implement GET /actuator/health/startup; FastAPI lifespan completes OIDC discovery before the app accepts requests, so Kubernetes can use liveness as its startup probe.
Do not implement /actuator/metrics or /actuator/metrics/{metric_name} until a concrete metrics registry/export contract exists. Current Logfire/OpenTelemetry setup provides instrumentation but no app-owned metric catalogue.
Acceptance criteria
All four endpoints above exist and have the documented status codes, response bodies, and no request body.
Liveness has no database, OIDC, telemetry, or other external dependency call.
Readiness checks PostgreSQL and the resolved OIDC JWKS document with bounded timeouts.
Readiness failure responses reveal only stable reason codes, never implementation-sensitive diagnostics.
The app is packaged and installed so importlib.metadata is the only runtime source for service name and application version; remove the duplicate ApplicationSettings.app_name source.
CI supplies full Git SHA and RFC 3339 UTC build time once per image build; the image records standard OCI version, revision, and created labels and exposes the latter two to the application without requiring Docker socket access.
Existing GET /health becomes an explicitly documented temporary compatibility alias for liveness, or is intentionally removed in a breaking release. Update scenario tests to wait on readiness, and update test expectations, telemetry exclusion, access-log filtering, Docker/Compose health configuration, and documentation accordingly.
Probe endpoints are unauthenticated but documented as network-restricted to the orchestrator; /actuator and /actuator/info have an explicit operator access policy.
Unit and integration tests cover success and each dependency-failure path; scenario tests wait on readiness.
README documents endpoint semantics, consumers, status codes, response schema, access policy, and Kubernetes/ECS probe configuration.
Context
The application currently exposes only
GET /health. It is a process-only liveness check that returns{"status":"up"}without querying PostgreSQL or another dependency. There is no distinct readiness endpoint, Actuator-style index/info contract, or build-provenance endpoint.This issue defines the complete initial operational endpoint contract. It complements, but is broader than, #18 (health split) and #19 (observability strategy).
Endpoint contract
GET /actuator/health/liveness200{"status":"UP"}503{"status":"DOWN"}A hung process will normally fail by probe timeout or connection failure rather than returning JSON.
GET /actuator/health/readinessSELECT 1. Check the resolved OIDC JWKS URI with a short timeout and require a valid JSON document with a non-emptykeysarray. Do not check Redis, migrations, or Logfire: Redis is not used, migrations are an external pre-start task, and Logfire export is optional.200{"status":"UP","checks":{"database":{"status":"UP"},"identity_provider":{"status":"UP"}}}503{"status":"DOWN","checks":{"database":{"status":"DOWN","reason":"unavailable"},"identity_provider":{"status":"UP"}}}Use stable non-sensitive reason codes only:
unavailable,timeout, orinvalid_response. Never expose raw exceptions, URLs, credentials, or connection details.GET /actuator200{"_links":{"self":{"href":"/actuator"},"liveness":{"href":"/actuator/health/liveness"},"readiness":{"href":"/actuator/health/readiness"},"info":{"href":"/actuator/info"}}}500application/problem+jsonresponse.GET /actuator/info200{"service":{"name":"fastapi-template","version":"0.1.0"},"build":{"revision":"<full-git-sha>","created":"<RFC-3339-UTC>"}}500application/problem+jsonresponse.Metadata sources of truth
[project].nameinpyproject.tomlimportlib.metadata[project].versioninpyproject.tomlimportlib.metadataorg.opencontainers.image.revisionlabel and an imageENVmirror for the endpointorg.opencontainers.image.createdlabel and an imageENVmirror for the endpointrequires-python = ">=3.13"is an interpreter compatibility constraint, not the application version. The runtime currently cannot read package metadata because this project is not installed as a distribution with discoverabledist-info; add an explicit build backend and install the application into the image before usingimportlib.metadata.Out of scope
GET /actuator/health; readiness is the single aggregate availability decision for this template.GET /actuator/health/startup; FastAPI lifespan completes OIDC discovery before the app accepts requests, so Kubernetes can use liveness as its startup probe./actuator/metricsor/actuator/metrics/{metric_name}until a concrete metrics registry/export contract exists. Current Logfire/OpenTelemetry setup provides instrumentation but no app-owned metric catalogue.Acceptance criteria
importlib.metadatais the only runtime source for service name and application version; remove the duplicateApplicationSettings.app_namesource.GET /healthbecomes an explicitly documented temporary compatibility alias for liveness, or is intentionally removed in a breaking release. Update scenario tests to wait on readiness, and update test expectations, telemetry exclusion, access-log filtering, Docker/Compose health configuration, and documentation accordingly./actuatorand/actuator/infohave an explicit operator access policy.References