- Honor AI_ENABLED across session AI, REST v1, LLM service, templates, and
context; add regression tests for the AI helper gate.
- Docker Compose: optional Ollama behind the ai profile; align env.example
and example compose with safe defaults.
- Add UNINSTALL.md with a dedicated AI teardown section; cross-link from
README, INSTALLATION, Getting Started, docs index, and Docker setup guide.
- Record 5.5.6 in CHANGELOG and sync version examples in BUILD_CONFIGURATION;
bump setup.py to 5.5.6.
Admin restore runs in a background thread; the finally block must not use current_app.logger outside an application context. Use the captured Flask app instance for safe_file_remove logging instead.
While restore_backup runs (extract through Alembic upgrade), set a per-app _database_restore_in_progress flag and expose is_database_restore_in_progress(). The client portal blueprint registers a global app_context_processor; get_current_client() now skips database access during restore and catches SQLAlchemy errors with session rollback so error pages and login can still render when the schema is briefly torn on PostgreSQL.
Documentation: add docs/admin/BACKUP_AND_RESTORE.md, link it from the admin index and import/export docs, cross-reference from DATABASE_RECOVERY.md, and extend IMPORT_EXPORT_GUIDE.md with concurrent-restore guidance.
Fix stale build-guide links, document the implemented quotes API scopes/endpoints, and clarify quote access plus permission-denial behavior so docs match route and test-backed behavior.
- Add ollama and ollama-init services with ollama_data volume; app waits for the model pull and receives AI_* defaults (AI_BASE_URL=http://ollama:11434).
- Document bundled stack, env vars, and Ollama vs host base URL in README and DOCKER_COMPOSE_SETUP.
- Align env.example AI defaults with the compose stack.
- fix(ai): include api_key_set on AIProviderConfig so from_settings(**get_ai_config()) matches the settings dict.
Timer starts always blocked a second running entry and never read the\nadmin-controlled Settings flag.\n\n- Add TimeTrackingService.can_start_timer() using Settings.get_settings()\n and wire it into start_timer, web timer routes, kiosk start, and\n legacy POST /api/timer/resume.\n- POST /api/v1/timer/start returns 409 with error_code\n timer_already_running when single-active mode is on and a timer\n is already running.\n- Deduplicate start_timer template handling in the service.\n\nTests: tests/test_single_active_timer_setting.py.\nDocs: REST_API (responses), GETTING_STARTED, REQUIREMENTS, Docker env\nnotes, TESTING_STRATEGY, env.example comment; CHANGELOG entry.
Introduce AUTH_METHOD values ldap and all, with LDAP_* environment settings, ldap3-based LDAPService (search, optional groupOfNames checks, user bind, DB sync), and users.auth_provider (local|oidc|ldap) via migration 153_add_user_auth_provider.
Login supports LDAP-only and combined all (local then LDAP where appropriate); OIDC callback sets auth_provider. Forgot/reset/change password flows skip LDAP-managed accounts. Admin System Settings gains a read-only LDAP summary and POST /admin/ldap/test. Production env validation requires core LDAP variables when LDAP is enabled; OIDC registration and docs recognize all.
Documentation: new docs/admin/configuration/LDAP_SETUP.md; updates to OIDC_SETUP, GETTING_STARTED, Docker guides, Render deploy notes, docs README, and CHANGELOG. Tests: tests/test_ldap_auth.py; test_oidc_logout allows auth_method all.
Introduce a web-first AI helper with admin-configurable providers (Ollama or hosted OpenAI-compatible), server-side context building, and confirmed write actions. Expose the feature via session /api/ai/* endpoints and scoped /api/v1/ai/* endpoints.
Harden security by requiring a strong SECRET_KEY for Docker Compose, adding optional settings encryption-at-rest (Fernet), and introducing TOTP-based 2FA plus password reset flows. Update admin UI, API docs, and install documentation.
Delete app/utils/posthog_features.py. It was unused by routes, and
is_posthog_enabled() always returned False, so flags never activated and
the API was misleading.
Document the real model: deployment behavior uses environment variables
and app/config.py; per-user UI preferences stay on the user record.
Refresh PostHog monitoring guides and README accordingly, update the
incomplete-implementations note, and soften posthog_segmentation wording
so it does not imply an in-app PostHog flag layer.
Describe how GET /api/openapi.json sets info.version via get_version_from_setup()
(setup.py at runtime, with TIMETRACKER_VERSION or APP_VERSION overrides and Flask
APP_VERSION fallback), and point contributors to the same rules in version
management and project structure docs.
Update the documentation audit entry for the former hardcoded OpenAPI version
gap, document tests/test_api_route_contract.py and the refined test_api_v1
isolation guidance in the testing strategy, add a quick-reference pytest
invocation for the contract suite, and note info.version in the API consistency
audit next to the OpenAPI references.
Add VersionService to fetch and cache the latest GitHub release, compare it to the installed semver (APP_VERSION when valid, else setup.py), and expose admin-only GET /api/version/check and POST /api/version/dismiss on the legacy /api blueprint (session or Bearer token).
Persist per-user dismissal in users.dismissed_release_version (Alembic 148) and show a non-blocking update card in base.html for administrators. Add packaging for semver parsing and tests for comparison, service, and routes.
Document configuration in docs/admin/deployment/VERSION_MANAGEMENT.md and endpoints in docs/api/REST_API.md and docs/API.md.
The will-navigate guard compared file URL origins to the literal string
file://, but the URL API reports an opaque origin for file pages, so
legitimate file navigations were blocked and the window could fail to
load reliably on Windows.
Import utils/helpers from the renderer entry so esbuild includes
window.Helpers in the bundle, restoring formatters and isValidUrl after
build:renderer.
Documentation: desktop README explains the renderer bundle workflow;
Windows desktop troubleshooting covers stuck loading; frontend quality
gates table notes the app.js entry and rebuild step.
Quotes (#583):
- Add requires_approval, approval_level, and can_be_sent; wire create form
- Migrations 145 (approval columns) and 146 (quote_items.position)
- Order Quote.items by position; set positions on create/edit/duplicate/API
- Fix view template approval branch (not_required); add web regression test
Invoices / PEPPOL:
- Use the same Factur-X embed and PDF/A-3 normalization for export and
email attachments; Associated File Data + text/xml metadata
- CII/UBL validators, pdfa3, zugferd, and invoice_pdf_postprocess helper
- Bundle compact sRGB ICC (app/resources/icc/); INVOICE_SRGB_ICC_PATH override
- Package data in setup.py; extend PEPPOL_EINVOICING.md and tests
Allow overriding nginx port mappings with environment variables so users behind a reverse proxy (Nginx Proxy Manager, Traefik, etc.) or with 80/443 already in use can deploy without editing docker-compose.yml.
- docker-compose.yml: use \:80 and \:443
- env.example: document HTTP_PORT and HTTPS_PORT with example
- DOCKER_COMPOSE_SETUP.md: add Docker/nginx ports to env reference
Closes#553
Switch embedded invoice PDFs to Factur-X CII payloads and tighten the PDF/A-3 and AS4 handling so exports better match the standards they advertise. Document the experimental native Peppol transport path and cover the new validation and embedding behavior with focused tests.
Implement native PEPPOL transport plumbing (identifier validation, SMP/SML discovery, and AS4 send path) and make ZUGFeRD/PDF export fail fast when embedding or PDF/A-3 normalization fails. Add settings, migrations, validators, tests, and docs so compliance issues are visible and verifiable.
- UBL: add unitCode C62 to InvoicedQuantity (required by EN 16931 / Peppol BR-CL-23)
- ZugFerd: attach XML as Associated File with relationship Alternative
- ZugFerd: inject ZUGFeRD XMP RDF for validators
- Docs: document AF/XMP, PDF/A-3 limitation, and validation (b2brouter, portinvoice)
- Tests: assert UBL contains InvoicedQuantity with unitCode in ZugFerd and Peppol tests
- Add run_seed() in app/utils/seed_dev_data.py: users, clients, projects,
tasks, time entries, expenses, comments, warehouses, stock items,
warehouse stock, stock movements, currencies, tax rules, invoices,
invoice items, and payments. Only runs when FLASK_ENV=development.
- Register 'flask seed' CLI command with options (users, clients,
projects-per-client, tasks-per-project, days-back).
- Add scripts/seed-dev-data.py and docker/seed-dev-data.sh for local
and Docker runs. Include seed scripts in image via Dockerfile chmod.
- Document in docs/development/SEED_DEV_DATA.md; update
DATABASE_RECOVERY.md, DOCKER_COMPOSE_SETUP.md, and development README.
Replace the single-page setup (telemetry + optional Google Calendar) with
a guided wizard that collects all base settings before completion.
Wizard steps:
1. Welcome - intro and Next
2. Region & time - timezone, date/time format, currency (Settings)
3. Company - name, address, email, optional phone/website (Settings)
4. System - allow self-registration, rounding minutes, single active
timer, idle timeout (Settings)
5. Integrations (optional) - Google Calendar OAuth; can skip
6. Privacy & finish - telemetry opt-in; Complete Setup submits form
Backend (app/routes/setup.py):
- GET: pass settings and timezones to template for prefilling
- POST: validate timezone, date_format, currency, rounding_minutes,
idle_timeout_minutes; persist all fields to Settings and
mark_setup_complete(telemetry_enabled)
- Default timezone/currency to UTC/EUR when missing (keeps tests passing)
Frontend:
- initial_setup.html: 6 wizard steps, progress bar (Step X of 6),
Back/Next and submit on last step
- setup-wizard.js: step navigation, progress update, optional
client-side validation for step 2 (timezone, currency required)
Docs updated: TELEMETRY_QUICK_START.md, GETTING_STARTED.md,
TELEMETRY_IMPLEMENTATION_SUMMARY.md.
- Add optional embedding of EN 16931 UBL XML in invoice PDFs (ZugFerd/Factur-X)
when 'Embed EN 16931 XML in invoice PDFs' is enabled in Admin > Peppol e-Invoicing.
Exported PDFs then contain ZUGFeRD-invoice.xml for hybrid human- and machine-readable
invoices; same UBL as Peppol, usable via Peppol or email.
- New setting invoices_zugferd_pdf (migration 128), pikepdf dependency, and
app.utils.zugferd helper (best-effort supplier/customer from Settings and client).
- Wire embed in export_invoice_pdf (and fallback path); admin checkbox and persistence.
- Docs: PEPPOL_EINVOICING.md retitled to 'Peppol and ZugFerd', new section for
ZugFerd embedding; README and CHANGELOG updated; migration 128 noted.
- Tests: test_zugferd.py (embed adds attachment with expected XML; invalid PDF
returns original bytes and error).
Make https://timetracker.drytrix.com/support.html visible so users can purchase a key to hide donate/support UI (one key per instance, €25 one-time).
- Add SUPPORT_PURCHASE_URL config and support_purchase_url in template context
- Donate page: 'Remove Donation Messages' section and CTA, link in Other Ways to Help
- Admin Settings: Support visibility copy and 'Get key at Support & Purchase' button
- User Settings: line and link for admins to purchase a key
- Support banner: 'Purchase key to hide' link
- Dashboard widget: 'Want to hide this widget? Purchase a key'
- README: Support section bullet and intro line for support/purchase key
- SUPPORT_VISIBILITY.md: 'How to get a code' subsection, issuing codes note
- docs/README.md: Support visibility in Configuration with purchase link
- messages.po: add new translatable strings
- Add Support visibility in Settings: users see a stable System ID and can
enter a code to permanently hide donate buttons, support banner, and
donate widgets.
- Verification supports two modes:
- Ed25519: server stores only public key; codes are signatures generated
offline with the private key (no secret on server).
- HMAC: server stores a secret; code = HMAC(secret, system_id).
- Add User.ui_show_donate and Settings.system_instance_id (migration 121).
- Add donate_hide_code utility (HMAC + Ed25519 verify) and config for
DONATE_HIDE_PUBLIC_KEY(_FILE) and DONATE_HIDE_UNLOCK_SECRET(_FILE).
- Wrap all donate UI in base, dashboard, about, help with conditional.
- Add admin doc SUPPORT_VISIBILITY.md; ignore docs/internal/ and
code-generation script in .gitignore.
- Add translations for new strings.
Co-authored-by: Cursor <cursoragent@cursor.com>
- Document that the default admin has no password; users set it on first
login (8+ characters) with AUTH_METHOD=local
- Add security note: self-register creates app users from entered
credentials only, not from DATABASE_URL; avoid using the DB username
(e.g. timetracker) as an app username
- Add "What is the default admin password?" to Common Questions
- Update GETTING_STARTED, DOCKER_COMPOSE_SETUP, DOCKER_STARTUP_TROUBLESHOOTING,
and env.example
- Config: clarify WTF_CSRF_TRUSTED_ORIGINS comment (include exact client URL)
- Mobile: README troubleshooting for DDNS/cert errors and subpath base URL
- Mobile: login screen helper text for exact URL and "Yes, trust" for certs
- Mobile: 404 diagnostics suggest using full base URL when app is at a subpath
- Docs: add NGINX_PUBLIC_DOMAIN.md (Docker vs host nginx, why /api/v1 404)
- Nginx: add example-public-domain.conf for exposing app at a public domain
- Add issuer fallback from OIDC_ISSUER when userinfo lacks iss (fixes Authelia)
- Fallback to unverified id_token decode for iss when ID token parsing failed
- Wrap authorize_access_token() in dedicated try/except; log token_exchange_failed
and suggest session cookie/proxy checks when state or PKCE validation fails
- Log reason=... before every redirect to login in callback for easier debugging
- Add 'Redirect loop / callback returns to login' troubleshooting to OIDC_SETUP.md
Fixes#486
Co-authored-by: Cursor <cursoragent@cursor.com>
- Add multiple DNS resolution strategies (socket, getaddrinfo, auto)
- Implement IP address caching with TTL for improved performance
- Add retry logic with exponential backoff for metadata fetching
- Support Docker internal service name resolution
- Add connection pooling and optimized HTTP session handling
- Improve error classification and diagnostics
- Add comprehensive OIDC configuration options in config.py
- Update OIDC initialization in app factory with lazy loading support
- Add background metadata refresh scheduling
- Update documentation with troubleshooting guide and setup instructions
Add Peppol BIS Billing 3.0 (UBL) invoice sending via a configurable access point, including admin-configurable settings, per-invoice send history, and documentation/README updates.
Also introduce stock lots/allocations (valuation layers) with supporting inventory route/report/UI updates and hardened startup migration handling.
Default admin backups to a writable, configurable folder (BACKUP_FOLDER/BACKUP_DIR, defaulting to /data/uploads/backups) to avoid permission denied errors in non-root containers.
Also update local-test compose and docs to reflect the backup location.
Addresses user deployment issues:
1. PostgreSQL database tables not being created automatically
2. Authentication issues when using multiple admin usernames
Documentation improvements:
- Added comprehensive troubleshooting sections for PostgreSQL database initialization
- Clarified that only the first username in ADMIN_USERNAMES is auto-created during initialization
- Documented that additional admin usernames must self-register or be created manually
- Added step-by-step solutions for both issues
Code improvements:
- Fixed whitespace handling in ADMIN_USERNAMES parsing (strip whitespace from all usernames)
- Fixed whitespace handling in all database initialization scripts to properly strip the first admin username
- Ensured consistent behavior across all initialization paths
Files updated:
- All Docker setup documentation files
- Configuration documentation
- README and env.example
- Database initialization scripts
- Config parsing logic
Complete reorganization of project documentation to improve discoverability,
navigation, and maintainability. All documentation has been restructured into
a clear, role-based hierarchy.
## Major Changes
### New Directory Structure
- Created `docs/api/` for API documentation
- Created `docs/admin/` with subdirectories:
- `admin/configuration/` - Configuration guides
- `admin/deployment/` - Deployment guides
- `admin/security/` - Security documentation
- `admin/monitoring/` - Monitoring and analytics
- Created `docs/development/` for developer documentation
- Created `docs/guides/` for user-facing guides
- Created `docs/reports/` for analysis reports and summaries
- Created `docs/changelog/` for detailed changelog entries (ready for future use)
### File Organization
#### Moved from Root Directory (40+ files)
- Implementation notes → `docs/implementation-notes/`
- Test reports → `docs/testing/`
- Analysis reports → `docs/reports/`
- User guides → `docs/guides/`
#### Reorganized within docs/
- API documentation → `docs/api/`
- Administrator documentation → `docs/admin/` (with subdirectories)
- Developer documentation → `docs/development/`
- Security documentation → `docs/admin/security/`
- Telemetry documentation → `docs/admin/monitoring/`
### Documentation Updates
#### docs/README.md
- Complete rewrite with improved navigation
- Added visual documentation map
- Organized by role (Users, Administrators, Developers)
- Better categorization and quick links
- Updated all internal links to new structure
#### README.md (root)
- Updated all documentation links to reflect new structure
- Fixed 8 broken links
#### app/templates/main/help.html
- Enhanced "Where can I get additional help?" section
- Added links to new documentation structure
- Added documentation index link
- Added admin documentation link for administrators
- Improved footer with organized documentation links
- Added "Complete Documentation" section with role-based links
### New Index Files
- Created README.md files for all new directories:
- `docs/api/README.md`
- `docs/guides/README.md`
- `docs/reports/README.md`
- `docs/development/README.md`
- `docs/admin/README.md`
### Cleanup
- Removed empty `docs/security/` directory (moved to `admin/security/`)
- Removed empty `docs/telemetry/` directory (moved to `admin/monitoring/`)
- Root directory now only contains: README.md, CHANGELOG.md, LICENSE
## Results
**Before:**
- 45+ markdown files cluttering root directory
- Documentation scattered across root and docs/
- Difficult to find relevant documentation
- No clear organization structure
**After:**
- 3 files in root directory (README, CHANGELOG, LICENSE)
- Clear directory structure organized by purpose and audience
- Easy navigation with role-based organization
- All documentation properly categorized
- Improved discoverability
## Benefits
1. Better Organization - Documentation grouped by purpose and audience
2. Easier Navigation - Role-based sections (Users, Admins, Developers)
3. Improved Discoverability - Clear structure with README files in each directory
4. Cleaner Root - Only essential files at project root
5. Maintainability - Easier to add and organize new documentation
## Files Changed
- 40+ files moved from root to appropriate docs/ subdirectories
- 15+ files reorganized within docs/
- 3 major documentation files updated (docs/README.md, README.md, help.html)
- 5 new README index files created
- 2 empty directories removed
All internal links have been updated to reflect the new structure.