alembic>=1.16.5
annotated-types==0.7.0
aiofiles>=24.1.0
aiohttp>=3.14.1  # 27 CVEs across 3.9-3.13; 3.14.1 patches the newer PYSEC-2026-2104..2113 chain (3.13.5 is affected)
anyio>=4.5.0
astroid>=3.3.8
bandit==1.9.2
black==26.3.1  # CVE-2026-32274 (arbitrary file writes via cache filename)
certifi==2026.1.4
cffi>=2.0.0
coverage>=7.0.0
click>=8.1.8
cryptography==50.0.0  # PKCS#7 EnvelopedData Bleichenbacher oracle (GHSA, Aug 2026); 49.0.0 was still affected. Earlier: CVE-2026-34073, CVE-2026-39892 (46.0.7->49.0.0)
dill==0.4.0
defusedxml>=0.7.1
dnspython>=2.7.0
email_validator==2.1.1
fastapi==0.136.3  # drops the starlette<1.0 cap so the CVE-2026-48710 fix can land
gevent==25.9.1
greenlet>=3.1.0
h11>=0.16.0
httpcore>=1.0.6
httptools==0.7.1
httpx>=0.27.2
idna==3.18  # CVE bypass of CVE-2024-3651 fix in idna.encode() (was 3.11)
iniconfig>=2.1.0
isort>=5.0.0
itsdangerous==2.2.0
Jinja2>=3.1.6
Mako==1.3.12  # CVE-2026-44307 path-traversal fix (was 1.3.11)
MarkupSafe==3.0.2
mccabe==0.7.0
orjson==3.11.6  # CVE-2025-67221 (no recursion limit on deeply nested JSON)
packaging>=24.0
Pillow>=12.2.0  # multiple CVEs in the 11.x series (heap overflows in image parsers)
platformdirs>=4.0.0
pluggy>=1.0.0
# psycopg-binary wheels exist only for Linux, macOS and Windows-x64. Everywhere
# else (the BSDs, Windows-ARM64) there is no binary wheel, so use the pure-Python
# psycopg, which links libpq at runtime (pg_config/postgresql-client is installed
# by the platform bootstrap).
psycopg[binary]>=3.2; platform_system == "Linux" or platform_system == "Darwin" or (platform_system == "Windows" and platform_machine != "ARM64")
psycopg>=3.2; (platform_system != "Linux" and platform_system != "Darwin" and platform_system != "Windows") or (platform_system == "Windows" and platform_machine == "ARM64")
argon2-cffi==25.1.0
bcrypt>=4.0.0
pyotp>=2.9.0  # Phase 10.3: TOTP-based multi-factor authentication
ldap3>=2.9.0  # Phase 10.5: LDAP/AD external IdP support
authlib>=1.7.2  # Phase 10.5 OIDC external IdP support; 10 CVEs in 1.3-1.6 (signature bypass + token-leak)
python3-saml>=1.16.0  # Phase 13.1.E SAML 2.0 external IdP support (xmlsec signature verification)
geoip2>=4.8.0  # Phase 12.7: GeoLite2 city/country lookup (pulls maxminddb transitively, both Apache-2.0)
pycparser==2.23
pydantic>=2.9.0,<2.13.0
pydantic-extra-types==2.11.0
pydantic-settings==2.14.2
PyJWT==2.13.0  # CVE-2026-32597 + JWK/HS256/JWKS advisories; bumped 2.12.0->2.13.0
pylint>=3.0.0
pytest>=9.0.3  # 9.0.3 patches the tmp-dir advisory affecting <9.0.3
pytest-asyncio>=0.21.0
pytest-cov>=4.0.0
pytest-xdist>=3.0.0
python-dotenv==1.2.2  # CVE-2026-28684 (symlink following in set_key)
python-multipart>=0.0.31  # 0.0.20 DoS + form-parser bypass; 0.0.31 patches PYSEC-2026-3036..3040 (0.0.27 still affected)
PyYAML==6.0.2
setuptools>=82.0.1  # 80.9.0 had CVE in pkg_resources path traversal
sniffio==1.3.1
SQLAlchemy==2.0.43
# SECURITY NOTE: starlette 1.0.1 first fixed CVE-2026-48710 (missing Host-header
# validation poisons request.url.path, bypassing path-based security checks);
# earlier <1.0 releases (incl. 0.52.1) are all affected.  1.3.1 additionally
# patches PYSEC-2026-2280/2281 (1.2.1 is affected).  FastAPI 0.136.3 dropped its
# starlette<1.0 cap (now >=0.46.0), so the fixed 1.x line is permitted; validated
# against the full backend suite.
starlette>=1.3.1
tomlkit==0.14.0
typing_extensions>=4.12.2
ujson==5.13.0  # 5.13.0 fixes CVE-2026-54911 (reject_bytes=False UTF-8 validation bypass); 5.12.1 covered prior memory-leak DoS / integer-overflow CVEs + Dependabot #115
uvicorn==0.40.0
watchfiles==1.1.0
websockets==16.0
zope.event==6.1
zope.interface==8.2
Babel==2.18.0
polib>=1.2.0  # PO file parsing for backend i18n validation
reportlab==4.4.4
safety==3.7.0
safety-schemas==0.0.16
# semgrep ships a compiled OCaml core with Linux/macOS wheels only — there is no
# OpenBSD/NetBSD/FreeBSD/Windows build, and pip would otherwise backtrack through
# every sdist forever trying (and failing) to build it.  Gate it to the platforms
# it actually supports; the BSDs run the rest of `make security` without it.
semgrep>=1.162.0 ; sys_platform == "linux" or sys_platform == "darwin"  # 1.162.0 relaxed tomli~=2.0.1 → ~=2.4.0
pip-audit>=2.10.0

# Note: On OpenBSD 7.7, coverage.py C tracer requires gcc and py3-cffi
# Install with: doas pkg_add gcc py3-cffi
# The install-dev target will automatically handle C tracer setup
# Playwright has no OpenBSD/NetBSD browser build; those platforms use the selenium
# fallback below (pure-Python, installs everywhere).  Gate to Linux/macOS/Windows.
playwright==1.58.0 ; sys_platform == "linux" or sys_platform == "darwin" or sys_platform == "win32"  # Cross-browser UI testing
selenium>=4.43.0  # Web automation framework (fallback for OpenBSD/FreeBSD where Playwright unavailable); CVE in 4.0-4.42 around insecure WebSocket frame handling
webdriver-manager>=4.0.0
requests>=2.33.1  # 2.32.0-2.32.5 has urllib3 redirect-leak CVE chain; 2.33.x is latest patched
urllib3>=2.7.0  # 2.5.0-2.6.3 has 3 CVEs (Set-Cookie isolation + redirect-Authorization leak); 2.7.0 is latest patched

# OpenTelemetry for observability
# Note: Using minimum versions to allow pip to resolve compatible version sets
# Instrumentation packages and exporters must be compatible with the resolved API/SDK version
opentelemetry-api>=1.12.0
opentelemetry-sdk>=1.12.0
opentelemetry-instrumentation>=0.48b0
opentelemetry-instrumentation-fastapi>=0.48b0
opentelemetry-instrumentation-sqlalchemy>=0.48b0
opentelemetry-instrumentation-requests>=0.48b0
opentelemetry-instrumentation-logging>=0.48b0
# grpcio (pulled transitively) ships no win_arm64 wheel, so on native ARM64 it is
# built from source by scripts/build-grpcio-win-arm64.ps1 (run from `make install-dev`
# before this install) — the same source-build approach the BSD platforms use.
# opentelemetry-exporter-otlp is EXCLUDED on Windows ARM64.  Its only reason to
# exist here is OTLP export, and it drags in grpcio, which has no win_arm64 wheel
# on PyPI.  Building grpcio from source there fails outright: it passes both
# /std:c++17 and /std:c11 to every source, and MSVC rejects that pair on a C++
# file (D8016).  Patching grpcio's setup.py to work around that is fragile.
#
# Dropping it costs OTLP export only.  backend/telemetry/otel_config.py imports
# the OTLP exporters in their OWN try/except, so OTLP_AVAILABLE goes False while
# the Prometheus exporter and every FastAPI/SQLAlchemy/requests/logging
# instrumentation keep working.  The OpenBSD port omits this package for exactly
# the same reason (installer/openbsd/build-libs.sh).
opentelemetry-exporter-otlp>=1.12.0; platform_system != "Windows" or platform_machine != "ARM64"  # win_arm64: see note below
opentelemetry-exporter-prometheus>=0.48b0
