Compare commits

...

37 Commits

Author SHA1 Message Date
Trenton H
0df0f3a21f And the rest of it 2026-01-16 15:28:35 -08:00
Trenton H
d81488d054 Latest 5.2 Django 2026-01-16 15:25:53 -08:00
Trenton H
8dc4f34743 Takes care of allauth, granian, psycopg 2026-01-16 15:24:43 -08:00
dependabot[bot]
f8ab81cef7 Chore(deps): Bump the utilities-patch group across 1 directory with 7 updates (#11793)
Bumps the utilities-patch group with 7 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [channels](https://github.com/django/channels) | `4.3.1` | `4.3.2` |
| [django-soft-delete](https://github.com/san4ezy/django_softdelete) | `1.0.21` | `1.0.22` |
| [django-treenode](https://github.com/fabiocaccamo/django-treenode) | `0.23.2` | `0.23.3` |
| [imap-tools](https://github.com/ikvk/imap_tools) | `1.11.0` | `1.11.1` |
| [python-gnupg](https://github.com/vsajip/python-gnupg) | `0.5.5` | `0.5.6` |
| [mkdocs-material](https://github.com/squidfunk/mkdocs-material) | `9.7.0` | `9.7.1` |
| [ruff](https://github.com/astral-sh/ruff) | `0.14.5` | `0.14.13` |



Updates `channels` from 4.3.1 to 4.3.2
- [Changelog](https://github.com/django/channels/blob/main/CHANGELOG.txt)
- [Commits](https://github.com/django/channels/compare/4.3.1...4.3.2)

Updates `django-soft-delete` from 1.0.21 to 1.0.22
- [Changelog](https://github.com/san4ezy/django_softdelete/blob/master/CHANGELOG.md)
- [Commits](https://github.com/san4ezy/django_softdelete/commits)

Updates `django-treenode` from 0.23.2 to 0.23.3
- [Release notes](https://github.com/fabiocaccamo/django-treenode/releases)
- [Changelog](https://github.com/fabiocaccamo/django-treenode/blob/main/CHANGELOG.md)
- [Commits](https://github.com/fabiocaccamo/django-treenode/compare/0.23.2...0.23.3)

Updates `imap-tools` from 1.11.0 to 1.11.1
- [Release notes](https://github.com/ikvk/imap_tools/releases)
- [Changelog](https://github.com/ikvk/imap_tools/blob/master/docs/release_notes.rst)
- [Commits](https://github.com/ikvk/imap_tools/compare/v1.11.0...v1.11.1)

Updates `python-gnupg` from 0.5.5 to 0.5.6
- [Release notes](https://github.com/vsajip/python-gnupg/releases)
- [Changelog](https://github.com/vsajip/python-gnupg/blob/master/release)
- [Commits](https://github.com/vsajip/python-gnupg/compare/0.5.5...0.5.6)

Updates `mkdocs-material` from 9.7.0 to 9.7.1
- [Release notes](https://github.com/squidfunk/mkdocs-material/releases)
- [Changelog](https://github.com/squidfunk/mkdocs-material/blob/master/CHANGELOG)
- [Commits](https://github.com/squidfunk/mkdocs-material/compare/9.7.0...9.7.1)

Updates `ruff` from 0.14.5 to 0.14.13
- [Release notes](https://github.com/astral-sh/ruff/releases)
- [Changelog](https://github.com/astral-sh/ruff/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/ruff/compare/0.14.5...0.14.13)

---
updated-dependencies:
- dependency-name: channels
  dependency-version: 4.3.2
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: utilities-patch
- dependency-name: django-soft-delete
  dependency-version: 1.0.22
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: utilities-patch
- dependency-name: django-treenode
  dependency-version: 0.23.3
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: utilities-patch
- dependency-name: imap-tools
  dependency-version: 1.11.1
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: utilities-patch
- dependency-name: python-gnupg
  dependency-version: 0.5.6
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: utilities-patch
- dependency-name: mkdocs-material
  dependency-version: 9.7.1
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: utilities-patch
- dependency-name: ruff
  dependency-version: 0.14.13
  dependency-type: direct:development
  update-type: version-update:semver-patch
  dependency-group: utilities-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-16 15:14:01 -08:00
dependabot[bot]
e9f7993ba5 Chore(deps): Bump the utilities-minor group across 1 directory with 10 updates (#11799)
* Chore(deps): Bump the utilities-minor group across 1 directory with 10 updates

Bumps the utilities-minor group with 10 updates in the / directory:

| Package | From | To |
| --- | --- | --- |
| [django-auditlog](https://github.com/jazzband/django-auditlog) | `3.3.0` | `3.4.1` |
| [drf-spectacular](https://github.com/tfranzel/drf-spectacular) | `0.28.0` | `0.29.0` |
| [faiss-cpu](https://github.com/kyamagu/faiss-wheels) | `1.10.0` | `1.13.2` |
| [gotenberg-client](https://github.com/stumpylog/gotenberg-client) | `0.12.0` | `0.13.1` |
| [ocrmypdf](https://github.com/ocrmypdf/OCRmyPDF) | `16.12.0` | `16.13.0` |
| [torch](https://github.com/pytorch/pytorch) | `2.7.1` | `2.9.1` |
| [psycopg-pool](https://github.com/psycopg/psycopg) | `3.2.7` | `3.3.0` |
| [pre-commit](https://github.com/pre-commit/pre-commit) | `4.4.0` | `4.5.1` |
| [celery-types](https://github.com/sbdchd/celery-types) | `0.23.0` | `0.24.0` |
| [mypy](https://github.com/python/mypy) | `1.18.2` | `1.19.1` |

Updates `django-auditlog` from 3.3.0 to 3.4.1
- [Release notes](https://github.com/jazzband/django-auditlog/releases)
- [Changelog](https://github.com/jazzband/django-auditlog/blob/master/CHANGELOG.md)
- [Commits](https://github.com/jazzband/django-auditlog/compare/v3.3.0...v3.4.1)

Updates `drf-spectacular` from 0.28.0 to 0.29.0
- [Release notes](https://github.com/tfranzel/drf-spectacular/releases)
- [Changelog](https://github.com/tfranzel/drf-spectacular/blob/master/CHANGELOG.rst)
- [Commits](https://github.com/tfranzel/drf-spectacular/compare/0.28.0...0.29.0)

Updates `faiss-cpu` from 1.10.0 to 1.13.2
- [Release notes](https://github.com/kyamagu/faiss-wheels/releases)
- [Commits](https://github.com/kyamagu/faiss-wheels/compare/v1.10.0...v1.13.2)

Updates `gotenberg-client` from 0.12.0 to 0.13.1
- [Release notes](https://github.com/stumpylog/gotenberg-client/releases)
- [Changelog](https://github.com/stumpylog/gotenberg-client/blob/main/CHANGELOG.md)
- [Commits](https://github.com/stumpylog/gotenberg-client/compare/0.12.0...0.13.1)

Updates `ocrmypdf` from 16.12.0 to 16.13.0
- [Release notes](https://github.com/ocrmypdf/OCRmyPDF/releases)
- [Changelog](https://github.com/ocrmypdf/OCRmyPDF/blob/main/docs/release_notes.md)
- [Commits](https://github.com/ocrmypdf/OCRmyPDF/compare/v16.12.0...v16.13.0)

Updates `torch` from 2.7.1 to 2.9.1
- [Release notes](https://github.com/pytorch/pytorch/releases)
- [Changelog](https://github.com/pytorch/pytorch/blob/main/RELEASE.md)
- [Commits](https://github.com/pytorch/pytorch/compare/v2.7.1...v2.9.1)

Updates `psycopg-pool` from 3.2.7 to 3.3.0
- [Changelog](https://github.com/psycopg/psycopg/blob/master/docs/news.rst)
- [Commits](https://github.com/psycopg/psycopg/compare/3.2.7...3.3.0)

Updates `pre-commit` from 4.4.0 to 4.5.1
- [Release notes](https://github.com/pre-commit/pre-commit/releases)
- [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
- [Commits](https://github.com/pre-commit/pre-commit/compare/v4.4.0...v4.5.1)

Updates `celery-types` from 0.23.0 to 0.24.0
- [Commits](https://github.com/sbdchd/celery-types/commits)

Updates `mypy` from 1.18.2 to 1.19.1
- [Changelog](https://github.com/python/mypy/blob/master/CHANGELOG.md)
- [Commits](https://github.com/python/mypy/compare/v1.18.2...v1.19.1)

---
updated-dependencies:
- dependency-name: django-auditlog
  dependency-version: 3.4.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: drf-spectacular
  dependency-version: 0.29.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: faiss-cpu
  dependency-version: 1.13.2
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: gotenberg-client
  dependency-version: 0.13.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: ocrmypdf
  dependency-version: 16.13.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: torch
  dependency-version: 2.9.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: psycopg-pool
  dependency-version: 3.3.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: pre-commit
  dependency-version: 4.5.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: celery-types
  dependency-version: 0.24.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: mypy
  dependency-version: 1.19.1
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

* Apply suggestion from @shamoon

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2026-01-16 14:40:42 -08:00
dependabot[bot]
3ea5e05137 Chore(deps): Bump pyasn1 from 0.6.1 to 0.6.2 (#11801)
Bumps [pyasn1](https://github.com/pyasn1/pyasn1) from 0.6.1 to 0.6.2.
- [Release notes](https://github.com/pyasn1/pyasn1/releases)
- [Changelog](https://github.com/pyasn1/pyasn1/blob/main/CHANGES.rst)
- [Commits](https://github.com/pyasn1/pyasn1/compare/v0.6.1...v0.6.2)

---
updated-dependencies:
- dependency-name: pyasn1
  dependency-version: 0.6.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-16 14:06:20 -08:00
dependabot[bot]
56fddf1e58 Chore(deps): Bump torch from 2.7.1 to 2.8.0 (#11800)
Bumps [torch](https://github.com/pytorch/pytorch) from 2.7.1 to 2.8.0.
- [Release notes](https://github.com/pytorch/pytorch/releases)
- [Changelog](https://github.com/pytorch/pytorch/blob/main/RELEASE.md)
- [Commits](https://github.com/pytorch/pytorch/compare/v2.7.1...v2.8.0)

---
updated-dependencies:
- dependency-name: torch
  dependency-version: 2.8.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-16 14:03:04 -08:00
dependabot[bot]
d447a9fb32 docker(deps): Bump astral-sh/uv (#11762)
Bumps [astral-sh/uv](https://github.com/astral-sh/uv) from 0.9.15-python3.12-trixie-slim to 0.9.24-python3.12-trixie-slim.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.9.15...0.9.24)

---
updated-dependencies:
- dependency-name: astral-sh/uv
  dependency-version: 0.9.24-python3.12-trixie-slim
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-16 13:43:43 -08:00
dependabot[bot]
155d69b211 Chore(deps): Bump brotli from 1.1.0 to 1.2.0 (#11796)
Bumps [brotli](https://github.com/google/brotli) from 1.1.0 to 1.2.0.
- [Release notes](https://github.com/google/brotli/releases)
- [Changelog](https://github.com/google/brotli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/google/brotli/compare/go/cbrotli/v1.1.0...v1.2.0)

---
updated-dependencies:
- dependency-name: brotli
  dependency-version: 1.2.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-16 11:16:34 -08:00
dependabot[bot]
4a7f9fa984 Chore(deps): Bump transformers from 4.51.3 to 4.53.0 (#11797)
Bumps [transformers](https://github.com/huggingface/transformers) from 4.51.3 to 4.53.0.
- [Release notes](https://github.com/huggingface/transformers/releases)
- [Commits](https://github.com/huggingface/transformers/compare/v4.51.3...v4.53.0)

---
updated-dependencies:
- dependency-name: transformers
  dependency-version: 4.53.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-16 17:25:52 +00:00
dependabot[bot]
c471c201ee Chore(deps): Bump django from 5.2.7 to 5.2.9 (#11794)
Bumps [django](https://github.com/django/django) from 5.2.7 to 5.2.9.
- [Commits](https://github.com/django/django/compare/5.2.7...5.2.9)

---
updated-dependencies:
- dependency-name: django
  dependency-version: 5.2.9
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-16 09:11:04 -08:00
dependabot[bot]
a9548afb42 Chore(deps): Bump the ai-group (#11798)
* Chore(deps): Bump llama-index-core from 0.12.33.post1 to 0.13.0

Bumps [llama-index-core](https://github.com/run-llama/llama_index) from 0.12.33.post1 to 0.13.0.
- [Release notes](https://github.com/run-llama/llama_index/releases)
- [Changelog](https://github.com/run-llama/llama_index/blob/main/CHANGELOG.md)
- [Commits](https://github.com/run-llama/llama_index/commits/v0.13.0)

---
updated-dependencies:
- dependency-name: llama-index-core
  dependency-version: 0.13.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

* Update llama-index to latest versions

* Fix embedding mock

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2026-01-16 16:31:47 +00:00
Trenton H
939b2f7553 Chore: Fixes Docker image pushing for every PR we get (#11777) 2026-01-16 07:35:49 -08:00
dependabot[bot]
8b58718fff Chore(deps): Bump marshmallow from 3.26.1 to 3.26.2 (#11790)
Bumps [marshmallow](https://github.com/marshmallow-code/marshmallow) from 3.26.1 to 3.26.2.
- [Changelog](https://github.com/marshmallow-code/marshmallow/blob/dev/CHANGELOG.rst)
- [Commits](https://github.com/marshmallow-code/marshmallow/compare/3.26.1...3.26.2)

---
updated-dependencies:
- dependency-name: marshmallow
  dependency-version: 3.26.2
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-16 15:25:09 +00:00
dependabot[bot]
ad78c436c0 Chore(deps): Bump uv from 0.9.3 to 0.9.6 (#11795)
Bumps [uv](https://github.com/astral-sh/uv) from 0.9.3 to 0.9.6.
- [Release notes](https://github.com/astral-sh/uv/releases)
- [Changelog](https://github.com/astral-sh/uv/blob/main/CHANGELOG.md)
- [Commits](https://github.com/astral-sh/uv/compare/0.9.3...0.9.6)

---
updated-dependencies:
- dependency-name: uv
  dependency-version: 0.9.6
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-16 07:14:59 -08:00
dependabot[bot]
c6697cd82b Chore(deps): Bump aiohttp from 3.11.18 to 3.13.3 (#11789)
---
updated-dependencies:
- dependency-name: aiohttp
  dependency-version: 3.13.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-15 21:26:01 -08:00
dependabot[bot]
0689c8ad3a Chore(deps): Bump urllib3 from 2.5.0 to 2.6.3 (#11792)
Bumps [urllib3](https://github.com/urllib3/urllib3) from 2.5.0 to 2.6.3.
- [Release notes](https://github.com/urllib3/urllib3/releases)
- [Changelog](https://github.com/urllib3/urllib3/blob/main/CHANGES.rst)
- [Commits](https://github.com/urllib3/urllib3/compare/2.5.0...2.6.3)

---
updated-dependencies:
- dependency-name: urllib3
  dependency-version: 2.6.3
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-15 20:15:52 -08:00
dependabot[bot]
825e9ca14c Chore(deps): Bump virtualenv from 20.34.0 to 20.36.1 (#11774)
Bumps [virtualenv](https://github.com/pypa/virtualenv) from 20.34.0 to 20.36.1.
- [Release notes](https://github.com/pypa/virtualenv/releases)
- [Changelog](https://github.com/pypa/virtualenv/blob/main/docs/changelog.rst)
- [Commits](https://github.com/pypa/virtualenv/compare/20.34.0...20.36.1)

---
updated-dependencies:
- dependency-name: virtualenv
  dependency-version: 20.36.1
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-15 20:12:12 -08:00
GitHub Actions
11cc2f8289 Auto translate strings 2026-01-15 23:02:39 +00:00
shamoon
055ce9172c Fix: use explicit order field for workflow actions (#11781) 2026-01-15 22:49:21 +00:00
shamoon
1b41559067 Chore: Reduce amd64 Docker image size by using CPU-only PyTorch wheels (#11779)
---------

Co-authored-by: Trenton H <797416+stumpylog@users.noreply.github.com>
2026-01-15 22:33:19 +00:00
shamoon
94a5af66eb Fix default llama3.1 2026-01-14 15:36:01 -08:00
shamoon
948c664dcf Correct get_tool_calls_from_response signature 2026-01-14 14:55:03 -08:00
dependabot[bot]
eeb5639990 Chore(deps): Bump azure-core from 1.33.0 to 1.38.0 (#11776)
Bumps [azure-core](https://github.com/Azure/azure-sdk-for-python) from 1.33.0 to 1.38.0.
- [Release notes](https://github.com/Azure/azure-sdk-for-python/releases)
- [Commits](https://github.com/Azure/azure-sdk-for-python/compare/azure-core_1.33.0...azure-core_1.38.0)

---
updated-dependencies:
- dependency-name: azure-core
  dependency-version: 1.38.0
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-01-13 15:02:22 -08:00
Trenton H
6cf8abc5d3 Chore: attempt to resolve Codecov patch coverage issues (#11773) 2026-01-13 12:25:36 -08:00
shamoon
9c0de249a6 Merge branch 'main' into dev 2026-01-13 11:53:40 -08:00
github-actions[bot]
71ecdc528e Documentation: Add v2.20.4 changelog (#11772)
---------

Co-authored-by: github-actions <41898282+github-actions[bot]@users.noreply.github.com>
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2026-01-13 11:51:37 -08:00
shamoon
00ec8a577b Merge branch 'hotfix/v2.20.4' 2026-01-13 11:45:55 -08:00
shamoon
3618c50b62 Bump version to 2.20.4 2026-01-13 10:01:42 -08:00
shamoon
6f4497185e Fix merge conflict 2026-01-13 10:01:41 -08:00
shamoon
e816269db5 Fix: recurring workflow to respect latest run time (#11735) 2026-01-13 09:36:53 -08:00
shamoon
d4e60e13bf Fixhancement: add error handling and retry when opening index (#11731) 2026-01-13 09:36:44 -08:00
shamoon
cb091665e2 Fix: validate cf integer values within PostgreSQL range (#11666) 2026-01-13 09:36:29 -08:00
shamoon
00bb92e3e1 Fix: support ordering by storage path name (#11661) 2026-01-13 09:36:14 -08:00
shamoon
11ec676909 Fix: propagate metadata override created value (#11659) 2026-01-13 09:36:07 -08:00
shamoon
7c457466b7 Security: prevent path traversal in storage paths 2026-01-13 09:29:48 -08:00
Antoine Mérino
65aed2405c Documentation: update notes for DB pool size (#11600) 2025-12-30 13:06:21 -08:00
25 changed files with 3090 additions and 2409 deletions

View File

@@ -1,6 +1,7 @@
# https://docs.codecov.com/docs/codecovyml-reference#codecov
codecov:
require_ci_to_pass: true
# https://docs.codecov.com/docs/components
# https://docs.codecov.com/docs/components
component_management:
individual_components:
- component_id: backend
@@ -9,35 +10,70 @@ component_management:
- component_id: frontend
paths:
- src-ui/**
# https://docs.codecov.com/docs/flags#step-2-flag-management-in-yaml
# https://docs.codecov.com/docs/carryforward-flags
flags:
backend:
# Backend Python versions
backend-python-3.10:
paths:
- src/**
carryforward: true
frontend:
backend-python-3.11:
paths:
- src/**
carryforward: true
backend-python-3.12:
paths:
- src/**
carryforward: true
# Frontend (shards merge into single flag)
frontend-node-24.x:
paths:
- src-ui/**
carryforward: true
# https://docs.codecov.com/docs/pull-request-comments
comment:
layout: "header, diff, components, flags, files"
# https://docs.codecov.com/docs/javascript-bundle-analysis
require_bundle_changes: true
bundle_change_threshold: "50Kb"
coverage:
# https://docs.codecov.com/docs/commit-status
status:
project:
default:
backend:
flags:
- backend-python-3.10
- backend-python-3.11
- backend-python-3.12
paths:
- src/**
# https://docs.codecov.com/docs/commit-status#threshold
threshold: 1%
removed_code_behavior: adjust_base
frontend:
flags:
- frontend-node-24.x
paths:
- src-ui/**
threshold: 1%
removed_code_behavior: adjust_base
patch:
default:
# For the changed lines only, target 100% covered, but
# allow as low as 75%
backend:
flags:
- backend-python-3.10
- backend-python-3.11
- backend-python-3.12
paths:
- src/**
target: 100%
threshold: 25%
frontend:
flags:
- frontend-node-24.x
paths:
- src-ui/**
target: 100%
threshold: 25%
# https://docs.codecov.com/docs/javascript-bundle-analysis
bundle_analysis:
# Fail if the bundle size increases by more than 1MB
warning_threshold: "1MB"
status: true

View File

@@ -88,13 +88,13 @@ jobs:
if: always()
uses: codecov/codecov-action@v5
with:
flags: backend,backend-python-${{ matrix.python-version }}
flags: backend-python-${{ matrix.python-version }}
files: junit.xml
report_type: test_results
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
flags: backend,backend-python-${{ matrix.python-version }}
flags: backend-python-${{ matrix.python-version }}
files: coverage.xml
report_type: coverage
- name: Stop containers

View File

@@ -35,7 +35,7 @@ jobs:
contents: read
packages: write
outputs:
can-push: ${{ steps.check-push.outputs.can-push }}
should-push: ${{ steps.check-push.outputs.should-push }}
push-external: ${{ steps.check-push.outputs.push-external }}
repository: ${{ steps.repo.outputs.name }}
ref-name: ${{ steps.ref.outputs.name }}
@@ -59,16 +59,28 @@ jobs:
env:
REF_NAME: ${{ steps.ref.outputs.name }}
run: |
# can-push: Can we push to GHCR?
# True for: pushes, or PRs from the same repo (not forks)
can_push=${{ github.event_name == 'push' || github.event.pull_request.head.repo.full_name == github.repository }}
echo "can-push=${can_push}"
echo "can-push=${can_push}" >> $GITHUB_OUTPUT
# should-push: Should we push to GHCR?
# True for:
# 1. Pushes (tags/dev/beta) - filtered via the workflow triggers
# 2. Internal PRs where the branch name starts with 'feature-' - filtered here when a PR is synced
should_push="false"
if [[ "${{ github.event_name }}" == "push" ]]; then
should_push="true"
elif [[ "${{ github.event_name }}" == "pull_request" && "${{ github.event.pull_request.head.repo.full_name }}" == "${{ github.repository }}" ]]; then
if [[ "${REF_NAME}" == feature-* || "${REF_NAME}" == fix-* ]]; then
should_push="true"
fi
fi
echo "should-push=${should_push}"
echo "should-push=${should_push}" >> $GITHUB_OUTPUT
# push-external: Should we also push to Docker Hub and Quay.io?
# Only for main repo on dev/beta branches or version tags
push_external="false"
if [[ "${can_push}" == "true" && "${{ github.repository_owner }}" == "paperless-ngx" ]]; then
if [[ "${should_push}" == "true" && "${{ github.repository_owner }}" == "paperless-ngx" ]]; then
case "${REF_NAME}" in
dev|beta)
push_external="true"
@@ -125,20 +137,20 @@ jobs:
labels: ${{ steps.docker-meta.outputs.labels }}
build-args: |
PNGX_TAG_VERSION=${{ steps.docker-meta.outputs.version }}
outputs: type=image,name=${{ env.REGISTRY }}/${{ steps.repo.outputs.name }},push-by-digest=true,name-canonical=true,push=${{ steps.check-push.outputs.can-push }}
outputs: type=image,name=${{ env.REGISTRY }}/${{ steps.repo.outputs.name }},push-by-digest=true,name-canonical=true,push=${{ steps.check-push.outputs.should-push }}
cache-from: |
type=registry,ref=${{ env.REGISTRY }}/${{ steps.repo.outputs.name }}/cache/app:${{ steps.ref.outputs.cache-ref }}-${{ matrix.arch }}
type=registry,ref=${{ env.REGISTRY }}/${{ steps.repo.outputs.name }}/cache/app:dev-${{ matrix.arch }}
cache-to: ${{ steps.check-push.outputs.can-push == 'true' && format('type=registry,mode=max,ref={0}/{1}/cache/app:{2}-{3}', env.REGISTRY, steps.repo.outputs.name, steps.ref.outputs.cache-ref, matrix.arch) || '' }}
cache-to: ${{ steps.check-push.outputs.should-push == 'true' && format('type=registry,mode=max,ref={0}/{1}/cache/app:{2}-{3}', env.REGISTRY, steps.repo.outputs.name, steps.ref.outputs.cache-ref, matrix.arch) || '' }}
- name: Export digest
if: steps.check-push.outputs.can-push == 'true'
if: steps.check-push.outputs.should-push == 'true'
run: |
mkdir -p /tmp/digests
digest="${{ steps.build.outputs.digest }}"
echo "digest=${digest}"
touch "/tmp/digests/${digest#sha256:}"
- name: Upload digest
if: steps.check-push.outputs.can-push == 'true'
if: steps.check-push.outputs.should-push == 'true'
uses: actions/upload-artifact@v6.0.0
with:
name: digests-${{ matrix.arch }}
@@ -149,7 +161,7 @@ jobs:
name: Merge and Push Manifest
runs-on: ubuntu-24.04
needs: build-arch
if: needs.build-arch.outputs.can-push == 'true'
if: needs.build-arch.outputs.should-push == 'true'
permissions:
contents: read
packages: write

View File

@@ -109,13 +109,13 @@ jobs:
if: always()
uses: codecov/codecov-action@v5
with:
flags: frontend,frontend-node-${{ matrix.node-version }}
flags: frontend-node-${{ matrix.node-version }}
directory: src-ui/
report_type: test_results
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v5
with:
flags: frontend,frontend-node-${{ matrix.node-version }}
flags: frontend-node-${{ matrix.node-version }}
directory: src-ui/coverage/
e2e-tests:
name: "E2E Tests (${{ matrix.shard-index }}/${{ matrix.shard-count }})"

View File

@@ -37,7 +37,7 @@ repos:
- json
# See https://github.com/prettier/prettier/issues/15742 for the fork reason
- repo: https://github.com/rbubley/mirrors-prettier
rev: 'v3.6.2'
rev: 'v3.8.0'
hooks:
- id: prettier
types_or:
@@ -49,7 +49,7 @@ repos:
- 'prettier-plugin-organize-imports@4.1.0'
# Python hooks
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.14.5
rev: v0.14.13
hooks:
- id: ruff-check
- id: ruff-format
@@ -76,7 +76,7 @@ repos:
hooks:
- id: shellcheck
- repo: https://github.com/google/yamlfmt
rev: v0.20.0
rev: v0.21.0
hooks:
- id: yamlfmt
exclude: "^src-ui/pnpm-lock.yaml"

View File

@@ -30,7 +30,7 @@ RUN set -eux \
# Purpose: Installs s6-overlay and rootfs
# Comments:
# - Don't leave anything extra in here either
FROM ghcr.io/astral-sh/uv:0.9.15-python3.12-trixie-slim AS s6-overlay-base
FROM ghcr.io/astral-sh/uv:0.9.26-python3.12-trixie-slim AS s6-overlay-base
WORKDIR /usr/src/s6
@@ -196,7 +196,11 @@ RUN set -eux \
&& apt-get install --yes --quiet --no-install-recommends ${BUILD_PACKAGES} \
&& echo "Installing Python requirements" \
&& uv export --quiet --no-dev --all-extras --format requirements-txt --output-file requirements.txt \
&& uv pip install --no-cache --system --no-python-downloads --python-preference system --requirements requirements.txt \
&& uv pip install --no-cache --system --no-python-downloads --python-preference system \
--index https://pypi.org/simple \
--index https://download.pytorch.org/whl/cpu \
--index-strategy unsafe-best-match \
--requirements requirements.txt \
&& echo "Installing NLTK data" \
&& python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" snowball_data \
&& python3 -W ignore::RuntimeWarning -m nltk.downloader -d "/usr/share/nltk_data" stopwords \

View File

@@ -1,9 +1,44 @@
# Changelog
## paperless-ngx 2.20.4
### Security
- Resolve [GHSA-28cf-xvcf-hw6m](https://github.com/paperless-ngx/paperless-ngx/security/advisories/GHSA-28cf-xvcf-hw6m)
### Bug Fixes
- Fix: propagate metadata override created value [@shamoon](https://github.com/shamoon) ([#11659](https://github.com/paperless-ngx/paperless-ngx/pull/11659))
- Fix: support ordering by storage path name [@shamoon](https://github.com/shamoon) ([#11661](https://github.com/paperless-ngx/paperless-ngx/pull/11661))
- Fix: validate cf integer values within PostgreSQL range [@shamoon](https://github.com/shamoon) ([#11666](https://github.com/paperless-ngx/paperless-ngx/pull/11666))
- Fixhancement: add error handling and retry when opening index [@shamoon](https://github.com/shamoon) ([#11731](https://github.com/paperless-ngx/paperless-ngx/pull/11731))
- Fix: fix recurring workflow to respect latest run time [@shamoon](https://github.com/shamoon) ([#11735](https://github.com/paperless-ngx/paperless-ngx/pull/11735))
### All App Changes
<details>
<summary>5 changes</summary>
- Fix: propagate metadata override created value [@shamoon](https://github.com/shamoon) ([#11659](https://github.com/paperless-ngx/paperless-ngx/pull/11659))
- Fix: support ordering by storage path name [@shamoon](https://github.com/shamoon) ([#11661](https://github.com/paperless-ngx/paperless-ngx/pull/11661))
- Fix: validate cf integer values within PostgreSQL range [@shamoon](https://github.com/shamoon) ([#11666](https://github.com/paperless-ngx/paperless-ngx/pull/11666))
- Fixhancement: add error handling and retry when opening index [@shamoon](https://github.com/shamoon) ([#11731](https://github.com/paperless-ngx/paperless-ngx/pull/11731))
- Fix: fix recurring workflow to respect latest run time [@shamoon](https://github.com/shamoon) ([#11735](https://github.com/paperless-ngx/paperless-ngx/pull/11735))
</details>
## paperless-ngx 2.20.3
### Security
- Resolve [GHSA-7cq3-mhxq-w946](https://github.com/paperless-ngx/paperless-ngx/security/advisories/GHSA-7cq3-mhxq-w946)
## paperless-ngx 2.20.2
### Security
- Resolve [GHSA-6653-vcx4-69mc](https://github.com/paperless-ngx/paperless-ngx/security/advisories/GHSA-6653-vcx4-69mc)
- Resolve [GHSA-24x5-wp64-9fcc](https://github.com/paperless-ngx/paperless-ngx/security/advisories/GHSA-24x5-wp64-9fcc)
### Features / Enhancements
- Tweakhancement: dim inactive users in users-groups list [@shamoon](https://github.com/shamoon) ([#11537](https://github.com/paperless-ngx/paperless-ngx/pull/11537))

View File

@@ -170,11 +170,18 @@ Available options are `postgresql` and `mariadb`.
!!! note
A small pool is typically sufficient — for example, a size of 4.
Make sure your PostgreSQL server's max_connections setting is large enough to handle:
```(Paperless workers + Celery workers) × pool size + safety margin```
For example, with 4 Paperless workers and 2 Celery workers, and a pool size of 4:
(4 + 2) × 4 + 10 = 34 connections required.
A pool of 8-10 connections per worker is typically sufficient.
If you encounter error messages such as `couldn't get a connection`
or database connection timeouts, you probably need to increase the pool size.
!!! warning
Make sure your PostgreSQL `max_connections` setting is large enough to handle the connection pools:
`(NB_PAPERLESS_WORKERS + NB_CELERY_WORKERS) × POOL_SIZE + SAFETY_MARGIN`. For example, with
4 Paperless workers and 2 Celery workers, and a pool size of 8:``(4 + 2) × 8 + 10 = 58`,
so `max_connections = 60` (or even more) is appropriate.
This assumes only Paperless-ngx connects to your PostgreSQL instance. If you have other applications,
you should increase `max_connections` accordingly.
#### [`PAPERLESS_DB_READ_CACHE_ENABLED=<bool>`](#PAPERLESS_DB_READ_CACHE_ENABLED) {#PAPERLESS_DB_READ_CACHE_ENABLED}
@@ -1866,7 +1873,7 @@ using the OpenAI API. This setting is required to be set to use the AI features.
#### [`PAPERLESS_AI_LLM_MODEL=<str>`](#PAPERLESS_AI_LLM_MODEL) {#PAPERLESS_AI_LLM_MODEL}
: The model to use for the AI backend, i.e. "gpt-3.5-turbo", "gpt-4" or any of the models supported by the
current backend. If not supplied, defaults to "gpt-3.5-turbo" for OpenAI and "llama3" for Ollama.
current backend. If not supplied, defaults to "gpt-3.5-turbo" for OpenAI and "llama3.1" for Ollama.
Defaults to None.

View File

@@ -1,6 +1,6 @@
[project]
name = "paperless-ngx"
version = "2.20.3"
version = "2.20.4"
description = "A community-supported supercharged document management system: scan, index and archive all your physical documents"
readme = "README.md"
requires-python = ">=3.10"
@@ -19,16 +19,16 @@ dependencies = [
"azure-ai-documentintelligence>=1.0.2",
"babel>=2.17",
"bleach~=6.3.0",
"celery[redis]~=5.5.1",
"celery[redis]~=5.6.2",
"channels~=4.2",
"channels-redis~=4.2",
"concurrent-log-handler~=0.9.25",
"dateparser~=1.2",
# WARNING: django does not use semver.
# Only patch versions are guaranteed to not introduce breaking changes.
"django~=5.2.5",
"django-allauth[mfa,socialaccount]~=65.12.1",
"django-auditlog~=3.3.0",
"django==5.2.10",
"django-allauth[mfa,socialaccount]~=65.13.0",
"django-auditlog~=3.4.1",
"django-cachalot~=2.8.0",
"django-celery-results~=2.6.0",
"django-compression-middleware~=0.5.0",
@@ -47,20 +47,20 @@ dependencies = [
"faiss-cpu>=1.10",
"filelock~=3.20.0",
"flower~=2.0.1",
"gotenberg-client~=0.12.0",
"gotenberg-client~=0.13.1",
"httpx-oauth~=0.16",
"imap-tools~=1.11.0",
"inotifyrecursive~=0.3",
"jinja2~=3.1.5",
"langdetect~=1.0.9",
"llama-index-core>=0.12.33.post1",
"llama-index-embeddings-huggingface>=0.5.3",
"llama-index-embeddings-openai>=0.3.1",
"llama-index-llms-ollama>=0.5.4",
"llama-index-llms-openai>=0.3.38",
"llama-index-vector-stores-faiss>=0.3",
"llama-index-core>=0.14.12",
"llama-index-embeddings-huggingface>=0.6.1",
"llama-index-embeddings-openai>=0.5.1",
"llama-index-llms-ollama>=0.9.1",
"llama-index-llms-openai>=0.6.13",
"llama-index-vector-stores-faiss>=0.5.2",
"nltk~=3.9.1",
"ocrmypdf~=16.12.0",
"ocrmypdf~=16.13.0",
"openai>=1.76",
"pathvalidate~=3.3.1",
"pdf2image~=1.17.0",
@@ -77,9 +77,10 @@ dependencies = [
"sentence-transformers>=4.1",
"setproctitle~=1.3.4",
"tika-client~=0.10.0",
"torch~=2.9.1",
"tqdm~=4.67.1",
"watchdog~=6.0",
"whitenoise~=6.9",
"whitenoise~=6.11",
"whoosh-reloaded>=2.7.5",
"zxing-cpp~=2.3.0",
]
@@ -88,13 +89,13 @@ optional-dependencies.mariadb = [
"mysqlclient~=2.2.7",
]
optional-dependencies.postgres = [
"psycopg[c,pool]==3.2.12",
"psycopg[c,pool]==3.3",
# Direct dependency for proper resolution of the pre-built wheels
"psycopg-c==3.2.12",
"psycopg-pool==3.2.7",
"psycopg-c==3.3",
"psycopg-pool==3.3",
]
optional-dependencies.webserver = [
"granian[uvloop]~=2.5.1",
"granian[uvloop]~=2.6.0",
]
[dependency-groups]
@@ -126,7 +127,7 @@ testing = [
]
lint = [
"pre-commit~=4.4.0",
"pre-commit~=4.5.1",
"pre-commit-uv~=4.2.0",
"ruff~=0.14.0",
]
@@ -151,7 +152,7 @@ typing = [
]
[tool.uv]
required-version = ">=0.5.14"
required-version = ">=0.9.0"
package = false
environments = [
"sys_platform == 'darwin'",
@@ -161,14 +162,23 @@ environments = [
[tool.uv.sources]
# Markers are chosen to select these almost exclusively when building the Docker image
psycopg-c = [
{ url = "https://github.com/paperless-ngx/builder/releases/download/psycopg-bookworm-3.2.12/psycopg_c-3.2.12-cp312-cp312-linux_x86_64.whl", marker = "sys_platform == 'linux' and platform_machine == 'x86_64' and python_version == '3.12'" },
{ url = "https://github.com/paperless-ngx/builder/releases/download/psycopg-bookworm-3.2.12/psycopg_c-3.2.12-cp312-cp312-linux_aarch64.whl", marker = "sys_platform == 'linux' and platform_machine == 'aarch64' and python_version == '3.12'" },
{ url = "https://github.com/paperless-ngx/builder/releases/download/psycopg-trixie-3.3.0/psycopg_c-3.3.0-cp312-cp312-linux_x86_64.whl", marker = "sys_platform == 'linux' and platform_machine == 'x86_64' and python_version == '3.12'" },
{ url = "https://github.com/paperless-ngx/builder/releases/download/psycopg-trixie-3.3.0/psycopg_c-3.3.0-cp312-cp312-linux_aarch64.whl", marker = "sys_platform == 'linux' and platform_machine == 'aarch64' and python_version == '3.12'" },
]
zxing-cpp = [
{ url = "https://github.com/paperless-ngx/builder/releases/download/zxing-2.3.0/zxing_cpp-2.3.0-cp312-cp312-linux_x86_64.whl", marker = "sys_platform == 'linux' and platform_machine == 'x86_64' and python_version == '3.12'" },
{ url = "https://github.com/paperless-ngx/builder/releases/download/zxing-2.3.0/zxing_cpp-2.3.0-cp312-cp312-linux_aarch64.whl", marker = "sys_platform == 'linux' and platform_machine == 'aarch64' and python_version == '3.12'" },
]
torch = [
{ index = "pytorch-cpu" },
]
[[tool.uv.index]]
name = "pytorch-cpu"
url = "https://download.pytorch.org/whl/cpu"
explicit = true
[tool.ruff]
target-version = "py310"
line-length = 88

View File

@@ -1,6 +1,6 @@
{
"name": "paperless-ngx-ui",
"version": "2.20.3",
"version": "2.20.4",
"scripts": {
"preinstall": "npx only-allow pnpm",
"ng": "ng",

View File

@@ -252,7 +252,7 @@ describe('WorkflowEditDialogComponent', () => {
expect(component.object.actions.length).toEqual(2)
})
it('should update order and remove ids from actions on drag n drop', () => {
it('should update order on drag n drop', () => {
const action1 = workflow.actions[0]
const action2 = workflow.actions[1]
component.object = workflow
@@ -261,8 +261,6 @@ describe('WorkflowEditDialogComponent', () => {
WorkflowAction[]
>)
expect(component.object.actions).toEqual([action2, action1])
expect(action1.id).toBeNull()
expect(action2.id).toBeNull()
})
it('should not include auto matching in algorithms', () => {

View File

@@ -1283,11 +1283,6 @@ export class WorkflowEditDialogComponent
const actionField = this.actionFields.at(event.previousIndex)
this.actionFields.removeAt(event.previousIndex)
this.actionFields.insert(event.currentIndex, actionField)
// removing id will effectively re-create the actions in this order
this.object.actions.forEach((a) => (a.id = null))
this.actionFields.controls.forEach((c) =>
c.get('id').setValue(null, { emitEvent: false })
)
}
save(): void {

View File

@@ -6,7 +6,7 @@ export const environment = {
apiVersion: '9', // match src/paperless/settings.py
appTitle: 'Paperless-ngx',
tag: 'prod',
version: '2.20.3',
version: '2.20.4',
webSocketHost: window.location.host,
webSocketProtocol: window.location.protocol == 'https:' ? 'wss:' : 'ws:',
webSocketBaseUrl: base_url.pathname + 'ws/',

View File

@@ -0,0 +1,28 @@
# Generated by Django 5.2.7 on 2026-01-14 16:53
from django.db import migrations
from django.db import models
from django.db.models import F
def populate_action_order(apps, schema_editor):
WorkflowAction = apps.get_model("documents", "WorkflowAction")
WorkflowAction.objects.all().update(order=F("id"))
class Migration(migrations.Migration):
dependencies = [
("documents", "1075_alter_paperlesstask_task_name"),
]
operations = [
migrations.AddField(
model_name="workflowaction",
name="order",
field=models.PositiveIntegerField(default=0, verbose_name="order"),
),
migrations.RunPython(
populate_action_order,
reverse_code=migrations.RunPython.noop,
),
]

View File

@@ -1295,6 +1295,8 @@ class WorkflowAction(models.Model):
default=WorkflowActionType.ASSIGNMENT,
)
order = models.PositiveIntegerField(_("order"), default=0)
assign_title = models.TextField(
_("assign title"),
null=True,

View File

@@ -2577,7 +2577,8 @@ class WorkflowSerializer(serializers.ModelSerializer):
set_triggers.append(trigger_instance)
if actions is not None and actions is not serializers.empty:
for action in actions:
for index, action in enumerate(actions):
action["order"] = index
assign_tags = action.pop("assign_tags", None)
assign_view_users = action.pop("assign_view_users", None)
assign_view_groups = action.pop("assign_view_groups", None)
@@ -2704,6 +2705,16 @@ class WorkflowSerializer(serializers.ModelSerializer):
return instance
def to_representation(self, instance):
data = super().to_representation(instance)
actions = instance.actions.order_by("order", "pk")
data["actions"] = WorkflowActionSerializer(
actions,
many=True,
context=self.context,
).data
return data
class TrashSerializer(SerializerWithPerms):
documents = serializers.ListField(

View File

@@ -421,7 +421,15 @@ def update_filename_and_move_files(
return
instance = instance.document
def validate_move(instance, old_path: Path, new_path: Path):
def validate_move(instance, old_path: Path, new_path: Path, root: Path):
if not new_path.is_relative_to(root):
msg = (
f"Document {instance!s}: Refusing to move file outside root {root}: "
f"{new_path}."
)
logger.warning(msg)
raise CannotMoveFilesException(msg)
if not old_path.is_file():
# Can't do anything if the old file does not exist anymore.
msg = f"Document {instance!s}: File {old_path} doesn't exist."
@@ -510,12 +518,22 @@ def update_filename_and_move_files(
return
if move_original:
validate_move(instance, old_source_path, instance.source_path)
validate_move(
instance,
old_source_path,
instance.source_path,
settings.ORIGINALS_DIR,
)
create_source_path_directory(instance.source_path)
shutil.move(old_source_path, instance.source_path)
if move_archive:
validate_move(instance, old_archive_path, instance.archive_path)
validate_move(
instance,
old_archive_path,
instance.archive_path,
settings.ARCHIVE_DIR,
)
create_source_path_directory(instance.archive_path)
shutil.move(old_archive_path, instance.archive_path)
@@ -763,7 +781,7 @@ def run_workflows(
if matching.document_matches_workflow(document, workflow, trigger_type):
action: WorkflowAction
for action in workflow.actions.all():
for action in workflow.actions.order_by("order", "pk"):
message = f"Applying {action} from {workflow}"
if not use_overrides:
logger.info(message, extra={"group": logging_group})

View File

@@ -262,6 +262,17 @@ def get_custom_fields_context(
return field_data
def _is_safe_relative_path(value: str) -> bool:
if value == "":
return True
path = PurePath(value)
if path.is_absolute() or path.drive:
return False
return ".." not in path.parts
def validate_filepath_template_and_render(
template_string: str,
document: Document | None = None,
@@ -309,6 +320,12 @@ def validate_filepath_template_and_render(
)
rendered_template = template.render(context)
if not _is_safe_relative_path(rendered_template):
logger.warning(
"Template rendered an unsafe path (absolute or containing traversal).",
)
return None
# We're good!
return rendered_template
except UndefinedError:

View File

@@ -219,6 +219,30 @@ class TestApiStoragePaths(DirectoriesMixin, APITestCase):
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(StoragePath.objects.count(), 1)
def test_api_create_storage_path_rejects_traversal(self):
"""
GIVEN:
- API request to create a storage paths
- Storage path attempts directory traversal
WHEN:
- API is called
THEN:
- Correct HTTP 400 response
- No storage path is created
"""
response = self.client.post(
self.ENDPOINT,
json.dumps(
{
"name": "Traversal path",
"path": "../../../../../tmp/proof",
},
),
content_type="application/json",
)
self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST)
self.assertEqual(StoragePath.objects.count(), 1)
def test_api_storage_path_placeholders(self):
"""
GIVEN:

View File

@@ -20,9 +20,6 @@ def get_workflows_for_trigger(
wrap it in a list; otherwise fetch enabled workflows for the trigger with
the prefetches used by the runner.
"""
if workflow_to_run is not None:
return [workflow_to_run]
annotated_actions = (
WorkflowAction.objects.select_related(
"assign_correspondent",
@@ -105,10 +102,25 @@ def get_workflows_for_trigger(
)
)
action_prefetch = Prefetch(
"actions",
queryset=annotated_actions.order_by("order", "pk"),
)
if workflow_to_run is not None:
return (
Workflow.objects.filter(pk=workflow_to_run.pk)
.prefetch_related(
action_prefetch,
"triggers",
)
.distinct()
)
return (
Workflow.objects.filter(enabled=True, triggers__type=trigger_type)
.prefetch_related(
Prefetch("actions", queryset=annotated_actions),
action_prefetch,
"triggers",
)
.order_by("order")

View File

@@ -2,7 +2,7 @@ msgid ""
msgstr ""
"Project-Id-Version: paperless-ngx\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-01-13 16:26+0000\n"
"POT-Creation-Date: 2026-01-15 23:01+0000\n"
"PO-Revision-Date: 2022-02-17 04:17\n"
"Last-Translator: \n"
"Language-Team: English\n"
@@ -89,7 +89,7 @@ msgstr ""
msgid "Automatic"
msgstr ""
#: documents/models.py:64 documents/models.py:456 documents/models.py:1527
#: documents/models.py:64 documents/models.py:456 documents/models.py:1529
#: paperless_mail/models.py:23 paperless_mail/models.py:143
msgid "name"
msgstr ""
@@ -264,7 +264,7 @@ msgid "The position of this document in your physical document archive."
msgstr ""
#: documents/models.py:318 documents/models.py:700 documents/models.py:754
#: documents/models.py:1570
#: documents/models.py:1572
msgid "document"
msgstr ""
@@ -1047,179 +1047,180 @@ msgstr ""
msgid "Workflow Action Type"
msgstr ""
#: documents/models.py:1299
msgid "assign title"
msgstr ""
#: documents/models.py:1303
msgid "Assign a document title, must be a Jinja2 template, see documentation."
msgstr ""
#: documents/models.py:1311 paperless_mail/models.py:274
msgid "assign this tag"
msgstr ""
#: documents/models.py:1320 paperless_mail/models.py:282
msgid "assign this document type"
msgstr ""
#: documents/models.py:1329 paperless_mail/models.py:296
msgid "assign this correspondent"
msgstr ""
#: documents/models.py:1338
msgid "assign this storage path"
msgstr ""
#: documents/models.py:1347
msgid "assign this owner"
msgstr ""
#: documents/models.py:1354
msgid "grant view permissions to these users"
msgstr ""
#: documents/models.py:1361
msgid "grant view permissions to these groups"
msgstr ""
#: documents/models.py:1368
msgid "grant change permissions to these users"
msgstr ""
#: documents/models.py:1375
msgid "grant change permissions to these groups"
msgstr ""
#: documents/models.py:1382
msgid "assign these custom fields"
msgstr ""
#: documents/models.py:1386
msgid "custom field values"
msgstr ""
#: documents/models.py:1390
msgid "Optional values to assign to the custom fields."
msgstr ""
#: documents/models.py:1399
msgid "remove these tag(s)"
msgstr ""
#: documents/models.py:1404
msgid "remove all tags"
msgstr ""
#: documents/models.py:1411
msgid "remove these document type(s)"
msgstr ""
#: documents/models.py:1416
msgid "remove all document types"
msgstr ""
#: documents/models.py:1423
msgid "remove these correspondent(s)"
msgstr ""
#: documents/models.py:1428
msgid "remove all correspondents"
msgstr ""
#: documents/models.py:1435
msgid "remove these storage path(s)"
msgstr ""
#: documents/models.py:1440
msgid "remove all storage paths"
msgstr ""
#: documents/models.py:1447
msgid "remove these owner(s)"
msgstr ""
#: documents/models.py:1452
msgid "remove all owners"
msgstr ""
#: documents/models.py:1459
msgid "remove view permissions for these users"
msgstr ""
#: documents/models.py:1466
msgid "remove view permissions for these groups"
msgstr ""
#: documents/models.py:1473
msgid "remove change permissions for these users"
msgstr ""
#: documents/models.py:1480
msgid "remove change permissions for these groups"
msgstr ""
#: documents/models.py:1485
msgid "remove all permissions"
msgstr ""
#: documents/models.py:1492
msgid "remove these custom fields"
msgstr ""
#: documents/models.py:1497
msgid "remove all custom fields"
msgstr ""
#: documents/models.py:1506
msgid "email"
msgstr ""
#: documents/models.py:1515
msgid "webhook"
msgstr ""
#: documents/models.py:1519
msgid "workflow action"
msgstr ""
#: documents/models.py:1520
msgid "workflow actions"
msgstr ""
#: documents/models.py:1529 paperless_mail/models.py:145
#: documents/models.py:1298 documents/models.py:1531
#: paperless_mail/models.py:145
msgid "order"
msgstr ""
#: documents/models.py:1535
#: documents/models.py:1301
msgid "assign title"
msgstr ""
#: documents/models.py:1305
msgid "Assign a document title, must be a Jinja2 template, see documentation."
msgstr ""
#: documents/models.py:1313 paperless_mail/models.py:274
msgid "assign this tag"
msgstr ""
#: documents/models.py:1322 paperless_mail/models.py:282
msgid "assign this document type"
msgstr ""
#: documents/models.py:1331 paperless_mail/models.py:296
msgid "assign this correspondent"
msgstr ""
#: documents/models.py:1340
msgid "assign this storage path"
msgstr ""
#: documents/models.py:1349
msgid "assign this owner"
msgstr ""
#: documents/models.py:1356
msgid "grant view permissions to these users"
msgstr ""
#: documents/models.py:1363
msgid "grant view permissions to these groups"
msgstr ""
#: documents/models.py:1370
msgid "grant change permissions to these users"
msgstr ""
#: documents/models.py:1377
msgid "grant change permissions to these groups"
msgstr ""
#: documents/models.py:1384
msgid "assign these custom fields"
msgstr ""
#: documents/models.py:1388
msgid "custom field values"
msgstr ""
#: documents/models.py:1392
msgid "Optional values to assign to the custom fields."
msgstr ""
#: documents/models.py:1401
msgid "remove these tag(s)"
msgstr ""
#: documents/models.py:1406
msgid "remove all tags"
msgstr ""
#: documents/models.py:1413
msgid "remove these document type(s)"
msgstr ""
#: documents/models.py:1418
msgid "remove all document types"
msgstr ""
#: documents/models.py:1425
msgid "remove these correspondent(s)"
msgstr ""
#: documents/models.py:1430
msgid "remove all correspondents"
msgstr ""
#: documents/models.py:1437
msgid "remove these storage path(s)"
msgstr ""
#: documents/models.py:1442
msgid "remove all storage paths"
msgstr ""
#: documents/models.py:1449
msgid "remove these owner(s)"
msgstr ""
#: documents/models.py:1454
msgid "remove all owners"
msgstr ""
#: documents/models.py:1461
msgid "remove view permissions for these users"
msgstr ""
#: documents/models.py:1468
msgid "remove view permissions for these groups"
msgstr ""
#: documents/models.py:1475
msgid "remove change permissions for these users"
msgstr ""
#: documents/models.py:1482
msgid "remove change permissions for these groups"
msgstr ""
#: documents/models.py:1487
msgid "remove all permissions"
msgstr ""
#: documents/models.py:1494
msgid "remove these custom fields"
msgstr ""
#: documents/models.py:1499
msgid "remove all custom fields"
msgstr ""
#: documents/models.py:1508
msgid "email"
msgstr ""
#: documents/models.py:1517
msgid "webhook"
msgstr ""
#: documents/models.py:1521
msgid "workflow action"
msgstr ""
#: documents/models.py:1522
msgid "workflow actions"
msgstr ""
#: documents/models.py:1537
msgid "triggers"
msgstr ""
#: documents/models.py:1542
#: documents/models.py:1544
msgid "actions"
msgstr ""
#: documents/models.py:1545 paperless_mail/models.py:154
#: documents/models.py:1547 paperless_mail/models.py:154
msgid "enabled"
msgstr ""
#: documents/models.py:1556
#: documents/models.py:1558
msgid "workflow"
msgstr ""
#: documents/models.py:1560
#: documents/models.py:1562
msgid "workflow trigger type"
msgstr ""
#: documents/models.py:1574
#: documents/models.py:1576
msgid "date run"
msgstr ""
#: documents/models.py:1580
#: documents/models.py:1582
msgid "workflow run"
msgstr ""
#: documents/models.py:1581
#: documents/models.py:1583
msgid "workflow runs"
msgstr ""

View File

@@ -1,6 +1,6 @@
from typing import Final
__version__: Final[tuple[int, int, int]] = (2, 20, 3)
__version__: Final[tuple[int, int, int]] = (2, 20, 4)
# Version string like X.Y.Z
__full_version_str__: Final[str] = ".".join(map(str, __version__))
# Version string like X.Y

View File

@@ -23,7 +23,7 @@ class AIClient:
def get_llm(self) -> Ollama | OpenAI:
if self.settings.llm_backend == "ollama":
return Ollama(
model=self.settings.llm_model or "llama3",
model=self.settings.llm_model or "llama3.1",
base_url=self.settings.llm_endpoint or "http://localhost:11434",
request_timeout=120,
)
@@ -52,7 +52,7 @@ class AIClient:
)
tool_calls = self.llm.get_tool_calls_from_response(
result,
error_on_no_tool_calls=True,
error_on_no_tool_call=True,
)
logger.debug("LLM query result: %s", tool_calls)
parsed = DocumentClassifierSchema(**tool_calls[0].tool_kwargs)

View File

@@ -11,14 +11,12 @@ from paperless_ai.chat import stream_chat_with_documents
@pytest.fixture(autouse=True)
def patch_embed_model():
from llama_index.core import settings as llama_settings
from llama_index.core.embeddings.mock_embed_model import MockEmbedding
mock_embed_model = MagicMock()
mock_embed_model._get_text_embedding_batch.return_value = [
[0.1] * 1536,
] # 1 vector per input
llama_settings.Settings._embed_model = mock_embed_model
# Use a real BaseEmbedding subclass to satisfy llama-index 0.14 validation
llama_settings.Settings.embed_model = MockEmbedding(embed_dim=1536)
yield
llama_settings.Settings._embed_model = None
llama_settings.Settings.embed_model = None
@pytest.fixture(autouse=True)

4813
uv.lock generated

File diff suppressed because it is too large Load Diff