Commit Graph
4317 Commits
Author SHA1 Message Date
stumpylog 227b03365c feat(search): add whoosh-compat, the shared field table and the field registry 2026-09-10 12:36:25 -07:00
GitHub Actions 8593f84cae Auto translate strings 2026-09-10 16:05:03 +00:00
shamoon ca512af5ec Fix: ensure remove inbox tag children on remove_inbox_tags (#14050) 2026-09-10 16:03:47 +00:00
shamoon abdf15466c Fix: connect add_to_index handler after document_added (#14058) 2026-09-10 07:19:12 -07:00
Trenton HandClaude Opus 5 60709b8319 Performance: cut redundant per-document lookups in bulk modify_custom_fields (#13807)
* Perf: batch the repeated lookups in modify_custom_fields

`modify_custom_fields()` re-resolved the same objects inside its
per-document loop: `custom_fields.get(id=field_id)` re-ran a CustomField
query for every document, and doc link fields called
`Document.objects.get(id=doc_id)` a second time for a document that was
already known.

Resolve both up front with `in_bulk()` and hand the resolved objects to
`update_or_create()` rather than bare ids. Passing the objects also
populates the FK cache on the newly created instance, so auditlog's
post_save receiver touching `.document`/`.field` no longer costs a reload
per row. The document map defers `content`, the one field here that is
both large and unused. The symmetrical-link removal pass and
`remove_doclink()` get `select_related()` for the same auditlog reason.

Measured over 50 documents, sqlite, audit log enabled:

                        before   after
  add 3 string fields    1502    1054
  update 1 string field   451     403
  add doc link            851     653
  remove doc link         604     354

`update_or_create()` is kept as-is. Dropping it for a hand-rolled
get-or-construct loop removes a further ~4 statements per row, but those
are the SAVEPOINT/RELEASE pairs of its `transaction.atomic()`, and the
`select_for_update()` and IntegrityError fallback that go with them. The
(document, field) unique constraint depends on that when two bulk edits
overlap, and the wall clock did not move to pay for it (331 ms vs 310 ms
for the string case above).

Also normalises the field ids to int once at the top so the old dict API,
whose keys may arrive as strings, indexes the resolved map correctly.

The `if custom_field:` branch it replaces was dead: `.get()` raises
DoesNotExist, it never returns None.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* Fixes the comment

---------

Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
2026-09-09 23:47:07 +00:00
GitHub Actions 1c96819625 Auto translate strings 2026-09-09 22:41:48 +00:00
Philipp Defner 3e56dace73 Enhancement: Improve matching for correspondents, storage path and labels by removing bias + adding minimum match threshold (#12164) 2026-09-09 22:40:24 +00:00
Trenton H 310628699d Fix: If a file remains stable but has zero size after the stability window has passed, drop it from tracking (#14047)
A slow writer might create a zero byte file, then take longer than the window to
finish the write.  We would then queue a zero byte file for consumption and race the writer
to most likely fail due to still being empty.  Instead, drop zero size files at yeild time.
The slow writer may or may not finish, but if it does, there will be a Change.modified
event fired again
2026-09-09 16:24:17 +00:00
GitHub Actions aff0f9cf41 Auto translate strings 2026-09-09 16:04:18 +00:00
shamoon bf716ebfd1 Fixhancement: better LLM errors (#14031) 2026-09-09 16:02:43 +00:00
GitHub Actions 7d67a10a35 Auto translate strings 2026-09-09 15:50:33 +00:00
shamoon 8d1bc5dd24 Fix: prevent orphaned versions from bulk delete (#14030) 2026-09-09 08:48:59 -07:00
Trenton H 43a8d7d412 Enhancement: add Tantivy full-text fallback adapter for taxonomy candidates (#13820)
This brings users without an embedding backend configured to closer
parity with those who do.  Reuse the search backend to locate similar
documents and use them to provide the LLM with the better suggestion pool
to draw from
2026-09-09 15:15:15 +00:00
Trenton H c40922440b Fix: prevent overlapping mail-account processing runs (#14046)
process_mail_accounts had no guard against a scheduled run still being
in progress when the next one fires. Skip a run outright
if another MAIL_FETCH task is already PENDING/STARTED.
2026-09-09 07:49:49 -07:00
GitHub Actions b989b74140 Auto translate strings 2026-09-08 15:57:05 +00:00
shamoon 5194f47291 Performance: ensure version-aware content filters on querysets (#13792) 2026-09-08 15:55:45 +00:00
GitHub Actions 714885d7a5 Auto translate strings 2026-09-08 15:32:41 +00:00
Trenton H 73e777a48c Fix: skip nested TagSerializer construction when a tag has no children (#14039)
TagSerializer.get_children() built a full nested TagSerializer(many=True)
for every tag, even when it had zero children, likely the common case for
most tags and maybe even most installs. Constructing a DRF ModelSerializer isn't
free (field introspection, deepcopy of declared fields, i18n lookups
all re-run per instantiation), so this scaled GET /api/tags/ linearly
with tag count in pure Python overhead, unrelated to SQL query count.
2026-09-08 15:30:58 +00:00
shamoon 7813375123 Enhancement (QoL): surface externally-set options in Config UI (#13989) 2026-09-08 14:39:22 +00:00
shamoon 937feb1bef Change: skip documents with empty content in apply AI suggestions WF (#13985) 2026-09-07 21:56:37 +00:00
Trenton H f5ff18326d Performance: resolve index-write permissions and effective content in bulk (#13869)
* fix(search): resolve index-write permissions and effective content in bulk

Add WriteBatch.add_or_update_ids() and use it in bulk_update_documents
and trash restore, cutting index writes from ~8 queries per document
to a constant handful per batch

* Always these new ones with xdist, try a better condition
2026-09-07 14:43:13 -07:00
Berk D. Demir d52cc1b609 Fix: Use PAPERLESS_REDIS_PREFIX for Celery result backend keys (#14015)
PR #12741 sets the result backend for Celery to Redis, but forget to carryover
transport option `global_keyprefix`. This resulted keys with prefix
`celery-task-meta-` prefix to be created.

This fix unbreaks strict Redis ACLs that allow a single prefix.
2026-09-07 21:08:34 +00:00
GitHub Actions 3f5f4f3ed4 Auto translate strings 2026-09-07 20:48:12 +00:00
shamoon 9a47b20d2a Enhancement: duplicates filter (#13994) 2026-09-07 20:46:49 +00:00
GitHub Actions 05905287b3 Auto translate strings 2026-09-07 20:29:01 +00:00
shamoon d65de00ca1 Fix: correct setting ai_enabled to false via UI (#13987) 2026-09-07 20:27:33 +00:00
dependabot[bot]andTrenton Holmes f287a4cb8c Chore(deps): Bump the utilities-minor group across 1 directory with 11 updates (#13988)
* Chore(deps): Bump the utilities-minor group across 1 directory with 11 updates

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

| Package | From | To |
| --- | --- | --- |
| [django-guardian](https://github.com/django-guardian/django-guardian) | `3.3.3` | `3.4.0` |
| [django-treenode](https://github.com/fabiocaccamo/django-treenode) | `0.24.0` | `0.25.0` |
| [drf-spectacular-sidecar](https://github.com/tfranzel/drf-spectacular-sidecar) | `2026.7.1` | `2026.8.1` |
| [imap-tools](https://github.com/ikvk/imap_tools) | `1.14.0` | `1.15.0` |
| [ocrmypdf](https://github.com/ocrmypdf/OCRmyPDF) | `17.10.0` | `17.11.0` |
| [prek](https://github.com/j178/prek) | `0.4.11` | `0.5.0` |
| [faker](https://github.com/joke2k/faker) | `40.36.0` | `40.37.0` |
| [pytest-django](https://github.com/pytest-dev/pytest-django) | `4.12.0` | `4.14.0` |
| [pytest-rerunfailures](https://github.com/pytest-dev/pytest-rerunfailures) | `16.4` | `16.6` |
| [time-machine](https://github.com/adamchainz/time-machine) | `3.2.0` | `3.5.0` |
| [types-pygments](https://github.com/python/typeshed) | `2.20.0.20260408` | `2.21.0.20260819` |



Updates `django-guardian` from 3.3.3 to 3.4.0
- [Release notes](https://github.com/django-guardian/django-guardian/releases)
- [Commits](https://github.com/django-guardian/django-guardian/compare/3.3.3...3.4.0)

Updates `django-treenode` from 0.24.0 to 0.25.0
- [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.24.0...0.25.0)

Updates `drf-spectacular-sidecar` from 2026.7.1 to 2026.8.1
- [Commits](https://github.com/tfranzel/drf-spectacular-sidecar/compare/2026.7.1...2026.8.1)

Updates `imap-tools` from 1.14.0 to 1.15.0
- [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.14.0...v1.15.0)

Updates `ocrmypdf` from 17.10.0 to 17.11.0
- [Release notes](https://github.com/ocrmypdf/OCRmyPDF/releases)
- [Commits](https://github.com/ocrmypdf/OCRmyPDF/compare/v17.10.0...v17.11.0)

Updates `prek` from 0.4.11 to 0.5.0
- [Release notes](https://github.com/j178/prek/releases)
- [Changelog](https://github.com/j178/prek/blob/master/CHANGELOG.md)
- [Commits](https://github.com/j178/prek/compare/v0.4.11...v0.5.0)

Updates `faker` from 40.36.0 to 40.37.0
- [Release notes](https://github.com/joke2k/faker/releases)
- [Changelog](https://github.com/joke2k/faker/blob/master/CHANGELOG.md)
- [Commits](https://github.com/joke2k/faker/compare/v40.36.0...v40.37.0)

Updates `pytest-django` from 4.12.0 to 4.14.0
- [Release notes](https://github.com/pytest-dev/pytest-django/releases)
- [Changelog](https://github.com/pytest-dev/pytest-django/blob/main/docs/changelog.rst)
- [Commits](https://github.com/pytest-dev/pytest-django/compare/v4.12.0...v4.14.0)

Updates `pytest-rerunfailures` from 16.4 to 16.6
- [Changelog](https://github.com/pytest-dev/pytest-rerunfailures/blob/master/CHANGES.rst)
- [Commits](https://github.com/pytest-dev/pytest-rerunfailures/compare/16.4...16.6)

Updates `time-machine` from 3.2.0 to 3.5.0
- [Changelog](https://github.com/adamchainz/time-machine/blob/main/docs/changelog.rst)
- [Commits](https://github.com/adamchainz/time-machine/compare/3.2.0...3.5.0)

Updates `types-pygments` from 2.20.0.20260408 to 2.21.0.20260819
- [Commits](https://github.com/python/typeshed/commits)

---
updated-dependencies:
- dependency-name: django-guardian
  dependency-version: 3.4.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: django-treenode
  dependency-version: 0.25.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: drf-spectacular-sidecar
  dependency-version: 2026.8.1
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: faker
  dependency-version: 40.37.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: imap-tools
  dependency-version: 1.15.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: ocrmypdf
  dependency-version: 17.11.0
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: prek
  dependency-version: 0.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: pytest-django
  dependency-version: 4.14.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: pytest-rerunfailures
  dependency-version: '16.6'
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: time-machine
  dependency-version: 3.5.0
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
- dependency-name: types-pygments
  dependency-version: 2.21.0.20260819
  dependency-type: direct:development
  update-type: version-update:semver-minor
  dependency-group: utilities-minor
...

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

* Handles pytest-django

* Formatting

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Trenton Holmes <797416+stumpylog@users.noreply.github.com>
2026-09-07 20:13:15 +00:00
GitHub Actions 340118ad51 Auto translate strings 2026-09-06 22:53:12 +00:00
shamoon 3899e0f0d6 Fix: correct add version actor parity (#14016) 2026-09-06 15:51:53 -07:00
shamoon d648526858 Fix: fix v3 favicon file (#14014) 2026-09-06 15:43:37 -07:00
shamoon f1679a2ee3 Fix: truncate mail subjects to field max length (#13991) 2026-09-05 01:52:18 -07:00
GitHub Actions 16568439c0 Auto translate strings 2026-09-04 14:17:01 +00:00
shamoon 3f4d2a4b5a And the backend 2026-09-04 07:14:58 -07:00
shamoon d48663e9eb Bump version to 3.1.3 2026-09-03 18:59:18 -07:00
github-actions[bot]andCrowdin Bot a28a6fe23b New Crowdin translations by GitHub Action (#13894)
Co-authored-by: Crowdin Bot <support+bot@crowdin.com>
2026-09-03 18:58:02 -07:00
dependabot[bot] a3851c157a Chore(deps-dev): Bump postcss-selector-parser from 6.1.2 to 6.1.4 in /src/paperless_mail/templates in the npm_and_yarn group across 1 directory (#13905)
Signed-off-by: dependabot[bot] <support@github.com>
2026-09-03 02:49:45 +00:00
shamoon 07f1a356f8 Fix: tweak tool calling localzation prompt (#13943) 2026-09-02 19:45:11 +00:00
GitHub Actions 8d41d31bd7 Auto translate strings 2026-09-02 18:10:21 +00:00
Trenton Handshamoon 351892bbab Fix: skip vector store document id filter for unrestricted chat users (#13937)
* Fix: skip vector store document id filter for unrestricted chat users

ChatStreamingView built an IN filter from every permitted document id
for the "chat over all documents" case, which exceeds the vector
store's SQLite bound-parameter safety limit on installs with more
than ~32700 documents, silently returning no context. For a user who
can see every document (an active superuser), that filter never
narrows anything, so skip it and let the retriever search the whole
index instead.

* Minor improvements from a Claude review

* When a user is unrestricted chatting, still exclude trashed documents using a 'NOT IN' SQL statement.  Wire that up where we need it

* Update src/paperless_ai/chat.py

Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2026-09-02 18:08:54 +00:00
Thomas Steinbachandshamoon 5d6ea11828 Fix: adopt the request stream when pinning an outbound host (#13927)
Co-authored-by: shamoon <4887959+shamoon@users.noreply.github.com>
2026-09-02 17:04:09 +00:00
shamoon c5765a50a1 Fix: ensure apply ai suggestions always runs after document created (#13940) 2026-09-02 16:12:49 +00:00
Trenton H c2a9532b8f Fix: Handle Celery enqueue failures when enqueuing files for consumption (#13935) 2026-09-02 15:58:27 +00:00
Trenton H 713c857a08 Fix: Handle Celery mail task chord errors (#13936)
* Fix: mail rule loops forever when all attachments are duplicates

When every attachment in a mail is rejected as a duplicate, the chord's
header tasks all fail. Celery's default task_allow_error_cb_on_chord_header
skips the error callback in that case, so no ProcessedMail row is ever
created, and the same mail is refetched and reprocessed on every poll for
as long as it stays in the rule's maximum_age window.

* Minor simplifications and cleanup
2026-09-02 08:41:30 -07:00
Trenton H d78754bff1 Security: validate remote OCR endpoint against internal SSRF (#13897)
* Security: validate remote OCR endpoint against internal SSRF

Adds PAPERLESS_REMOTE_OCR_ALLOW_INTERNAL_ENDPOINTS (default true)
and validates remote_ocr_endpoint via validate_outbound_http_url
on the config serializer, matching the existing LLM endpoint handling.

* Validates te outbound url again right before use

* cover empty-value branch of validate_remote_ocr_endpoint because coverage

* re-validate remote OCR endpoint on every outbound request
2026-09-01 20:22:10 +00:00
GitHub Actions 08f2f4bfe2 Auto translate strings 2026-09-01 19:54:47 +00:00
Trenton H f993462973 Security: Minor additional hardening (#13898)
* Security: bump jinja2 floor to 3.1.6 (CVE-2025-27516)

* Security: anchor the /share/ URL pattern

* Security: handle missing file on public share view without 500

* Security: scope correspondent last_correspondence to permitted documents

* Security: disable PUT/PATCH on share link bundles
2026-09-01 19:53:28 +00:00
shamoon ae70b8d60f Chore: consolidate pickle hmac signing (#13899) 2026-09-01 12:41:45 -07:00
GitHub Actions 31e9f4272c Auto translate strings 2026-09-01 16:56:33 +00:00
shamoon b8659c1af3 Fix: use root doc metadata for filename generation (#13893) 2026-09-01 09:55:04 -07:00
shamoon ca98dffbd2 Bump version to 3.1.2 2026-09-01 08:09:13 -07:00