Skip to content

PDFCLOUD-5556 Add digital signature support#26

Merged
datalogics-cgreen merged 23 commits intopdfrest:mainfrom
datalogics-kam:kam-pdfcloud-5464-sign
Feb 19, 2026
Merged

PDFCLOUD-5556 Add digital signature support#26
datalogics-cgreen merged 23 commits intopdfrest:mainfrom
datalogics-kam:kam-pdfcloud-5464-sign

Conversation

@datalogics-kam
Copy link
Copy Markdown
Contributor

@datalogics-kam datalogics-kam commented Feb 16, 2026

Replaces #21
PDFCLOUD-5556

Overview

This PR introduces first-class PDF digital signing support in the SDK, with parity across both sync and async clients. It adds a clear, typed interface for signature setup and credential input so callers can sign documents with either PFX credentials or certificate/private-key pairs while keeping request construction simple and consistent.

Motivation

Signing workflows are a core document-finalization step, but they’re easy to misconfigure when payload shape, credential formats, and signature-field behavior are not explicit. The goal here is to make signing reliable by default: guide users into valid inputs, fail fast with actionable validation errors, and still preserve low-level request customization when advanced control is needed.

What This Delivers

  • End-to-end sign_pdf support for both client variants against the /signed-pdf endpoint.
  • A more explicit signature model that distinguishes creating a new signature field from signing an existing one, including stricter rules where location is required.
  • Simplified credential handling that accepts ergonomic caller input while normalizing to the wire format expected by pdfRest.
  • Improved compatibility for real-world certificate uploads (including common DER MIME-type variations) and cleaner live-test handling of passphrase content.
  • Stronger confidence through broad unit and live coverage of success paths, customization plumbing, and invalid-input behavior.

Outcome

The SDK now offers a production-ready signing surface that is easier to use correctly, harder to misuse, and better aligned with live API behavior. Developers can adopt document signing with clearer contracts, better error feedback, and verified sync/async consistency.

@datalogics-kam datalogics-kam changed the title PDFCLOUD-5464 Sign PDF PDFCLOUD-5556 Add digital signature support Feb 17, 2026
@datalogics-kam datalogics-kam marked this pull request as ready for review February 17, 2026 16:56
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 642662046b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/pdfrest/models/_internal.py
Comment thread src/pdfrest/models/_internal.py
@netlify
Copy link
Copy Markdown

netlify Bot commented Feb 17, 2026

Deploy Preview for pdfrest-python ready!

Name Link
🔨 Latest commit 6d004b8
🔍 Latest deploy log https://app.netlify.com/projects/pdfrest-python/deploys/6997430c8194970008646853
😎 Deploy Preview https://deploy-preview-26--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.

Copy link
Copy Markdown
Contributor

@datalogics-cgreen datalogics-cgreen left a comment

Choose a reason for hiding this comment

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

PR Review Skill found these:

  • Medium: sign_pdf can raise raw TypeError instead of validation errors for bad credentials shape.
    • Evidence: _internal.py (line 1606) and _internal.py (line 1611) raise TypeError in _normalize_credentials; repro returned TypeError: credentials must be a mapping... from client.sign_pdf(...).
    • Impact: inconsistent error surface for caller input validation.
  • Medium: new sign endpoint tests do not meet full transport/literal/boundary coverage policy.
    • Evidence: only sync local-validation tests exist (test_sign_pdf.py (line 193), test_sign_pdf.py (line 215)), while async only covers customization (test_sign_pdf.py (line 307)).
    • Evidence: no parametrized literal matrix in new unit/live modules (NO_PARAMETRIZE_MATCHES).
    • Evidence: live invalid path only checks malformed JSON (test_live_sign_pdf.py (line 220), test_live_sign_pdf.py (line 234)), not invalid literal/boundary payloads.
    • Evidence: boundary coverage for logo_opacity is missing (test_live_sign_pdf.py (line 184) is the only occurrence).

Copy link
Copy Markdown
Contributor

@datalogics-cgreen datalogics-cgreen left a comment

Choose a reason for hiding this comment

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

Audit returned one finding above Low priority.

Comment thread tests/live/test_live_sign_pdf.py
datalogics-cgreen and others added 18 commits February 19, 2026 10:55
Assisted-by: Codex
- Refactored the credentials logic in `client.py` to remove redundant
  validation and mapping code.
- Added a `_normalize_credentials` model validator in `_internal.py` to
  handle credential normalization and enforce valid inputs.
- Updated test cases in `test_sign_pdf.py` to align with the new
  credentials structure, consolidating `pfx` and `certificate` data
  under a unified `credentials` field.

Assisted-by: Codex
- Replaced manual JSON construction with the built-in `model_dump_json`
  method, streamlining and optimizing the serialization process.

Assisted-by: Codex
- Updated `_PdfSignatureConfigurationModel` to enforce location
  requirements for `type="new"` via a model validator.
- Extended `type` field to include `"existing"` in both the model and
  the public `PdfSignatureConfiguration` type.
- Added tests to verify:
  - Validation error is raised when `type="new"` and location is missing.
  - `type="existing"` does not require location fields.

Assisted-by: Codex
- Adjusted `location` coordinates in `test_live_sign_pdf` to begin at
  `(1, 1)` instead of `(0, 0)` for improved consistency.
- Add required location for new signature.
- Updated test configurations to reflect the changes in signature
  naming and layout.

Assisted-by: Codex
- Introduced `test_live_sign_pdf_with_existing_signature_field` to verify
  signing a PDF with an existing signature field.
- Tested both "new" and "existing" signature types for compatibility.
- Ensured proper validation of output file type, name, and input IDs.

Assisted-by: Codex
- Changed the `pytest.raises` match regex to validate against the updated
  error message: "Both pfx and passphrase".
- Ensures consistency with the revised validation logic.

Assisted-by: Codex
- Strip whitespace from the passphrase file content to prevent errors.
- Updated `client.files.create` to include sanitized passphrase data
  within the payload.

Assisted-by: Codex
- Changed the error message to correctly list `combined_allowed_mime_types`
  instead of `allowed_mime_types` for improved clarity and accuracy
  during validation.

Assisted-by: Codex
- Added a test to validate the handling of `application/x-x509-ca-cert` MIME
  type for DER certificate and private key uploads in `PdfSignPayload`.
- Updated `_internal.py` to allow `application/x-x509-ca-cert` and other
  relevant MIME types for DER credentials to maintain compatibility with
  provider/browser file type detection.

Assisted-by: Codex
- Introduced `PdfNewSignatureConfiguration` and `PdfExistingSignatureConfiguration`
  to replace the unified `PdfSignatureConfiguration` type.
- `PdfSignatureConfiguration` is now a union of `PdfNewSignatureConfiguration`
  and `PdfExistingSignatureConfiguration`, allowing stricter type validation
  and clarity.
- Ensures each signature type has its respective required and optional fields.

Assisted-by: Codex
- Updated `test_live_sign_pdf_invalid_signature_configuration` to improve
  validation by matching against specific error messages.
- Added `test_live_async_sign_pdf_invalid_signature_configuration` to
  test async behavior for invalid signature configurations.
- Introduced `test_sign_pdf_request_customization` to validate request
  headers, query params, payload, and timeout customization during PDF
  signing.
- Ensured stricter validation of malformed JSON in signature configuration.

Assisted-by: Codex
- Changed `BeforeValidator` to `AfterValidator` in `_internal.py` to
  improve validation reliability and sequencing.
- Added support for `application/pem-certificate-chain` MIME type
  for PEM credentials to widen compatibility with certificate formats.
- Updated tests to ensure validation handles `pem-certificate-chain`
  MIME type for both certificates and private keys.
- Introduced `test_sign_payload_accepts_logo_tuple_sequence` to verify
  the logo field supports tuple sequences in payloads.

Assisted-by: Codex
- Updated `_PdfSignaturePointModel` and `PdfSignaturePoint` to enforce
  `x` and `y` as `float` instead of accepting `str | int | float`.
- Ensures stricter type validation for signature positioning.

Assisted-by: Codex
- Updated payload modeling section to emphasize mirroring pdfRest's
  request field layout for consistency.
- Added recommendations to use `@model_validator(mode="before")` for
  mapping user-friendly input onto pdfRest fields.
- Advised against using `@model_serializer` on payload models to
  maintain separation of wire formatting in field serializers.

Assisted-by: Codex
- Added tests for new and existing signature type literals to ensure
  consistent behavior across sync and async API clients.
- Introduced logo opacity bounds tests to validate edge case constraints
  for this field.
- Implemented invalid configuration tests for unsupported signature types
  and logo opacity values.
- Refactored reusable components:

  - `SIGNATURE_TYPES`, `LOGO_OPACITY_BOUNDS`, and `INVALID_LOGO_OPACITY_VALUES`
    for parametrized test cases.
  - `_to_json_string` utility function for consistent JSON encoding.

Assisted-by: Codex
- Updated `_internal.py` to raise `ValueError` instead of `TypeError`
  for credential validation errors, ensuring compliance with Pydantic
  error handling best practices.
- Documented this change in AGENTS.md to guide contributors on proper
  error types for validators.

Assisted-by: Codex
- Updated `_PdfSignatureConfigurationModel` to set `logo_opacity` lower
  bound as strictly greater than 0 (`gt=0`) instead of greater than or
  equal to 0 (`ge=0`).
- Modified `test_sign_pdf.py` to reflect the updated constraint:
  - Adjusted parametrized tests to replace 0.0 with 0.01 for minimum
    valid opacity.
  - Added test case for 0.0 as an invalid opacity value.
  - Updated validation error match regex to account for the new rule.

Assisted-by: Codex
…l files

- Introduced validation tests in `test_sign_pdf.py` to ensure rejection of
  multiple input PDFs, logos, and credential files during PDF signing.
- Added corresponding async validation tests for enhanced API behavior coverage.
- Verified HTTP request counts (`POST` and `GET`) in sync and async test cases.

Assisted-by: Codex
- Refactored `test_sign_pdf_rejects_multiple_credential_files` and
  `test_async_sign_pdf_rejects_multiple_credential_files` to use
  `@pytest.mark.parametrize`.
- Introduced `MULTI_FILE_CREDENTIAL_CASES` for test parameterization,
  covering different credential file types and combinations.
- Enhanced validation error matching for clearer and more precise
  diagnostics.

Assisted-by: Codex
- Added `test_sign_pdf_rejects_invalid_signature_type_literal` to validate
  rejection of unsupported signature types for synchronous clients.
- Added `test_async_sign_pdf_rejects_invalid_signature_type_literal` for
  async client behavior validation.
- Ensures consistent error handling for unsupported configurations.

Assisted-by: Codex
@datalogics-cgreen datalogics-cgreen merged commit df9491f into pdfrest:main Feb 19, 2026
19 checks passed
@datalogics-kam datalogics-kam deleted the kam-pdfcloud-5464-sign branch February 19, 2026 18:03
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