# v1.1 ## v1.1.0 — 2026-09-24 Maintenance release from the 2026-09-24 review (`reports/maintenance-2026-09-24.md`). ### Security - Rate limits now apply to each client. nginx resolves the real client IP through Cloudflare → NPM (`set_real_ip_from` + `real_ip_recursive`). Before this, every request looked like it came from NPM, so all users shared one login limit. - ntfy alerts show the real client IP (`X-Real-IP` from nginx). They no longer use the first `X-Forwarded-For` entry, which the client controls. - Python dependency updates (pydantic now pinned at 2.13.5): - PyJWT 2.15.0 (fixes an auth bypass) - anyio 4.15.1 - fastapi 0.141.1 / starlette 1.7.0 - cryptography 50.0.1 - python-multipart 0.0.32 - alembic 1.20.0 / Mako 1.4.3 - Base images: - python 3.12.14-slim, with `apt-get upgrade` and without the unused gcc/mysqlclient headers - nginx 1.30.5-alpine (stable), with `apk upgrade` - Node 24 LTS for the build stage - axios 1.20.0 and vite 5.4.21. Frontend dependencies are now locked in `package-lock.json` and installed with `npm ci`. ### Platform - MySQL 8.0.40 (EOL) → **8.4.11 LTS**. The data dictionary is upgraded in place, and **you can't downgrade in place**. Restore the pre-upgrade volume copy or dump instead; see README "Backup, Restore & Rollback". ### Reliability - The backend retries the DB connection for up to 180s at startup. Before this it crash-looped after host reboots, because the restart policy ignores `depends_on`. - Healthchecks on backend (`/api/health`) and frontend. The db healthcheck has `start_period: 180s`. - Docker log rotation on all services: json-file, 10 MB × 3. ### Fixes - **Timer actions returned 500** after the FastAPI 0.141 upgrade. The session queries didn't load `Subject.options`, which `DailySessionOut` serializes. Old FastAPI silently swallowed the failed lazy-load; the new one raises it. Now eager-loaded in `sessions.py` (get/timer) and `dashboard.py`. - The meeting alert catch-up window fix (`8e92ae6`) is now deployed. ### Known / accepted - npm audit: vite ≤6.4.2 and esbuild advisories affect only the **dev server**, which production never runs (it serves the static build). Fixing them fully needs Vite 6.4+/7. - mysql:8.4.11 has upstream findings in Oracle's image: curl, bundled Python tools, and gosu's Go stdlib. ## v1.1.1 — 2026-09-25 Low-severity items from the 2026-09-24 review. - Frontend runs as non-root: `nginxinc/nginx-unprivileged:1.30.5-alpine`, listening on **8080** in the container. Host port 8054 is unchanged, so NPM needs no change. - Replaced unmaintained `passlib` with `bcrypt` 5.0.0 directly. Existing `$2b$` hashes still verify; passwords are truncated to 72 bytes as before. A malformed hash now fails verification instead of raising. - `DOCS_ENABLED` is now passed to the backend container (default `false`), so the README instructions work. - db `mem_limit` 512m → 768m (MySQL 8.4 was at ~86% of 512m).