diff --git a/app/backend/core/config.py b/app/backend/core/config.py index 8b6969e..6cd3e6d 100644 --- a/app/backend/core/config.py +++ b/app/backend/core/config.py @@ -1,16 +1,20 @@ """Environment configuration derived from environment variables.""" from functools import lru_cache +from pydantic import SecretStr # Import SecretStr for sensitive data from pydantic_settings import BaseSettings, SettingsConfigDict class Settings(BaseSettings): - """Application settings.""" + """ + Application settings class using Pydantic BaseSettings. + Settings are loaded from environment variables and have default values defined here. + """ - service_name: str = "avaaz-backend" # Used as a functional ID - environment: str = "development" + service_name: str = "avaaz-backend" # A unique functional identifier for the microservice + environment: str = "development" # Defines the current deployment stage (e.g., 'development', 'staging', 'production') title: str = "Avaaz Language Tutoring API" - description: str =""" + description: str = """ # Avaaz Language Tutoring API This API powers the **avaaz.ai** mobile and web applications, providing the robust backend services for our AI-driven oral language skills tutor. The platform is specifically engineered to help students achieve oral proficiency using adaptive, conversational AI agents. @@ -22,14 +26,24 @@ class Settings(BaseSettings): * **Cross-Platform Sync:** Ensures seamless learning continuity and progress synchronization across all user devices. """ - version: str = "0.1.0" + version: str = "0.1.0" # The current semantic version of the API application - database_url: str = "postgresql+psycopg://postgres:postgres@postgres:5432/avaaz" - - model_config = SettingsConfigDict(env_prefix="", case_sensitive=False) + # Use SecretStr to prevent accidental logging of credentials. + # Access the actual value using settings.database_url.get_secret_value() + database_url: SecretStr = SecretStr("postgresql+psycopg://postgres:postgres@postgres:5432/avaaz") + model_config = SettingsConfigDict( + env_prefix="", # Load variables without a specific prefix (e.g., `DATABASE_URL` instead of `APP_DATABASE_URL`) + case_sensitive=False # Environment variable names are treated as case-insensitive during loading + ) @lru_cache(maxsize=1) def get_settings() -> Settings: - """Return cached settings instance.""" + """ + Return a cached singleton instance of the application settings. + + This function leverages functools.lru_cache to ensure that environment variables + are read only once during the application's lifecycle, improving performance + and ensuring consistency across requests. + """ return Settings() diff --git a/app/backend/main.py b/app/backend/main.py index e6245e1..3ee0e6b 100644 --- a/app/backend/main.py +++ b/app/backend/main.py @@ -1,19 +1,28 @@ -"""Application entrypoint and router wiring.""" +""" +API Application Entrypoint and Router Wiring. + +This module initializes the core FastAPI application instance, loads +configuration, applies middleware, and wires up all defined API routers. +""" from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware - +from typing import List from api.v1.router import router as api_v1_router from operations.health.router import router as health_router +from core.config import get_settings, Settings # Import Settings type for clarity -from core.config import get_settings +def create_app(settings: Settings = get_settings()) -> FastAPI: + """ + Create and configure the FastAPI application instance. -def create_app() -> FastAPI: - """Create and configure the FastAPI application.""" - - settings = get_settings() + Args: + settings: Configuration object from core.config. Defaults to current settings. + Returns: + A configured FastAPI application instance. + """ app = FastAPI( title=settings.title, description=settings.description, @@ -23,19 +32,25 @@ def create_app() -> FastAPI: openapi_url="/openapi.json", ) - # CORS for local dev (frontend on 3000). Tighten/override in prod. + # Define allowed origins dynamically based on local dev environment needs + # In a production setting, this list would typically be sourced from environment variables. + allowed_origins: List[str] = ["http://localhost:3000", "http://127.0.0.1:3000"] + + # Configure CORS middleware + # TODO: Tightly restrict origins in production deployment. app.add_middleware( CORSMiddleware, - allow_origins=["http://localhost:3000", "http://127.0.0.1:3000"], + allow_origins=allowed_origins, allow_credentials=True, allow_methods=["*"], allow_headers=["*"], ) + # Include API routers app.include_router(health_router) app.include_router(api_v1_router, prefix="/api/v1") return app - +# Main entry point for services like Uvicorn (e.g., `uvicorn main:app --reload`) app = create_app()