docs(spec): add design for Python 3.14 + dependency update
This commit is contained in:
@@ -0,0 +1,98 @@
|
|||||||
|
# Python 3.14 + Dependency Update — Design
|
||||||
|
|
||||||
|
**Date:** 2026-07-08
|
||||||
|
**Status:** Approved
|
||||||
|
**Author:** brainstorming session
|
||||||
|
|
||||||
|
## Goal
|
||||||
|
|
||||||
|
Update the project to run on Python 3.14 and bring all dependencies up to recent stable versions. No functional changes to application behavior.
|
||||||
|
|
||||||
|
## Background
|
||||||
|
|
||||||
|
- The local interpreter is already Python 3.14.6 (`/opt/homebrew/bin/python3.14`).
|
||||||
|
- `Dockerfile` pins `python:3.9-alpine` and hardcodes `/usr/local/lib/python3.9/site-packages` in the final stage — a latent bug that breaks on any version bump.
|
||||||
|
- `python-jose` is declared in `requirements.txt` but never imported anywhere in the codebase (verified by grep across all `*.py`). It is effectively unmaintained (last release 3.5.0).
|
||||||
|
- `main.py` already runs fine under pydantic v2 and recent FastAPI on the local 3.14 venv; no code changes are required for the version bumps.
|
||||||
|
- The repo contains pre-existing duplicate trees (`code/`, `source/`) that are out of scope.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
**In scope:**
|
||||||
|
- `requirements.txt`
|
||||||
|
- `requirements-test.txt`
|
||||||
|
- `Dockerfile`
|
||||||
|
- New `.python-version` file
|
||||||
|
|
||||||
|
**Out of scope:**
|
||||||
|
- Any code changes to `main.py`, `generate_favicon.py`, or templates.
|
||||||
|
- Type-hint modernization (e.g. `Optional[X]` → `X | None`). Not caused by this change.
|
||||||
|
- Removal of unused imports in `main.py` (`HTTPException`, `Header`, `StaticFiles`). Pre-existing dead code.
|
||||||
|
- The `code/` and `source/` duplicate directories.
|
||||||
|
- Switching the Docker base image from alpine to slim. Considered and rejected — alpine is the existing convention and keeps the diff minimal.
|
||||||
|
|
||||||
|
## Decisions
|
||||||
|
|
||||||
|
### Dependency specifier strategy
|
||||||
|
Keep the existing `>=` lower-bound convention, but bump floors to recent stable majors. Rationale: matches existing convention, allows automatic patch/minor updates, avoids the maintenance burden of exact pinning.
|
||||||
|
|
||||||
|
### `python-jose` removal
|
||||||
|
Drop `python-jose` from `requirements.txt`. Rationale: unused (no imports anywhere), unmaintained, reduces install time and attack surface. All JWT operations use `pyjwt`.
|
||||||
|
|
||||||
|
### Dockerfile base image
|
||||||
|
`python:3.9-alpine` → `python:3.14-alpine`. Keeps the alpine + multi-stage + non-root-user convention. Only changes that are forced by the version bump will be touched (base image tag + the two hardcoded `python3.9` path references).
|
||||||
|
|
||||||
|
## Changes
|
||||||
|
|
||||||
|
### 1. `requirements.txt`
|
||||||
|
|
||||||
|
Replace contents with:
|
||||||
|
|
||||||
|
```
|
||||||
|
fastapi>=0.115.0
|
||||||
|
uvicorn>=0.30.0
|
||||||
|
pyjwt>=2.9.0
|
||||||
|
requests>=2.32.0
|
||||||
|
cryptography>=44.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
(`python-jose` line removed.)
|
||||||
|
|
||||||
|
### 2. `requirements-test.txt`
|
||||||
|
|
||||||
|
Replace contents with:
|
||||||
|
|
||||||
|
```
|
||||||
|
pytest>=8.3.0
|
||||||
|
pytest-cov>=5.0.0
|
||||||
|
coverage>=7.4.0
|
||||||
|
httpx>=0.27.0
|
||||||
|
asgi_lifespan>=2.0.0
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. `Dockerfile`
|
||||||
|
|
||||||
|
Two surgical edits:
|
||||||
|
- Line 2: `FROM python:3.9-alpine AS python-base` → `FROM python:3.14-alpine AS python-base`
|
||||||
|
- Line 32: `COPY --from=builder /usr/local/lib/python3.9/site-packages /usr/local/lib/python3.9/site-packages` → `python3.14` in both path segments.
|
||||||
|
|
||||||
|
Everything else in the Dockerfile stays unchanged: alpine packages (`curl`, `gcc musl-dev libffi-dev openssl-dev`), non-root user, port, healthcheck, CMD.
|
||||||
|
|
||||||
|
### 4. `.python-version` (new file)
|
||||||
|
|
||||||
|
Contents: `3.14`
|
||||||
|
|
||||||
|
Purpose: signals the intended interpreter to `pyenv`-aware tooling and documents the target version for local development.
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
Success criteria — all must pass:
|
||||||
|
|
||||||
|
1. **Venv install:** Recreate `venv/` with `python3.14 -m venv venv`, `pip install -r requirements.txt -r requirements-test.txt` exits 0.
|
||||||
|
2. **Test suite:** `./run_tests.sh` exits 0 with the same (or better) coverage as before. No new failures.
|
||||||
|
3. **Docker build (if available):** `docker build -t oidc-validator .` exits 0.
|
||||||
|
|
||||||
|
## Risks
|
||||||
|
|
||||||
|
- **cryptography build from source on alpine:** mitigated by the existing `gcc musl-dev libffi-dev openssl-dev` build-deps line. cryptography 44+ ships musllinux wheels for 3.14, so a wheel should be available; if not, the build deps cover it.
|
||||||
|
- **New dependency majors changing behavior:** FastAPI 0.115 and pydantic v2 are already running locally without issue; no code changes observed as necessary. If tests surface breakage, it will be caught by the verification step and addressed then.
|
||||||
Reference in New Issue
Block a user