feat(FN-002): complete Step 3 — FastAPI Backend App Skeleton

This commit is contained in:
Fusion
2026-05-14 01:31:58 +02:00
parent 79203d2f0f
commit 80f04a5c45
12 changed files with 148 additions and 0 deletions
View File
+28
View File
@@ -0,0 +1,28 @@
from pydantic_settings import BaseSettings, SettingsConfigDict
class Settings(BaseSettings):
model_config = SettingsConfigDict(
env_file=".env",
env_file_encoding="utf-8",
extra="ignore",
)
app_name: str = "Headquarter API"
debug: bool = False
api_v1_prefix: str = "/api/v1"
# Authentik OIDC placeholders (to be wired in FN-004)
authentik_issuer_url: str = ""
authentik_client_id: str = ""
authentik_client_secret: str = ""
# Database (to be wired in FN-004)
database_url: str = "postgresql://postgres:postgres@localhost:5432/headquarter"
# Deployment
root_domain: str = "localhost"
tool_subdomain_pattern: str = "{tool}-{project}-{user}.tools.{root_domain}"
settings = Settings()
+22
View File
@@ -0,0 +1,22 @@
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.config import settings
app = FastAPI(
title=settings.app_name,
debug=settings.debug,
)
app.add_middleware(
CORSMiddleware,
allow_origins=["http://localhost:5173"],
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
@app.get("/health")
def health() -> dict[str, str]:
return {"status": "ok", "service": settings.app_name}
@@ -0,0 +1,13 @@
Metadata-Version: 2.4
Name: headquarter-api
Version: 0.0.1
Summary: Headquarter FastAPI backend
Requires-Python: >=3.11
Requires-Dist: fastapi>=0.115.0
Requires-Dist: uvicorn[standard]>=0.34.0
Requires-Dist: pydantic-settings>=2.8.0
Provides-Extra: dev
Requires-Dist: pytest>=8.3.0; extra == "dev"
Requires-Dist: httpx>=0.28.0; extra == "dev"
Requires-Dist: ruff>=0.11.0; extra == "dev"
Requires-Dist: mypy>=1.15.0; extra == "dev"
@@ -0,0 +1,10 @@
pyproject.toml
app/__init__.py
app/config.py
app/main.py
headquarter_api.egg-info/PKG-INFO
headquarter_api.egg-info/SOURCES.txt
headquarter_api.egg-info/dependency_links.txt
headquarter_api.egg-info/requires.txt
headquarter_api.egg-info/top_level.txt
tests/test_health.py
@@ -0,0 +1 @@
@@ -0,0 +1,9 @@
fastapi>=0.115.0
uvicorn[standard]>=0.34.0
pydantic-settings>=2.8.0
[dev]
pytest>=8.3.0
httpx>=0.28.0
ruff>=0.11.0
mypy>=1.15.0
@@ -0,0 +1 @@
app
+12
View File
@@ -0,0 +1,12 @@
{
"name": "@headquarter/api",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": ".venv/bin/uvicorn app.main:app --reload --port 8000",
"build": "echo 'Python build step skipped (no compilation required)'",
"lint": ".venv/bin/ruff check app tests",
"test": ".venv/bin/pytest",
"typecheck": ".venv/bin/mypy app tests"
}
}
+38
View File
@@ -0,0 +1,38 @@
[project]
name = "headquarter-api"
version = "0.0.1"
description = "Headquarter FastAPI backend"
requires-python = ">=3.11"
dependencies = [
"fastapi>=0.115.0",
"uvicorn[standard]>=0.34.0",
"pydantic-settings>=2.8.0",
]
[project.optional-dependencies]
dev = [
"pytest>=8.3.0",
"httpx>=0.28.0",
"ruff>=0.11.0",
"mypy>=1.15.0",
]
[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"
[tool.setuptools]
packages = ["app"]
[tool.ruff]
line-length = 100
target-version = "py311"
[tool.ruff.lint]
select = ["E", "F", "I", "N", "W", "UP"]
[tool.mypy]
python_version = "3.11"
strict = true
warn_return_any = true
warn_unused_configs = true
View File
+14
View File
@@ -0,0 +1,14 @@
from fastapi.testclient import TestClient
from app.config import settings
from app.main import app
client = TestClient(app)
def test_health_returns_ok() -> None:
response = client.get("/health")
assert response.status_code == 200
data = response.json()
assert data["status"] == "ok"
assert data["service"] == settings.app_name