Commit Graph
5 Commits
Author SHA1 Message Date
Robert Vind-GardoșandPR #6029 Reviewer c74f475679 fix(upload): honor no-login mode after account setup (#6528)
* fix(upload): honor no-login mode after account setup

* ci: refresh checks against the current dev base

* test(upload): add regression tests for unconfigured auth and no-login POST

* fix(upload): fail closed on missing auth_manager and preserve cross-user isolation

Enforce strict cross-user isolation so that authenticated users cannot access
files owned by other accounts when app.state.auth_manager is absent or None.
Fail closed with HTTP 503 for non-loopback requests when AUTH_ENABLED=true and
authentication infrastructure is unexpectedly unavailable, while preserving
intended single-user mode (AUTH_ENABLED=false) and intentional first-run setup
mode (auth_manager.is_configured=False).

* fix(upload): eliminate fail-open paths for unconfigured manager and loopback transport

- Eliminate early return on unconfigured auth_manager (Finding A): fail closed with HTTP 401 Setup required
- Eliminate loopback transport bypass when auth_manager is missing (Finding B): fail closed with HTTP 503
- Enforce strict ownership isolation: non-owners and legacy ownerless uploads require verified administrator access
- Add regression suites in tests/test_upload_no_login.py covering Finding A, Finding B, bearer tokens, and ownerless files
- Explicitly set AUTH_ENABLED=false for unauthenticated tests in tests/test_upload_routes_owner_scope.py

* fix(upload): prevent delegated API tokens from inheriting admin privileges and enforce upload scopes

- Prevent delegated bearer API credentials from inheriting interactive administrator privileges over other users' files or legacy ownerless files.
- Enforce granular upload scopes for delegated credentials: chat and documents:write for upload creation and vision OCR editing; chat, documents:read, and documents:write for downloads, thumbnails, and vision OCR reads.
- Reject requests with missing token owners or reserved sentinel identities (api, demo, system, internal-tool) with 403 Forbidden.
- Add comprehensive regression tests in tests/test_upload_no_login.py verifying delegated token scope isolation, sentinel rejection, owner isolation, and untouched OCR state on rejected edits.

---------

Co-authored-by: PR #6029 Reviewer <reviewer@odysseus-review.local>
2026-10-15 11:08:58 +01:00
Robert Vind-GardoșandPR #6166 Reviewer 501059805f fix(cleanup): preserve transcripts with stale message counts (#6610)
* fix(cleanup): preserve transcripts with stale message counts

* fix(cleanup): accurately attribute freed space and bound recent session query

* fix(cleanup): add portable fallback for SQLite runtimes lacking RETURNING

---------

Co-authored-by: PR #6166 Reviewer <reviewer@odysseus-review.local>
2026-10-14 11:21:53 +01:00
Robert Vind-GardoșandPR #6166 Reviewer 0c56527d12 fix(email): preserve mail when bulk Trash moves fail (#6633)
* fix(email): preserve mail when bulk Trash moves fail

* fix(email): selective UID EXPUNGE and safe bulk delete cache invalidation

* fix(email): eliminate mailbox-wide EXPUNGE TOCTOU race

- Strictly prohibit mailbox-wide EXPUNGE in bulk email deletion fallback
- Restrict cleanup exclusively to selective RFC 4315 UID EXPUNGE <set>
- Track and preserve pre-existing \Deleted flags if selective expunge fails
- Retain local index records and preserve source emails when cleanup fails
- Ensure consistent partial-failure error semantics across all failure modes
- Add comprehensive hermetic tests for concurrent clients, missing UIDPLUS,
  disconnects after COPY/STORE/EXPUNGE, and retry safety

---------

Co-authored-by: PR #6166 Reviewer <reviewer@odysseus-review.local>
2026-10-14 09:01:42 +01:00
Robert Vind-GardoșandAlexandre Teixeira c23b1be3f8 fix(history): reject implicit and coerced truncation targets (#6565)
* fix(history): reject implicit and coerced truncation targets

* fix(history): reject falsy non-string message IDs; drop redundant keep_count guard

The or-chain used to resolve before_msg_id / message_id evaluated
falsy non-strings (False, 0) to '' before the isinstance(…, str) check
was reached, so they silently bypassed type validation.  Replace the
chain with explicit presence-aware logic that falls through on None or
empty string (preserving alias semantics) but rejects any other
non-string value with HTTP 400.

Also remove the now-tautological 'if keep_count >= 0:' guard, which
is always True after the negativity check introduced in the parent
commit.  The DB block is unconditional and indented accordingly.

Tests: add {'before_msg_id': False}, {'before_msg_id': 0},
{'message_id': 0} to the parametrised rejection suite.

36 passed, 0 failed (Python 3.14.4 / pytest 9.1.1).

---------

Co-authored-by: Alexandre Teixeira <111787685+alteixeira20@users.noreply.github.com>
2026-10-14 08:41:38 +01:00
Robert Vind-Gardoș a8c147b238 fix(reminders): retry failed note delivery through the configured channel (#6566) 2026-10-07 15:38:41 +02:00