Skip to content

chore(sync): merge upstream documenso/main (v2.18.0..c81bc72c4) - #14

Merged
JOY (JOY) merged 23 commits into
mainfrom
chore/sync-upstream-main
Sep 22, 2026
Merged

JOY (JOY) merged 23 commits into
mainfrom
chore/sync-upstream-main

Conversation

@JOY

Copy link
Copy Markdown

What

First upstream sync audit + merge of the 22 commits documenso/documenso landed on main since our fork base tag v2.18.0 (no v2.19.0 release exists yet, so the release-based sync script is a no-op today - this merges main directly, matching the fork's precedent commit 8606464).

Highlights: inbox filters, signing reason override env (NEXT_PRIVATE_SIGNING_REASON), template naming options, passwordless action auth fix (documenso#3358), bulk download dialog fix, base-path email asset fix.

Conflict resolution (2 files)

  • packages/signing/index.ts: took upstream's NEXT_PRIVATE_SIGNING_REASON(); our hardcoded branding moves to the prod env (NEXT_PRIVATE_SIGNING_REASON="Signed by Crove Sign") applied during deploy - zero code divergence.
  • apps/openpage-api/lib/cors.ts: took upstream's simplified cors; caller call-shapes are identical on both sides so no caller churn.

The branding patch (scripts/patch-crove-branding.mjs) ran post-merge: no source changes needed (favicon already matched).

Verification

  • Conflict probe pre-measured in a worktree: exactly these 2 files, both resolved to upstream side.
  • CI-equivalent biome check (LF worktree): 0 errors (841 warnings, non-blocking)
  • tsc --noEmit (remix): clean
  • @documenso/lib: 431/431 tests pass (6 new from upstream)

Deploy note

Production env addition required at deploy time: NEXT_PRIVATE_SIGNING_REASON="Signed by Crove Sign" (upstream default is the Documenso string).

Selecting password auth failed with a generic "Unauthorized" for users
who signed up via OAuth or passkey, with no way to set one.

Detect the missing password and email the existing reset link from the
signing dialog and security settings. Require a 2FA code and rate limit
update-password.
22 upstream commits since v2.18.0: inbox filters, signing reason
override env, template naming options, passwordless action auth fix
(documenso#3358), bulk download dialog fix, base path email asset fix, and
chores. Conflicts resolved: signing/index.ts takes the upstream
NEXT_PRIVATE_SIGNING_REASON() (branding default handled by the
branding patch), openpage-api cors.ts takes the upstream simplified
cors (caller signatures already match).

# Conflicts:
#	apps/openpage-api/lib/cors.ts
#	packages/signing/index.ts
@coderabbitai

coderabbitai Bot commented Sep 22, 2026

Copy link
Copy Markdown

Important

Review skipped

Too many files!

This PR contains 129 files, which is 29 over the limit of 100.

To get a review, reduce the PR to 100 files or fewer by splitting it into smaller PRs or changing its base branch.

Upgrade to a paid plan to raise the limit.

This review couldn't start because sufficient usage credits or metered capacity aren't available. Add credits or update usage-based reviews in the billing tab, then retry.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 45f99c8b-5687-4f99-abf8-6d568633cccf

📥 Commits

Reviewing files that changed from the base of the PR and between a79a327 and 61837f3.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (129)
  • .env.example
  • apps/docs/content/docs/developers/api/common-errors.mdx
  • apps/docs/content/docs/developers/api/fields.mdx
  • apps/docs/content/docs/developers/api/index.mdx
  • apps/docs/content/docs/developers/api/recipients.mdx
  • apps/docs/content/docs/developers/api/teams.mdx
  • apps/docs/content/docs/developers/api/templates.mdx
  • apps/docs/content/docs/developers/examples/common-workflows.mdx
  • apps/docs/content/docs/developers/getting-started/authentication.mdx
  • apps/docs/content/docs/developers/getting-started/first-api-call.mdx
  • apps/docs/package.json
  • apps/openpage-api/lib/cors.ts
  • apps/openpage-api/package.json
  • apps/remix/app/components/dialogs/envelopes-bulk-delete-dialog.tsx
  • apps/remix/app/components/dialogs/envelopes-bulk-download-dialog.tsx
  • apps/remix/app/components/dialogs/envelopes-bulk-move-dialog.tsx
  • apps/remix/app/components/dialogs/template-bulk-send-dialog.tsx
  • apps/remix/app/components/dialogs/template-use-dialog.tsx
  • apps/remix/app/components/embed/authoring/configure-document-recipients.tsx
  • apps/remix/app/components/forms/2fa/two-factor-code-dialog.tsx
  • apps/remix/app/components/forms/password-setup-request-button.tsx
  • apps/remix/app/components/forms/password-setup-request.tsx
  • apps/remix/app/components/forms/password.tsx
  • apps/remix/app/components/general/avatar-with-recipient.tsx
  • apps/remix/app/components/general/document-signing/document-signing-auth-password.tsx
  • apps/remix/app/components/general/document-signing/document-signing-auth-set-password.tsx
  • apps/remix/app/components/general/document/document-edit-form.tsx
  • apps/remix/app/components/general/document/document-search.tsx
  • apps/remix/app/components/general/envelope-editor/envelope-editor-recipient-form.tsx
  • apps/remix/app/components/general/envelope-editor/envelope-editor-settings-dialog.tsx
  • apps/remix/app/components/general/envelope-editor/envelope-editor-upload-page.tsx
  • apps/remix/app/components/general/skeletons/document-edit-skeleton.tsx
  • apps/remix/app/components/general/stack-avatar.tsx
  • apps/remix/app/components/general/stack-avatars-with-tooltip.tsx
  • apps/remix/app/components/general/stack-avatars.tsx
  • apps/remix/app/components/general/template/template-edit-form.tsx
  • apps/remix/app/components/general/template/template-search.tsx
  • apps/remix/app/components/general/user-profile-skeleton.tsx
  • apps/remix/app/components/tables/documents-table-status-filter.tsx
  • apps/remix/app/components/tables/inbox-table.tsx
  • apps/remix/app/components/tables/templates-table-action-dropdown.tsx
  • apps/remix/app/components/tables/templates-table-owner-filter.tsx
  • apps/remix/app/components/tables/templates-table-view-filter.tsx
  • apps/remix/app/routes/_authenticated+/admin+/claims.tsx
  • apps/remix/app/routes/_authenticated+/admin+/email-transports._index.tsx
  • apps/remix/app/routes/_authenticated+/admin+/organisation-stats._index.tsx
  • apps/remix/app/routes/_authenticated+/admin+/organisations._index.tsx
  • apps/remix/app/routes/_authenticated+/inbox.tsx
  • apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.members.tsx
  • apps/remix/app/routes/_authenticated+/o.$orgUrl.settings.teams.tsx
  • apps/remix/app/routes/_authenticated+/settings+/security._index.tsx
  • apps/remix/app/routes/_authenticated+/t.$teamUrl+/settings.groups.tsx
  • apps/remix/app/routes/_authenticated+/t.$teamUrl+/settings.members.tsx
  • apps/remix/app/routes/_authenticated+/t.$teamUrl+/settings.webhooks.$id._index.tsx
  • apps/remix/app/routes/_authenticated+/t.$teamUrl+/templates._index.tsx
  • apps/remix/app/utils/inbox-search-params.ts
  • apps/remix/app/utils/templates-search-params.ts
  • apps/remix/server/context.ts
  • package.json
  • packages/app-tests/e2e/api/trpc/find-inbox.spec.ts
  • packages/app-tests/e2e/document-auth/action-auth-password.spec.ts
  • packages/app-tests/e2e/documents/find-documents.spec.ts
  • packages/app-tests/e2e/documents/inbox.spec.ts
  • packages/app-tests/e2e/fixtures/hydration.ts
  • packages/app-tests/e2e/templates/manage-templates.spec.ts
  • packages/app-tests/e2e/templates/organisation-templates.spec.ts
  • packages/app-tests/e2e/templates/test-unauthorized-find-templates-access.spec.ts
  • packages/app-tests/e2e/user/password-two-factor.spec.ts
  • packages/auth/server/routes/email-password.ts
  • packages/auth/server/types/email-password.ts
  • packages/email/template-components/template-access-auth-2fa.tsx
  • packages/email/template-components/template-branding-logo.tsx
  • packages/email/template-components/template-document-completed.tsx
  • packages/email/template-components/template-document-image.tsx
  • packages/email/template-components/template-document-pending.tsx
  • packages/email/template-components/template-document-recipient-signed.tsx
  • packages/email/template-components/template-document-self-signed.tsx
  • packages/email/template-components/template-image.tsx
  • packages/email/templates/admin-user-created.tsx
  • packages/email/templates/reset-password.tsx
  • packages/email/utils/asset-url.ts
  • packages/lib/client-only/hooks/use-password-setup-request.ts
  • packages/lib/constants/app.test.ts
  • packages/lib/constants/app.ts
  • packages/lib/constants/time-zones.ts
  • packages/lib/errors/app-error.ts
  • packages/lib/jobs/definitions/emails/send-password-reset-success-email.handler.ts
  • packages/lib/jobs/definitions/emails/send-password-reset-success-email.ts
  • packages/lib/package.json
  • packages/lib/schemas/common.ts
  • packages/lib/server-only/2fa/disable-2fa.ts
  • packages/lib/server-only/2fa/enable-2fa.ts
  • packages/lib/server-only/2fa/validate-2fa.ts
  • packages/lib/server-only/2fa/view-backup-codes.ts
  • packages/lib/server-only/auth/send-reset-password.ts
  • packages/lib/server-only/document/resend-document.ts
  • packages/lib/server-only/rate-limit/rate-limits.ts
  • packages/lib/server-only/template/build-template-search-filter.ts
  • packages/lib/server-only/template/find-organisation-templates.ts
  • packages/lib/server-only/template/find-templates.ts
  • packages/lib/server-only/user/get-user-auth-methods.ts
  • packages/lib/server-only/user/reset-password.ts
  • packages/lib/server-only/user/update-password.ts
  • packages/lib/types/document-meta.ts
  • packages/lib/types/user-auth-method.ts
  • packages/lib/utils/is-valid-redirect-url.ts
  • packages/lib/utils/templates.ts
  • packages/lib/utils/user-auth-methods.test.ts
  • packages/lib/utils/user-auth-methods.ts
  • packages/prisma/prisma-middleware.ts
  • packages/signing/index.ts
  • packages/trpc/server/auth-router/get-auth-methods.ts
  • packages/trpc/server/auth-router/get-auth-methods.types.ts
  • packages/trpc/server/auth-router/router.ts
  • packages/trpc/server/document-router/find-inbox.ts
  • packages/trpc/server/document-router/find-inbox.types.ts
  • packages/trpc/server/embedding-router/_router.ts
  • packages/trpc/server/embedding-router/apply-multi-sign-signature.ts
  • packages/trpc/server/embedding-router/apply-multi-sign-signature.types.ts
  • packages/trpc/server/envelope-router/envelope-fields/update-envelope-fields.ts
  • packages/trpc/server/team-router/find-teams.ts
  • packages/trpc/server/template-router/find-templates-internal.ts
  • packages/trpc/server/template-router/find-templates-internal.types.ts
  • packages/trpc/server/template-router/router.ts
  • packages/tsconfig/process-env.d.ts
  • packages/ui/primitives/document-flow/add-settings.types.ts
  • packages/ui/primitives/document-flow/add-signers.tsx
  • packages/ui/primitives/template-flow/add-template-placeholder-recipients.tsx
  • packages/ui/primitives/template-flow/add-template-settings.types.tsx

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review

This pull request introduces several enhancements, including support for a customizable PDF signing reason, updated API documentation for CSC signing errors, and a migration to nuqs for search query state management across various routes. It also adds 2FA verification to password updates and introduces a password setup flow for passwordless users. Feedback on these changes highlights a critical error-handling issue where a notification failure after a successful password update transaction could cause a mismatch, a UI layout bug with nested PinInputGroup elements in the 2FA dialog, and a robustness improvement for handling empty member names in the templates filter.

Comment on lines +104 to +110
await jobsClient.triggerJob({
name: 'send.password.reset.success.email',
payload: {
userId,
source: 'UPDATE',
},
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

The jobsClient.triggerJob call is executed after the database transaction has successfully committed. If the job queue or Redis is temporarily unavailable, this call will throw an error, causing the entire updatePassword operation to fail with a 500 error. However, because the database transaction already succeeded, the user's password will have been updated in the database. This creates a critical mismatch where the user receives a failure message but their password was actually changed. Wrapping this call in a try/catch block ensures that a notification failure does not disrupt a successful password update.

  try {
    await jobsClient.triggerJob({
      name: 'send.password.reset.success.email',
      payload: {
        userId,
        source: 'UPDATE',
      },
    });
  } catch (err) {
    console.error('Failed to trigger password update notification email', err);
  }

Comment on lines +112 to +118
{Array(6)
.fill(null)
.map((_, i) => (
<PinInputGroup key={i}>
<PinInputSlot index={i} />
</PinInputGroup>
))}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Wrapping each PinInputSlot in its own PinInputGroup inside the loop will render six separate groups. In standard PIN/OTP input components, PinInputGroup acts as a styled container that manages borders and rounded corners for its child slots. Creating a separate group for each slot will break the visual layout (e.g., rendering individual rounded boxes instead of a single cohesive input field). Wrapping the loop inside a single PinInputGroup will fix the layout.

Suggested change
{Array(6)
.fill(null)
.map((_, i) => (
<PinInputGroup key={i}>
<PinInputSlot index={i} />
</PinInputGroup>
))}
<PinInputGroup>
{Array(6)
.fill(null)
.map((_, i) => (
<PinInputSlot key={i} index={i} />
))}
</PinInputGroup>

});

const options = (data ?? []).map((member) => ({
label: member.name ?? member.email,

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Using the nullish coalescing operator (??) on member.name will only fall back to member.email if member.name is strictly null or undefined. If a member's name is saved as an empty string (""), it will be used as the label, resulting in an empty option in the filter dropdown. Using the logical OR operator (||) and trimming the name is more robust and ensures a proper fallback.

Suggested change
label: member.name ?? member.email,
label: member.name?.trim() || member.email,

@JOY
JOY (JOY) merged commit 7ace15e into main Sep 22, 2026
11 of 12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants