|
| 1 | +# FastAPI Boilerplate Changelog |
| 2 | + |
| 3 | +## Introduction |
| 4 | + |
| 5 | +The Changelog documents all notable changes to FastAPI Boilerplate, organized by version. For releases before v0.18.0, see [GitHub releases](https://github.com/benavlabs/FastAPI-boilerplate/releases). |
| 6 | + |
| 7 | +For the full narrative on each release — rationale, decisions, migration guide — see the corresponding GitHub release page. |
| 8 | + |
| 9 | +___ |
| 10 | + |
| 11 | +## [0.18.0] - May 24, 2026 — The Pluggable Restructure |
| 12 | + |
| 13 | +This is the release we promised in v0.17.0; the one that tears the layout apart and rebuilds it as a real plugin system. If you've been pinned to v0.17.0 waiting for it, this is your moment. |
| 14 | + |
| 15 | +A heads-up before we go further: **the diff is enormous**; v0.17.0 → v0.18.0 is not the kind of upgrade you run `git pull` for. The Python package moved, auth changed completely, workers changed, the admin panel changed, there's a new CLI in a new workspace member. We didn't do this lightly. |
| 16 | + |
| 17 | +### Why this release is so different |
| 18 | + |
| 19 | +We didn't iterate on the v0.17.0 codebase to get here. We **rebased the project on the [fastroai-template](https://fastro.ai) structure**. |
| 20 | + |
| 21 | +fastroai-template is the production-tested template we use internally (and sell) for AI SaaS products. It's been running real apps for months and the structural choices (three-layer architecture, vertical-slice modules, server-side sessions, SQLAdmin, Taskiq, swappable infrastructure) have proven themselves under load. Reinventing all of that for FastAPI-boilerplate would have meant another six months of polish; rebasing meant we could ship the good parts on day one. |
| 22 | + |
| 23 | +The trade-off is that fastroai-template carries a lot of stuff this boilerplate's audience doesn't necessarily need: a Stripe integration, subscription/credits/entitlements modeling, AI agent orchestration, usage tracking with cost calculation, OAuth-specific provisioning for SaaS, an Astro frontend. Excellent for an AI SaaS starter, wrong for a general FastAPI boilerplate. |
| 24 | + |
| 25 | +**So this release is fastroai-template minus the SaaS/AI parts, plus a plugin system that fastroai-template doesn't have.** What's left is the structural skeleton; the parts that any FastAPI app needs and that we've watched hold up in real use: |
| 26 | + |
| 27 | +- The three-layer split (`interfaces/`, `infrastructure/`, `modules/`) |
| 28 | +- Vertical-slice modules (`user/`, `tier/`, `api_keys/`, `rate_limit/`) |
| 29 | +- Server-side sessions + CSRF, OAuth (Google wired, GitHub scaffolded) |
| 30 | +- SQLAdmin, Taskiq, swappable cache/session/rate-limit backends |
| 31 | +- The production security validator that refuses to boot with insecure defaults |
| 32 | + |
| 33 | +The new part, the one fastroai-template doesn't have, is **`bp` — a plugin-aware CLI**. fastroai-template ships everything in-tree because that's appropriate for an AI SaaS starter. FastAPI-boilerplate's whole pitch is "use what you need, drop what you don't", and that pitch only works if dropping things and adding things are first-class operations. The `bp.commands` and `bp.features` entry points are how external Python packages contribute new commands and feature generators without touching the core. Build a Stripe plugin, a Prometheus plugin, a CRUD-generator plugin, they all ship as separate packages. |
| 34 | + |
| 35 | +### If you can stay on v0.17.0, consider it |
| 36 | + |
| 37 | +For brand-new projects, v0.18.0 is the better starting point. For existing apps with significant custom code on v0.17.0, the honest answer is: **the migration path is "copy your business logic into the new structure"**, not a sed-style find-and-replace. If your fork has diverged from v0.17.0 in non-trivial ways, pinning to v0.17.0 may be the right call. We'll keep v0.17.0 around as a tag forever. |
| 38 | + |
| 39 | +For the full migration guide and per-section detail, see the [full release notes on GitHub](https://github.com/benavlabs/FastAPI-boilerplate/releases/tag/v0.18.0). |
| 40 | + |
| 41 | +--- |
| 42 | + |
| 43 | +#### Added |
| 44 | + |
| 45 | +- **Three-layer architecture** by [@igorbenav](https://github.com/igorbenav) |
| 46 | + - `backend/src/{interfaces,infrastructure,modules}/` split |
| 47 | + - Vertical-slice modules: each domain owns its full vertical (`models`, `schemas`, `crud`, `service`, `routes`, `enums`) |
| 48 | + - Modules shipped: `user`, `tier`, `api_keys`, `rate_limit`, `common` |
| 49 | + |
| 50 | +- **uv workspace split** by [@igorbenav](https://github.com/igorbenav) |
| 51 | + - Workspace root with two members: `backend/` (deployable) and `cli/` (developer tool) |
| 52 | + - Single shared `.venv`; prod Dockerfile only copies `backend/src/` |
| 53 | + - Install with `uv sync --all-packages --all-extras` from the repo root |
| 54 | + |
| 55 | +- **`bp` CLI with plugin extension points** by [@igorbenav](https://github.com/igorbenav) |
| 56 | + - `bp.commands` — external Typer sub-apps mount under the root |
| 57 | + - `bp.features` — external feature generators with manifest + plan + rollback |
| 58 | + - In-tree commands: `bp deploy generate {local,prod,nginx}`, `bp env gen-secret`, `bp env validate` |
| 59 | + - Built-in `deploy` feature with Jinja templates for compose + nginx |
| 60 | + |
| 61 | +- **OAuth provider framework** by [@igorbenav](https://github.com/igorbenav), [@LucasQR](https://github.com/LucasQR) |
| 62 | + - Google end-to-end (callback creates session, sets cookie) |
| 63 | + - GitHub scaffolded with the same provider/factory shape |
| 64 | + - Documentation at `docs/user-guide/authentication/` |
| 65 | + |
| 66 | +- **API keys module** by [@igorbenav](https://github.com/igorbenav) |
| 67 | + - Named keys with permissions and usage limits |
| 68 | + - Per-call usage recording for analytics |
| 69 | + - scrypt hashing with per-row salt (CodeQL strong-KDF compliant) |
| 70 | + - Lookup via indexed `key_prefix` column with constant-time verify |
| 71 | + |
| 72 | +- **Production security validator** by [@igorbenav](https://github.com/igorbenav) |
| 73 | + - Startup gate that refuses to boot prod with insecure defaults |
| 74 | + - Checks `SECRET_KEY`, DB credentials, CORS policy, session flags, debug mode, `CREATE_TABLES_ON_STARTUP` |
| 75 | + - `bp env validate` runs the same checks against any config |
| 76 | + |
| 77 | +- **Server-side sessions** by [@igorbenav](https://github.com/igorbenav) |
| 78 | + - Opaque session IDs in `HttpOnly` cookies |
| 79 | + - Backed by Redis (default), Memcached, or in-memory |
| 80 | + - CSRF enforced by default for state-changing endpoints |
| 81 | + - Documentation at `docs/user-guide/authentication/sessions.md` |
| 82 | + |
| 83 | +- **Swappable infrastructure backends** by [@igorbenav](https://github.com/igorbenav) |
| 84 | + - Cache, rate limit, session storage all behind ABCs in `*/base.py` |
| 85 | + - Concrete backends in `*/backends/{redis,memcached,memory}.py` |
| 86 | + - Env-selectable: `SESSION_BACKEND`, `CACHE_BACKEND`, `RATE_LIMITER_BACKEND` |
| 87 | + |
| 88 | +- **Multi-stage Dockerfile** by [@igorbenav](https://github.com/igorbenav) |
| 89 | + - `dev` / `migrate` / `prod` stages from a single `backend/Dockerfile` |
| 90 | + - Uses `uv export` against the lockfile for reproducible builds with hash verification |
| 91 | + - Pinned uv version (`0.9.9`) for build reproducibility |
| 92 | + |
| 93 | +- **Python 3.14 dependency compatibility** by [@carlosplanchon](https://github.com/carlosplanchon) |
| 94 | + - Dependency bumps that compile and run on Python 3.14 |
| 95 | + |
| 96 | +- **CI workflows for the workspace** by [@igorbenav](https://github.com/igorbenav) |
| 97 | + - `tests.yml`, `linting.yml`, `type-checking.yml`, `docs.yml` covering both members |
| 98 | + - Least-privilege `permissions: contents: read` on all workflows (`docs.yml` additionally has `pages: write` and `id-token: write`) |
| 99 | + |
| 100 | +#### Changed |
| 101 | + |
| 102 | +- **JWT → server-side sessions** by [@igorbenav](https://github.com/igorbenav) |
| 103 | + - JWT access tokens, refresh tokens, and the `token_blacklist` table removed |
| 104 | + - API surface is cookie-based now; clients sending `Authorization: Bearer` are rejected |
| 105 | + |
| 106 | +- **CRUDAdmin → SQLAdmin** by [@igorbenav](https://github.com/igorbenav) |
| 107 | + - Custom admin panel replaced with SQLAdmin |
| 108 | + - `DataclassModelMixin` added for `MappedAsDataclass` model compatibility |
| 109 | + - Env: `CRUD_ADMIN_*` removed; use `ADMIN_ENABLED` (uses main `SECRET_KEY`) |
| 110 | + |
| 111 | +- **ARQ → Taskiq** by [@igorbenav](https://github.com/igorbenav) |
| 112 | + - Async-native worker stack with Redis or RabbitMQ broker |
| 113 | + - Worker command: `taskiq worker infrastructure.taskiq.worker:default_broker` |
| 114 | + - `DBSession` dependency injection in tasks |
| 115 | + |
| 116 | +- **MkDocs → Zensical** by [@igorbenav](https://github.com/igorbenav) |
| 117 | + - Docs site generator swapped; configured via `zensical.toml` |
| 118 | + - Local: `uvx zensical serve`; build: `uvx zensical build` |
| 119 | + - Deploy via `.github/workflows/docs.yml` to GitHub Pages |
| 120 | + |
| 121 | +- **Settings layout** by [@igorbenav](https://github.com/igorbenav) |
| 122 | + - Composed setting groups (`AuthSettings`, `CacheSettings`, `RateLimiterSettings`, etc.) in `infrastructure/config/settings.py` |
| 123 | + - `get_settings()` returns the composed `Settings` instance |
| 124 | + - Most env var names stable; a few moved between groups |
| 125 | + |
| 126 | +#### Security |
| 127 | + |
| 128 | +- **Dropped `python-jose` / `ecdsa`** by [@igorbenav](https://github.com/igorbenav) |
| 129 | + - Removed unused `fastsecure` dep, which was pulling in `python-jose` and `ecdsa` |
| 130 | + - Addresses the Minerva timing attack on P-256 in python-ecdsa (the project explicitly won't fix it; switching to `cryptography` was the upstream recommendation) |
| 131 | + - `bcrypt` is now a direct dependency (was transitive via `fastsecure`) |
| 132 | + |
| 133 | +- **Bumped `idna` to 3.16** by [@igorbenav](https://github.com/igorbenav) |
| 134 | + - Fixes CVE-2024-3651 bypass for crafted inputs to `idna.encode()` |
| 135 | + |
| 136 | +- **Bumped `sqladmin` to 0.26.0** by [@igorbenav](https://github.com/igorbenav) |
| 137 | + - Fixes the `ajax_lookup` authorization bypass |
| 138 | + |
| 139 | +- **scrypt for API key hashing** by [@igorbenav](https://github.com/igorbenav) |
| 140 | + - Per-row salt, format `scrypt$N$r$p$salt$derived` |
| 141 | + - Compliance with CodeQL's strong-KDF allowlist |
| 142 | + - Constant-time verify via `hmac.compare_digest` |
| 143 | + |
| 144 | +- **Workflow permissions tightened** by [@igorbenav](https://github.com/igorbenav) |
| 145 | + - All CI workflows now declare explicit `permissions:` blocks |
| 146 | + - Read-only on test/lint/type-check; targeted writes only where needed |
| 147 | + |
| 148 | +#### Improved |
| 149 | + |
| 150 | +- **Full documentation rewrite** by [@igorbenav](https://github.com/igorbenav), [@LucasQR](https://github.com/LucasQR), [@emiliano-gandini-outeda](https://github.com/emiliano-gandini-outeda) |
| 151 | + - Every page under `docs/user-guide/` rewritten for the new structure |
| 152 | + - New `docs/cli/` section: `index.md`, `commands.md`, `plugins.md` |
| 153 | + - New `docs/user-guide/authentication/sessions.md` |
| 154 | + - README slimmed but still self-contained |
| 155 | + |
| 156 | +- **Lint enforcement: `PLC0415`** by [@igorbenav](https://github.com/igorbenav) |
| 157 | + - No deferred imports anywhere — all imports at module top |
| 158 | + - Surfaced and resolved a circular import in session storage by extracting `AbstractSessionStorage` to `auth/session/base.py` |
| 159 | + |
| 160 | +- **README polish** by [@carlosplanchon](https://github.com/carlosplanchon) |
| 161 | + - Installation scripts moved out of Gists into the repo |
| 162 | + - DeepWiki documentation link added |
| 163 | + |
| 164 | +#### Removed |
| 165 | + |
| 166 | +- **`src/app/` layout** — replaced by `backend/src/{interfaces,infrastructure,modules}/` |
| 167 | +- **JWT auth + `token_blacklist` table** — replaced by server-side sessions |
| 168 | +- **CRUDAdmin views** — replaced by SQLAdmin |
| 169 | +- **ARQ workers** — replaced by Taskiq |
| 170 | +- **Deployment scripts** (`setup.py`, `scripts/{local_with_uvicorn,gunicorn_managing_uvicorn_workers,production_with_nginx}/`) — replaced by `bp deploy generate` |
| 171 | +- **`mkdocs.yml`** — replaced by `zensical.toml` |
| 172 | +- **Demo `posts` module** — pure demo code, not needed |
| 173 | +- **`backend/uv.lock`** — stale duplicate of workspace `uv.lock` |
| 174 | + |
| 175 | +#### Breaking Changes |
| 176 | + |
| 177 | +⚠️ Eight breaking changes. The migration path for forks with significant custom code is "copy your business logic into the new structure" — there is no sed-style find-and-replace. |
| 178 | + |
| 179 | +| Change | Impact | Migration | |
| 180 | +|---|---|---| |
| 181 | +| `src/app/` layout removed | Imports break at import time | Manual restructure into `modules/<name>/` | |
| 182 | +| JWT removed | `Authorization: Bearer` clients rejected | Switch clients to cookie auth | |
| 183 | +| CRUDAdmin → SQLAdmin | Custom admin views need porting | Port to `ModelView` shape | |
| 184 | +| ARQ → Taskiq | Workers need re-registration | Rewrite tasks as `@broker.task` async functions | |
| 185 | +| API key hash format | Existing keys won't validate | Users must regenerate | |
| 186 | +| Settings composition | Env var names mostly stable; a few moved | Diff `.env.example` | |
| 187 | +| Sync command | `cd backend && uv sync --extra dev` produces broken venv | Use `uv sync --all-packages --all-extras` from repo root | |
| 188 | +| Deployment scaffolder | `./setup.py local` removed | `uv run bp deploy generate {local,prod,nginx}` | |
| 189 | + |
| 190 | +For brand-new projects, v0.18.0 is the better starting point. For existing apps with significant custom code on v0.17.0, **pinning to v0.17.0 may be the right call** — that tag stays supported. |
| 191 | + |
| 192 | +#### New Co-Maintainers |
| 193 | + |
| 194 | +- [@carlosplanchon](https://github.com/carlosplanchon) and [@emiliano-gandini-outeda](https://github.com/emiliano-gandini-outeda) are now officially helping maintain and improve the boilerplate. |
| 195 | + |
| 196 | +**Full release notes**: https://github.com/benavlabs/FastAPI-boilerplate/releases/tag/v0.18.0 |
| 197 | +**Full changelog**: https://github.com/benavlabs/FastAPI-boilerplate/compare/v0.17.0...v0.18.0 |
0 commit comments