Skip to content

feat: add observer participant role for signature requests - #8143

Open
lfals wants to merge 50 commits into
LibreSign:mainfrom
lfals:feat/participant-role-observer
Open

feat: add observer participant role for signature requests#8143
lfals wants to merge 50 commits into
LibreSign:mainfrom
lfals:feat/participant-role-observer

Conversation

@lfals

@lfals lfals commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Resolves: #6957

📝 Summary

Adds an observer participant role (UI label: Observer / Testemunha) to signature requests. Observers can be invited to follow document progress and open the validation view, but cannot sign. The feature is gated by the new policy enable_observer_profile (default: disabled).

Backend is the source of truth: role validation, signing denial, status/progress calculations, DocMDP signer limits, sequential signing, e-mail/notification routing, and API contracts all treat observers separately from signers. The request UI exposes separate Signers and Observers lists when the policy is enabled.

Also includes pre-merge hardening: preserve observers when reordering signers in ordered flow, require at least one signer before requesting signatures, regenerate OpenAPI/TypeScript types, and focused regression tests.

🧪 How to test

  1. Enable the policy Enable observer profile (system, group, or user scope as needed).
  2. Open the Files app, select a PDF, and open Request signature.
  3. Use Add → Signer and Add → Observer to add participants.
  4. Confirm the UI shows two sections (Signers / Observers) and that observer labels use localized copy (e.g. Testemunha in pt_BR).
  5. Try requesting signatures with only observers → must be blocked (toast + API error).
  6. Add at least one signer and request signatures → request should succeed; observers should not appear as pending signers.
  7. As an observer, open the notification/link → should land on validation, not the signing flow.
  8. In ordered numeric flow, reorder signers with observers present → observers must remain in the list.
  9. Open validation for a document with both roles → signers and observers appear in separate groups; observer status shows Observing when applicable.

🎨 UI / Front‑end changes

  • Policy-gated Add → Signer / Observer menu in request signature flow
  • Separate Signers and Observers lists in request and validation views
  • Observer-specific labels in participant modal (search, name validation, custom message)
  • Client-side guard: block signature request when only observers are present
  • Fix drag-and-drop reorder in ordered flow so observers are not removed from file.signers
  • Screenshots before/after (add images or links)
image Captura de Tela 2026-09-04 às 16 12 59 image
🏚️ Before 🏡 After
Single signer list only Signers + Observers sections when policy enabled
  • Tested in multiple browsers (Chrome, Firefox, Safari) – optional but appreciated
  • Components, Unit (with vitest) and/or e2e (with Playwright) tests added - Required
  • Accessibility verified (contrast, keyboard navigation, screen reader friendly) – if applicable
  • Design review approved – optional, link to feedback if available
  • Documentation updated (if applicable) – docs repository

🚧 Tasks

  • Sync translations via Transifex before release (local l10n/ edits included for dev)
  • Add/update user-facing documentation for observer role in LibreSign documentation
  • [ ]

⚙️ API / Back‑end changes

  • New participant_role column on sign requests (signer | observer) with idempotent migration
  • New policy provider enable_observer_profile (default false, system/group/user scopes)
  • Validation: reject observers when policy disabled; reject signing attempts by observers
  • Exclude observers from signing status, envelope progress, sequential signing, and DocMDP signer counts
  • Route observer notifications to validation view
  • Require at least one signing participant when moving out of draft / requesting signatures
  • Map OBSERVING (status 3) in signer summaries; defensive ParticipantRole::fromNullable()
  • Unit and/or integration tests added – required for backend changes
  • Capabilities updated (if applicable) – if adding/modifying Nextcloud capabilities
  • Documentation updated (if applicable) - docs repository
  • API documentation updated with the command composer openapi if necessary

🚧 Tasks

  • Confirm no environment still depends on dropped participant_profile_id column (migration included)

✅ Checklist

  • I have read and followed the contribution guide.
  • OpenAPI specs and TypeScript types regenerated (composer openapi, npm run typescript:generate)
  • Focused PHPUnit and Vitest suites pass locally
  • PHP CS Fixer clean (composer cs:check)
  • Conventional Commits with DCO sign-off on all commits

🤖 AI (if applicable)

  • The content of this PR was partially or fully generated using AI

lfals added 10 commits August 30, 2026 20:46
Introduce signer/observer participant roles at the database layer so
request-signature flows can distinguish signing participants from
view-only observers.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Allow administrators to enable observer participants through the policy
workbench before requesters can assign view-only roles.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Persist participant roles, block observers from signing, and keep
sequential signing logic scoped to actual signers only.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Replace the single add-signer action with an add dropdown, separate
signers from observers in the participant list, and hide multi-signer
controls when only one signer is present.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Run occ as www-data when setup runs as root and add a reusable script
to reconfigure LibreSign after environment restarts.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Remove the experimental column that was not mapped by SignRequest and
broke participant creation in local development databases.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Observers must not affect partial or fully signed file status, envelope
progress, or pending signer checks used for signing order.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Send observer emails and in-app links to the validation page instead of
the signing flow, and redirect legacy sign URLs to validation.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Show the plus icon and Add label on the participant dropdown action.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Group signers and observers in validation UI, recognize OBSERVING status,
and ignore observers when checking partial or full signature completion.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
lfals added 8 commits August 31, 2026 09:35
Register observer UI strings in en_GB and translate the role as
testemunha in pt_BR and pt_PT while keeping Observer in English.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Force-refresh validation data when opening the page right after signing
so the first load does not fail before the signed document is ready.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Register Add and Add participant strings used by the request signature
tab so the dropdown button is localized in English and Portuguese.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Switch SignerSelect copy and NcSelect input label based on participant
role so adding a witness shows observer-specific search text.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Block observer-only signature requests in the UI and API, showing an
error toast instead of treating the operation as successful.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Preserve observers when reordering signers, exclude them from DocMDP
signer limits, map OBSERVING status in summaries, regenerate OpenAPI
types, and add focused regression tests for policy and signing rules.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Keep lint-php-cs CI green after observer workflow changes.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
This reverts commit bd2f828.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
@lfals
lfals force-pushed the feat/participant-role-observer branch from 130da68 to cfa42bc Compare August 31, 2026 12:35
@codecov-commenter

codecov-commenter commented Aug 31, 2026

Copy link
Copy Markdown

⚠️ Please install the 'codecov app svg image' to ensure uploads and comments are reliably processed by Codecov.

Codecov Report

❌ Patch coverage is 55.52147% with 145 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
...rc/components/RightSidebar/RequestSignatureTab.vue 33.33% 56 Missing and 16 partials ⚠️
...kbench/settings/observer-profile/realDefinition.ts 44.11% 16 Missing and 3 partials ⚠️
src/components/validation/EnvelopeValidation.vue 77.27% 8 Missing and 2 partials ⚠️
src/views/Validation.vue 66.66% 7 Missing and 3 partials ⚠️
src/components/Signers/Signers.vue 70.37% 5 Missing and 3 partials ⚠️
...ngs/observer-profile/ObserverProfileRuleEditor.vue 56.25% 6 Missing and 1 partial ⚠️
src/components/Request/IdentifySigner.vue 50.00% 1 Missing and 4 partials ⚠️
src/components/validation/SignerDetails.vue 28.57% 4 Missing and 1 partial ⚠️
src/utils/participantRole.ts 73.33% 2 Missing and 2 partials ⚠️
src/components/Request/SignerSelect.vue 66.66% 1 Missing and 2 partials ⚠️
... and 2 more
❗ Your organization needs to install the Codecov GitHub app to enable full functionality.
Files with missing lines Coverage Δ
src/components/validation/SigningProgress.vue 76.28% <100.00%> (-0.19%) ⬇️
src/constants.js 100.00% <ø> (ø)
src/services/validationDocument.ts 77.19% <ø> (+1.49%) ⬆️
src/store/files.js 75.50% <100.00%> (+0.64%) ⬆️
...ttings/PolicyWorkbench/settings/realDefinitions.ts 100.00% <ø> (ø)
...omponents/validation/DocumentValidationDetails.vue 92.50% <92.85%> (-0.36%) ⬇️
src/utils/getSignRequestStatusText.ts 20.00% <0.00%> (-5.00%) ⬇️
src/components/Request/SignerSelect.vue 86.20% <66.66%> (-0.22%) ⬇️
src/utils/participantRole.ts 73.33% <73.33%> (ø)
src/components/Request/IdentifySigner.vue 80.83% <50.00%> (-2.50%) ⬇️
... and 7 more

... and 201 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@lfals
lfals marked this pull request as draft August 31, 2026 13:45
lfals added 5 commits August 31, 2026 11:45
Add a shared helper for the renamed Add participant control and update
E2E specs that previously clicked the removed Add signer button.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Centralize account/email signer picking on the combobox used by the
add-participant dialog so specs stop relying on removed placeholders.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Update request-signature E2E specs to select account and email signers
through the shared combobox helpers.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
When an Everyone rule already exists, edit it instead of waiting for a
missing Everyone scope option, and make save paths dirty the form first.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
…tate

Reset stale certificates/signatures when needed, keep signature stamp in
a graphic-capable mode, and click Sign document with a viewport-safe helper.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
@lfals
lfals marked this pull request as ready for review August 31, 2026 17:33
@lfals
lfals marked this pull request as draft August 31, 2026 17:33
Official migrations must not drop an unknown column created only in local
or experimental environments.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Persisted roles are always valid after migration, so invalid values must
fail rather than silently become signer.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Changing signer to observer after signing would rewrite participant
meaning in audit history.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Stop inferring observer status from OBSERVING when the explicit role is
already stored by the backend.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
The Add menu is only needed when enable_observer_profile is enabled,
preserving the previous UI and reducing unrelated E2E churn.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Keeps observer notification coverage focused on data instead of Entity
magic-method plumbing.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Add focused Playwright and Behat scenarios for enabling observers,
separating roles, validation links, and blocked signing.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
@vitormattos

Copy link
Copy Markdown
Member

If possible, could you also add a few screenshots to the PR description showing the observer flow?

It would be useful to show:

  • the Add menu with Signer and Observer;
  • the Signers and Observers sections;
  • the validation page with an observer.

Also, sorry for reviewing this PR while it is still a draft. I added the comments now only to help keep the work close to the expected flow and avoid bigger changes later.

For the next review, it is better to add me as a reviewer and request the review when the PR is ready and is no longer a draft. After pushing new changes, when the PR is ready for review again, use the GitHub option to request my review again. This makes it clear when a new review is needed.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
@lfals

lfals commented Sep 4, 2026

Copy link
Copy Markdown
Contributor Author

If possible, could you also add a few screenshots to the PR description showing the observer flow?

It would be useful to show:

  • the Add menu with Signer and Observer;
  • the Signers and Observers sections;
  • the validation page with an observer.

Also, sorry for reviewing this PR while it is still a draft. I added the comments now only to help keep the work close to the expected flow and avoid bigger changes later.

For the next review, it is better to add me as a reviewer and request the review when the PR is ready and is no longer a draft. After pushing new changes, when the PR is ready for review again, use the GitHub option to request my review again. This makes it clear when a new review is needed.

No problem, I left it as a draft after the changes you requested. I was fixing the tests that broke. I'm going to add the observer flow and let you know when it's ready for review.

@vitormattos

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
@lfals
lfals marked this pull request as ready for review September 4, 2026 14:42
@lfals
lfals requested a review from vitormattos September 4, 2026 14:45
Existing requests without enable_observer_profile in policy_snapshot
must stay disabled even if the live policy is later turned on.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Sign requests are linked to the envelope, so the observer policy must
be frozen there as well as on child files.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
@lfals
lfals requested a review from vitormattos September 4, 2026 16:32

@vitormattos vitormattos left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Only a small change:

At file appinfo/info.xml, change from:

16.0.0-dev.1

to:

16.0.0-dev.2

This will make all environments of all developers to run the migration because will identify that the version was changed.

Trigger migrations in all development environments after the version change.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
@vitormattos

Copy link
Copy Markdown
Member

Could you also check this?

It would be useful to show:

  • the Add menu with Signer and Observer;
  • the Signers and Observers sections;
  • the validation page with an observer.

@vitormattos

Copy link
Copy Markdown
Member

I found another case during manual testing.

I created a signature request with one signer while the Observer policy was disabled. Then I enabled the Observer policy in Administration Settings and opened the same request again.

The UI correctly showed Add → Observer, but saving the observer returned:

Observer participants are not enabled

This happens because the frontend uses the current policy, while the backend keeps the old false value from the file snapshot.

I think the expected behavior should be:

  1. If an existing request has Observer disabled and the current policy becomes enabled, Observer can be added while the request can still be edited.
  2. After an Observer is added to this request, disabling the global policy later must not remove Observer from this existing flow. It should still be possible to keep and add observers to this request.
  3. New requests should continue to use the current policy value.

The saved policy state may need to move from false to true when Observer is first added to an existing request. Once enabled for that request, it should stay enabled for this flow.

There is also a frontend error handling problem in this case. The API returned HTTP 422 with the message Observer participants are not enabled, but the UI did not show this message.

IdentifySigner.vue should show the error message returned by the API when saving a participant fails, instead of losing it in the catch.

Please add regression tests for both parts:

  • backend/integration: create a request with Observer disabled, enable the policy, add an observer, disable the policy again, and confirm that the same request can still use observers;
  • frontend: make the participant save request fail with a 422 OCS response and confirm that the API error message is shown to the user and the participant modal stays open.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: 1. to do

Development

Successfully merging this pull request may close these issues.

Add participant role permissions: Sign and Observe

3 participants