# Production runtime dependencies only
# This file is AUTO-GENERATED from requirements.txt
# DO NOT EDIT MANUALLY - run scripts/update-requirements-prod.py instead
#
# For development dependencies, see requirements.txt

# Capped below 16.0 because websockets 16.x dropped Python 3.9 wheels.

# OL9 / RHEL 9 / CentOS Stream 9 / Amazon Linux 2023 ship cp39 as the

# default python3, and the rpm's vendor dir relies on per-Python wheel

# downloads; a >=15.0.1 unbounded constraint resolved to 16.0, which has

# no cp39 wheel, leaving cp39 targets without a websockets install and

# crashing the agent with "No matching distribution". Bump the upper

# bound only when cp39 is dropped from the supported Python matrix.

#

# VERIFIED 2026-08-08: websockets 16.0 works fine on cp310+ (tested on Linux,

# and the FreeBSD port runs against 16.0 because ports ignore this file

# entirely and declare their own dependencies).  The cap is NOT about API

# compatibility — it is purely about cp39 wheel availability.  ci.yml runs a

# 3.9 leg off THIS file, so relaxing it here breaks CI, not just packaging.
websockets>=15.0.1,<16
PyYAML>=6.0.2

# aiohttp: the PYSEC-2026-2104..2113 fix is in 3.14.x, which requires Python >=3.10;

# the agent's 3.9 leg (RHEL9/OL9 cp39) can only reach 3.13.x (no backport of the

# fix exists — an accepted gap until cp39 is dropped).  Express this as a BARE

# FLOOR, NOT a ``; python_version`` marker: the COPR/RPM vendor step runs

# ``pip download --python-version 3.9.21``, and pip evaluates env markers against

# the BUILD HOST's interpreter (3.12), not the target — so a ``>= '3.10'`` marker

# is wrongly ACTIVE during the 3.9 wheel pass and pulls 3.14.x (no cp39 wheel) →

# build fails.  A bare floor instead lets pip's Requires-Python metadata pick the

# right version per target automatically: verified to resolve to 3.14.1 on the

# 3.10+ passes (the fix) and 3.13.5 on 3.9.  Same constraint as the

# python_multipart note below — prod deps must not gate on python_version markers.
aiohttp>=3.13.5
cryptography>=48.0.1  # 45.0.7-47.x buffer overflow + DNS name-constraint CVEs; 48.0.1 fixes GHSA-537c-gmf6-5ccf (48.0.0 affected). Supports cp39.
psutil>=5.9.0
bcrypt>=4.0.0
aiofiles>=24.1.0

# defusedxml is used by package_collector_windows when parsing the

# Chocolatey API XML response — even though Chocolatey is a trusted

# endpoint, parsing untrusted XML via stdlib ``xml.etree`` is the

# pattern semgrep ``use-defused-xml`` (correctly) flags.  defusedxml

# rejects external-entity references + billion-laughs payloads.
defusedxml>=0.7.1

# python_multipart was briefly pinned here as defense-in-depth against

# the 0.0.20 DoS + form-parser-bypass CVE chain that affected the

# server.  Removed because:

#   1. ``pip download --python-version 3.9.21`` evaluates env markers

#      against the CI HOST's python (3.12), not the target — so a

#      ``; python_version >= '3.10'`` gate doesn't actually skip the

#      pin in the Python-3.9 wheel-download passes that the RPM

#      builder uses.  pip then can't find a 0.0.27+ wheel for cp39

#      (no such release exists) and the build fails.

#   2. The agent has no untrusted-form-parser surface, so the CVE

#      class doesn't reach it even if 0.0.20 lands transitively.

# If a future code change starts parsing multipart input on the

# agent, add the pin back AND split requirements per Python version.

# Database dependencies
SQLAlchemy>=2.0.43
alembic>=1.16.5

# Transitive but SHIPPED at runtime, so pinned to their patched releases:

#   Mako  — pulled by alembic (migration templates).  PYSEC-2026-2617 fixed in 1.3.12.

#   idna  — pulled by aiohttp (via yarl) for hostname handling.  PYSEC-2026-215

#           fixed in 3.15.
Mako>=1.3.12
idna>=3.15

# packaging — imported directly by

# src/sysmanage_agent/operations/package_compliance_operations.py.  It was never

# declared, so only the FreeBSD port (which lists py-packaging in RUN_DEPENDS)

# actually got it; every pip-installed platform fell through the module's

# try/except ImportError to _lex_compare().  That is not a graceful degradation,

# it is WRONG ANSWERS: lexical comparison sorts "1.10" before "1.9", and every

# "~=" constraint reports non-compliant with "compatible-release (~=) requires

# the packaging library".  Pure-Python (py3-none-any), so it installs anywhere.

#

# NOT declared here on purpose: netifaces, also imported (guarded) by

# registration/discovery.py.  netifaces 0.11.0 is from 2021 and publishes NO

# wheel usable on cp312+, so pinning it would force a source build needing MSVC

# on Windows and break the install outright.  The FreeBSD port gets it from

# ports where a maintained build exists; everywhere else the guarded fallback in

# discovery.py is the intended path.
packaging>=24.0

