Skip to content

PDFCLOUD-6572 Add ZUGFeRD PDF validation - #58

Open
datalogics-tsmith wants to merge 13 commits into
mainfrom
pdfcloud-6572-add-zugferd-pdf-validation
Open

datalogics-tsmith wants to merge 13 commits into
mainfrom
pdfcloud-6572-add-zugferd-pdf-validation

Conversation

@datalogics-tsmith

Copy link
Copy Markdown
Contributor

PDFCLOUD-6572

Dependency: This PR is stacked on #57 and must not be merged until #57 has merged. The branch includes the current ZUGFeRD creation work from #57 and is hosted in the main pdfrest/pdfrest-python repository so GitHub Actions can run correctly.

Why this change

The Python SDK does not expose pdfRest's ZUGFeRD validation operation, so callers cannot use the typed clients to verify an existing ZUGFeRD or Factur-X PDF. This adds a supported way to check package structure, embedded invoice XML, visible-content consistency, and PDF/A-3 conformance before accepting or distributing an electronic invoice.

What changed (high level)

New synchronous and asynchronous validate_zugferd_pdf helpers accept an uploaded PDF resource and return a typed validation response. A dedicated Pydantic payload model owns resource validation and wire serialization, while public response models preserve status, content-match results, findings, and free-tier notices with forward-compatible handling of additional response fields.

The change also adds focused unit coverage, live endpoint coverage, creator-to-validator round-trip assertions, a runnable example, and API documentation.

Behavior changes

Callers can submit one uploaded PDF and receive its overall VALID or INVALID status, independent PDF/A result, content-match status, input resource metadata, and detailed findings. Non-PDF inputs and multiple resources fail locally before transport. Free-tier responses with redacted comparison details remain parseable through the typed models.

ZUGFeRD PDFs produced by create_zugferd_pdf are now exercised through this validation route across all live render-option cases and the mismatched-PDF regeneration workflow. The API is additive and does not change existing helper behavior.

Validation

The complete non-live suite passed with 3,257 tests and 10 expected skips. The Python 3.10-3.14 Nox matrix passed with the same results on each interpreter. The focused live creation and validation suites passed all 16 sync and async cases, including creator-to-validator round trips, invalid resource IDs, and server-side invalid-option rejection.

Ruff formatting and linting passed, basedpyright reported zero errors, the strict MkDocs build passed, uv build passed, and the runnable validation example returned VALID with PDF/A-3 conformance against the local service.

Risks and follow-ups

Merge #57 first, then refresh this branch against main before merging so the final diff contains only the validation work. Demo-tier deployments can return DEMO_REDACTED for content comparison details; callers still receive a parseable response and the overall validation status. CI on the main repository provides the final clean-environment verification.

- Add typed rendering options for invoice appearance and localization.
- Validate uploaded resources, color channels, fonts, and regeneration.
- Serialize the public input shape into the pdfRest wire contract.

Assisted-by: Codex
- Add synchronous and asynchronous helpers for uploaded invoice XML.
- Support optional PDFs, logos, rendering controls, and request options.
- Cover serialization, validation, response mapping, and both transports.

Assisted-by: Codex
- Exercise every closed rendering option through both client transports.
- Verify regenerated PDFs, response metadata, and server-side rejection.
- Add a deterministic minimum-profile invoice fixture.

Assisted-by: Codex
- Add a standalone typed example with a deterministic invoice fixture.
- Verify the generated PDF and print useful response metadata.
- Link the helper from the API guide and example inventories.

Assisted-by: Codex
- Compose page ranges from typed ascending selections and reject invalid
  combinations before transport.
- Add deterministic sync and async annotation assertions with a printable
  PDF fixture.

Assisted-by: Codex
- Validate a single uploaded PDF resource before request serialization.
- Model validation findings and response status fields returned by pdfRest.
- Export the public response models for typed client consumers.

Assisted-by: Codex
- Send uploaded PDF resource IDs to the validation endpoint.
- Return typed results from synchronous and asynchronous clients.
- Preserve request customization and timeout support.

Assisted-by: Codex
- Verify payload serialization and local resource validation.
- Exercise response literals, aliases, findings, and demo redactions.
- Assert sync and async request customization and transport behavior.

Assisted-by: Codex
- Exercise valid and invalid validation requests through both clients.
- Confirm created and regenerated invoices pass validation and PDF/A checks.
- Accept confirmed and demo-redacted content comparison results.

Assisted-by: Codex
- Create a deterministic invoice before validating its conformance.
- Display typed status, PDF/A, content-match, and finding details.
- Add the workflow to the runnable example inventory.

Assisted-by: Codex
- Link the validation helper from the electronic invoice API guide.
- Describe package, content, and PDF/A conformance validation.

Assisted-by: Codex
@netlify

netlify Bot commented Oct 22, 2026 •

Copy link
Copy Markdown

✅ Deploy Preview for pdfrest-python ready!

Name Link
🔨 Latest commit 8b5cda0
🔍 Latest deploy log https://app.netlify.com/projects/pdfrest-python/deploys/6ae8f96f8d600d3d77bfa13e
😎 Deploy Preview https://deploy-preview-58--pdfrest-python.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@datalogics-kam datalogics-kam left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed only PR #58's incremental changes over PR #57 (7d951b6 to 02cb915), excluding the inherited creation implementation.

Requesting changes for the two inline test-coverage findings: add a real nonconforming-document validation case to the live suite, and make mocked response scenarios and assertions match across the synchronous and asynchronous clients. No runtime or CI regression was found.

Validation passed: 26 focused unit tests, 16 focused live tests, the Python 3.10–3.14 non-live Nox matrix (3,257 passed and 10 expected skips per interpreter), all class-coverage gates, Ruff formatting/lint, and basedpyright. Exploratory validation of the existing report.pdf fixture returned INVALID with pdfa=false through both clients; please preserve that behavior in regression tests.

Comment thread tests/test_validate_zugferd_pdf.py Resolved

@datalogics-kam datalogics-kam left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Follow-up to the existing review, scoped to the validation changes over PR #57 at the unchanged head 02cb915.

The existing findings remain recorded there. This review adds only the uncovered empty-resource-list boundary described inline; please add that regression coverage before merging.

No source files changed and no new runtime defect was found. Tests were not rerun for this posting step because the head is unchanged from the completed audit.

Comment thread tests/test_validate_zugferd_pdf.py Resolved
- Verify INVALID report.pdf responses live through both clients.
- Match valid and demo-redacted response assertions across transports.
- Cover empty resource-list rejection before request execution.

Assisted-by: Codex

This branch was successfully deployed

1 active deployment
ci-live — 8b5cda0d Deployed Nov 2, 2026 by datalogics-tsmith via Examples (Python 3.11) #602
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