Syndarix Backend API
The pragmatic, production-ready FastAPI backend for Syndarix.
Overview
Opinionated, secure, and fast. This backend provides the solid foundation you need to ship features, not boilerplate.
Features:
- Authentication: JWT with refresh tokens, session management, device tracking
- Database: Async PostgreSQL with SQLAlchemy 2.0, Alembic migrations
- Security: Rate limiting, CORS, CSP headers, password hashing (bcrypt)
- Multi-tenancy: Organization-based access control with roles (Owner/Admin/Member)
- Testing: 97%+ coverage with security-focused test suite
- Performance: Async throughout, connection pooling, optimized queries
- Modern Tooling: uv for dependencies, Ruff for linting/formatting, mypy for type checking
Quick Start
Prerequisites
- Python 3.12+
- PostgreSQL 14+ (or SQLite for development)
- uv - Modern Python package manager (replaces pip)
Installation
# Install uv (if not already installed)
curl -LsSf https://astral.sh/uv/install.sh | sh
# Install all dependencies (production + dev)
cd backend
uv sync --extra dev
# Or use the Makefile
make install-dev
# Copy environment template
cp .env.example .env
# Edit .env with your configuration
Why uv?
- 🚀 10-100x faster than pip
- 🔒 Reproducible builds via
uv.locklockfile - 📦 Better dependency resolution
- ⚡ Built by Astral (creators of Ruff)
Database Setup
# Run migrations
python migrate.py apply
# Or use Alembic directly
alembic upgrade head
Run Development Server
# Using uv
uv run uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
# Or activate environment first
source .venv/bin/activate # On Windows: .venv\Scripts\activate
uvicorn app.main:app --reload --host 0.0.0.0 --port 8000
API will be available at:
- API: http://localhost:8000
- Swagger Docs: http://localhost:8000/docs
- ReDoc: http://localhost:8000/redoc
Dependency Management with uv
Understanding uv
uv is the modern standard for Python dependency management, built in Rust for speed and reliability.
Key files:
pyproject.toml- Declares dependencies and tool configurationsuv.lock- Locks exact versions for reproducible builds (commit to git)
Common Commands
Installing Dependencies
# Install all dependencies from lockfile
uv sync --extra dev
# Install only production dependencies (no dev tools)
uv sync
# Or use the Makefile
make install-dev # Install with dev dependencies
make sync # Sync from lockfile
Adding Dependencies
# Add a production dependency
uv add httpx
# Add a development dependency
uv add --dev pytest-mock
# Add with version constraint
uv add "fastapi>=0.115.0,<0.116.0"
# Add exact version
uv add "pydantic==2.10.6"
After adding dependencies, commit both pyproject.toml and uv.lock to git.
Removing Dependencies
# Remove a package
uv remove httpx
# Remove a dev dependency
uv remove --dev pytest-mock
Updating Dependencies
# Update all packages to latest compatible versions
uv sync --upgrade
# Update a specific package
uv add --upgrade fastapi
# Check for outdated packages
uv pip list --outdated
Running Commands in uv Environment
# Run any Python command via uv (no activation needed)
uv run python script.py
uv run pytest
uv run mypy app/
# Or activate the virtual environment
source .venv/bin/activate
python script.py
pytest
Makefile Commands
We provide convenient Makefile commands that use uv:
# Setup
make install-dev # Install all dependencies (prod + dev)
make sync # Sync from lockfile
# Code Quality
make lint # Run Ruff linter (check only)
make lint-fix # Run Ruff with auto-fix
make format # Format code with Ruff
make format-check # Check if code is formatted
make type-check # Run mypy type checking
make validate # Run all checks (lint + format + types)
# Testing
make test # Run all tests
make test-cov # Run tests with coverage report
# Utilities
make clean # Remove cache and build artifacts
make help # Show all commands
Dependency Workflow Example
# 1. Clone repository
git clone <repo-url>
cd backend
# 2. Install dependencies
make install-dev
# 3. Make changes, add a new dependency
uv add httpx
# 4. Test your changes
make test
# 5. Commit (includes uv.lock)
git add pyproject.toml uv.lock
git commit -m "Add httpx dependency"
# 6. Other developers pull and sync
git pull
make sync # Uses the committed uv.lock
Troubleshooting uv
Dependencies not found after install:
# Make sure you're using uv run or activated environment
uv run pytest # Option 1: Run via uv
source .venv/bin/activate # Option 2: Activate first
pytest
Lockfile out of sync:
# Regenerate lockfile
uv lock
# Force reinstall from lockfile
uv sync --reinstall
uv not found:
# Install uv globally
curl -LsSf https://astral.sh/uv/install.sh | sh
# Add to PATH if needed
export PATH="$HOME/.cargo/bin:$PATH"
Development
Project Structure
app/
├── api/ # API routes and dependencies
│ ├── routes/ # Endpoint implementations
│ └── dependencies/ # Auth, permissions, etc.
├── core/ # Core functionality
│ ├── config.py # Settings management
│ ├── database.py # Database engine setup
│ ├── auth.py # JWT token handling
│ └── exceptions.py # Custom exceptions
├── crud/ # Database operations
├── models/ # SQLAlchemy ORM models
├── schemas/ # Pydantic request/response schemas
├── services/ # Business logic layer
└── utils/ # Utility functions
See docs/ARCHITECTURE.md for detailed architecture documentation.
Configuration
Environment variables (.env):
# Database
POSTGRES_USER=postgres
POSTGRES_PASSWORD=your_password
POSTGRES_HOST=localhost
POSTGRES_PORT=5432
POSTGRES_DB=app_db
# Security (IMPORTANT: Change these!)
SECRET_KEY=your-secret-key-min-32-chars-change-in-production
ENVIRONMENT=development # development | production
# Optional
BACKEND_CORS_ORIGINS=["http://localhost:3000"]
CSP_MODE=relaxed # strict | relaxed | disabled
# First superuser (auto-created on startup)
FIRST_SUPERUSER_EMAIL=admin@example.com
FIRST_SUPERUSER_PASSWORD=SecurePass123!
⚠️ Security Note: Never commit .env files. Use strong, unique values in production.
Database Migrations
We use Alembic for database migrations with a helper script:
# Generate migration from model changes
python migrate.py generate "add user preferences"
# Apply migrations
python migrate.py apply
# Generate and apply in one step
python migrate.py auto "add user preferences"
# Check current version
python migrate.py current
# List all migrations
python migrate.py list
Manual Alembic usage:
# Generate migration
alembic revision --autogenerate -m "description"
# Apply migrations
alembic upgrade head
# Rollback one migration
alembic downgrade -1
Testing
# Using Makefile (recommended)
make test # Run all tests
make test-cov # Run with coverage report
# Using uv directly
IS_TEST=True uv run pytest
IS_TEST=True uv run pytest --cov=app --cov-report=term-missing -n 0
# Run specific test file
IS_TEST=True uv run pytest tests/api/test_auth.py -v
# Run single test
IS_TEST=True uv run pytest tests/api/test_auth.py::TestLogin::test_login_success -v
# Generate HTML coverage report
IS_TEST=True uv run pytest --cov=app --cov-report=html -n 0
open htmlcov/index.html
Test Environment: Uses SQLite in-memory database. Tests run in parallel via pytest-xdist.
Code Quality
# Using Makefile (recommended)
make lint # Ruff linting
make format # Ruff formatting
make type-check # mypy type checking
make validate # All checks at once
# Using uv directly
uv run ruff check app/ tests/
uv run ruff format app/ tests/
uv run mypy app/
Tools:
- Ruff: All-in-one linting, formatting, and import sorting (replaces Black, Flake8, isort)
- mypy: Static type checking with Pydantic plugin
All configurations are in pyproject.toml.
API Documentation
Once the server is running, interactive API documentation is available:
-
Swagger UI: http://localhost:8000/docs
- Try out endpoints directly
- See request/response schemas
- View authentication requirements
-
ReDoc: http://localhost:8000/redoc
- Alternative documentation interface
- Better for reading/printing
-
OpenAPI JSON: http://localhost:8000/api/v1/openapi.json
- Raw OpenAPI 3.0 specification
- Use for client generation
Authentication
Token-Based Authentication
The API uses JWT tokens for authentication:
-
Login:
POST /api/v1/auth/login- Returns access token (15 min expiry) and refresh token (7 day expiry)
- Session tracked with device information
-
Refresh:
POST /api/v1/auth/refresh- Exchange refresh token for new access token
- Validates session is still active
-
Logout:
POST /api/v1/auth/logout- Invalidates current session
- Use
logout-allto invalidate all user sessions
Using Protected Endpoints
Include access token in Authorization header:
curl -H "Authorization: Bearer <access_token>" \
http://localhost:8000/api/v1/users/me
Roles & Permissions
- Superuser: Full system access (user/org management)
- Organization Roles:
Owner: Full control of organizationAdmin: Can manage members (except owners)Member: Read-only access
Common Tasks
Create a Superuser
Superusers are created automatically on startup using FIRST_SUPERUSER_EMAIL and FIRST_SUPERUSER_PASSWORD from .env.
To create additional superusers, update a user via SQL or admin API.
Add a New API Endpoint
See docs/FEATURE_EXAMPLE.md for step-by-step guide.
Quick overview:
- Create Pydantic schemas in
app/schemas/ - Create CRUD operations in
app/crud/ - Create route in
app/api/routes/ - Register router in
app/api/main.py - Write tests in
tests/api/
Database Health Check
# Check database connection
python migrate.py check
# Health endpoint
curl http://localhost:8000/health
Docker Support
The Dockerfile uses uv for fast, reproducible builds:
# Development with hot reload
docker-compose -f docker-compose.dev.yml up
# Production
docker-compose up -d
# Rebuild after changes
docker-compose build backend
Docker features:
- Multi-stage builds (development + production)
- uv for fast dependency installation
uv.lockensures exact versions in containers- Development stage includes dev dependencies
- Production stage optimized for size and security
Troubleshooting
Common Issues
Module Import Errors
# Ensure dependencies are installed
make install-dev
# Or sync from lockfile
make sync
# Verify Python environment
uv run python --version
uv command not found
# Install uv globally
curl -LsSf https://astral.sh/uv/install.sh | sh
# Add to PATH (add to ~/.bashrc or ~/.zshrc)
export PATH="$HOME/.cargo/bin:$PATH"
Database Connection Failed
# Check PostgreSQL is running
sudo systemctl status postgresql
# Verify credentials in .env
cat .env | grep POSTGRES
Migration Conflicts
# Check migration history
python migrate.py list
# Downgrade and retry
alembic downgrade -1
alembic upgrade head
Tests Failing
# Run with verbose output
make test
# Run single test to isolate issue
IS_TEST=True uv run pytest tests/api/test_auth.py::TestLogin::test_login_success -vv
Dependencies out of sync
# Regenerate lockfile from pyproject.toml
uv lock
# Reinstall everything
make install-dev
Getting Help
See our detailed documentation:
- ARCHITECTURE.md - System design and patterns
- CODING_STANDARDS.md - Code quality guidelines
- COMMON_PITFALLS.md - Mistakes to avoid
- FEATURE_EXAMPLE.md - Adding new features
Performance
Database Connection Pooling
Configured in app/core/config.py:
- Pool size: 20 connections
- Max overflow: 50 connections
- Pool timeout: 30 seconds
- Connection recycling: 1 hour
Async Operations
- All I/O operations use async/await
- CPU-intensive operations (bcrypt) run in thread pool
- No blocking calls in request handlers
Query Optimization
- N+1 query prevention via eager loading
- Bulk operations for admin actions
- Indexed foreign keys and common lookups
Security
Built-in Security Features
- Password Security: bcrypt hashing, strength validation, common password blocking
- Token Security: HMAC-SHA256 signed, short-lived access tokens, algorithm validation
- Session Management: Database-backed, device tracking, revocation support
- Rate Limiting: Per-endpoint limits on auth/sensitive operations
- CORS: Explicit origins, methods, and headers only
- Security Headers: CSP, HSTS, X-Frame-Options, etc.
- Input Validation: Pydantic schemas, SQL injection prevention (ORM)
Security Best Practices
- Never commit secrets: Use
.envfiles (git-ignored) - Strong SECRET_KEY: Min 32 chars, cryptographically random
- HTTPS in production: Required for token security
- Regular updates: Keep dependencies current (
uv sync --upgrade) - Audit logs: Monitor authentication events
Monitoring
Health Check
curl http://localhost:8000/health
Returns:
- API version
- Environment
- Database connectivity
- Timestamp
Logging
Logs are written to stdout with structured format:
# Configure log level
logging.basicConfig(level=logging.INFO)
# In production, use JSON logs for log aggregation
Additional Resources
Official Documentation
- uv: https://docs.astral.sh/uv/
- FastAPI: https://fastapi.tiangolo.com
- SQLAlchemy 2.0: https://docs.sqlalchemy.org/en/20/
- Pydantic: https://docs.pydantic.dev/
- Alembic: https://alembic.sqlalchemy.org/
- Ruff: https://docs.astral.sh/ruff/
Our Documentation
- Root README - Project-wide information
- CLAUDE.md - Comprehensive development guide
Built with modern Python tooling:
- 🚀 uv - 10-100x faster dependency management
- ⚡ Ruff - 10-100x faster linting & formatting
- 🔍 mypy - Static type checking
- ✅ pytest - Comprehensive test suite
All configured in a single pyproject.toml file!