Commit Graph

139 Commits

Author SHA1 Message Date
copilot-swe-agent[bot] 575b4e088e fix(views): resolve mypy TemplateResponse typing and owner fallback
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-03-06 10:47:46 +00:00
copilot-swe-agent[bot] 5722252dcb feat(multi-user): add unclaimed doc visibility, claim/assign-owner endpoints, default_owner_id
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-03-05 21:22:51 +00:00
copilot-swe-agent[bot] 71f437e43a feat(multi-user): add multi-user feature flag, owner_id model field, and user-scoped queries
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-03-05 11:26:24 +00:00
github-actions[bot] fea8f5c0de style: apply ruff auto-fix
- Auto-formatted code with ruff format
- Applied ruff linting fixes with --fix

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-02 15:26:48 +00:00
Christian Krakau-Louis 8fee5c8d0b Merge branch 'main' into copilot/add-pdfa-export-option 2026-03-02 16:26:31 +01:00
copilot-swe-agent[bot] 144a90fa73 fix(pdfa): address code review - validate pdfa_format, add S3 comment, add format test
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-03-02 14:01:26 +00:00
copilot-swe-agent[bot] a03b3af933 feat(pdfa): add FreeTSA timestamping, per-provider folder overrides, individual upload toggles
- Add RFC 3161 timestamping via FreeTSA (PDFA_TIMESTAMP_ENABLED, PDFA_TIMESTAMP_URL)
- Replace PDFA_UPLOAD_TO_PROVIDERS with individual PDFA_UPLOAD_ORIGINAL and PDFA_UPLOAD_PROCESSED
- Add PDFA_UPLOAD_FOLDER setting for per-provider subfolder configuration
- Add GOOGLE_DRIVE_PDFA_FOLDER_ID for Google Drive-specific folder override
- Add folder_override parameter to all 8 folder-using upload tasks
- Add folder_overrides dict parameter to send_to_all_destinations
- Add _compute_pdfa_folder_overrides() and _timestamp_file() helpers
- Expand tests to 26 (timestamping, folder overrides, individual toggles)
- Update docs/ConfigurationGuide.md and .env.demo

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-03-02 13:55:34 +00:00
copilot-swe-agent[bot] 55543be3b0 fix(similarity): address code review - column-only queries, configurable batch size, WCAG touch targets
- Use column-only query in embeddings overview to reduce memory for 100K+ files
- Add embedding_backfill_batch_size config setting (default 50)
- Fix WCAG touch target on backfill button (min-height/min-width 44px)
- Add inline comment explaining 3 chars/token truncation estimate
- Import settings in compute_embedding task for configurable batch size

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-03-02 13:39:10 +00:00
copilot-swe-agent[bot] eea99eb01d feat(pdfa): add PDF/A archival conversion using ocrmypdf
- Add ENABLE_PDFA_CONVERSION, PDFA_FORMAT, PDFA_UPLOAD_TO_PROVIDERS config settings
- Add original_pdfa_path and processed_pdfa_path columns to FileRecord model
- Create Alembic migration 011_add_pdfa_paths
- Create app/tasks/convert_to_pdfa.py Celery task using ocrmypdf + Ghostscript
- Integrate PDF/A conversion into finalize_document_storage pipeline
- Add comprehensive unit tests (15 tests)
- Update .env.demo and docs/ConfigurationGuide.md

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-03-02 13:35:13 +00:00
copilot-swe-agent[bot] c724b8d83a feat(similarity): add similarity pairs dashboard, step tracking, and fix tests for pre-computed embeddings
- Add GET /api/similarity/pairs endpoint for corpus-wide pair discovery
- Add /similarity view route and similarity_dashboard.html template
- Add Similarity link to desktop and mobile nav menus
- Register compute_embedding as a tracked FileProcessingStep
- Update compute_embedding task with update_step_status calls
- Add compute_embedding to flow visualization in _compute_processing_flow
- Add backfill_missing_embeddings periodic beat task (every 5 min)
- Return clear message when embedding not yet computed in similar docs API
- Fix all tests to use pre-computed embeddings (no lazy API calls)
- Add tests for similarity pairs, backfill task, and embedding-not-computed

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-03-02 13:12:59 +00:00
copilot-swe-agent[bot] 8d7c8e7c4e feat(similarity): add embedding pipeline, debug endpoints, backfill task, and scalable similarity search
- Add embedding_model config setting (replaces hardcoded text-embedding-3-small)
- Add compute_document_embedding Celery task for ingestion-time embedding
- Chain embedding task into finalize_document_storage pipeline
- Add backfill_missing_embeddings periodic task (every 5 min) for legacy files
- Add debug API endpoints: embedding-status, compute-embedding, diagnostic/embeddings, diagnostic/compute-all-embeddings
- Refactor find_similar_documents to only use pre-computed embeddings (no lazy API calls)
- Use yield_per(500) and column-only queries for 100K+ scale
- Add embedding status indicator and recompute button in file detail UI

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-03-02 13:01:57 +00:00
copilot-swe-agent[bot] e60914127c feat(webhooks): add webhook support for external integrations
Add WebhookConfig model, CRUD API endpoints, HMAC-SHA256 signed delivery,
and Celery-based async dispatch with retry/backoff for document events
(document.uploaded, document.processed, document.failed).

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-03-01 20:42:57 +00:00
copilot-swe-agent[bot] 5ff7b72a80 feat(tasks): add retry logic with exponential backoff and jitter
- Rewrite app/tasks/retry_config.py with compute_countdown() function
  implementing per-retry delays with ±20% jitter (default: 60s, 300s, 900s)
- Add BaseTaskWithRetry.retry() override to inject proper countdown
- Add OcrTaskWithRetry (120s, 600s, 1800s) for OCR/AI tasks
- Add UploadTaskWithRetry for cloud-storage upload tasks
- Add config settings: TASK_RETRY_MAX_RETRIES, TASK_RETRY_DELAYS, TASK_RETRY_JITTER
- Update process_with_ocr and process_with_azure tasks to use OcrTaskWithRetry
- Update all 11 upload tasks to use UploadTaskWithRetry
- Add 38 unit tests in tests/test_retry_config.py
- Update docs/ConfigurationGuide.md and .env.demo

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-03-01 17:37:41 +00:00
copilot-swe-agent[bot] f8c5dd539d feat(imap): add IMAP_READONLY_MODE feature flag to safeguard shared mailboxes
When enabled, IMAP processing will fetch and process attachments but
will NOT modify the mailbox state (no starring, labeling, deleting,
or flag changes). This allows preprod instances to safely share a
Gmail inbox with production without interfering with production
email processing.

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-03-01 14:28:51 +00:00
copilot-swe-agent[bot] 83c3405c98 feat: persist ocr_quality_score and use it for numeric filtering
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-03-01 13:46:43 +00:00
copilot-swe-agent[bot] 2c55f076be fix(tasks): resolve files stuck in Pending status despite completed processing
The status calculation required ALL steps to be explicitly marked as
success/skipped before a file could be "completed". This failed for
dynamic pipelines where:

1. check_for_duplicates was logged before the file record existed (no
   file_id), so its FileProcessingStep was never updated from "pending"
2. extract_text was not marked as "skipped" for non-PDF files that go
   through PDF conversion first

Fix:
- Move check_for_duplicates success log to after initialize_file_steps()
  with the correct file_id so the step actually gets updated
- Mark extract_text as "skipped" for non-PDF files
- Add terminal-step fallback: if send_to_all_destinations is "success",
  the file is "completed" even if intermediate steps remain "pending"
  (handles any other dynamic pipeline edge cases)

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-27 16:38:10 +00:00
copilot-swe-agent[bot] e6dd39c27d fix(status): prevent false Completed status when mandatory pipeline steps have not run
Add a terminal-step guard (send_to_all_destinations) to all status
calculation paths so that files are only marked Completed once the
entire processing pipeline has been recorded.

- get_file_overall_status: require TERMINAL_STEP to be present
- get_files_processing_status: same guard for bulk status
- get_step_summary: count missing terminal step as queued so
  total_main_steps > main_completed when pipeline is incomplete
- apply_status_filter: SQL sub-query requires terminal step for
  completed filter
- process_document: call initialize_file_steps after creating a new
  file record so all mandatory steps are pre-created as pending

Define TERMINAL_STEP constant in step_manager.py and reference it in
file_status.py and file_queries.py to avoid magic strings.

Tests updated: add send_to_all_destinations to completed-file
fixtures; add test verifying initialize_file_steps is called for
new files.

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-27 00:51:14 +00:00
copilot-swe-agent[bot] a05690bd5f feat(upload): adaptive 429 backoff, full Gotenberg file types, directory traversal
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-26 23:24:26 +00:00
copilot-swe-agent[bot] a08bfb9f1a feat(helm): add Helm chart for Kubernetes deployment and update DeploymentGuide
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-25 13:31:54 +00:00
copilot-swe-agent[bot] ff96340154 fix(config): default meilisearch_url to http://meilisearch:7700 for Docker/K8s service discovery
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-25 13:27:09 +00:00
copilot-swe-agent[bot] 89d5df71c8 feat(ocr): fine-tune OCR quality criteria with stricter threshold and head-to-head comparison
- Raise quality acceptance threshold from 65→85 (configurable via TEXT_QUALITY_THRESHOLD)
- Reject text with significant issues (excessive_typos, garbage_characters,
  incoherent_text, fragmented_sentences) even when score is above threshold
  (configurable via TEXT_QUALITY_SIGNIFICANT_ISSUES)
- Add compare_text_quality() for AI-powered head-to-head comparison of
  original embedded text vs fresh OCR output
- Update process_document to pass original text to OCR task for comparison
- Update process_with_ocr to run comparison and keep the higher-quality text
- Add new settings to settings_service.py metadata
- Update docs/ConfigurationGuide.md with new settings
- Add comprehensive tests for new threshold and comparison logic

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-25 13:03:21 +00:00
copilot-swe-agent[bot] 37a3f7aae7 fix(ocr): sync workflow steps with process_with_ocr replacing legacy azure step
- Update _compute_processing_flow to recognize process_with_ocr as the OCR
  stage and remap legacy process_with_azure_document_intelligence log entries
  for backward compatibility
- Normalize legacy OCR step name in _compute_step_summary log fallback
- Add process_with_ocr to REAL_MAIN_STEPS/REAL_STEPS in step_manager,
  file_status, and file_queries (keeping legacy name for old DB entries)
- Update retry logic in api/files.py to retry failed OCR via process_with_ocr
  (handles both step names as aliases)
- Fix process_document.py to log process_with_ocr as skipped (not azure step)
  for the local text extraction path

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-24 22:22:06 +00:00
copilot-swe-agent[bot] b03bfb5e02 feat(ocr): add AI-based embedded text quality check with automatic OCR fallback
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-24 18:41:27 +00:00
copilot-swe-agent[bot] fec032643b feat(ocr): embed searchable text layer for providers without native PDF output
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-24 13:19:52 +00:00
github-actions[bot] 5ee3d8cd84 style: apply ruff auto-fix
- Auto-formatted code with ruff format
- Applied ruff linting fixes with --fix

Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-02-23 21:24:11 +00:00
copilot-swe-agent[bot] 1f843fe460 feat(ocr): add self-hosted OCR engine support (Tesseract, EasyOCR) with multi-provider cross-checking
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-23 20:59:43 +00:00
copilot-swe-agent[bot] 044da0ff47 feat: update all OpenAI/ChatGPT refs + settings dropdown for fixed-value fields
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-23 20:06:57 +00:00
copilot-swe-agent[bot] d4c7fb26ac feat: add AI provider abstraction layer with OpenAI, Azure, Anthropic, Gemini, Ollama, OpenRouter, LiteLLM support
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-23 19:26:45 +00:00
copilot-swe-agent[bot] f2eff3e2fb fix: return boolean values from _should_upload functions and fix test expectations
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-16 16:59:17 +00:00
copilot-swe-agent[bot] e6a4995a5c style: run ruff format on 6 files to fix formatting issues
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-13 22:39:34 +00:00
copilot-swe-agent[bot] bcf5f652fc style: fix linting issues in retry and metadata extraction code
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-13 21:07:23 +00:00
copilot-swe-agent[bot] 42d35c7c6f fix: handle file in processed directory when retrying embed_metadata_into_pdf
- Update _retry_pipeline_step to check for file in tmp, processed, and fallback locations
- Pass full path to extract_metadata_with_gpt instead of just basename
- Update extract_metadata_with_gpt to handle both basename and full path parameters
- Add test case for retrying when file is in processed directory

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-13 21:06:20 +00:00
copilot-swe-agent[bot] defcf746ea fix: serialize dict to JSON in rotate_pdf_pages log_task_progress calls
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-13 20:54:34 +00:00
copilot-swe-agent[bot] aa077f2b6c fix: track TLS usage with variable instead of isinstance check
Replace isinstance(ftp, ftplib.FTP_TLS) with a boolean flag to avoid issues when FTP_TLS is mocked in tests. Also fix Google Drive test parameter passing.

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-13 16:20:32 +00:00
copilot-swe-agent[bot] b42c6f5f64 fix: resolve all Ruff linting errors
- Fix PLW2901: Use different variable name for stripped lines in loop
- Fix E721: Use 'is' instead of '==' for type comparisons
- Add noqa comments for intentional security warnings (S321, S507, S110, S603)

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-13 16:12:39 +00:00
copilot-swe-agent[bot] 4897cb6655 fix: apply Phase 1-2 correctness and constant extraction from PR #273
- Replace datetime.utcnow() with datetime.now(timezone.utc) in 4 files
- Extract duplicate literals to constants in 5 files
  - models.py: "files.id" → _FILES_ID_FK
  - upload_to_email.py: "logo.png" → _LOGO_FILENAME
  - general.py: "%B %d, %Y" → _DATE_DISPLAY_FORMAT
  - files.py: "File not found" → _FILE_NOT_FOUND
  - upload_to_google_drive.py: Google token URL → _GOOGLE_TOKEN_URL

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-13 11:25:30 +00:00
copilot-swe-agent[bot] b03ebab747 chore: apply ruff formatting and fix whitespace issues
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-13 09:12:11 +00:00
copilot-swe-agent[bot] 43bc58770d refactor: consolidate linting tools into Ruff
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-13 09:10:52 +00:00
copilot-swe-agent[bot] ff9a3ff49f style: fix code formatting with black, isort, and flake8
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-12 03:21:41 +00:00
copilot-swe-agent[bot] cc98039246 fix(deps): upgrade PyPDF2 to pypdf >= 3.9.0 to fix CVE-2023-36464
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-12 02:52:17 +00:00
Christian Krakau-Louis 9a2c2d20b1 feat(duplication): implement duplicate file handling and detection across processing steps 2026-02-12 02:38:00 +01:00
Christian Krakau-Louis 70757e5644 feat(step-timeout): add automatic recovery for stalled processing steps
- Implement step timeout detection to prevent files from getting stuck in 'pending' state
- Add monitor_stalled_steps periodic task running every minute (Celery Beat)
- Automatically mark in-progress steps as failed if they exceed timeout (default: 10 minutes)
- Add step_timeout configuration setting (default: 600 seconds)
- Recover stalled steps with error message indicating when timeout was triggered
- Fix duplicate check to exclude self-comparison (file not duplicate of itself)

When processing crashes or hangs:
1. Worker detects stalled steps (in_progress for >10 minutes)
2. Marks them as failed with timeout error message
3. Updates UI to show failure status
4. Allows file to be retried or handled by user

This prevents files from being indefinitely stuck in processing state and provides
visibility into what went wrong.
2026-02-12 02:38:00 +01:00
Christian Krakau-Louis 7bbd095152 fix(deduplication): handle UNIQUE constraint violation for duplicate files
- Remove duplicate record creation to avoid UNIQUE constraint on filehash
- When duplicate detected, return original file_id instead of creating new record
- Avoids sqlite3.IntegrityError: UNIQUE constraint failed
- Simpler approach: duplicates not tracked as separate records, just rejected
- Revert filehash column back to NOT NULL (required for original files)
- Fixes error: (sqlite3.IntegrityError) UNIQUE constraint failed: files.filehash
2026-02-12 02:38:00 +01:00
Christian Krakau-Louis 4c11cfd6dd feat(deduplication): implement configurable duplicate file detection
- Add enable_deduplication and show_deduplication_step config options
- Rename hash_file step to check_for_duplicates
- Make deduplication step conditional based on configuration
- Add is_duplicate and duplicate_of_id fields to FileRecord model
- Create database migration for new deduplication fields
- Update process_document task to log deduplication results
- Update step visualization to show/hide step based on config
- Update status calculations to include deduplication step conditionally
- Default: deduplication enabled, step displayed
- Can be configured to hide from UI while still processing
2026-02-12 02:38:00 +01:00
Christian Krakau-Louis 83c65f3c40 feat: enhance processing status tracking and UI display for file details 2026-02-12 01:07:22 +01:00
copilot-swe-agent[bot] 952e27b339 test: add tests for storage reorganization features
- Add tests for get_unique_filepath_with_counter collision handling
- Add tests for immutable original storage
- Add tests for metadata augmentation with file paths
- Add tests for force_cloud_ocr parameter
- Verify existing process_document tests still pass

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-11 20:13:17 +00:00
copilot-swe-agent[bot] 73a0222e56 feat(storage): implement immutable original/processed file storage and collision handling
- Add original_file_path and processed_file_path columns to FileRecord model
- Create database migration for new fields
- Implement get_unique_filepath_with_counter() with -0001 suffix format
- Update process_document to save immutable copy to /workdir/original
- Add force_cloud_ocr parameter to process_document for forced OCR
- Update embed_metadata to use new collision handling
- Update metadata JSON to include file path references
- Add /files/{file_id}/reprocess-with-cloud-ocr API endpoint
- Update processed_file_path in database during embedding

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-11 20:10:19 +00:00
copilot-swe-agent[bot] 2b2394f858 fix: pass task_id to check_page_rotation helper for consistent log prefixing
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-11 10:15:08 +00:00
copilot-swe-agent[bot] 6f286e37b3 feat(tasks): add detailed logging to upload_with_rclone task functions
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-11 10:06:51 +00:00
copilot-swe-agent[bot] 14eacc7c23 feat(tasks): add detailed logging to rotate_pdf_pages task
Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
2026-02-11 10:02:25 +00:00