LibreSign / LibreSign/libresign

Add signature rejection to the request and signing flow

Open
#8,161 6 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

feature-request frontend javascript
Dominant language
PHP
Stars
818
Forks
146
Avg merge
11h 31m
Merged PRs (30d)
326

Description

Implement the requester and signer frontend flows for signature rejection defined by #7832.

The backend support is already available from #8159.

Request-signature flow

When the effective signature_rejection policy allows rejection, the requester must be able to choose if signers may reject that specific file or envelope.

The administrative policy only gives permission to use rejection.

It does not automatically enable rejection for the request.

Read the policy

Use the existing effective Policies & Rules data already used by the request-signature UI.

The signature_rejection effective value has this structure:

{
  "enabled": true,
  "comment_mode": "optional",
  "cancel_workflow": false,
  "public_status": false,
  "show_comment_on_validation": false
}

Only show the requester option when the administrative effective value has:

{
  "enabled": true
}

The requester only chooses if rejection is enabled for the request.

The requester must not edit:

  • comment_mode;
  • cancel_workflow;
  • public_status;
  • show_comment_on_validation.

These values are controlled by the administrative policy.

Save the requester choice

Create and update signature requests through the existing endpoint:

PATCH /ocs/v2.php/apps/libresign/api/v1/request-signature

Send the rejection choice through policy.overrides.

To enable rejection for the request:

{
  "policy": {
    "overrides": {
      "signature_rejection": true
    }
  }
}

To disable rejection:

{
  "policy": {
    "overrides": {
      "signature_rejection": false
    }
  }
}

If the request already uses a policy activeContext, preserve it together with the overrides.

Example:

{
  "policy": {
    "overrides": {
      "signature_rejection": true
    },
    "activeContext": {
      "type": "group",
      "id": "example-group"
    }
  }
}

Do not replace or remove other existing policy overrides when updating signature_rejection.

The requester only chooses the boolean signature_rejection value.

Do not send the complete administrative signature_rejection policy as a request override.

The backend already prevents the requester from enabling rejection when the administrative policy does not allow it.

Draft lifecycle

The UI must preserve the value stored for the request.

Expected behavior:

  • new request with no explicit rejection choice → rejection disabled;
  • draft with rejection disabled + unrelated edit → rejection stays disabled;
  • draft with rejection enabled + unrelated edit → rejection stays enabled;
  • requester can explicitly change the choice before the signing flow starts;
  • after the signing flow starts, the value cannot be changed.

Updates that do not change rejection must preserve the existing value instead of rebuilding it from the current administrative policy.

Do not calculate the stored request choice again from the administrative policy when editing an existing request.

For existing requests, use the effective request value returned by the backend as the source of truth.

The same behavior must work for:

  • normal files;
  • envelopes.

Signer flow

When rejection is enabled for the request, show a Reject action together with the existing Sign action.

When rejection is disabled, keep the current signing-only behavior.

The frontend must use the effective policy stored for the request. A later change to the administrative policy must not change an existing signing flow.

Reject dialog

Rejecting must require explicit confirmation.

The dialog must follow comment_mode.

disabled
  • do not show a comment field;
  • do not show the private comment option.
optional
  • show the comment field;
  • allow rejection without a comment;
  • allow the signer to mark the comment as private.
required
  • show the comment field;
  • require a non-empty comment;
  • allow the signer to mark the comment as private.

Comment privacy is controlled by the signer.

It is not controlled by the administrator policy.

Reject API

For the authenticated file flow use:

POST /ocs/v2.php/apps/libresign/api/v1/sign/file_id/{fileId}/reject

For the public signer UUID flow use:

POST /ocs/v2.php/apps/libresign/api/v1/sign/uuid/{uuid}/reject

Request parameters:

{
  "comment": "I do not agree with this document",
  "privateComment": true
}

comment can be empty when allowed by comment_mode.

privateComment defaults to false.

Use the UUID endpoint for the public signer flow.

The backend validates:

  • signer identity;
  • whether rejection is enabled for the request;
  • comment requirements;
  • current signer state;
  • current workflow state.

Do not reproduce these validation rules as security checks in the frontend.

Frontend validation may be used only to improve the user experience.

After rejection

Use the response returned by the backend to update the UI.

Do not decide in the frontend if the workflow was canceled.

If the backend reports that the workflow was canceled:

  • the current signer must no longer see signing or rejection actions;
  • other signers must not be offered actions that are no longer valid;
  • refresh or update the local file state so the UI uses the backend state.

If the workflow continues:

  • the rejected signer remains rejected;
  • other eligible signers may continue signing.

The backend remains the source of truth even when the frontend hides an action.

Tests

Add or update frontend tests covering at least:

Requester flow
  • administrative policy disabled → rejection option not available;
  • administrative policy enabled → requester can choose rejection;
  • no explicit requester choice → rejection disabled;
  • correct policy.overrides.signature_rejection payload when enabling;
  • correct policy.overrides.signature_rejection payload when disabling;
  • other policy overrides are preserved;
  • activeContext is preserved;
  • stored disabled choice restored when editing a draft;
  • stored enabled choice restored when editing a draft;
  • unrelated draft updates preserve the stored choice;
  • explicit change before signing starts;
  • change rejected after signing starts;
  • normal file flow;
  • envelope flow.
Signer flow
  • Reject hidden when rejection is disabled;
  • Reject shown when rejection is enabled;
  • confirmation before rejection;
  • comments disabled;
  • optional comment;
  • required comment;
  • private comment;
  • successful rejection by file ID;
  • successful rejection by signer UUID;
  • backend validation error;
  • workflow canceled after rejection;
  • workflow continues after rejection.

Follow the existing request-signature and signing-flow frontend test patterns.

Quality gates

The implementation must pass the existing frontend checks, including:

  • ESLint;
  • type checking;
  • frontend tests.

Out of scope

This issue does not implement:

  • backend rejection behavior;
  • Policy Workbench configuration;
  • validation page presentation.

These are handled by #8159, #8160, and #8162.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the existing request-signature and signing-flow frontend entry points and their tests, following the stated frontend test patterns. Trace the PATCH request-signature endpoint and the file-ID and signer-UUID rejection endpoints. Done means requester and signer flows preserve policy state, enforce the described comment behavior, update from backend responses, and pass ESLint, type checking, and frontend tests.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, php
Domain
api, frontend, testing-qa
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.