# Story 1.3: FastAPI Application Shell

Status: done

## Story

As a **developer**,
I want **the FastAPI application structure with routing and middleware**,
so that **I can add endpoints for each feature**.

## Acceptance Criteria

1. **AC1:** Running `uvicorn src.api.main:app --reload` starts the API server on port 8000 without errors

2. **AC2:** OpenAPI docs are accessible at `/docs` with valid schema

3. **AC3:** The following FastAPI application structure is in place:
   - `src/api/main.py` - FastAPI app initialization with lifespan management
   - `src/api/routes/__init__.py` - Route module package
   - `src/api/routes/health.py` - Health endpoint route (shell)
   - `src/api/routes/documents.py` - Documents endpoint routes (shell)
   - `src/api/routes/query.py` - Query endpoint routes (shell)
   - `src/api/dependencies.py` - Dependency injection setup
   - `src/api/middleware.py` - CORS and error handling middleware

4. **AC4:** Exception handling middleware is configured:
   - `src/core/exceptions.py` contains `DSOLError` base class with `code`, `message`, `details` attributes
   - Subclasses: `ExtractionError`, `RetrievalError`, `ValidationError`, `NotFoundError`
   - Middleware catches `DSOLError` and returns JSON: `{"error": {"code": "...", "message": "...", "details": {...}}}`
   - Unhandled exceptions return 500 with `{"error": {"code": "INTERNAL_ERROR", "message": "..."}}`

5. **AC5:** CORS middleware is configured for development:
   - Allow origins: `["*"]` (dev mode)
   - Allow methods: `["*"]`
   - Allow headers: `["*"]`
   - Allow credentials: `true`

6. **AC6:** FastAPI lifespan context manager:
   - On startup: Logs "API starting" with version
   - On shutdown: Logs "API shutting down"
   - Future hooks for database/redis connection cleanup

7. **AC7:** Route modules are wired to the main app:
   - `/health` prefix from `health.py` (AC verified in Story 1.5)
   - `/documents` prefix from `documents.py` (AC verified in Epic 2)
   - `/query` prefix from `query.py` (AC verified in Epic 5)

## Tasks / Subtasks

- [x] **Task 1: Create exception classes** (AC: 4)
  - [x] Implement `DSOLError` base class in `src/core/exceptions.py` with `code`, `message`, `details` attributes
  - [x] Implement `to_dict()` method for JSON serialization
  - [x] Add subclasses: `ExtractionError`, `RetrievalError`, `ValidationError`, `NotFoundError`, `AuthenticationError`

- [x] **Task 2: Create middleware module** (AC: 4, 5)
  - [x] Create `src/api/middleware.py`
  - [x] Implement `add_exception_handlers()` function to register error handlers
  - [x] Implement `DSOLError` exception handler returning structured JSON
  - [x] Implement generic `Exception` handler returning 500 with INTERNAL_ERROR
  - [x] Implement `add_cors_middleware()` function with development settings

- [x] **Task 3: Create dependencies module** (AC: 3)
  - [x] Create `src/api/dependencies.py`
  - [x] Re-export `get_async_session` from `src/db/session.py`
  - [x] Add placeholder for future auth dependency

- [x] **Task 4: Create route module shells** (AC: 3, 7)
  - [x] Create `src/api/routes/__init__.py` with router exports
  - [x] Create `src/api/routes/health.py` with `router = APIRouter(prefix="/health", tags=["Health"])` and placeholder GET endpoint
  - [x] Create `src/api/routes/documents.py` with `router = APIRouter(prefix="/documents", tags=["Documents"])` and placeholder
  - [x] Create `src/api/routes/query.py` with `router = APIRouter(prefix="/query", tags=["Query"])` and placeholder

- [x] **Task 5: Create main FastAPI application** (AC: 1, 2, 6, 7)
  - [x] Create `src/api/main.py` with FastAPI app initialization
  - [x] Implement `lifespan` async context manager for startup/shutdown
  - [x] Import and apply middleware (CORS, exception handlers)
  - [x] Include all route modules
  - [x] Configure app metadata (title, version, description)

- [x] **Task 6: Verify application starts correctly** (AC: 1, 2)
  - [x] Run `uv run uvicorn src.api.main:app --reload`
  - [x] Verify server starts on port 8000
  - [x] Access `/docs` and verify OpenAPI schema loads
  - [x] Verify placeholder endpoints appear in docs

## Dev Notes

### Architecture Patterns and Constraints

- **Framework:** FastAPI 0.122 with async support
- **Middleware Pattern:** Exception handlers + CORS middleware
- **Dependency Injection:** FastAPI's `Depends()` system
- **Error Response Format:** `{"error": {"code": "...", "message": "...", "details": {...}}}`
- **Lifespan:** Use `@asynccontextmanager` for startup/shutdown hooks

### Project Structure Notes

From Story 1.2, the following already exist and should be used:
- `src/core/config.py` - Pydantic Settings configuration (DO NOT recreate)
- `src/db/session.py` - Async session factory with `get_async_session` dependency
- `src/db/models.py` - ORM models

Files to create/modify in this story:
- `src/api/__init__.py` - exists (empty)
- `src/api/main.py` - exists (empty shell, needs FastAPI app)
- `src/api/routes/__init__.py` - exists (empty)
- `src/api/dependencies.py` - needs creation
- `src/api/middleware.py` - needs creation
- `src/api/routes/health.py` - needs creation
- `src/api/routes/documents.py` - needs creation
- `src/api/routes/query.py` - needs creation
- `src/core/exceptions.py` - exists (empty shell, needs exception classes)

### Learnings from Previous Story

**From Story 1-2-database-schema-migrations (Status: done)**

- **Pydantic Settings Created**: `src/core/config.py` with all environment variables - REUSE, do not recreate
- **Async Session Available**: `src/db/session.py` provides `get_async_session` and `AsyncSessionDep` for dependency injection
- **Package Manager**: Project uses `uv` (not Poetry) - use `uv run uvicorn` commands
- **Dependencies**: FastAPI, uvicorn already installed via pyproject.toml

[Source: docs/sprint-artifacts/1-2-database-schema-migrations.md#Dev-Agent-Record]

### References

- [Source: docs/sprint-artifacts/tech-spec-epic-1.md#Services-and-Modules] - Module responsibilities
- [Source: docs/sprint-artifacts/tech-spec-epic-1.md#APIs-and-Interfaces] - Health check response format
- [Source: docs/sprint-artifacts/tech-spec-epic-1.md#Reliability] - Error handling pattern
- [Source: docs/architecture.md#Implementation-Patterns] - Code organization, error handling
- [Source: docs/architecture.md#API-Contracts] - Error response format
- [Source: docs/epics.md#Story-1.3] - Original story definition

## Dev Agent Record

### Context Reference

N/A - Story context will be generated by story-context workflow

### Agent Model Used

Claude Opus 4.5 (claude-opus-4-5-20251101)

### Debug Log References

- Server started successfully on port 8000
- All endpoints verified: /health, /documents, /query
- OpenAPI docs accessible at /docs with valid schema
- CORS and exception handling middleware configured

### Completion Notes List

- Implemented DSOLError exception hierarchy with 5 subclasses in `src/core/exceptions.py`
- Created middleware module with CORS configuration and exception handlers
- Created dependencies module re-exporting async session dependency
- Created route module shells for health, documents, and query endpoints
- Implemented FastAPI app with lifespan management, middleware, and route inclusion
- Verified all ACs through manual testing: server starts, /docs works, all endpoints respond

### File List

| Status | File Path |
|--------|-----------|
| MODIFIED | src/core/exceptions.py |
| MODIFIED | src/api/main.py |
| MODIFIED | src/api/middleware.py |
| MODIFIED | src/api/dependencies.py |
| MODIFIED | src/api/routes/__init__.py |
| MODIFIED | src/api/routes/health.py |
| MODIFIED | src/api/routes/documents.py |
| MODIFIED | src/api/routes/query.py |
