Pillow>=12.3.0  # https://github.com/python-pillow/Pillow
argon2-cffi==25.1.0  # https://github.com/hynek/argon2_cffi
hiredis==3.4.0  # https://github.com/redis/hiredis-py
redis==8.0.1  # https://github.com/redis/redis-py
celery==5.6.3  # pyup: < 6.0  # https://github.com/celery/celery
flower==2.0.1  # https://github.com/mher/flower
django-celery-beat==2.9.0  # https://github.com/celery/django-celery-beat
pyjwt==2.13.0  # https://github.com/jpadilla/pyjwt
cryptography==49.0.0  # https://github.com/pyca/cryptography
pydantic==2.*
typing-extensions==4.*  # https://github.com/python/typing_extensions
requests>=2.34.2,<3  # https://requests.readthedocs.io/en/latest/
httpx>=0.28.1,<1  # https://github.com/encode/httpx - async HTTP for agent tools
brotli>=1.2.0  # decoder for httpx Content-Encoding: br responses (e.g. OpenAI API, VCR cassettes). Floor raised to 1.2.0 to pick up the upstream security fix that bounds decompressor output via Decompressor.output_buffer_limit, preventing memory exhaustion from crafted br-encoded payloads.

# Django
# ------------------------------------------------------------------------------
django==5.2.15  # https://www.djangoproject.com/
django-environ==0.14.0  # https://github.com/joke2k/django-environ
django-redis==7.0.0  # https://github.com/jazzband/django-redis
django-filter==25.1  # https://github.com/carltongibson/django-filter
django-storages[boto3,google]==1.14.6  # https://github.com/jschneier/django-storages
whitenoise==6.12.0
django-tree-queries[admin]==0.24.0  # https://pypi.org/project/django-tree-queries/0.21.0/
django-cte==3.0.0  # https://github.com/dimagi/django-cte
pgvector>=0.4.2  # Python binding for pgvector; PostgreSQL extension v0.8.2+ required for HNSW iterative scan (installed separately)
channels==4.3.2  # https://github.com/django/channels
daphne==4.2.2  # https://github.com/django/daphne
channels-redis==4.3.0
Twisted[tls,http2]>=26.4.0

# Django REST Framework
# ------------------------------------------------------------------------------
djangorestframework==3.17.1  # https://github.com/encode/django-rest-framework
django-cors-headers==4.9.0  # https://github.com/adamchainz/django-cors-headers
drf-extra-fields==3.7.0  # https://github.com/Hipo/drf-extra-fields

# Doc Analysis (NLP dependencies, placeholder) - WARNING, these are all in same environment... not ideal.
# ------------------------------------------------------------------------------
pypdf>=6.14.2,<7  # https://github.com/py-pdf/pypdf
plasmapdf==0.1.3  # https://github.com/Jsv4/plasmapdf
pdf2image>=1.17.0
openai>=2.44.0,<3  # https://github.com/openai/openai-python (pydantic-ai 1.x requires >=2.11.0)
# Bumping pydantic-ai is a deliberate decision: this codebase relies on the
# precedence rule that ``instructions=`` (not ``system_prompt=``) is the only
# way to deliver a system instruction when ``message_history`` is non-empty
# (see issue #1451 and CLAUDE.md pitfall #14). The regression test in
# ``opencontractserver/tests/test_pydantic_ai_factory.py`` pins this behaviour
# against the version installed; if that test fails on a bump, validate the
# new precedence semantics before widening this pin.
#
# We deliberately depend on ``pydantic-ai-slim`` with the minimum set of
# provider extras the codebase actually uses, rather than the meta-package
# ``pydantic-ai``. ``pydantic-ai`` unconditionally pulls in all ~20 provider
# extras (including ``mistral``, ``google``, ``groq``, ``cohere``, etc.); any
# one of those provider SDKs disappearing from PyPI — as ``mistralai`` did
# on 2026-05-12, where ``pypi.org/pypi/mistralai/json`` started 404ing —
# breaks the entire install chain. Narrow extras = stable resolves.
pydantic-ai-slim[openai,anthropic,google,mcp]>=1.107.0,<2  # see issue #1451 before bumping the upper bound
spacy
pdfplumber>=0.11.10  # https://github.com/jsvine/pdfplumber - PDF token extraction
shapely>=2.1.2  # https://github.com/shapely/shapely - spatial operations for bbox intersection

# Data Processing Tools
# -------------------------------------------------------------------------------
opencv-python-headless==5.0.0.93 # https://github.com/opencv/opencv-python (headless: no GUI deps needed for server)
filetype==1.2.0  # https://github.com/h2non/filetype.py

# Permissioning
# ------------------------------------------------------------------------------
django-guardian

# GraphQL
# ------------------------------------------------------------------------------
graphene-django==3.2.3  # TODO - evaluate migration path; Django 5.2 not officially supported, slow maintenance pace
django-graphql-jwt==0.4.0

# Telemetry
# ------------------------------------------------------------------------------
posthog==7.21.3  # https://github.com/posthog/posthog-python

# Model Context Protocol
# ------------------------------------------------------------------------------
mcp>=1.28.1  # https://github.com/anthropics/python-sdk

# Not directly required, pinned by Snyk to avoid a vulnerability
# ------------------------------------------------------------------------------
twisted>=24.7.0rc1 # not directly required, pinned by Snyk to avoid a vulnerability
ipython>=9.15.0 # not directly required, pinned by Snyk to avoid a vulnerability
setuptools>=82.0.1 # not directly required, pinned by Snyk to avoid a vulnerability
sqlparse>=0.5.5 # not directly required, pinned by Snyk to avoid a vulnerability
tornado>=6.5.7 # not directly required, pinned by Snyk to avoid a vulnerability
urllib3>=2.7.0 # not directly required, pinned by Snyk to avoid a vulnerability
zipp>=4.1.0 # not directly required, pinned by Snyk to avoid a vulnerability
pillow>=10.3.0 # not directly required, pinned by Snyk to avoid a vulnerability
