API users were inadvertently sending documents without signature fields, causing confusion for recipients and breaking their signing flows. - Add getRecipientsWithMissingFields helper in recipients.ts - Add server-side validation in sendDocument to block distribution - Fix v1 API to return 400 instead of 500 for validation errors - Consolidate UI signature field checks to use isSignatureFieldType - Add E2E tests for both v1 and v2 APIs
3.2 KiB
date, title
| date | title |
|---|---|
| 2026-01-26 | Validate Signer Fields On Distribute |
Summary
Validate that signers have at least one signature field before allowing document/envelope distribution via API, matching the existing UI behavior.
Background
The API originally allowed distributing documents/envelopes without validating that signers had signature fields assigned. This was intentional - we thought API users might have specific flows where this flexibility was needed.
However, after running it this way for a while, we've observed that more often than not, API users inadvertently send documents without fields assigned. This causes confusion for their recipients (who receive a document with nothing to sign) and breaks their own systems expecting a completed signing flow.
Problem
The API allowed distributing documents/envelopes even when signers had no signature fields assigned. This was inconsistent with the UI which validates this condition before allowing distribution.
Solution
1. Create centralized validation helper
File: packages/lib/utils/recipients.ts
- Added
RECIPIENT_ROLES_THAT_REQUIRE_FIELDSconstant (currently onlySIGNER) - Added
getRecipientsWithMissingFields()function that returns recipients missing required fields - Uses existing
isSignatureFieldTypeguard frompackages/prisma/guards/is-signature-field.ts
2. Add server-side validation
File: packages/lib/server-only/document/send-document.ts
- Added validation check that throws
AppErrorwithINVALID_REQUESTcode when signers are missing signature fields - This blocks both v1 and v2 API distribution endpoints since they both use
sendDocument()
3. Fix v1 API error handling
File: packages/api/v1/implementation.ts
- Changed
sendDocumentendpoint to useAppError.toRestAPIError(err)instead of always returning 500 - Now returns 400 for validation errors
4. Update UI to use shared helper
Files:
apps/remix/app/components/dialogs/envelope-distribute-dialog.tsxpackages/ui/primitives/document-flow/add-fields.tsx
5. Consolidate hasSignatureField checks
Updated to use isSignatureFieldType guard (checks both SIGNATURE and FREE_SIGNATURE):
apps/remix/app/components/general/document-signing/document-signing-form.tsxapps/remix/app/components/general/envelope-signing/envelope-signer-form.tsxapps/remix/app/components/embed/multisign/multi-sign-document-signing-view.tsxapps/remix/app/components/embed/embed-direct-template-client-page.tsxapps/remix/app/components/embed/embed-document-signing-page-v1.tsx
6. Add E2E tests
Files:
packages/app-tests/e2e/api/v1/document-sending.spec.ts- 5 new testspackages/app-tests/e2e/api/v2/distribute-validation.spec.ts- 8 new tests
Test Coverage
- Distribution fails when signer has no fields
- Distribution fails when signer has only non-signature fields
- Distribution succeeds with SIGNATURE field
- Distribution succeeds with FREE_SIGNATURE field (v1 only via Prisma)
- Distribution succeeds when VIEWER/CC/APPROVER have no fields
- Distribution fails when one of multiple signers is missing signature field
- Distribution succeeds when all signers have signature fields