# ANetBBS — production runtime dependencies
# Curated list. Use `pip install -e .` to install this plus the package metadata in setup.py.

# Core
bcrypt>=4.0.0
python-dotenv>=1.0.0

# IANA timezone data for stdlib zoneinfo (anetbbs/core/tz.py — converts
# stored UTC timestamps to US/Eastern for display). zoneinfo normally
# reads the HOST OS's own tzdata, which isn't guaranteed present on
# minimal Docker base images or every distro this project installs on
# (see reference_pi_compat / install.sh's cross-distro history) — this
# pure-Python package is zoneinfo's own documented fallback data source,
# so EST/EDT conversion works even when the host has no system tzdata.
tzdata>=2024.1

# Web framework (Flask app)
Flask>=3.1.0
Flask-Login>=0.6.3
Flask-SocketIO>=5.5.0
Flask-WTF>=1.2.0
Flask-SQLAlchemy>=3.1.0
Flask-Migrate>=4.0.0
WTForms>=3.1.0
Werkzeug>=3.0.0
# 3.1.6 floor: CVE-2024-22195/CVE-2024-34064 (xmlattr XSS),
# CVE-2024-56326/CVE-2025-27516 (sandbox escape via str.format/attr) --
# found + verified in a security audit. Sandbox-escape CVEs only bite
# if a SandboxedEnvironment ever runs untrusted template source (not
# currently done here), but the floor costs nothing to bump regardless.
Jinja2>=3.1.6
itsdangerous>=2.2.0
click>=8.1.0
blinker>=1.9.0
MarkupSafe>=3.0.0

# Database
SQLAlchemy>=2.0.0
alembic>=1.13.0
Mako>=1.3.0
greenlet>=3.0.0

# WebSocket transport (Flask-SocketIO + eventlet worker for Gunicorn).
# Gunicorn 25 deprecates the eventlet worker, but the documented
# replacement (gevent + gevent-websocket 0.10.1) hangs websocket
# upgrades against modern gevent. Pinned to eventlet until flask-socketio
# offers a maintained gevent path.
python-socketio>=5.10.0
python-engineio>=4.10.0
simple-websocket>=1.0.0
# 0.40.3 floor: CVE-2025-58068, HTTP request smuggling via malformed
# chunked-encoding trailers in eventlet's WSGI parser -- this is the
# worker the main web app's WSGI request path runs through.
eventlet>=0.40.3

# SSH server
# 2.14.2 floor: CVE-2023-46445/CVE-2023-46446 (rogue extension/session
# negotiation) + CVE-2023-48795 (Terrapin protocol downgrade) -- the
# real SSH daemon callers connect to, so directly network-facing.
asyncssh>=2.14.2
# 44.0.1 floor: CVE-2024-26130 (NULL-pointer DoS in pkcs12 serialize)
# + CVE-2024-12797 (vulnerable OpenSSL bundled in cryptography's own
# wheels 42.0.0-44.0.0).
cryptography>=44.0.1

# MRC web bridge (standalone aiohttp service)
# 3.12.14 floor: CVE-2025-53643, HTTP request/response smuggling via
# incorrect chunked-trailer parsing in aiohttp's pure-Python parser.
aiohttp>=3.12.14
aiosignal>=1.3.0
multidict>=6.0.0
yarl>=1.9.0
frozenlist>=1.4.0
attrs>=23.0.0

# Production WSGI server.
# Upper-bound at <23 because gunicorn 23.0.0 stopped registering the
# eventlet worker via setuptools entry_points; a fresh install on
# Python 3.12 then dies with "Entry point ('gunicorn.workers',
# 'eventlet') not found" on first start. 22.0 ships the worker.
gunicorn>=22.0.0,<23

# Email validation + DNS (email-validator)
email-validator>=2.1.0
# 2.6.1 floor: CVE-2023-29483 ("TuDoor" DNS response-spoofing DoS) --
# 2.6.0 alone still had a bug in its own fix, 2.6.1 is the real floor.
dnspython>=2.6.1
idna>=3.6

# Imaging (avatars / file uploads) -- processes untrusted uploads.
# 10.3.0 floor: CVE-2023-50447 (arbitrary code execution via
# ImageMath.eval, fixed 10.2.0) + CVE-2024-28219 (buffer overflow via
# unbounded strcpy in _imagingcms.c, fixed 10.3.0).
Pillow>=10.3.0

# HTTP client (echomail poller / general) -- fetches operator- and
# sometimes remote-peer-supplied URLs.
# 2.32.4 floor: CVE-2024-47081, .netrc credential leak via a crafted
# URL's netloc parsing.
requests>=2.32.4
# 2.2.2 floor: CVE-2024-37891, Proxy-Authorization header not stripped
# on a cross-origin redirect.
urllib3>=2.2.2
certifi>=2024.2.0
charset-normalizer>=3.3.0

# Markdown rendering for messages (graceful degradation if missing — see web_app.py)
markdown>=3.5
bleach>=6.1

# RSS / Atom parser for the in-app feed reader (anetbbs.rss.poller)
feedparser>=6.0

# FTP server (anetbbs.ftp) — serves the FileArea tree to anonymous + auth users.
pyftpdlib>=2.0.0
# pyOpenSSL is what makes pyftpdlib's TLS_FTPHandler importable; without
# it FTPS is silently disabled and AUTH TLS clients get refused on the
# control channel. Required for the FTPS path that update.sh wires up
# when FTP_TLS_CERTFILE is configured.
pyopenssl>=24.0.0

# Internet email — LMTP listener that takes mail handed off from the
# sysop's local Postfix/Exim/OpenSMTPD, and an outbound submitter that
# hands fresh mail back to the MTA at 127.0.0.1:25.
aiosmtpd>=1.4.0
aiosmtplib>=3.0.0

# Service Control Center — per-PID CPU% + memory sampling for the
# live graphs at /admin/control/. Reads /proc, no special privileges.
psutil>=5.9.0

# Spell check for ANEdit (anetbbs/features/anedit.py, terminal message
# editor). Pure Python, bundles its own English dictionary (no network
# call, no external wordlist file to ship) — imported lazily and degrades
# silently if ever missing, same pattern as markdown/bleach above.
pyspellchecker>=0.8.0
