Skip to content

fix: CRL disabled flow and signing error UX#7402

Merged
vitormattos merged 28 commits intomainfrom
fix/crl-signing-blocking-flow
Apr 4, 2026
Merged

fix: CRL disabled flow and signing error UX#7402
vitormattos merged 28 commits intomainfrom
fix/crl-signing-blocking-flow

Conversation

@vitormattos
Copy link
Copy Markdown
Member

@vitormattos vitormattos commented Apr 4, 2026

Context

This PR fixes regressions around certificate revocation (CRL) behavior when external validation is disabled, and aligns signing error UX with the new backend behavior.

What changed

  1. CRL disabled policy alignment
  • When external CRL validation is disabled, signing is no longer blocked for missing/empty CRL distribution points.
  • Policy decision for missing CDP is handled at certificate parsing stage.
  1. Signing error UX
  • Non-retriable signing failures (422) close the password modal and show a blocked signing state with explicit retry action.
  • Blocking/non-blocking behavior is now covered in unit and E2E tests.
  1. PDF visibility behavior
  • PDF viewer is hidden only for PDF-loading failures.
  • For other error classes (for example signing-time errors), PDF remains visible and errors are surfaced in the signing flow/sidebar.
  1. i18n clarity
  • Added translator context note for the blocked-signing message to avoid ambiguous localization.

Validation

  • PHP unit:
    • CrlRevocationCheckerTest
    • PasswordTest
    • AEngineHandlerTest
  • Frontend unit:
    • Sign.spec.ts
    • SignPDF.spec.ts
    • Full npm run test
  • E2E:
    • sign-password-non-retriable-error.spec.ts
  • Static/style:
    • npm run ts:check
    • composer cs:fix
    • composer psalm

When the admin disables external CRL validation
(crl_external_validation_enabled=false), an empty CRL distribution-point
list was still returning NO_URLS instead of DISABLED, causing signing to
be blocked even though the admin intended to bypass validation.

Move the toggle check before the empty-URL guard so that an empty list
is treated the same as all points being intentionally skipped.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…abled

CrlValidationStatus::MISSING is assigned in AEngineHandler before the
CRL checker runs (certificate has no CDP extension), so the
crl_external_validation_enabled toggle was never consulted for this case.

Check the toggle explicitly in validateCertificateRevocation so that
certificates without any revocation information follow the same policy
as all other non-revoked statuses when the admin disables external
CRL validation.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Update the data-provider case that previously asserted NO_URLS regardless
of the toggle setting, and add a dedicated test confirming that empty
URL lists still return NO_URLS when external validation is enabled.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
…isabled

Stub getAppConfig on the identifyService mock used by the CRL data-provider
tests so the new toggle check path is covered. Add an isolated test that
verifies signing is not blocked when the admin disables external CRL
validation and the certificate has no CDP extension (MISSING status).

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
When a certificate has no crlDistributionPoints extension, the handler now
maps the status to DISABLED when external CRL validation is turned off,
instead of always setting MISSING. This makes the source status align with
the configured policy before signature validation runs.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
After moving the missing-CDP policy decision to AEngineHandler, Password
no longer needs to re-check app config for MISSING. Keep only status-based
validation in validateCertificateRevocation.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Remove the test scenario that depended on Password reading app config for
MISSING status. Policy derivation now happens in AEngineHandler, so
Password tests focus on status handling only.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Refactor the non-retriable signing error spec to avoid ambiguous strict
text matching and assert the current blocked-UI behavior explicitly
(hidden sign CTA + retry button).

Add a second scenario that returns success from the sign endpoint and
verifies that the blocking warning is not shown when no non-retriable
error is returned.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Keep PdfEditor visible for generic/signing errors and only hide it when the
error was produced by PDF/envelope loading. Tag load-time errors with
scope=pdfLoad and gate PdfEditor rendering using that scope.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Add unit tests proving PdfEditor is hidden only for pdfLoad-scoped errors
and remains visible for non-pdfLoad errors. Update PdfEditor mock to expose
a stable DOM marker for assertions.

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
@github-project-automation github-project-automation Bot moved this to 0. Needs triage in Roadmap Apr 4, 2026
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
@vitormattos vitormattos changed the title fix: align CRL disabled behavior and signing blocking UX fix: CRL disabled flow and signing error UX Apr 4, 2026
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Add @return array{status: CrlValidationStatus, revoked_at?: string} docblocks
- Applied to validate(), validateFromUrlsWithDetails(), downloadAndValidateWithDetails()
- Applied to checkCertificateInCrlWithDetails()
- Ensures Psalm understands status is always CrlValidationStatus enum, never string
- Provides strong typing guarantee at the source (producer) level
- Allows simplified, trusting consumption without defensive checks

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Remove normalizeRevocationStatus() helper method as no longer needed
- Remove defensive mixed type handling and instanceof checks
- Trust CrlRevocationChecker type declarations that status is always enum
- logRevocationBlockedSigning() now accepts CrlValidationStatus directly
- Remove test cases with serialized string data (legacy compatibility no longer needed)
- Simplified code expresses contract: CRL validation status is always enum from source

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- getRevocationErrorMessage() now accepts non-nullable CrlValidationStatus
- Status is always present and typed as enum (never null) from CrlRevocationChecker
- Reflects contract that certificate data always has validated CRL status

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
- Document context for i18n translators on each CRL status error message
- Clarify technical meaning: inaccessible URLs, validation errors, missing CRL
- Helps translators understand certificate revocation domain terminology

Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
@vitormattos
Copy link
Copy Markdown
Member Author

/backport to stable33

@vitormattos
Copy link
Copy Markdown
Member Author

/backport to stable32

Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR adjusts LibreSign’s CRL validation behavior to avoid blocking signing when external CRL checks are disabled, and updates the signing UI to treat non-retriable signing failures (HTTP 422) as a “blocked signing” state with an explicit retry path, while keeping the PDF visible for signing-time errors.

Changes:

  • Backend: align CRL parsing/validation so missing/empty CRL distribution points don’t block signing when external validation is disabled, while preserving fail-closed behavior when enabled.
  • Frontend: introduce “blocking sign error” UX for 422 failures (close password modal, disable sign CTA, show retry action), and only hide the PDF viewer for PDF-load-scoped errors.
  • Tests: extend PHP unit coverage for CRL-disabled behavior, add frontend unit assertions for PDF visibility + blocked UX, and add a Playwright E2E flow for the non-retriable password error.

Reviewed changes

Copilot reviewed 10 out of 10 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
tests/php/Unit/Service/IdentifyMethod/PasswordTest.php Updates certificate validation test cases for revised CRL status handling and logging needs.
tests/php/Unit/Service/Crl/CrlRevocationCheckerTest.php Adjusts expectations for empty URL list when external validation is disabled; adds explicit “setting on” test.
lib/Service/IdentifyMethod/SignatureMethod/Password.php Adds CRL-blocking logging and more specific translated error messages for fail-closed statuses.
lib/Service/Crl/CrlRevocationChecker.php Treats empty URL list as DISABLED when external validation is off; tightens return type docs.
lib/Handler/CertificateEngine/AEngineHandler.php Sets CRL status to DISABLED (instead of MISSING) when CRL DP info is absent and external validation is off.
src/views/SignPDF/SignPDF.vue Scopes PDF-load errors so the PDF viewer hides only for PDF-loading failures.
src/views/SignPDF/_partials/Sign.vue Adds blocked-signing UI for 422 errors, closes password modal on non-retriable failures, and surfaces errors in the main CTA area.
src/tests/views/SignPDF/SignPDF.spec.ts Adds unit tests ensuring PDF visibility depends on error scope.
src/tests/views/SignPDF/Sign.spec.ts Adds unit tests for closing password modal on 422 and for blocked CTA + retry action UX.
playwright/e2e/sign-password-non-retriable-error.spec.ts Adds E2E test covering blocked-to-normal flow when toggling CRL external validation.

Comment thread tests/php/Unit/Service/IdentifyMethod/PasswordTest.php
Comment thread tests/php/Unit/Service/IdentifyMethod/PasswordTest.php
Comment thread src/views/SignPDF/_partials/Sign.vue Outdated
Comment thread src/views/SignPDF/SignPDF.vue Outdated
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
Signed-off-by: Vitor Mattos <1079143+vitormattos@users.noreply.github.com>
@vitormattos vitormattos merged commit 3ffb041 into main Apr 4, 2026
77 checks passed
@vitormattos vitormattos deleted the fix/crl-signing-blocking-flow branch April 4, 2026 17:51
@github-project-automation github-project-automation Bot moved this from 0. Needs triage to 4. to release in Roadmap Apr 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 4. to release

Development

Successfully merging this pull request may close these issues.

2 participants