Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
174 changes: 174 additions & 0 deletions .github/copilot-instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
# Python Template Server - AI Agent Instructions

## Project Overview

FastAPI-based template server providing reusable infrastructure for building secure HTTPS applications.
Implements authentication, rate limiting, security headers, and observability foundations via a base `TemplateServer` class.
Developers extend `TemplateServer` to create application-specific servers (see `ExampleServer` in `main.py`).

## Architecture & Key Components

### Application Factory Pattern

- Entry: `main.py:run()` → instantiates `ExampleServer` (subclass of `TemplateServer`) → calls `.run()`
- `TemplateServer.__init__()` sets up middleware, rate limiting, metrics, and calls `setup_routes()`
- **Critical**: Middleware order matters - request logging → security headers → rate limiting
- **Extensibility**: Subclasses implement `setup_routes()` to add custom endpoints and `validate_config()` for config validation

### Configuration System

- `config.json` loaded via `TemplateServer.load_config()` method
- Validated using Pydantic models in `models.py` (TemplateServerConfig hierarchy)
- Subclasses override `validate_config()` to provide custom config models
- Logging configured automatically on `logging_setup.py` import with rotating file handler
- Environment variables stored in `.env` (API_TOKEN_HASH only, never commit)

### Authentication Architecture

- **Token Generation**: `uv run generate-new-token` creates secure token + SHA-256 hash
- **Hash Storage**: Only hash stored in `.env` (API_TOKEN_HASH), raw token shown once
- **Token Loading**: `load_hashed_token()` loads hash from .env on server startup, stored in `TemplateServer.hashed_token`
- **Verification Flow**: Request → `_verify_api_key()` dependency → `verify_token()` → hash comparison
- **Metrics**: Success/failure counters with labeled reasons (missing/invalid/error)
- **Health Endpoint**: `/api/health` does NOT require authentication, reports unhealthy if token not configured
- Header: `X-API-Key` (defined in `constants.API_KEY_HEADER_NAME`)

### Rate Limiting

- Uses `slowapi` with configurable storage (in-memory/Redis/Memcached)
- Applied via `_limit_route()` wrapper when `config.rate_limit.enabled=true`
- Custom exception handler increments `rate_limit_exceeded_counter` per endpoint
- Format: `"100/minute"` (supports /second, /minute, /hour)

### Observability Stack

- **Prometheus**: `/metrics` endpoint always exposed (no auth), custom auth/rate-limit metrics
- **Grafana**: Pre-configured dashboards in `grafana/dashboards/*.json`
- **Logging**: Dual output (console + rotating file), 10MB per file, 5 backups in `logs/`
- **Request Tracking**: `RequestLoggingMiddleware` logs all requests with client IP

## Developer Workflows

### Essential Commands

```powershell
# Setup (first time)
uv sync # Install dependencies
uv run generate-certificate # Create self-signed SSL certs (certs/ dir)
uv run generate-new-token # Generate API key, save hash to .env

# Development
uv run python-template-server # Start server (https://localhost:443/api)
uv run -m pytest # Run tests with coverage
uv run -m mypy . # Type checking
uv run -m ruff check . # Linting

# Docker Development
docker compose up --build -d # Build + start all services
docker compose logs -f python-template-server # View logs
docker compose down # Stop and remove containers
```

### Testing Patterns

- **Fixtures**: All tests use `conftest.py` fixtures, auto-mock `pyhere.here()` to tmp_path
- **Config Mocking**: Use fixtures for consistent test config
- **Integration Tests**: Test via FastAPI TestClient with auth headers
- **Coverage Target**: 99% (currently achieved)
- **Pattern**: Unit tests per module (test\_\*.py) + integration tests (test_template_server.py)

### Docker Multi-Stage Build

- **Stage 1 (builder)**: Uses `uv` to build wheel, copies `configuration/` directory and other required files
- **Stage 2 (runtime)**: Installs wheel, copies runtime files (.here, configs, LICENSE, README.md) from wheel to /app
- **Startup Script**: `/app/start.sh` generates token/certs if missing, starts server
- **Config Selection**: Uses `config.json` for all environments
- **Build Args**: `PORT=443` (exposes port)
- **Health Check**: Curls `/api/health` with unverified SSL context (no auth required)
- **User**: Switches to non-root user `templateserver` (UID 1000)

## Project-Specific Conventions

### Code Organization

- **Handlers**: Separate modules for auth (`authentication_handler.py`), certs (`certificate_handler.py`)
- **Middleware**: Dedicated package `middleware/` with base classes extending `BaseHTTPMiddleware`
- **Constants**: All magic strings/numbers in `constants.py` (ports, file names, log config)
- **Models**: Pydantic models for config + API responses, use `@property` for derived values

### Security Patterns

- **Never log secrets**: Print tokens via `print()`, not `logger` (see `generate_new_token()`)
- **Path validation**: Use Pydantic validators, Path objects for cert paths
- **Security headers**: HSTS, CSP, X-Frame-Options via `SecurityHeadersMiddleware`
- **Cert generation**: RSA-4096, SHA-256, 365-day validity, SANs for localhost

### API Design

- **Prefix**: All routes under `/api` (API_PREFIX constant)
- **Authentication**: Applied via `dependencies=[Security(self._verify_api_key)]` in route registration
- **Unauthenticated Endpoints**: `/health` and `/metrics` do not require authentication
- **Response Models**: All endpoints return `BaseResponse` subclasses with code/message/timestamp
- **Health Status**: `/health` includes `status` field (HEALTHY/DEGRADED/UNHEALTHY), reports unhealthy if no token configured

### Logging Format

- Format: `[DD/MM/YYYY | HH:MM:SS] (LEVEL) module: message`
- Client IPs logged in requests: `"Request: GET /api/health from 192.168.1.1"`
- Auth failures: `"Invalid API key attempt!"`

## Development Constraints

### What's NOT Implemented Yet

- Custom domain-specific endpoints (template provides base functionality only)
- Database/metadata storage (users implement as needed in subclasses)
- CORS configuration (can be added by subclasses)
- API key rotation/expiry
- Multi-user auth (JWT/OAuth2)

### Testing Requirements

- Mock `pyhere.here()` for all file path tests (see `conftest.py`)
- Use fixtures for TemplateServer/ExampleServer instantiation
- Test async endpoints with `@pytest.mark.asyncio`
- Mock `uvicorn.run` when testing server `.run()` methods

### CI/CD Validation

All PRs must pass:

**CI Workflow:**

1. `validate-pyproject` - pyproject.toml schema validation
2. `ruff` - linting (120 char line length, strict rules in pyproject.toml)
3. `mypy` - 100% type coverage (strict mode)
4. `pytest` - 99% code coverage, HTML report uploaded
5. `version-check` - pyproject.toml vs uv.lock version consistency

**Docker Workflow:**

1. `docker-development` - Build and test dev image with docker compose
2. `docker-production` - Build and test prod image with ENV=prod, PORT=443

## Quick Reference

### Key Files

- `template_server.py` - Base TemplateServer class with middleware/metrics/auth setup
- `main.py` - ExampleServer implementation showing how to extend TemplateServer
- `authentication_handler.py` - Token generation, hashing, verification
- `logging_setup.py` - Logging configuration (executed on import)
- `models.py` - All Pydantic models (config + responses)
- `constants.py` - Project constants, logging config
- `docker-compose.yml` - FastAPI + Prometheus + Grafana stack

### Environment Variables

- `API_TOKEN_HASH` - SHA-256 hash of API token (only var required)

### Configuration Files

- `configuration/config.json` - Configuration (used for all environments)
- `.env` - API token hash (auto-created by generate-new-token)
- **Docker**: Startup script uses config.json for all environments
128 changes: 108 additions & 20 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,40 +1,128 @@
[![python](https://img.shields.io/badge/Python-3.12-3776AB.svg?style=flat&logo=python&logoColor=ffd343)](https://docs.python.org/3.12/)
[![uv](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/uv/main/assets/badge/v0.json)](https://github.com/astral-sh/uv)
[![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
[![FastAPI](https://img.shields.io/badge/FastAPI-Latest-009688?style=flat&logo=fastapi&logoColor=white)](https://fastapi.tiangolo.com/)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)

<!-- omit from toc -->
# Template Python Repository
This repository can be used as a template for a Python application.
# Python Template Server

A production-ready FastAPI server template with built-in authentication, rate limiting, security headers, and Prometheus metrics. This repository provides a solid foundation for building secure, observable FastAPI applications.

<!-- omit from toc -->
## Table of Contents
- [uv](#uv)
- [Installing Dependencies](#installing-dependencies)
- [Testing, Linting, and Type Checking](#testing-linting-and-type-checking)
- [Features](#features)
- [Architecture](#architecture)
- [Quick Start](#quick-start)
- [Prerequisites](#prerequisites)
- [Installation](#installation)
- [Generate Certificates and API Token](#generate-certificates-and-api-token)
- [Run the Server](#run-the-server)
- [Using as a Template](#using-as-a-template)
- [Docker Deployment](#docker-deployment)
- [Documentation](#documentation)

## Features

- **TemplateServer Base Class**: Reusable foundation
- **FastAPI Framework**: Modern, fast, async-ready web framework
- **Observability Stack**: Pre-configured Prometheus + Grafana dashboards
- **Docker Support**: Multi-stage builds with docker-compose orchestration
- **Production Patterns**: Token generation, SSL certificate handling, health checks

## Architecture

This project uses a **`TemplateServer` base class** that encapsulates cross-cutting concerns:

- **Request Logging**: All requests/responses logged with client IP tracking
- **Security Headers**: HSTS/CSP/X-Frame-Options automatically applied
- **API Key Verification**: SHA-256 hashed tokens with secure validation
- **Rate Limiting**: Configurable limits using `slowapi` (in-memory/Redis/Memcached)
- **Prometheus Metrics**: Custom authentication/rate-limit metrics + HTTP instrumentation

**Application-specific servers** (like `ExampleServer` in `main.py`) extend `TemplateServer` to implement domain-specific endpoints and business logic. The base class handles all infrastructure concerns, letting you focus on your API functionality.

## Quick Start

## uv
This repository is managed using the `uv` Python project manager: https://docs.astral.sh/uv/
### Prerequisites

To install `uv`:
- Python 3.12+
- [uv](https://docs.astral.sh/uv/) package manager

Install `uv`:

```sh
curl -LsSf https://astral.sh/uv/install.sh | sh # Linux/Mac
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex" # Windows
# Linux/Mac
curl -LsSf https://astral.sh/uv/install.sh | sh

# Windows (PowerShell)
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
```

## Installing Dependencies
Install the required dependencies using `uv`:
### Installation

```sh
# Clone the repository
git clone https://github.com/javidahmed64592/python-template-server.git
cd python-template-server

# Install dependencies
uv sync --extra dev
```

uv sync
### Generate Certificates and API Token

To install with `dev` dependencies:
```sh
# Generate self-signed SSL certificate (saves to certs/ directory)
uv run generate-certificate

uv sync --extra dev
# Generate API authentication token (saves hash to .env)
uv run generate-new-token
# ⚠️ Save the displayed token - you'll need it for API requests!
```

### Run the Server

```sh
# Start the server
uv run python-template-server

# Server runs at https://localhost:443/api
# Health check: curl -k https://localhost:443/api/health
# Metrics: curl -k https://localhost:443/api/metrics
```

## Using as a Template

To create your own server:

1. **Create a subclass of `TemplateServer`** (see `python_template_server/main.py:ExampleServer` as reference)
2. **Implement required methods**:
- `validate_config()`: Validate your config model
- `setup_routes()`: Define your API endpoints
3. **Add custom routes** using FastAPI decorators on `self.app`
4. **Configure** via `configuration/config.json`

See the [Software Maintenance Guide](./docs/SMG.md) for detailed setup instructions.

## Docker Deployment

```sh
# Start all services (FastAPI + Prometheus + Grafana)
docker compose up -d

# View logs
docker compose logs -f python-template-server

# Access services:
# - API: https://localhost:443/api
# - Prometheus: http://localhost:9090
# - Grafana: http://localhost:3000 (admin/admin)
```

## Testing, Linting, and Type Checking
## Documentation

- **Run tests:** `uv run pytest`
- **Lint code:** `uv run ruff check .`
- **Format code:** `uv run ruff format .`
- **Type check:** `uv run mypy .`
- **[API Documentation](./docs/API.md)**: Endpoints, authentication, metrics
- **[Software Maintenance Guide](./docs/SMG.md)**: Development setup, configuration
- **[Docker Deployment Guide](./docs/DOCKER_DEPLOYMENT.md)**: Container orchestration
- **[Workflows](./docs/WORKFLOWS.md)**: CI/CD pipeline details
Loading