step 1 complete: runnable FastAPI skeleton

- Full directory structure with all __init__.py stubs
- requirements.txt with all pinned dependencies
- app/config/settings.py (BaseSettings, env-based)
- app/main.py (CORS, lifespan, /api/v1/health)
- Dockerfile (multi-stage, Python 3.12-slim, non-root user)
- docker-compose.yml (app + postgres:16 with healthcheck)
- .env.example
- BACKEND_PLAN.md: mark step 1 done, add one-step-at-a-time rule

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-01 23:51:37 +01:00
parent 71fd1a0a7c
commit 4d0917f5df
16 changed files with 208 additions and 8 deletions

0
app/__init__.py Normal file
View File

0
app/agents/__init__.py Normal file
View File

0
app/api/__init__.py Normal file
View File

View File

View File

0
app/billing/__init__.py Normal file
View File

0
app/config/__init__.py Normal file
View File

31
app/config/settings.py Normal file
View File

@@ -0,0 +1,31 @@
from typing import Literal
from pydantic_settings import BaseSettings
class Settings(BaseSettings):
DATABASE_URL: str = "postgresql+asyncpg://postgres:postgres@localhost:5432/adiuva"
JWT_SECRET: str = "change-me-in-production"
JWT_ALGORITHM: str = "HS256"
JWT_ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
JWT_REFRESH_TOKEN_EXPIRE_DAYS: int = 30
STRIPE_SECRET_KEY: str = ""
STRIPE_WEBHOOK_SECRET: str = ""
S3_BUCKET: str = ""
S3_REGION: str = "us-east-1"
AWS_ACCESS_KEY_ID: str = ""
AWS_SECRET_ACCESS_KEY: str = ""
OPENAI_API_KEY: str = ""
CORS_ORIGINS: list[str] = ["app://.", "http://localhost:3000", "http://localhost:5173"]
ENV: Literal["dev", "prod"] = "dev"
class Config:
env_file = ".env"
env_file_encoding = "utf-8"
settings = Settings()

0
app/core/__init__.py Normal file
View File

52
app/main.py Normal file
View File

@@ -0,0 +1,52 @@
from contextlib import asynccontextmanager
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from app.config.settings import settings
@asynccontextmanager
async def lifespan(app: FastAPI):
# Startup: initialise DB connection pool and agent registry
from app.core.agent_registry import registry # noqa: F401 — triggers module load
import app.agents # noqa: F401 — triggers @registry.register decorators
yield
# Shutdown: nothing to clean up for now
def create_app() -> FastAPI:
app = FastAPI(
title="Adiuva Cloud API",
version="0.1.0",
docs_url="/docs" if settings.ENV == "dev" else None,
redoc_url=None,
lifespan=lifespan,
)
app.add_middleware(
CORSMiddleware,
allow_origins=settings.CORS_ORIGINS,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Routers (registered when implemented)
# from app.api.routes import auth, chat, plans, backup, billing
# app.include_router(auth.router, prefix="/api/v1")
# app.include_router(chat.router, prefix="/api/v1")
# app.include_router(plans.router, prefix="/api/v1")
# app.include_router(backup.router, prefix="/api/v1")
# app.include_router(billing.router, prefix="/api/v1")
@app.get("/api/v1/health", tags=["health"])
async def health() -> dict:
return {"status": "ok", "version": app.version}
return app
app = create_app()