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>
This commit is contained in:
copilot-swe-agent[bot]
2026-03-02 13:35:13 +00:00
parent 34b9d529e7
commit eea99eb01d
9 changed files with 755 additions and 1 deletions
+27
View File
@@ -222,6 +222,33 @@ class Settings(BaseSettings):
# Feature flags
allow_file_delete: bool = True # Default to allowing file deletion from database
# PDF/A archival conversion settings
enable_pdfa_conversion: bool = Field(
default=False,
description=(
"Enable PDF/A archival variant generation. When enabled, PDF/A copies of both the "
"original ingested file and the processed file are created and saved alongside the "
"standard copies. Uses ocrmypdf with Ghostscript for the conversion. "
"This may double or triple storage but provides better legal coverage. Default: False."
),
)
pdfa_format: str = Field(
default="2",
description=(
"PDF/A format variant to produce. Passed to ocrmypdf --output-type pdfa-N. "
"Valid values: '1' (PDF/A-1b), '2' (PDF/A-2b), '3' (PDF/A-3b). Default: '2'."
),
)
pdfa_upload_to_providers: bool = Field(
default=False,
description=(
"When enabled and PDF/A conversion is active, also upload the PDF/A variants "
"to all configured storage providers in addition to the standard processed file. "
"PDF/A files are uploaded with a '-PDFA' suffix in their filename. Default: False."
),
)
imap_readonly_mode: bool = Field(
default=False,
description=(