Skip to content

feat(audit): record a guest signer's name and email from the web form - #33

Merged
batonac merged 2 commits into
developfrom
feat/guest-signer-name
Oct 23, 2026
Merged

batonac merged 2 commits into
developfrom
feat/guest-signer-name

Conversation

@batonac

@batonac batonac commented Oct 23, 2026 •

Copy link
Copy Markdown
Member

Change

Guest signers were named only by email in the audit trail: _collect_audit_data looked the signer's name up from a User with the signer's email, so a signer with no account had no name on the timeline card or in the notification email, even when the form asked for their name.

The eSign settings of a Web Form now have a Signer section with two settings:

  • Signer Name Field: the form field the signer types their name into. Its value is recorded as signer_name.
  • Signer Email Field: the form field the signer types their email into. A single valid address in it is recorded as signer_email.

Both are recorded in the eSign Communication (also as its sender and sender_full_name). They show on the timeline card ("Document signed by ...", and Email under Signing Details) and in the audit table added to the notification email.

Design

  • Both settings are Select fields whose options are filled at runtime from the web form's own Data fields (web_form.js), as for Set Property After Response. EsignWebForm.validate_signer_fields refuses a field that is not on the form or is not a Data field. The audit trail records only what the signer submitted on the form.
  • The audit code reads a setting only while it still names a Data field on the form. If the form has changed since the setting was saved, the setting counts as unset.
  • URL parameters are not trusted for identity. With a Signer Email Field set, the link's email parameter only pre-fills that field (the signer can change it), and it is never recorded on its own. If the field is empty or invalid, the logged-in user is used, then nothing.
  • If neither setting is set, the signer is identified exactly as before: the email parameter, then a Data field with options Email, then the logged-in user, with the name taken from a matching User. If the name field is set but empty, the matching User's name is still used.
  • The name is whitespace-normalised and cut to 140 characters, the length of sender_full_name. Values on the timeline card and in the email were already escaped.
  • _is_single_email replaces the validate_email_address(x) == x check. That check accepted a comma-separated list, because validate_email_address returns the valid addresses joined by commas. This also applies to the existing email parameter path.
  • The demo web form uses both settings, and the demo signed agreement's audit record names Dana Whitfield.

Nothing here touches money or payroll. The permission checks in accept, the key validation and the signing page are unchanged.

Verification

  • New tests in tests/test_web_form.py:
    • the settings are validated (a field not on the form, a non-Data field, unset)
    • a guest's name and email come from the fields through accept
    • the link's email parameter does not override or fill in for the email field (invalid, multi-address or empty values)
    • fallbacks when a field is empty or unset, the name length cap, and a stale setting
    • the email parameter pre-fills the configured field on the signing page
    • the name reaches the Communication and the notification email
  • tests/test_demo.py checks the demo settings and the audit record's name.
  • frappe-test --ci: 105 tests pass, coverage 98.5%, testmap complete. prek run --all-files is clean. types/doctypes.d.ts is regenerated.
  • Screenshots: audit-trail was retaken and now shows "Document signed by Dana Whitfield". The new signer-settings (light and dark) shows the Signer section on the Web Form.

Docs

The README Features, Configuration and How It Works sections and docs/README.md are updated. The "Guest signers have no name in the audit trail" limitation is removed. It is replaced by a note that the name and email are what the signer typed, not a verified identity.

Notes

  • The signed PDF has no audit section (the README's Limitations say it carries no visual audit page), so nothing was added to it. Adding a page after the hash is computed would change what the hash covers.
  • Unrelated and existing behaviour: opening an eSign web form in the desk shows "Not Saved", because frappe's Web Form script sets allow_edit to 0 when login is not required. Saving restores it to 1 through validate. It is visible in the new screenshot.

Review follow-up

  • Get Fields and the signer selects (632c104). Get Fields adds rows with add_child and refresh_field, which fire no row or field event. On a new web form built with Get Fields, the Signer Name Field and Signer Email Field selects offered none of its fields until the form was reloaded. The options are now also refreshed when either select is focused or pressed, and the selects are re-rendered only when the list changed. Checked in the desk on the demo site: after a Data row was added the way Get Fields adds one, the select still lacked it; after the select was pressed, it listed the row and kept its selected value. yarn check and prek run --all-files are clean.
  • Reviewed and kept: the five new tests in test_web_form.py all fail against develop's web_form.py and web_form.json. The timeline card and email audit table escape the typed name.

🤖 Generated with Claude Code

https://claude.ai/code/session_01SvdEeMiewirZ3ifFoUix5F

batonac and others added 2 commits October 23, 2026 07:57
Add Signer Name Field and Signer Email Field to the eSign settings of a
Web Form. They name the form's own Data fields that hold the signer's
name and email, and the audit trail records what the signer submitted
there, so a guest signer is named on the timeline card and in the
notification email. With a Signer Email Field set, the link's email
parameter only pre-fills that field and is not recorded on its own.
Unset, the signer is identified as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SvdEeMiewirZ3ifFoUix5F
The Signer Name Field and Signer Email Field options were refreshed on
form refresh, row removal and a row's fieldname or fieldtype change.
Get Fields adds rows with add_child and refresh_field, which fire none
of those events, so on a new web form built with Get Fields the selects
offered none of its fields until the form was reloaded.

The options are now also refreshed when either select is focused or
pressed, and the selects are re-rendered only when the list changed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SvdEeMiewirZ3ifFoUix5F
@batonac
batonac merged commit 6f63664 into develop Oct 23, 2026
12 of 13 checks passed
@batonac
batonac deleted the feat/guest-signer-name branch October 23, 2026 12:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant