feat: allow sending a document back to a signer for correction - #145
Conversation
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
🔁 PR #145 · changes-requestedBuild: ❌ · Playwright E2E: ❌
Screenshots |
🔁 PR #145 · changes-requestedBuild: ❌ · Playwright E2E: ❌
Screenshots |
🔁 PR #145 · changes-requestedBuild: ❌ · Playwright E2E: ❌
|
🔁 PR #145 · changes-requestedBuild: ✅ · Playwright E2E: ❌
What I testedI built PR #145 ( The recipient-initiated flow worked correctly end-to-end: the dialog opened, the "earlier recipients" dropdown was populated, submitting with a target recipient and reason produced a "Document sent back" toast, and I confirmed in Postgres that the target recipient's The document-owner flow is broken: clicking the "Send back for correction" icon button on the recipients list does nothing — the dialog never opens. In Screenshots in Screenshots |
Recipients and document owners can now route a pending envelope back to an earlier recipient (or the sender) to fix a mistake, instead of rejecting and restarting the whole document. The target recipient's signing status and fields are reset so they can redo their part; every other recipient's data is left untouched. Affected parties are notified by email and the action is recorded in the audit log. Closes #143
|
No description provided. |
✅ PR #145 · validatedBuild: ✅ · Playwright E2E: ✅
What I testedI validated PR #145 ("allow sending a pending document back to a signer for correction") by building commit The dialog closed and a "Document sent back" toast appeared. I then verified directly in Postgres that the mutation did exactly what the PR describes: Alice's Caveat: the Screenshots |
|
Caution The consumer version of Gemini Code Assist on GitHub has been sunset. All code review activity has officially ceased. |
















Problem
Freshservice ticket FS-162755: a recipient partway through signing a document has no way to fix a mistake made by an earlier recipient (or the sender) without rejecting the whole envelope. Reject immediately seals the document as terminal
REJECTED(packages/lib/server-only/document/reject-document-with-token.ts,packages/lib/jobs/definitions/internal/seal-document.handler.ts), which throws away every other recipient's work and forces starting over.Approach
Added a "send back for correction" action, modeled closely on the existing reject flow but non-terminal: the document stays
PENDING, and only the targeted recipient is reset.rejectDocumentWithToken) or the document owner (via an authenticated, team-scoped mutation, mirroringresendDocument).SIGNER/APPROVER/ASSISTANTrecipient who has already completed their part (signingStatus === SIGNED) — that's the concrete, checkable meaning of "earlier" given the schema has no linear recipient state machine. A recipient can also target "the sender" (the document owner), represented as anulltarget — that path is notification-only since the owner isn't aRecipientrow.signingStatus/signedAtand their ownField/Signaturerows are cleared. No schema migration was needed —SigningStatus.NOT_SIGNEDalready exists, and the correction reason is recorded on the audit log entry rather than a new column. Every other recipient's data is left untouched, satisfying the "already-collected signatures are preserved" acceptance criterion by construction rather than by extra bookkeeping.send.document.sent-back-for-correction.emails) emails whoever must act (the target recipient, or the owner if sent back to the sender), and separately notifies the document owner as an FYI when a recipient (not the owner) initiated the send-back.DOCUMENT_RECIPIENT_SENT_BACK_FOR_CORRECTIONentry, following the samecreateDocumentAuditLogDatapattern asDOCUMENT_RECIPIENT_REJECTED.Note on environment: this worktree's
packages/prisma/generated/directory was missing when I started (not caused by this change) — regenerated it withnpx prisma generateper the worktree's documented exception for that exact failure mode, since it was blocking typecheck.Rebuild note (validation attempt 3)
Validation attempt 2 found the owner-side "Send back for correction" icon button inert: the
triggerpassed toDocumentSendBackForCorrectionDialogwas a<TooltipProvider>tree, and Radix's<DialogTrigger asChild>clones its click handlers onto its immediate child — a bare context provider that renders no DOM node — so they never reached the<button>.Fixed by moving the tooltip outside the dialog component:
TooltipTrigger asChildnow clones onto a<span>wrapper, and the dialog's ownDialogTrigger asChildclones onto the<Button>directly. This matches the pattern already used a few lines below in the same file for the "Copy Signing Links" button, and matches every othertrigger-prop consumer in the repo, which all pass a single DOM-forwarding element. Single file changed:apps/remix/app/components/general/document/document-page-view-recipients.tsx.The recipient-initiated flow, the DB reset logic and the audit-log entry were all verified working in validation attempt 2 and are unchanged.
Changes
packages/lib/server-only/document/send-document-back-for-correction.ts— core logic:sendDocumentBackForCorrectionWithToken(recipient-initiated) andsendDocumentBackForCorrection(owner-initiated), sharing aresetRecipientForCorrectiontransaction helper.packages/lib/types/document-audit-logs.ts,packages/lib/utils/document-audit-logs.ts— new audit log type, Zod event schema, and human-readable formatting.packages/lib/jobs/definitions/emails/send-sent-back-for-correction-emails.{ts,handler.ts},packages/lib/jobs/client.ts— new background job that sends the correction/notification emails.packages/email/templates/document-sent-back-for-correction.tsx,packages/email/template-components/template-document-sent-back-for-correction.tsx— new email template (shared by the "please correct this" and "FYI" copy variants).packages/trpc/server/recipient-router/{schema,router}.ts—sendDocumentBackForCorrectionWithTokenmutation (token auth, likerejectDocumentWithToken).packages/trpc/server/envelope-router/send-back-for-correction.{ts,types.ts},packages/trpc/server/envelope-router/router.ts—sendBackForCorrectionmutation (authenticated, owner-initiated), registered asenvelope.sendBackForCorrection.apps/remix/app/components/general/document-signing/document-signing-send-back-dialog.tsx,document-signing-page-view-v2.tsx— recipient-side "Send Back for Correction" dialog in the signing page's Quick Actions, with a select for which earlier recipient (or the sender) to target.apps/remix/app/components/general/document/document-send-back-for-correction-dialog.tsx,document-page-view-recipients.tsx— owner-side action: a small icon button next to a "Signed" recipient's badge that opens the same kind of dialog scoped to that recipient. This build fixed the icon button's deadtriggerprop (see Rebuild note above).Test plan
npx tsc --noEmitviaapps/remix'snpm run typecheck— passes for every file touched by this change, with output identical before/after the fix (confirmed viagit stash/stash popdiff of the error set). The run surfaces ~20 pre-existing, unrelated errors from duplicate@lingui/corepackage versions (workspace hoisting), a missinggoogleapistype declaration, and a couple of ReactRefObject<T | null>generics — none in files this PR touches./sign/<token>→ Actions → Send Back for Correction: dialog opens, "earlier recipients" dropdown populates, submit produces a "Document sent back" toast.signingStatus→NOT_SIGNED,signedAtcleared, theirField.inserted/customTextcleared, theirSignaturerow deleted, other recipients untouched.DOCUMENT_RECIPIENT_SENT_BACK_FOR_CORRECTIONwritten with correct actor, target and reason.Closes #143