Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
83c96ee
chore: back-merge v5.19.1 into develop
evilguy4000 Nov 7, 2026
364e606
Merge pull request #855 from DRYTRIX/chore/back-merge-v5.19.1
evilguy4000 Nov 7, 2026
9300f02
Document overdue invoice reminders and recurring invoice flows.
evilguy4000 Nov 7, 2026
d9029c9
Add DigitalOcean one-click and Unraid CA root profile for catalog sub…
evilguy4000 Nov 7, 2026
80a9939
Document Unraid CA submit via the unraid-ca template-only branch.
evilguy4000 Nov 7, 2026
26d009d
fix(payments): use the currency's minor unit for Stripe amounts
5eBeKs Nov 7, 2026
8d26983
Merge pull request #859 from 5eBeKs/fix/stripe-zero-decimal-amounts
evilguy4000 Nov 7, 2026
2584645
fix(peppol): report recorded payments as PrepaidAmount in the UBL
5eBeKs Nov 8, 2026
b49a8a1
Merge pull request #860 from 5eBeKs/fix/peppol-prepaid-amount
evilguy4000 Nov 8, 2026
eb6ec50
docs: archive stale gap analyses and track Phase 6 in GAP_ROADMAP
evilguy4000 Nov 8, 2026
b5c17bc
feat(extension): add 2FA login, Firefox packaging, and tab URL sugges…
evilguy4000 Nov 8, 2026
f8815e5
feat(desktop): surface failed offline sync items and broaden i18n
evilguy4000 Nov 8, 2026
e15a9c7
feat(mobile): add sync retry backoff and a failed-sync screen
evilguy4000 Nov 8, 2026
0157f92
feat(web): enforce kanban WIP limits and extend custom fields
evilguy4000 Nov 8, 2026
e89b3e6
feat(invoicing): add XRechnung export and PDF QR/barcode elements
evilguy4000 Nov 8, 2026
0867fe1
feat(inventory): add stock location, PO email, and stock-levels CSV e…
evilguy4000 Nov 8, 2026
afaa9b7
feat(auth): implement OAuth2 apps, SAML login, SCIM provisioning, and…
evilguy4000 Nov 8, 2026
124ecf3
feat: add API coverage, payroll/labor exports, bank reconciliation, a…
evilguy4000 Nov 8, 2026
670705f
chore(deps-dev): bump the npm-desktop group in /desktop with 3 updates
dependabot[bot] Nov 9, 2026
8c17620
chore(deps): bump the npm-root group with 2 updates
dependabot[bot] Nov 9, 2026
0e31c17
chore(deps): bump flutter_local_notifications
dependabot[bot] Nov 9, 2026
e09bff1
chore(deps): bump softprops/action-gh-release
dependabot[bot] Nov 9, 2026
c24e0c1
chore(deps): bump the pip group with 13 updates
dependabot[bot] Nov 9, 2026
02f0654
fix(reports): apply the export form's filters to CSV and Excel
jayhemnani9910 Nov 9, 2026
677f468
fix(invoices): store time_entry_ids as text
jayhemnani9910 Nov 9, 2026
0677f76
Merge pull request #861 from DRYTRIX/dependabot/npm_and_yarn/desktop/…
evilguy4000 Nov 10, 2026
b1efbf4
Merge pull request #862 from DRYTRIX/dependabot/npm_and_yarn/develop/…
evilguy4000 Nov 10, 2026
acc4b44
Merge pull request #863 from DRYTRIX/dependabot/pub/mobile/develop/pu…
evilguy4000 Nov 10, 2026
9aaf824
Merge pull request #864 from DRYTRIX/dependabot/github_actions/develo…
evilguy4000 Nov 10, 2026
6f8d0f2
Merge pull request #865 from DRYTRIX/dependabot/pip/develop/pip-89a59…
evilguy4000 Nov 10, 2026
3e3a707
Merge pull request #866 from jayhemnani9910/fix/report-export-apply-f…
evilguy4000 Nov 10, 2026
dc0b8e3
Merge branch 'develop' into fix/invoice-item-time-entry-ids-text
evilguy4000 Nov 10, 2026
82561e3
Merge pull request #867 from jayhemnani9910/fix/invoice-item-time-ent…
evilguy4000 Nov 10, 2026
a57e7c1
fix(ci): restore lint, docker boot, wizard tests, and push migration …
evilguy4000 Nov 10, 2026
7e8b506
fix(security): clear open CodeQL redirect, stack-trace, hashing, and …
evilguy4000 Nov 10, 2026
5df7904
Merge branch 'fix/ci-run-42778066883' into develop
evilguy4000 Nov 10, 2026
511f838
style: apply isort/black after merging CI fixes into develop
evilguy4000 Nov 10, 2026
72dc7be
chore(deps): bump flutter_riverpod in /mobile in the pub-mobile group
dependabot[bot] Nov 10, 2026
728d538
chore(deps): bump types-markdown
dependabot[bot] Nov 10, 2026
e6da01a
Merge pull request #870 from DRYTRIX/dependabot/pip/develop/pip-6a13f…
evilguy4000 Nov 10, 2026
75f6bbb
Merge pull request #869 from DRYTRIX/dependabot/pub/mobile/develop/pu…
evilguy4000 Nov 10, 2026
c5db522
feat(peppol): add Let’s Peppol bridge provider and inbound inbox
evilguy4000 Nov 10, 2026
e169935
fix(ci): restore Riverpod 2 pin and black wrap for develop
evilguy4000 Nov 10, 2026
afb55b5
style: black-format Peppol inbox files for lint CI
evilguy4000 Nov 10, 2026
5fb4cb8
style: isort bank_reconciliation_service imports for lint CI
evilguy4000 Nov 10, 2026
5171813
chore(release): prep 5.20.0 notes and fix mobile CD builds
evilguy4000 Nov 10, 2026
2d2c6e8
chore(release): bump version to 5.20.0
github-actions[bot] Nov 10, 2026
e43a971
fix(security): ignore APScheduler Safety advisory with no 3.x fix
evilguy4000 Nov 10, 2026
621a0a2
Merge pull request #872 from DRYTRIX/fix/safety-apscheduler-ignore
evilguy4000 Nov 10, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions .do/deploy.template.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# DigitalOcean App Platform — Deploy to DigitalOcean button
# https://docs.digitalocean.com/products/app-platform/how-to/add-deploy-do-button/
#
# Uses the public Docker Hub image (same multi-arch build as GHCR).
# Dev Database only (Deploy button limitation). For production, use a managed
# Postgres cluster or self-host with docker-compose.nas.yml.
#
# Button: https://cloud.digitalocean.com/apps/new?repo=https://github.com/DRYTRIX/TimeTracker/tree/develop
# (default branch; switch to /tree/main after the template is merged to main)

spec:
name: timetracker
services:
- name: web
image:
registry_type: DOCKER_HUB
registry: drytrix
repository: timetracker
tag: latest
instance_count: 1
instance_size_slug: basic-xxs
http_port: 8080
health_check:
http_path: /_health
initial_delay_seconds: 30
period_seconds: 15
timeout_seconds: 10
success_threshold: 1
failure_threshold: 5
envs:
- key: FLASK_ENV
scope: RUN_TIME
value: production
- key: FLASK_APP
scope: RUN_TIME
value: app:create_app()
- key: AUTH_METHOD
scope: RUN_TIME
value: local
- key: REDIS_ENABLED
scope: RUN_TIME
value: "false"
- key: SECRET_KEY
scope: RUN_TIME
type: SECRET
# Replace at deploy time: openssl rand -hex 32
value: "CHANGE_ME_openssl_rand_hex_32"
- key: DATABASE_URL
scope: RUN_TIME
value: ${timetracker-db.DATABASE_URL}
databases:
- name: timetracker-db
engine: PG
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ extensions:
extensible: barrierModel
data:
- ["app.utils.safe_redirect", "Member[safe_redirect_target].ReturnValue", "url-redirection"]
- ["app.utils.safe_redirect", "Member[match_registered_redirect].ReturnValue", "url-redirection"]
- ["app.utils.safe_redirect", "Member[_rebuild_relative].ReturnValue", "url-redirection"]
- ["app.utils.safe_redirect", "Member[_rebuild_same_host].ReturnValue", "url-redirection"]
- ["app.utils.error_handling", "Member[sanitize_log_value].ReturnValue", "log-injection"]
Expand Down
8 changes: 8 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ updates:
labels:
- dependencies
- python
# Gunicorn 26 removed the eventlet worker used by docker/start-fixed.py.
ignore:
- dependency-name: gunicorn
update-types: ["version-update:semver-major"]

- package-ecosystem: npm
directory: /
Expand Down Expand Up @@ -73,6 +77,10 @@ updates:
labels:
- dependencies
- mobile
# Riverpod 3 removed StateNotifier; stay on 2.x until providers are migrated.
ignore:
- dependency-name: flutter_riverpod
update-types: ["version-update:semver-major"]

- package-ecosystem: github-actions
directory: /
Expand Down
5 changes: 5 additions & 0 deletions .github/workflows/build-mobile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,11 @@ jobs:
working-directory: mobile
run: flutter test

- name: Install CocoaPods deps
working-directory: mobile/ios
run: |
pod install --repo-update

- name: Build iOS (simulator)
working-directory: mobile
env:
Expand Down
7 changes: 6 additions & 1 deletion .github/workflows/cd-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -854,6 +854,11 @@ jobs:
working-directory: mobile
run: flutter test

- name: Install CocoaPods deps
working-directory: mobile/ios
run: |
pod install --repo-update

# Release mode is invalid for iOS simulator; this validates compilation and produces Runner.app for the artifact zip.
- name: Build iOS (simulator)
working-directory: mobile
Expand Down Expand Up @@ -1073,7 +1078,7 @@ jobs:
cat RELEASE_NOTES.md

- name: Create draft GitHub Release
uses: softprops/action-gh-release@efb35369e0ad2afab669f228072c1b0d510eae64 # v3.0.3
uses: softprops/action-gh-release@8a0cd651e5b2365bd640854a3fa5dfc70e4875f3 # v3.0.4
with:
tag_name: ${{ needs.determine-version.outputs.version }}
name: Release ${{ needs.determine-version.outputs.version }}
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,9 @@ jobs:
app/utils/integration_http.py
- name: Silent exception ratchet
run: python scripts/check_silent_excepts.py
- name: Route file size guard (soft)
run: python scripts/ci/check_route_file_sizes.py
continue-on-error: true
- name: Translation coverage
run: python scripts/check_translation_coverage.py
- name: Version consistency
Expand Down
20 changes: 15 additions & 5 deletions .github/workflows/migration-validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,16 @@ jobs:
- name: Check for migration changes
id: migration_check
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
# PRs use the PR base; pushes use the previous tip (github.event.before).
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
run: |
# Compare against the PR base (not HEAD~1) so multi-commit PRs are covered
# All-zero "before" means first push / force-push with no prior tip.
if [ "${BASE_SHA:-}" = "0000000000000000000000000000000000000000" ]; then
BASE_SHA=""
fi
# Compare against the PR/push base (not HEAD~1) so multi-commit ranges are covered
if [ -z "$BASE_SHA" ]; then
echo "⚠️ No PR base SHA; falling back to HEAD~1"
echo "⚠️ No PR/push base SHA; falling back to HEAD~1"
DIFF_RANGE="HEAD~1"
else
DIFF_RANGE="${BASE_SHA}...HEAD"
Expand All @@ -88,16 +93,21 @@ jobs:
DATABASE_URL: postgresql+psycopg2://test_user:test_password@localhost:5432/test_db
FLASK_APP: app.py
FLASK_ENV: testing
BASE_SHA: ${{ github.event.pull_request.base.sha }}
BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.before }}
run: |
set -euo pipefail

# All-zero "before" means first push / force-push with no prior tip.
if [ "${BASE_SHA:-}" = "0000000000000000000000000000000000000000" ]; then
BASE_SHA=""
fi

echo "🔍 Validating migration consistency..."
echo "Current directory: $(pwd)"
echo "Migration files:"
ls -la migrations/versions/ | tail -5

# Ensure PR base commit is available for checkout (fork PRs / shallow edges)
# Ensure PR/push base commit is available for checkout (fork PRs / shallow edges)
if [ -n "${BASE_SHA:-}" ]; then
git fetch --no-tags --depth=1 origin "$BASE_SHA" 2>/dev/null || git fetch --no-tags origin "$BASE_SHA" || true
fi
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ junit.xml
*.xml
!mobile/android/app/src/main/AndroidManifest.xml
!templates/unraid/*.xml
!ca_profile.xml
test-results/
.pytest_tmp*/
bandit-report.json
Expand Down
8 changes: 7 additions & 1 deletion .safety-policy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,11 @@ security:
ignore-unpinned-requirements: false
ignore-cvss-severity-below: 0
ignore-cvss-unknown-severity: false
ignore-vulnerabilities: {}
ignore-vulnerabilities:
# No fixed 3.x release yet (advisory range <3.12; latest is 3.11.3). We use the
# default MemoryJobStore only — not Redis/Mongo/SQLAlchemy stores that pickle
# job_state — so the persistent job-store deserialization path does not apply.
SFTY-20261008-90293:
reason: APScheduler MemoryJobStore only; no fixed 3.x release available
expires: '2027-05-01'
continue-on-vulnerability-error: false
36 changes: 36 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,42 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [5.20.0] - 2026-11-10
### Added

- **Enterprise identity** — OAuth 2.0 API apps (authorization code + PKCE, admin CRUD), SAML 2.0 login, SCIM Users provisioning, and shared Slack/Teams timer bot commands.
- **Bank reconciliation & payroll** — Bank reconciliation workflows plus payroll/labor export APIs and UI.
- **Inventory** — Stock locations, purchase-order email, and stock-levels CSV export.
- **Invoicing** — XRechnung export and PDF QR/barcode elements on invoice/quote layouts.
- **Peppol bridge: Let’s Peppol + inbox** — `PEPPOL_BRIDGE_PROVIDER=letspeppol` for Belgian access-point delivery, plus inbound Peppol inbox poll/ack in the bridge and admin UI.
- **Kanban & custom fields** — Enforce kanban WIP limits; extend custom fields coverage.
- **Clients** — Mobile sync retry backoff and failed-sync screen; desktop failed offline-sync surfacing and broader i18n; browser extension 2FA login, Firefox packaging, and tab URL suggestions.
- **DigitalOcean one-click** — `.do/deploy.template.yaml` (Docker Hub image + Dev Database) and Deploy to DigitalOcean button in the README / Distribution guide.
- **Unraid CA profile** — Root `ca_profile.xml` (`CommunityApplications` + `<Profile>`) required for Community Applications submission.

### Security

- **CodeQL** — Clear open redirect, stack-trace, weak-hashing, and XML-related alerts on develop paths used by auth/OAuth and related utilities.

### Fixed

- **Invoices** — Generating an invoice from many time entries no longer fails on PostgreSQL: `invoice_items.time_entry_ids` is now `TEXT` (was `VARCHAR(500)`).
- **Report export** — CSV and Excel exports from the report form now apply the client, task, billable, source and tags filters.
- **Payments** — Stripe checkout now sends JPY and other zero-decimal currencies (and three-decimal ones such as KWD) in the unit Stripe expects; before, every amount was multiplied by 100, so a JPY invoice was charged 100 times its balance, and the webhook amount was divided by 100 the same way.
- **Peppol** — The UBL invoice now reports payments already recorded on the invoice as `PrepaidAmount` and sets `PayableAmount` to the total minus those payments (BR-CO-16), never below zero, as the Factur-X/ZUGFeRD export already does; before, a partly paid invoice sent or exported as UBL asked the buyer for the full total.
- **CI / Docker** — Restore gunicorn 25.x (eventlet worker) after a major bump broke image boot; isolate setup-wizard fixture state; use push `before` SHA for migration drift; keep mobile on Riverpod 2.x.

### Changed

- **Mobile Android** — Bump Gradle wrapper to 8.14 so Flutter 3.47 release builds satisfy the minimum Gradle version.
- **Dependencies** — Pip, Actions, npm (root + desktop), and Flutter mobile dependency bumps (with Dependabot major ignores for gunicorn and flutter_riverpod).

### Documentation

- **OrcaRouter** — AI Helper docs and Admin settings include a signup link for an OrcaRouter API key (`https://www.orcarouter.ai/ref/ref_984e584cb4cd86485a8c`).
- **Deploy & discovery** — DigitalOcean and Railway deploy guides; Unraid CA + directory listing submission packages; publishing checklist (`docs/deploy/*`, `docs/marketing/*`).
- **Gap roadmap** — Archive stale gap analyses; Phase 6 marked done for the implementation pass.

## [5.19.1] - 2026-11-07
### Added

Expand Down
5 changes: 5 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
# Fonts
fonts-liberation \
fonts-dejavu-core \
# python3-saml / xmlsec (SAML SSO — see docs/design/SAML_SCIM.md)
libxml2-dev \
libxmlsec1-dev \
libxmlsec1-openssl \
pkg-config \
# PostgreSQL client dependencies
gnupg \
wget \
Expand Down
8 changes: 7 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
# Common development and testing tasks

.PHONY: help install test test-smoke test-unit test-integration test-security test-coverage \
test-fast test-parallel lint format clean docker-build docker-run setup dev security-scan frontend-a11y
test-fast test-parallel lint format clean docker-build docker-run setup dev security-scan frontend-a11y \
check-route-sizes

# Default target
help:
Expand Down Expand Up @@ -33,6 +34,7 @@ help:
@echo " make lint - Run linters (flake8)"
@echo " make format - Format code (black + isort)"
@echo " make format-check - Check code formatting"
@echo " make check-route-sizes - Soft route file line-count guard (warn >2000, fail >2500)"
@echo " make security-scan - Run security scanners"
@echo " make frontend-a11y - Run accessibility check on web app (requires app running; set FRONTEND_URL)"
@echo ""
Expand Down Expand Up @@ -113,6 +115,10 @@ lint:
flake8 app/ --count --select=E9,F63,F7,F82 --show-source --statistics
flake8 app/ --count --max-complexity=10 --max-line-length=120 --statistics

check-route-sizes:
@echo "Checking app/routes/*.py line counts..."
python3 scripts/ci/check_route_file_sizes.py

format:
@echo "Running black..."
black app/
Expand Down
10 changes: 6 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ docker compose -f docker-compose.nas.yml up -d
# open http://localhost:8080 — first login creates the admin
```

**Latest release: v5.19.1** — see [CHANGELOG.md](CHANGELOG.md).
**Latest release: v5.20.0** — see [CHANGELOG.md](CHANGELOG.md).

### First 5 minutes

Expand Down Expand Up @@ -152,11 +152,11 @@ Timers, projects, clients, CRM pipeline, PDF + Peppol invoicing, expenses, repor
| **NAS compose** | QNAP, Synology, Portainer | Paste [`docker-compose.nas.yml`](docker-compose.nas.yml) — [NAS guide](docs/admin/deployment/NAS_DEPLOYMENT.md) |
| **GitHub Release** | Compose files + desktop/mobile | [Releases](https://github.com/drytrix/TimeTracker/releases) |
| **Cloud (Render)** | Managed hosting | [![Deploy to Render](https://render.com/images/deploy-to-render-button.svg)](https://render.com/deploy?repo=https://github.com/drytrix/TimeTracker) |
| **Cloud (DigitalOcean)** | Managed hosting | [![Deploy to DigitalOcean](https://www.deploytodo.com/do-btn-blue.svg)](https://cloud.digitalocean.com/apps/new?repo=https://github.com/DRYTRIX/TimeTracker/tree/develop) |
| **Railyard** | Managed hosting | [![Deploy to Railyard](https://app.railyard.run/deploy/badge)](https://app.railyard.run/deploy?repo=https://github.com/DRYTRIX/TimeTracker) |
| **Cloud (RepoCloud)** | Managed hosting | <a href="https://repocloud.io/details/TimeTracker/"><img src="https://d16t0pc4846x52.cloudfront.net/deploylobe.svg" alt="Deploy on RepoCloud" height="32"></a> |


**Full list of install paths:** [Distribution Guide](docs/admin/deployment/DISTRIBUTION.md) (Portainer templates, Unraid, Railway, Fly.io, Coolify, [Docker Hub](https://hub.docker.com/r/drytrix/timetracker))
**Full list of install paths:** [Distribution Guide](docs/admin/deployment/DISTRIBUTION.md) (Portainer templates, Unraid, Railway, Fly.io, Coolify, DigitalOcean, [Docker Hub](https://hub.docker.com/r/drytrix/timetracker))

> **Docker Hub namespace:** images are published at [`drytrix/timetracker`](https://hub.docker.com/r/drytrix/timetracker) (formerly `driesp/timetracker`).

Expand Down Expand Up @@ -343,6 +343,7 @@ Comprehensive documentation is available in the [`docs/`](docs/) directory. See
- **[Task Management](docs/TASK_MANAGEMENT_README.md)** — Task tracking system
- **[Client Management](docs/CLIENT_MANAGEMENT_README.md)** — Client relationships
- **[Invoice System](docs/INVOICE_FEATURE_README.md)** — Invoice generation
- **[Overdue reminders & recurring invoices](docs/features/INVOICE_REMINDERS_AND_RECURRING.md)** — Daily overdue check and recurring billing

**Advanced Features:**
- **[Calendar & Bulk Entry](docs/CALENDAR_FEATURES_README.md)** — Calendar view and bulk operations
Expand Down Expand Up @@ -439,6 +440,7 @@ TimeTracker includes an optional **server-side AI helper** for the web app and A

- **Enable (any setup)**: set `AI_ENABLED=true` (environment or **Admin → System Settings → AI Helper**).
- **Ollama**: set `AI_PROVIDER=ollama`, `AI_MODEL=...`, and `AI_BASE_URL` to `http://ollama:11434` when Ollama runs in Docker on the same Compose network, or `http://127.0.0.1:11434` when Ollama runs on the host.
- **OrcaRouter** (hosted multi-model gateway): set `AI_PROVIDER=orcarouter`, `AI_BASE_URL=https://api.orcarouter.ai`, and `AI_API_KEY=...`. [Sign up for an API key](https://www.orcarouter.ai/ref/ref_984e584cb4cd86485a8c).
- **Hosted OpenAI-compatible**: set `AI_PROVIDER=openai_compatible` and `AI_API_KEY=...`

The AI helper is exposed as:
Expand Down Expand Up @@ -472,7 +474,7 @@ The root `docker-compose.yml` defines a CPU-only **`ollama`** service and a one-
- Pulled models are cached in the `ollama_data` named volume, so subsequent boots are faster.
- Verify in the UI: **Admin → System Settings → AI helper**, then click *Test connection*.
- To pull additional models manually: `docker compose exec ollama ollama pull <model>` (with the `ai` profile active).
- **Hosted provider only (no Ollama containers):** set `AI_PROVIDER=openai_compatible`, `AI_BASE_URL`, and `AI_API_KEY` in `.env`; keep `docker compose up -d` without the `ai` profile.
- **Hosted provider only (no Ollama containers):** set `AI_PROVIDER=orcarouter` (or `openai_compatible`), `AI_BASE_URL`, and `AI_API_KEY` in `.env`; keep `docker compose up -d` without the `ai` profile. For OrcaRouter, [sign up here](https://www.orcarouter.ai/ref/ref_984e584cb4cd86485a8c).

**Disable or remove AI** (turn off LLM calls, stop Ollama, revoke tokens, delete `ollama_data` safely): [UNINSTALL.md](UNINSTALL.md#disabling-or-removing-the-ai-helper).

Expand Down
2 changes: 1 addition & 1 deletion VERSION
Original file line number Diff line number Diff line change
@@ -1 +1 @@
5.19.1
5.20.0
Loading
Loading