LibreSign / LibreSign/libresign
Add signature rejection to the request and signing flow
Nobody has claimed this yet.
- 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_rejectionpayload when enabling; - correct
policy.overrides.signature_rejectionpayload when disabling; - other policy overrides are preserved;
activeContextis 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
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- 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