Skip to content

feat: add generic post-processing command for generated files - #1693

Open
manuc66 wants to merge 2 commits into
masterfrom
feature/generic-pdf-post-processing
Open

feat: add generic post-processing command for generated files#1693
manuc66 wants to merge 2 commits into
masterfrom
feature/generic-pdf-post-processing

Conversation

@manuc66

@manuc66 manuc66 commented Aug 31, 2026

Copy link
Copy Markdown
Owner

Implements the generic post-processing hook discussed in #… (picks up the PDF/A/archival idea without bundling or maintaining Ghostscript or any other tool in the project).

What

New option --post-command \ (CLI on \listen, \single-scan, \�df-autoscan) or \post_command\ in the config file. It runs an external command over every generated scan file before it is uploaded or cleaned up:

  • PDFs from the --pdf\ output mode and the Paperless --paperless-always-send-as-pdf-file\ / --paperless-group-multi-page-scan-into-a-pdf\ flows;
  • delivered images (pages kept on disk or uploaded as images), so the command also covers Jpeg/Bmp outputs.

Typical uses (documented in the README): PDF/A conversion with Ghostscript, digital signature, metadata injection for PDFs; recompression/resize, watermark, EXIF metadata for images.

Template contract

  • {input}\ = absolute path of the generated file.
  • {output}\ = optional temp path; when present, the resulting file atomically replaces the original on success (needed by tools like Ghostscript that cannot overwrite their own input).
  • Without {output}, the command is expected to modify the file in place.

Failure policy: a non-zero exit or missing {output}\ file keeps the original and logs an error — the scan flow never blocks or fails because of the hook. The hook is synchronous within the existing per-job processing pipeline (the app already awaits PDF build + uploads there).

Files

  • \src/filePostProcessing.ts\ — new generic runner (\child_process\ exec, atomic temp+rename).
  • Wired in \pdfProcessing.ts\ (\createPdfFrom), \postProcessing.ts\ image flow, \paperless.ts.
  • Config/CLI plumbing following existing conventions (\program.ts, \FileConfig.ts, \scanConfigs.ts).
  • Tests: CLI parsing, config schema, hook runner (stub
    ode -e\ commands), image + PDF flows in \postProcessing.test.ts.
  • \README.md\ help blocks regenerated; \CHANGELOG.md\ [Unreleased]\ entry; \scripts/live-test.sh\ smoke test for \single-scan --pdf --post-command.

Notes

  • The option is opt-in, disabled by default.
  • The template is executed by the local shell — documented as a security consideration in the README.
  • \post-processing queue\ design (moving post-processing out of the scan-critical path for \listen) deliberately left out of this change: it touches the listen state machine, file lifecycle and error reporting, and deserves its own review.

Runs an external command over every generated scan file (PDFs and
delivered images) before it is uploaded or cleaned up. The template
supports {input} and an optional {output} that atomically replaces
the file on success; failures keep the original file and are logged,
so the hook never blocks the scan flow.
Comment thread src/filePostProcessing.ts
function runShellCommand(command: string): Promise<number> {
return new Promise((resolve) => {
exec(
command,
Resolve the CHANGELOG conflict by combining the [Unreleased] sections
(post-processing command => Added, pattern validation => Changed,
Windows test fixes => Fixed); README help blocks and program.ts merged
cleanly and the blocks were re-verified against the merged program.
@manuc66

manuc66 commented Sep 5, 2026

Copy link
Copy Markdown
Owner Author

Integration note: event ordering with the webhook (PR #1706/#1707)

The webhook event advertises files[]/pages[] (name, size, sha256, dimensions, locations) as a snapshot. Because --post-command can change the output (PDF/A, recompression, split/merge, sidecar files), the webhook must describe the files after the hook:

  • Enforce: capture → post-command → upload → webhook.
  • files[]/pages[] should be built from the post-processed files (a PDF/A is one file instead of N JPG; sidecars uploaded must appear in files[]).
  • If sidecars are intentionally not uploaded/advertised, document it so consumers don't expect them.

The webhook schema itself is generic (one descriptor per file) and does not need to change; only the source of the descriptors moves later in the pipeline.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants