Skip to content

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

Draft
lfals wants to merge 40 commits into
LibreSign:mainfrom
lfals:feat/participant-role-observer
Draft

feat: add observer participant role for signature requests#8143
lfals wants to merge 40 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)
🏚️ 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 75.70% <ø> (ø)
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
@lfals
lfals marked this pull request as ready for review August 31, 2026 17:45
Comment thread l10n/en_GB.js
@github-project-automation github-project-automation Bot moved this from 0. Backlog to 1. to do in Roadmap Sep 2, 2026
Translations under l10n/ are synced by Transifex; keep new strings
only in source code until the bot updates locale files.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
Resolve conflicts keeping observer participant behavior alongside the
mail sender strategy policy and NcSelect validation updates from main.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
@lfals
lfals marked this pull request as draft September 2, 2026 16:48
Nextcloud entities expose getUuid through magic __call, so configuring
getUuid directly on the File mock breaks MailServiceTest.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
NcSelect now exposes the method placeholder as the combobox name, so
helpers must use #account-or-email-input instead of Search signer.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
@lfals
lfals marked this pull request as ready for review September 2, 2026 19:44
@lfals
lfals requested a review from vitormattos September 2, 2026 20:01
Resolve merge conflicts to keep participantRole observer support alongside
signer geolocation policy changes from main.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
@lfals
lfals marked this pull request as draft September 2, 2026 22:36
Update unit test callbacks to expect participantRole before afterPersist
after merging observer role support with signer geolocation changes.

Signed-off-by: Luis Amorim <luisfelipeamorim@hotmail.com>
@lfals
lfals force-pushed the feat/participant-role-observer branch from 8a74b3e to 6c8ddb1 Compare September 2, 2026 22:41
Comment thread lib/Migration/Version19001Date20260831000000.php Outdated
Comment thread src/components/RightSidebar/RequestSignatureTab.vue
Comment thread lib/Enum/ParticipantRole.php
Comment thread lib/Service/SignRequest/SignRequestService.php
Comment thread src/utils/participantRole.ts Outdated
return true
}

return participant.status === SIGN_REQUEST_STATUS.OBSERVING

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.

Please use participantRole as the source of truth for the role.

OBSERVING is a status created by this feature, so we do not need it as a legacy fallback. With the current code, inconsistent data such as participantRole: signer with status: OBSERVING is treated as an observer.

The backend already stores the explicit role. The frontend should not silently change the role based on status. Please update the related unit test too.

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.

Please add one focused Playwright test for the observer workflow.

The PR changes many existing E2E tests, but none tests the new feature end to end.

The scenario should:

  1. enable enable_observer_profile;
  2. add one signer and one observer;
  3. request signatures;
  4. verify both roles are shown separately;
  5. open the observer link;
  6. verify the observer goes to validation and cannot enter the signing flow.

This will test the main business flow instead of only the individual frontend and backend pieces.

We also need similar scenario at integration tests with Behat to validate the API contract too.

$this->mailer->expects($this->once())
->method('send');

$signRequest = $this->createMock(SignRequest::class);

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.

Could we use a real SignRequest entity here instead of mocking __call()?

This test only needs entity data such as UUID, file ID, display name, and participant role. Using the real entity will make the test easier to read and less coupled to the entity magic methods.

The same approach can be used for the file entity if possible.

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>
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