From 138d663c250e22d7d231efc4e22230eccd8e965e Mon Sep 17 00:00:00 2001 From: ephraimduncan Date: Tue, 12 May 2026 11:46:11 +0000 Subject: [PATCH] chore: merge main, resolve biome formatting conflicts Merge origin/main into feat/external-2fa-codes. Resolve formatting conflicts caused by biome rollout; preserve both feature streams: PR's external 2FA token + signing-session 2FA proof additions plus main's RateLimit/RecipientExpired/signingReminders/date-auto-insert. In complete-document-with-token.ts, drop the duplicate early field-fetching block introduced when main moved that logic later with date auto-insert support; keep the EXTERNAL_TWO_FACTOR_AUTH check using derivedRecipientActionAuth. --- ...t-emerald-flower-bullmq-background-jobs.md | 239 + .../calm-violet-tide-envelope-expiration.md | 519 + ...zel-beam-swap-subscription-between-orgs.md | 151 + ...resh-gold-rock-cert-page-width-mismatch.md | 168 + ...eal-tree-platform-signing-page-branding.md | 138 + .../plans/pale-lemon-rock-pnpm-migration.md | 312 + ...ooth-coral-earth-database-rate-limiting.md | 551 + ...h-ivory-sky-partial-signed-pdf-download.md | 94 + ...r-custom-email-domain-sync-and-recovery.md | 263 + ...-teal-wind-add-folder-support-to-v1-api.md | 210 + .../scratches/search-query-optimization.md | 113 + .agents/skills/agent-browser/SKILL.md | 207 + .../references/authentication.md | 202 + .../agent-browser/references/commands.md | 259 + .../agent-browser/references/proxy-support.md | 188 + .../references/session-management.md | 193 + .../agent-browser/references/snapshot-refs.md | 194 + .../references/video-recording.md | 173 + .../templates/authenticated-session.sh | 97 + .../templates/capture-workflow.sh | 69 + .../templates/form-automation.sh | 62 + .agents/skills/create-documentation/SKILL.md | 337 + .../skills}/create-justification/SKILL.md | 0 .../skills}/create-plan/SKILL.md | 0 .../skills}/create-scratch/SKILL.md | 0 .../skills/envelope-editor-v2-e2e/SKILL.md | 371 + .env.example | 31 +- .eslintignore | 8 - .eslintrc.cjs | 16 - .github/actions/node-install/action.yml | 4 + .github/labeler.yml | 5 +- .github/workflows/e2e-tests.yml | 1 + .gitignore | 7 + .npmrc | 3 +- .opencode/commands/create-documentation.md | 27 + .opencode/commands/create-justification.md | 68 +- .opencode/commands/create-plan.md | 69 +- .opencode/commands/create-scratch.md | 68 +- .opencode/commands/document.md | 201 - .prettierignore | 17 - .vscode/settings.json | 24 +- AGENTS.md | 2 +- ARCHITECTURE.md | 358 + README.md | 3 + WRITING_STYLE.md | 343 + apps/docs/.gitignore | 26 + apps/docs/README.md | 45 + apps/docs/cli.json | 13 + .../docs/compliance/certifications.mdx | 57 + apps/docs/content/docs/compliance/esign.mdx | 187 + apps/docs/content/docs/compliance/gdpr.mdx | 174 + apps/docs/content/docs/compliance/index.mdx | 58 + apps/docs/content/docs/compliance/meta.json | 4 + .../docs/compliance/signature-levels.mdx | 284 + .../content/docs/compliance/standards.mdx | 108 + .../docs/concepts/document-lifecycle.mdx | 97 + .../content/docs/concepts/field-types.mdx | 314 + apps/docs/content/docs/concepts/index.mdx | 70 + apps/docs/content/docs/concepts/meta.json | 4 + .../content/docs/concepts/recipient-roles.mdx | 171 + .../docs/concepts/signing-certificates.mdx | 123 + .../docs/concepts/signing-workflow.mdx | 260 + .../docs/developers/api/developer-mode.mdx | 42 + .../content/docs/developers/api/documents.mdx | 819 + .../content/docs/developers/api/fields.mdx | 742 + .../content/docs/developers/api/index.mdx | 72 + .../content/docs/developers/api/meta.json | 4 + .../docs/developers/api}/rate-limits.mdx | 14 +- .../docs/developers/api/recipients.mdx | 504 + .../content/docs/developers/api/teams.mdx | 373 + .../content/docs/developers/api/templates.mdx | 1030 + .../docs/developers/api}/versioning.mdx | 11 +- .../contributing-translations.mdx | 53 +- .../docs}/developers/contributing/index.mdx | 61 +- .../docs/developers/contributing/meta.json | 4 + .../developers/demo-environment/index.mdx | 64 + .../developers/embedding/authoring/index.mdx | 56 + .../developers/embedding/authoring/meta.json | 4 + .../developers/embedding/authoring/v1.mdx | 300 + .../developers/embedding/authoring/v2.mdx | 344 + .../developers/embedding/css-variables.mdx | 216 + .../developers/embedding/direct-links.mdx | 514 + .../docs/developers/embedding/index.mdx | 244 + .../docs/developers/embedding/meta.json | 4 + .../developers/embedding/sdks/angular.mdx | 92 + .../docs/developers/embedding/sdks/index.mdx | 37 + .../docs/developers/embedding/sdks/meta.json | 4 + .../docs/developers/embedding/sdks/preact.mdx | 96 + .../docs/developers/embedding/sdks/react.mdx | 136 + .../docs/developers/embedding/sdks/solid.mdx | 96 + .../docs/developers/embedding/sdks/svelte.mdx | 104 + .../docs/developers/embedding/sdks/vue.mdx | 107 + .../developers/examples/common-workflows.mdx | 1157 ++ .../docs/developers/examples/index.mdx | 12 + .../docs/developers/examples/meta.json | 4 + .../getting-started/authentication.mdx | 202 + .../getting-started/first-api-call.mdx | 519 + .../docs/developers/getting-started/index.mdx | 17 + .../docs/developers/getting-started/meta.json | 4 + apps/docs/content/docs/developers/index.mdx | 87 + .../developers/local-development/gitpod.mdx | 7 +- .../developers/local-development/index.mdx | 13 +- .../developers/local-development/manual.mdx | 54 +- .../developers/local-development/meta.json | 4 + .../local-development/quickstart.mdx | 37 +- .../local-development/signing-certificate.mdx | 39 +- .../local-development/translations.mdx | 8 +- apps/docs/content/docs/developers/meta.json | 15 + .../docs/developers/webhooks/events.mdx | 867 + .../docs/developers/webhooks/index.mdx | 65 + .../docs/developers/webhooks/meta.json | 4 + .../docs/developers/webhooks/setup.mdx | 361 + .../docs/developers/webhooks/verification.mdx | 296 + apps/docs/content/docs/index.mdx | 163 + apps/docs/content/docs/meta.json | 13 + .../docs/policies/community-edition.mdx | 205 + .../docs/policies/enterprise-edition.mdx | 244 + apps/docs/content/docs/policies/fair-use.mdx | 68 + apps/docs/content/docs/policies/index.mdx | 47 + apps/docs/content/docs/policies/licenses.mdx | 173 + apps/docs/content/docs/policies/meta.json | 13 + apps/docs/content/docs/policies/privacy.mdx | 6 + apps/docs/content/docs/policies/security.mdx | 242 + apps/docs/content/docs/policies/support.mdx | 240 + apps/docs/content/docs/policies/terms.mdx | 6 + .../configuration/advanced}/ai-features.mdx | 58 +- .../configuration/advanced/index.mdx | 17 + .../configuration/advanced/meta.json | 4 + .../advanced/oauth-providers.mdx | 155 + .../configuration/background-jobs.mdx | 187 + .../self-hosting/configuration/database.mdx | 490 + .../docs/self-hosting/configuration/email.mdx | 473 + .../configuration/environment.mdx | 402 + .../docs/self-hosting/configuration/index.mdx | 47 + .../docs/self-hosting/configuration/meta.json | 13 + .../signing-certificate/google-cloud-hsm.mdx | 95 + .../signing-certificate/index.mdx | 85 + .../signing-certificate/local.mdx | 202 + .../signing-certificate/meta.json | 4 + .../signing-certificate/timestamp-server.mdx | 68 + .../signing-certificate/troubleshooting.mdx | 91 + .../self-hosting/configuration/storage.mdx | 569 + .../self-hosting/configuration}/telemetry.mdx | 59 +- .../deployment/docker-compose.mdx | 494 + .../docs/self-hosting/deployment/docker.mdx | 312 + .../docs/self-hosting/deployment/index.mdx | 39 + .../self-hosting/deployment/kubernetes.mdx | 868 + .../docs/self-hosting/deployment/manual.mdx | 162 + .../docs/self-hosting/deployment/meta.json | 4 + .../docs/self-hosting/deployment/railway.mdx | 474 + .../self-hosting/getting-started/index.mdx | 17 + .../self-hosting/getting-started/meta.json | 4 + .../getting-started/quick-start.mdx | 186 + .../getting-started/requirements.mdx | 178 + .../self-hosting/getting-started/tips.mdx | 176 + apps/docs/content/docs/self-hosting/index.mdx | 144 + .../docs/self-hosting/maintenance/backups.mdx | 674 + .../docs/self-hosting/maintenance/index.mdx | 22 + .../docs/self-hosting/maintenance/meta.json | 4 + .../maintenance/troubleshooting.mdx | 1222 ++ .../self-hosting/maintenance/upgrades.mdx | 651 + apps/docs/content/docs/self-hosting/meta.json | 6 + .../docs/users/documents/add-fields.mdx | 296 + .../docs/users/documents/add-recipients.mdx | 187 + .../users/documents/advanced/ai-detection.mdx | 132 + .../documents/advanced/default-recipients.mdx | 54 + .../advanced/document-visibility.mdx | 74 + .../docs/users/documents/advanced/index.mdx | 37 + .../docs/users/documents/advanced/meta.json | 12 + .../documents/advanced}/pdf-placeholders.mdx | 43 +- .../advanced/recipient-expiration.mdx | 183 + .../documents/advanced/signing-reminders.mdx | 195 + .../docs/users/documents/direct-links.mdx | 226 + .../content/docs/users/documents/index.mdx | 30 + .../content/docs/users/documents/meta.json | 4 + .../content/docs/users/documents/send.mdx | 236 + .../content/docs/users/documents/upload.mdx | 158 + .../users/getting-started/create-account.mdx | 109 + .../docs/users/getting-started/index.mdx | 17 + .../docs/users/getting-started/meta.json | 4 + .../getting-started/send-first-document.mdx | 108 + apps/docs/content/docs/users/index.mdx | 145 + apps/docs/content/docs/users/meta.json | 6 + .../docs}/users/organisations/billing.mdx | 11 +- .../docs/users/organisations/create-team.mdx | 166 + .../users/organisations}/email-domains.mdx | 67 +- .../docs/users/organisations/groups.mdx | 150 + .../docs/users/organisations/index.mdx | 55 + .../docs/users/organisations/members.mdx | 214 + .../docs/users/organisations/meta.json | 4 + .../docs/users/organisations/overview.mdx | 99 + .../organisations/preferences/branding.mdx | 149 + .../organisations/preferences/document.mdx | 56 + .../users/organisations/preferences/email.mdx | 32 + .../users/organisations/preferences/index.mdx | 26 + .../users/organisations/preferences/meta.json | 4 + .../single-sign-on/configuration.mdx | 266 + .../organisations/single-sign-on/index.mdx | 25 + .../organisations/single-sign-on/meta.json | 4 + .../single-sign-on/microsoft-entra-id.mdx | 125 + .../docs/users/settings/api-tokens.mdx | 26 + .../docs/users/settings/delete-account.mdx | 44 + .../content/docs/users/settings/index.mdx | 43 + .../content/docs/users/settings/meta.json | 4 + .../content/docs/users/settings/profile.mdx | 78 + .../docs/users/settings/public-profile.mdx | 67 + .../content/docs/users/settings/security.mdx | 166 + .../content/docs/users/settings/sessions.mdx | 82 + .../content/docs/users/templates/create.mdx | 217 + .../content/docs/users/templates/index.mdx | 39 + .../content/docs/users/templates/meta.json | 4 + .../templates/organisation-templates.mdx | 131 + .../docs/content/docs/users/templates/use.mdx | 147 + apps/docs/next.config.mjs | 462 + apps/docs/package.json | 36 + apps/docs/postcss.config.mjs | 5 + .../public/apple-touch-icon.png | Bin ...nisation-default-recipients-role-step.webp | Bin ...sation-default-recipients-select-step.webp | Bin .../team-default-recipients.webp | Bin .../field-coordinates-legacy-editor.webp | Bin 0 -> 119594 bytes .../field-coordinates-new-editor.webp | Bin 0 -> 128834 bytes ...hoose-direct-link-recipient-documenso.webp | Bin .../direct-links/documenso-profile.webp | Bin .../document-direct-link-documenso.webp | Bin .../enable-document-direct-link-modal.webp | Bin .../ai-field-detection-button.webp | Bin .../ai-field-detection-dialog.webp | Bin .../ai-recipient-detect-button.webp | Bin .../checkbox-field-document-editor-view.webp | Bin .../date-field-document-editor-view.webp | Bin .../documenso-document-email-settings.webp | Bin .../documenso-document-fields.webp | Bin .../documenso-documents-dashboard.webp | Bin .../documenso-editor-email-settings.webp | Bin .../documenso-editor-general-settings.webp | Bin .../documenso-editor-preview.webp | Bin .../documenso-editor-security-settings.webp | Bin .../documenso-sign-email.webp | Bin .../documenso-signing-links.webp | Bin .../dropdown-field-document-editor-view.webp | Bin .../document-signing/editor-overview.webp | Bin .../editor-upload-recipients.webp | Bin .../email-field-document-editor-view.webp | Bin .../initials-field-document-editor-view.webp | Bin .../name-field-document-editor-view.webp | Bin .../number-field-document-editor-view.webp | Bin .../radio-field-document-editor-view.webp | Bin .../signature-field-document-editor-view.webp | Bin .../text-field-document-editor-view.webp | Bin .../email-domains/email-domain-sync.webp | Bin .../email-domains-manage-create-email.webp | Bin .../email-domains/email-domains-manage.webp | Bin .../email-domains/email-domains-record.webp | Bin .../email-domains-settings-page.webp | Bin .../public/embedding/copy-recipient-token.png | Bin .../public/embedding/enable-direct-link.png | Bin .../public/embedding/team-templates.png | Bin .../public/favicon-16x16.png | Bin .../public/favicon-32x32.png | Bin apps/docs/public/fonts/inter-bold.ttf | Bin 0 -> 316100 bytes apps/docs/public/fonts/inter-regular.ttf | Bin 0 -> 309828 bytes apps/docs/public/fonts/inter-semibold.ttf | Bin 0 -> 315756 bytes .../documenso-account-security-page.webp | Bin .../documenso-add-passkey-box.webp | Bin ...umenso-enable-2-factor-authentication.webp | Bin .../documenso-passkeys-page.webp | Bin apps/docs/public/logo.png | Bin 0 -> 4119 bytes .../organisations/organisation-branding.webp | Bin .../organisation-document-preferences.webp | Bin .../organisation-document-visibility.webp | Bin .../organisation-email-preferences.webp | Bin .../organisation-group-assignment.webp | Bin .../organisation-group-create.webp | Bin .../organisation-group-manage.webp | Bin .../organisations-basic-diagram.webp | Bin .../organisations/organisations-billing.webp | Bin .../organisations/organisations-create.webp | Bin .../organisations-member-invite.webp | Bin .../organisations-sso-settings.webp | Bin .../api-tokens-page-documenso.webp | Bin .../documenso-api-key-blurred.webp | Bin .../documenso-user-dropdown-menu.webp | Bin ...umenso-enable-public-profile-settings.webp | Bin .../documenso-public-profile-settings.webp | Bin .../configure-expiration.webp | Bin 0 -> 127262 bytes .../recipient-expired.webp | Bin 0 -> 124274 bytes .../teams/document-visibility-settings.webp | Bin .../public/teams/team-create-dialog.webp | Bin .../public/teams/team-create.webp | Bin ...menso-template-page-uploaded-document.webp | Bin .../templates/documenso-template-page.webp | Bin .../documenso-template-recipients.webp | Bin .../templates/documenso-use-template.webp | Bin .../webhook-images/create-webhook-dialog.webp | Bin .../webhook-images/documenso-main-page.webp | Bin .../webhook-images/webhook-detail-page.webp | Bin .../webhook-images/webhook-run-page.webp | Bin .../webhook-images/webhook-test-trigger.webp | Bin .../webhook-images/webhooks-main-page.webp | Bin .../public/webhook-images/webhooks-page.webp | Bin apps/docs/source.config.ts | 23 + apps/docs/src/app/(home)/layout.tsx | 6 + apps/docs/src/app/(home)/page.tsx | 258 + apps/docs/src/app/api/search/route.ts | 7 + apps/docs/src/app/apple-icon.png | Bin 0 -> 14365 bytes apps/docs/src/app/docs/[[...slug]]/page.tsx | 71 + apps/docs/src/app/docs/layout.tsx | 114 + apps/docs/src/app/favicon.ico | Bin 0 -> 5430 bytes apps/docs/src/app/global.css | 177 + apps/docs/src/app/layout.tsx | 39 + apps/docs/src/app/llms-full.txt/route.ts | 10 + .../app/llms.mdx/docs/[[...slug]]/route.ts | 24 + apps/docs/src/app/llms.txt/route.ts | 16 + apps/docs/src/app/not-found.tsx | 26 + apps/docs/src/app/og/docs/[...slug]/route.tsx | 145 + apps/docs/src/app/robots.ts | 12 + apps/docs/src/app/sitemap.ts | 20 + apps/docs/src/components/ai/page-actions.tsx | 158 + apps/docs/src/components/mdx/mermaid.tsx | 66 + apps/docs/src/lib/cn.ts | 1 + apps/docs/src/lib/layout.shared.tsx | 23 + apps/docs/src/lib/merge-refs.ts | 13 + apps/docs/src/lib/source.ts | 80 + apps/docs/src/mdx-components.tsx | 14 + apps/{documentation => docs}/tsconfig.json | 36 +- apps/documentation/.gitignore | 41 - apps/documentation/README.md | 1 - .../components/call-to-action.tsx | 35 - apps/documentation/next-sitemap.config.js | 5 - apps/documentation/next.config.ts | 21 - apps/documentation/package.json | 32 - apps/documentation/pages/_app.tsx | 18 - apps/documentation/pages/_meta.js | 34 - apps/documentation/pages/developers/_meta.js | 19 - .../pages/developers/contributing/_meta.js | 4 - .../developer-mode/field-coordinates.mdx | 26 - .../pages/developers/embedded-authoring.mdx | 396 - .../pages/developers/embedding/_meta.js | 10 - .../pages/developers/embedding/angular.mdx | 90 - .../developers/embedding/css-variables.mdx | 197 - .../pages/developers/embedding/index.mdx | 200 - .../pages/developers/embedding/preact.mdx | 107 - .../pages/developers/embedding/react.mdx | 111 - .../pages/developers/embedding/solid.mdx | 107 - .../pages/developers/embedding/svelte.mdx | 107 - .../pages/developers/embedding/vue.mdx | 114 - apps/documentation/pages/developers/index.mdx | 18 - .../developers/local-development/_meta.js | 8 - .../pages/developers/public-api/_meta.js | 6 - .../developers/public-api/authentication.mdx | 53 - .../pages/developers/public-api/index.mdx | 49 - .../pages/developers/public-api/reference.mdx | 456 - .../pages/developers/self-hosting/_meta.js | 8 - .../pages/developers/self-hosting/how-to.mdx | 399 - .../pages/developers/self-hosting/index.mdx | 12 - .../setting-up-oauth-providers.mdx | 59 - .../self-hosting/signing-certificate.mdx | 73 - .../pages/developers/webhooks.mdx | 659 - apps/documentation/pages/index.mdx | 73 - apps/documentation/pages/users/_meta.js | 23 - apps/documentation/pages/users/branding.mdx | 28 - .../pages/users/compliance/_meta.js | 4 - .../users/compliance/signature-levels.mdx | 110 - .../compliance/standards-and-regulations.mdx | 52 - .../pages/users/direct-links.mdx | 48 - .../pages/users/documents/_meta.js | 10 - .../pages/users/documents/ai-detection.mdx | 68 - .../users/documents/default-recipients.mdx | 45 - .../users/documents/document-preferences.mdx | 44 - .../users/documents/document-visibility.mdx | 53 - .../users/documents/email-preferences.mdx | 26 - .../pages/users/documents/fields.mdx | 199 - .../users/documents/sending-documents.mdx | 209 - apps/documentation/pages/users/fair-use.mdx | 47 - .../users/get-started/account-creation.mdx | 38 - .../users/get-started/account-security.mdx | 91 - apps/documentation/pages/users/index.mdx | 8 - .../pages/users/licenses/_meta.js | 5 - .../users/licenses/community-edition.mdx | 49 - .../users/licenses/enterprise-edition.mdx | 57 - .../pages/users/licenses/index.mdx | 21 - .../pages/users/organisations/_meta.js | 8 - .../pages/users/organisations/groups.mdx | 75 - .../pages/users/organisations/index.mdx | 65 - .../pages/users/organisations/members.mdx | 65 - .../pages/users/organisations/sso/_meta.js | 4 - .../pages/users/organisations/sso/index.mdx | 149 - .../organisations/sso/microsoft-entra-id.mdx | 76 - .../pages/users/organisations/teams.mdx | 121 - apps/documentation/pages/users/profile.mdx | 70 - apps/documentation/pages/users/support.mdx | 38 - apps/documentation/pages/users/templates.mdx | 66 - apps/documentation/postcss.config.cjs | 6 - apps/documentation/postcss.config.js | 6 - apps/documentation/providers/plausible.tsx | 11 - .../field-coordinates-legacy-editor.webp | Bin 610065 -> 0 bytes .../field-coordinates-new-editor.webp | Bin 585032 -> 0 bytes .../public/images/admin-license-status.webp | Bin 76524 -> 0 bytes apps/documentation/styles.css | 7 - apps/documentation/styles/globals.css | 3 - apps/documentation/tailwind.config.cjs | 21 - apps/documentation/theme.config.tsx | 66 - .../app/community/total-forks/route.ts | 1 + .../app/community/total-issues/route.ts | 1 + .../app/community/total-prs/route.ts | 1 + .../app/community/total-stars/route.ts | 1 + apps/openpage-api/app/github/forks/route.ts | 1 + apps/openpage-api/app/github/issues/route.ts | 1 + apps/openpage-api/app/github/prs/route.ts | 1 + apps/openpage-api/app/github/stars/route.ts | 1 + .../app/growth/completed-documents/route.ts | 1 + .../app/growth/new-users/route.ts | 1 + .../app/growth/signer-conversion/route.ts | 1 + .../growth/total-completed-documents/route.ts | 1 + .../app/growth/total-customers/route.ts | 1 + .../growth/total-signer-conversion/route.ts | 1 + .../app/growth/total-users/route.ts | 1 + apps/openpage-api/lib/add-zero-month.ts | 52 +- apps/openpage-api/lib/cors.ts | 23 +- .../growth/get-monthly-completed-document.ts | 16 +- .../lib/growth/get-signer-conversion.ts | 13 +- .../lib/growth/get-user-monthly-growth.ts | 12 +- apps/openpage-api/lib/transform-data.ts | 23 +- apps/openpage-api/package.json | 2 +- apps/openpage-api/tsconfig.json | 4 +- apps/remix/app/app.css | 36 +- .../dialogs/account-delete-dialog.tsx | 32 +- .../dialogs/admin-document-delete-dialog.tsx | 31 +- .../admin-organisation-create-dialog.tsx | 48 +- ...dmin-organisation-member-delete-dialog.tsx | 133 + ...dmin-organisation-member-update-dialog.tsx | 54 +- .../admin-swap-subscription-dialog.tsx | 181 + .../admin-team-member-delete-dialog.tsx | 128 + .../dialogs/admin-user-delete-dialog.tsx | 33 +- .../dialogs/admin-user-disable-dialog.tsx | 41 +- .../dialogs/admin-user-enable-dialog.tsx | 37 +- .../admin-user-reset-two-factor-dialog.tsx | 45 +- .../dialogs/ai-features-enable-dialog.tsx | 52 +- .../dialogs/ai-field-detection-dialog.tsx | 65 +- .../dialogs/ai-recipient-detection-dialog.tsx | 59 +- .../dialogs/assistant-confirmation-dialog.tsx | 43 +- .../dialogs/claim-create-dialog.tsx | 17 +- .../dialogs/claim-delete-dialog.tsx | 13 +- .../dialogs/claim-update-dialog.tsx | 15 +- .../dialogs/document-duplicate-dialog.tsx | 133 - .../document-move-to-folder-dialog.tsx | 39 +- .../dialogs/document-resend-dialog.tsx | 40 +- ...-dialog.tsx => envelope-delete-dialog.tsx} | 101 +- .../dialogs/envelope-distribute-dialog.tsx | 101 +- .../dialogs/envelope-download-dialog.tsx | 176 +- .../dialogs/envelope-duplicate-dialog.tsx | 89 +- .../dialogs/envelope-item-delete-dialog.tsx | 58 +- .../dialogs/envelope-item-edit-dialog.tsx | 344 + .../dialogs/envelope-redistribute-dialog.tsx | 33 +- .../dialogs/envelope-rename-dialog.tsx | 120 + .../envelope-save-as-template-dialog.tsx | 176 + .../dialogs/envelopes-bulk-delete-dialog.tsx | 21 +- .../dialogs/envelopes-bulk-move-dialog.tsx | 45 +- .../dialogs/folder-create-dialog.tsx | 48 +- .../dialogs/folder-delete-dialog.tsx | 36 +- .../components/dialogs/folder-move-dialog.tsx | 34 +- .../dialogs/folder-update-dialog.tsx | 32 +- .../dialogs/organisation-create-dialog.tsx | 109 +- .../dialogs/organisation-delete-dialog.tsx | 38 +- .../organisation-email-create-dialog.tsx | 27 +- .../organisation-email-delete-dialog.tsx | 50 +- ...rganisation-email-domain-create-dialog.tsx | 47 +- ...rganisation-email-domain-delete-dialog.tsx | 33 +- ...ganisation-email-domain-records-dialog.tsx | 17 +- .../organisation-email-update-dialog.tsx | 26 +- .../organisation-group-create-dialog.tsx | 87 +- .../organisation-group-delete-dialog.tsx | 55 +- .../dialogs/organisation-leave-dialog.tsx | 46 +- .../organisation-member-delete-dialog.tsx | 14 +- .../organisation-member-invite-dialog.tsx | 115 +- .../organisation-member-update-dialog.tsx | 62 +- .../dialogs/passkey-create-dialog.tsx | 61 +- .../public-profile-template-manage-dialog.tsx | 84 +- .../dialogs/session-logout-all-dialog.tsx | 10 +- .../dialogs/sign-field-checkbox-dialog.tsx | 279 +- .../dialogs/sign-field-dropdown-dialog.tsx | 5 +- .../dialogs/sign-field-email-dialog.tsx | 32 +- .../dialogs/sign-field-initials-dialog.tsx | 129 +- .../dialogs/sign-field-name-dialog.tsx | 122 +- .../dialogs/sign-field-number-dialog.tsx | 25 +- .../dialogs/sign-field-signature-dialog.tsx | 36 +- .../dialogs/sign-field-text-dialog.tsx | 155 +- .../components/dialogs/team-create-dialog.tsx | 85 +- .../components/dialogs/team-delete-dialog.tsx | 55 +- .../dialogs/team-email-add-dialog.tsx | 49 +- .../dialogs/team-email-delete-dialog.tsx | 64 +- .../dialogs/team-email-update-dialog.tsx | 44 +- .../dialogs/team-group-create-dialog.tsx | 99 +- .../dialogs/team-group-delete-dialog.tsx | 19 +- .../dialogs/team-group-update-dialog.tsx | 46 +- .../team-inherit-member-disable-dialog.tsx | 9 +- .../team-inherit-member-enable-dialog.tsx | 8 +- .../dialogs/team-member-create-dialog.tsx | 210 +- .../dialogs/team-member-delete-dialog.tsx | 58 +- .../dialogs/team-member-update-dialog.tsx | 43 +- .../dialogs/template-bulk-send-dialog.tsx | 70 +- .../dialogs/template-delete-dialog.tsx | 93 - .../dialogs/template-direct-link-dialog.tsx | 99 +- .../dialogs/template-duplicate-dialog.tsx | 89 - .../template-move-to-folder-dialog.tsx | 35 +- .../dialogs/template-use-dialog.tsx | 134 +- .../dialogs/token-delete-dialog.tsx | 51 +- .../dialogs/webhook-create-dialog.tsx | 52 +- .../dialogs/webhook-delete-dialog.tsx | 43 +- .../dialogs/webhook-edit-dialog.tsx | 44 +- .../dialogs/webhook-test-dialog.tsx | 46 +- .../configure-document-advanced-settings.tsx | 47 +- .../configure-document-recipients.tsx | 80 +- .../authoring/configure-document-upload.tsx | 56 +- .../authoring/configure-document-view.tsx | 36 +- .../configure-document-view.types.ts | 11 +- .../embed/authoring/configure-fields-view.tsx | 148 +- .../authoring/configure-fields-view.types.ts | 7 +- .../field-advanced-settings-drawer.tsx | 12 +- .../embed/embed-authentication-required.tsx | 8 +- .../components/embed/embed-client-loading.tsx | 7 +- .../embed-direct-template-client-page.tsx | 152 +- .../embed/embed-document-completed.tsx | 12 +- .../embed/embed-document-fields.tsx | 24 +- .../embed/embed-document-rejected.tsx | 14 +- .../embed/embed-document-signing-page-v1.tsx | 135 +- .../embed/embed-document-signing-page-v2.tsx | 42 +- .../embed/embed-document-waiting-for-turn.tsx | 11 +- .../app/components/embed/embed-paywall.tsx | 21 +- .../embed/embed-recipient-expired.tsx | 44 + .../embed/embed-signing-context.tsx | 14 +- .../multisign/multi-sign-document-list.tsx | 61 +- .../multi-sign-document-signing-view.tsx | 160 +- .../components/filters/date-range-filter.tsx | 16 +- .../2fa/disable-authenticator-app-dialog.tsx | 37 +- .../2fa/enable-authenticator-app-dialog.tsx | 220 +- .../forms/2fa/recovery-code-list.tsx | 19 +- .../forms/2fa/view-recovery-codes-dialog.tsx | 30 +- .../app/components/forms/avatar-image.tsx | 44 +- .../forms/branding-preferences-form.tsx | 308 +- .../forms/document-preferences-form.tsx | 182 +- .../editor/editor-field-checkbox-form.tsx | 77 +- .../forms/editor/editor-field-date-form.tsx | 22 +- .../editor/editor-field-dropdown-form.tsx | 57 +- .../forms/editor/editor-field-email-form.tsx | 20 +- .../editor-field-generic-field-forms.tsx | 49 +- .../editor/editor-field-initials-form.tsx | 15 +- .../forms/editor/editor-field-name-form.tsx | 15 +- .../forms/editor/editor-field-number-form.tsx | 61 +- .../forms/editor/editor-field-radio-form.tsx | 53 +- .../editor/editor-field-signature-form.tsx | 20 +- .../forms/editor/editor-field-text-form.tsx | 27 +- .../forms/email-preferences-form.tsx | 63 +- .../app/components/forms/forgot-password.tsx | 28 +- .../forms/organisation-update-form.tsx | 30 +- apps/remix/app/components/forms/password.tsx | 41 +- apps/remix/app/components/forms/profile.tsx | 37 +- .../components/forms/public-profile-form.tsx | 62 +- .../app/components/forms/reset-password.tsx | 37 +- .../forms/search-param-selector.tsx | 10 +- .../forms/send-confirmation-email.tsx | 32 +- apps/remix/app/components/forms/signin.tsx | 171 +- apps/remix/app/components/forms/signup.tsx | 400 +- .../forms/subscription-claim-form.tsx | 78 +- .../components/forms/support-ticket-form.tsx | 122 +- .../app/components/forms/team-update-form.tsx | 26 +- apps/remix/app/components/forms/token.tsx | 102 +- .../app/components/general/admin-details.tsx | 40 + .../general/admin-global-settings-section.tsx | 152 + .../components/general/admin-license-card.tsx | 105 +- .../general/admin-license-status-banner.tsx | 28 +- .../admin-monthly-active-user-charts.tsx | 7 +- .../admin-stats-signer-conversion-chart.tsx | 12 +- .../admin-stats-users-with-documents.tsx | 21 +- .../general/animated-document-scanner.tsx | 18 +- .../app/components/general/app-banner.tsx | 4 +- .../components/general/app-command-menu.tsx | 152 +- .../app/components/general/app-header.tsx | 31 +- .../components/general/app-nav-desktop.tsx | 39 +- .../app/components/general/app-nav-mobile.tsx | 29 +- .../general/avatar-with-recipient.tsx | 21 +- .../app/components/general/billing-plans.tsx | 63 +- .../app/components/general/claim-account.tsx | 38 +- ...efault-recipients-multiselect-combobox.tsx | 36 +- .../direct-template-configure-form.tsx | 42 +- .../direct-template/direct-template-page.tsx | 56 +- .../direct-template-signing-auth-page.tsx | 14 +- .../direct-template-signing-form.tsx | 71 +- .../document-signing/access-auth-2fa-form.tsx | 44 +- .../document-signing-attachments-popover.tsx | 17 +- .../document-signing-auth-2fa.tsx | 77 +- .../document-signing-auth-account.tsx | 131 +- .../document-signing-auth-dialog.tsx | 64 +- .../document-signing-auth-page.tsx | 19 +- .../document-signing-auth-passkey.tsx | 128 +- .../document-signing-auth-password.tsx | 29 +- .../document-signing-auth-provider.tsx | 35 +- .../document-signing-auto-sign.tsx | 38 +- .../document-signing-checkbox-field.tsx | 73 +- .../document-signing-complete-dialog.tsx | 235 +- .../document-signing-date-field.tsx | 30 +- .../document-signing-disclosure.tsx | 23 +- .../document-signing-dropdown-field.tsx | 48 +- .../document-signing-email-field.tsx | 21 +- .../document-signing-field-container.tsx | 136 +- .../document-signing-fields.tsx | 16 +- .../document-signing-form.tsx | 249 +- .../document-signing-initials-field.tsx | 22 +- .../document-signing-mobile-widget.tsx | 65 +- .../document-signing-name-field.tsx | 42 +- .../document-signing-number-field.tsx | 50 +- .../document-signing-page-view-v1.tsx | 139 +- .../document-signing-page-view-v2.tsx | 296 +- .../document-signing-provider.tsx | 3 +- .../document-signing-radio-field.tsx | 37 +- .../document-signing-recipient-provider.tsx | 19 +- .../document-signing-reject-dialog.tsx | 32 +- .../document-signing-signature-field.tsx | 39 +- .../document-signing-text-field.tsx | 40 +- .../envelope-signing-provider.tsx | 122 +- .../document/document-attachments-popover.tsx | 71 +- .../document-audit-log-download-button.tsx | 21 +- .../document-certificate-download-button.tsx | 18 +- .../document/document-certificate-qr-view.tsx | 72 +- .../general/document/document-edit-form.tsx | 62 +- .../document/document-page-view-button.tsx | 19 +- .../document/document-page-view-dropdown.tsx | 144 +- .../document-page-view-information.tsx | 25 +- .../document-page-view-recent-activity.tsx | 70 +- .../document-page-view-recipients.tsx | 199 +- .../document-recipient-link-copy-dialog.tsx | 29 +- .../general/document/document-search.tsx | 10 +- .../general/document/document-status.tsx | 17 +- .../document-upload-button-legacy.tsx | 35 +- .../embedded-editor-attachment-popover.tsx | 202 + .../envelope-editor-fields-drag-drop.tsx | 92 +- .../envelope-editor-fields-page-renderer.tsx | 209 +- .../envelope-editor-fields-page.tsx | 217 +- .../envelope-editor-header.tsx | 211 +- .../envelope-editor-preview-page.tsx | 95 +- .../envelope-editor-recipient-form.tsx | 860 +- ...elope-editor-renderer-provider-wrapper.tsx | 28 + .../envelope-editor-settings-dialog.tsx | 792 +- .../envelope-editor-title-input.tsx | 22 +- .../envelope-editor-upload-page.tsx | 450 +- .../envelope-editor/envelope-editor.tsx | 650 +- .../envelope-file-selector.tsx | 30 +- .../envelope-generic-page-renderer.tsx | 88 +- .../envelope-recipient-selector.tsx | 94 +- .../envelope-signing/envelope-signer-form.tsx | 17 +- .../envelope-signer-header.tsx | 33 +- .../envelope-signer-page-renderer.tsx | 101 +- .../envelope-signing-complete-dialog.tsx | 36 +- .../envelope/envelope-drop-zone-wrapper.tsx | 94 +- .../envelope/envelope-upload-button.tsx | 64 +- .../components/general/folder/folder-card.tsx | 52 +- .../components/general/folder/folder-grid.tsx | 40 +- .../general/generic-error-layout.tsx | 16 +- .../general/legacy-field-warning-popover.tsx | 27 +- .../app/components/general/menu-switcher.tsx | 44 +- .../app/components/general/metric-card.tsx | 11 +- .../general/multiselect-role-combobox.tsx | 32 +- .../components/general/org-menu-switcher.tsx | 89 +- ...ganisation-groups-multiselect-combobox.tsx | 114 + ...anisation-members-multiselect-combobox.tsx | 111 + .../organisation-billing-banner.tsx | 58 +- .../organisation-billing-portal-button.tsx | 22 +- .../organisation-invitations.tsx | 19 +- .../pdf-viewer/envelope-pdf-viewer.tsx | 57 + .../general/pdf-viewer/pdf-viewer-lazy.tsx | 34 + .../pdf-viewer/pdf-viewer-page-image.tsx | 35 + .../general/pdf-viewer/pdf-viewer-states.tsx | 25 + .../general/pdf-viewer/pdf-viewer.tsx | 506 + .../general/pdf-viewer/use-scroll-to-page.ts | 43 + .../components/general/period-selector.tsx | 18 +- .../components/general/recipient-branding.tsx | 90 + .../components/general/refresh-on-focus.tsx | 26 - .../components/general/settings-header.tsx | 13 +- .../general/settings-nav-desktop.tsx | 70 +- .../general/settings-nav-mobile.tsx | 69 +- .../skeletons/document-edit-skeleton.tsx | 5 +- .../app/components/general/stack-avatar.tsx | 4 +- .../general/stack-avatars-with-tooltip.tsx | 65 +- .../app/components/general/stack-avatars.tsx | 16 +- .../general/teams/team-email-dropdown.tsx | 11 +- .../general/teams/team-email-usage.tsx | 60 +- .../teams/team-inherit-member-alert.tsx | 13 +- .../template/template-direct-link-badge.tsx | 15 +- .../general/template/template-edit-form.tsx | 67 +- .../template-page-view-documents-table.tsx | 58 +- .../template-page-view-information.tsx | 23 +- .../template-page-view-recent-activity.tsx | 37 +- .../template-page-view-recipients.tsx | 41 +- .../general/template/template-type.tsx | 12 +- .../general/user-profile-skeleton.tsx | 43 +- .../components/general/user-profile-timur.tsx | 43 +- .../general/verify-email-banner.tsx | 41 +- .../general/virtual-list/use-virtual-list.ts | 346 + .../components/general/webhook-logs-sheet.tsx | 317 +- .../general/webhook-multiselect-combobox.tsx | 19 +- .../components/tables/admin-claims-table.tsx | 30 +- .../tables/admin-dashboard-users-table.tsx | 30 +- .../tables/admin-document-jobs-table.tsx | 29 +- .../tables/admin-document-logs-table.tsx | 30 +- .../admin-document-recipient-item-table.tsx | 88 +- .../admin-organisation-overview-table.tsx | 29 +- .../tables/admin-organisations-table.tsx | 82 +- .../tables/admin-user-teams-table.tsx | 28 +- .../components/tables/document-logs-table.tsx | 25 +- .../tables/documents-table-action-button.tsx | 47 +- .../documents-table-action-dropdown.tsx | 148 +- .../tables/documents-table-empty-state.tsx | 7 +- .../tables/documents-table-sender-filter.tsx | 13 +- .../tables/documents-table-title.tsx | 19 +- .../app/components/tables/documents-table.tsx | 40 +- .../envelopes-table-bulk-action-bar.tsx | 8 +- .../app/components/tables/inbox-table.tsx | 53 +- .../tables/internal-audit-log-table.tsx | 43 +- .../organisation-billing-invoices-table.tsx | 30 +- .../organisation-email-domains-table.tsx | 54 +- .../tables/organisation-groups-table.tsx | 20 +- .../tables/organisation-insights-table.tsx | 36 +- .../organisation-member-invites-table.tsx | 118 +- .../tables/organisation-members-table.tsx | 31 +- .../tables/organisation-teams-table.tsx | 23 +- ...ettings-public-profile-templates-table.tsx | 47 +- .../settings-security-activity-table.tsx | 16 +- ...ettings-security-passkey-table-actions.tsx | 109 +- .../settings-security-passkey-table.tsx | 16 +- .../components/tables/team-groups-table.tsx | 31 +- .../components/tables/team-members-table.tsx | 26 +- .../templates-table-action-dropdown.tsx | 186 +- .../app/components/tables/templates-table.tsx | 86 +- .../user-billing-organisations-table.tsx | 22 +- .../tables/user-organisations-table.tsx | 19 +- apps/remix/app/entry.client.tsx | 17 +- apps/remix/app/entry.server.tsx | 18 +- apps/remix/app/providers/team.tsx | 5 +- apps/remix/app/root.tsx | 83 +- .../app/routes/_authenticated+/_layout.tsx | 11 +- .../routes/_authenticated+/admin+/_layout.tsx | 76 +- .../routes/_authenticated+/admin+/claims.tsx | 14 +- .../_authenticated+/admin+/documents.$id.tsx | 154 +- .../admin+/documents._index.tsx | 55 +- .../admin+/email-domains.$id.tsx | 276 + .../admin+/email-domains._index.tsx | 193 + .../admin+/organisation-insights.$id.tsx | 8 +- .../admin+/organisation-insights._index.tsx | 12 +- .../admin+/organisations.$id.tsx | 244 +- .../admin+/organisations._index.tsx | 14 +- .../_authenticated+/admin+/site-settings.tsx | 51 +- .../routes/_authenticated+/admin+/stats.tsx | 86 +- .../_authenticated+/admin+/teams.$id.tsx | 325 + .../admin+/unsealed-documents._index.tsx | 183 + .../_authenticated+/admin+/users.$id.tsx | 55 +- .../_authenticated+/admin+/users._index.tsx | 16 +- .../app/routes/_authenticated+/dashboard.tsx | 69 +- .../app/routes/_authenticated+/inbox.tsx | 9 +- .../_authenticated+/o.$orgUrl._index.tsx | 63 +- .../_authenticated+/o.$orgUrl._layout.tsx | 3 +- .../o.$orgUrl.settings._layout.tsx | 15 +- .../o.$orgUrl.settings.billing.tsx | 103 +- .../o.$orgUrl.settings.branding.tsx | 110 +- .../o.$orgUrl.settings.document.tsx | 24 +- .../o.$orgUrl.settings.email-domains.$id.tsx | 49 +- ....$orgUrl.settings.email-domains._index.tsx | 30 +- .../o.$orgUrl.settings.email.tsx | 26 +- .../o.$orgUrl.settings.general.tsx | 28 +- .../o.$orgUrl.settings.groups.$id.tsx | 95 +- .../o.$orgUrl.settings.members.tsx | 17 +- .../o.$orgUrl.settings.sso.tsx | 105 +- .../o.$orgUrl.settings.teams.tsx | 9 +- .../_authenticated+/o.$orgUrl.support.tsx | 77 +- .../_dynamic_personal_routes+/_layout.tsx | 6 +- .../_dynamic_personal_routes+/document.tsx | 2 +- .../public-profile.tsx | 2 +- .../_authenticated+/settings+/_layout.tsx | 5 +- .../_authenticated+/settings+/billing.tsx | 3 +- .../_authenticated+/settings+/profile.tsx | 14 +- .../settings+/security._index.tsx | 72 +- .../settings+/security.activity.tsx | 2 +- .../settings+/security.linked-accounts.tsx | 28 +- .../settings+/security.passkeys.tsx | 8 +- .../settings+/security.sessions.tsx | 27 +- .../_authenticated+/t.$teamUrl+/_index.tsx | 3 +- .../_authenticated+/t.$teamUrl+/_layout.tsx | 22 +- .../t.$teamUrl+/documents.$id._index.tsx | 118 +- .../t.$teamUrl+/documents.$id._layout.tsx | 16 +- .../t.$teamUrl+/documents.$id.edit.tsx | 38 +- .../documents.$id.legacy_editor.tsx | 31 +- .../t.$teamUrl+/documents.$id.logs.tsx | 31 +- .../t.$teamUrl+/documents._index.tsx | 60 +- .../t.$teamUrl+/documents.folders._index.tsx | 155 +- .../t.$teamUrl+/settings._index.tsx | 42 +- .../t.$teamUrl+/settings._layout.tsx | 21 +- .../t.$teamUrl+/settings.branding.tsx | 92 +- .../t.$teamUrl+/settings.document.tsx | 14 +- .../t.$teamUrl+/settings.email.tsx | 16 +- .../t.$teamUrl+/settings.groups.tsx | 14 +- .../t.$teamUrl+/settings.members.tsx | 8 +- .../t.$teamUrl+/settings.public-profile.tsx | 47 +- .../t.$teamUrl+/settings.tokens.tsx | 39 +- .../settings.webhooks.$id._index.tsx | 50 +- .../t.$teamUrl+/settings.webhooks._index.tsx | 46 +- .../t.$teamUrl+/templates.$id._index.tsx | 187 +- .../t.$teamUrl+/templates.$id._layout.tsx | 46 +- .../templates.$id.legacy_editor.tsx | 15 +- .../t.$teamUrl+/templates._index.tsx | 172 +- .../t.$teamUrl+/templates.folders._index.tsx | 157 +- apps/remix/app/routes/_index.tsx | 3 +- .../_internal+/[__htmltopdf]+/audit-log.tsx | 21 +- .../_internal+/[__htmltopdf]+/certificate.tsx | 96 +- apps/remix/app/routes/_profile+/_layout.tsx | 21 +- apps/remix/app/routes/_profile+/p.$url.tsx | 72 +- apps/remix/app/routes/_recipient+/_layout.tsx | 23 +- .../routes/_recipient+/d.$token+/_index.tsx | 86 +- .../_recipient+/sign.$token+/_index.tsx | 158 +- .../_recipient+/sign.$token+/complete.tsx | 320 +- .../_recipient+/sign.$token+/expired.tsx | 124 + .../_recipient+/sign.$token+/rejected.tsx | 101 +- .../_recipient+/sign.$token+/waiting.tsx | 83 +- .../routes/_share+/share.$slug.opengraph.tsx | 17 +- apps/remix/app/routes/_share+/share.$slug.tsx | 3 +- .../app/routes/_unauthenticated+/_layout.tsx | 3 +- .../articles.signature-disclosure.tsx | 75 +- .../routes/_unauthenticated+/check-email.tsx | 13 +- .../_unauthenticated+/forgot-password.tsx | 12 +- .../_unauthenticated+/o.$orgUrl.signin.tsx | 51 +- .../organisation.decline.$token.tsx | 16 +- .../organisation.invite.$token.tsx | 29 +- .../organisation.sso.confirmation.$token.tsx | 80 +- .../reset-password.$token.tsx | 12 +- .../reset-password._index.tsx | 14 +- .../app/routes/_unauthenticated+/signin.tsx | 53 +- .../app/routes/_unauthenticated+/signup.tsx | 43 +- .../team.verify.email.$token.tsx | 30 +- .../_unauthenticated+/unverified-account.tsx | 19 +- .../_unauthenticated+/verify-email.$token.tsx | 60 +- .../_unauthenticated+/verify-email._index.tsx | 18 +- .../api+/branding.logo.organisation.$orgId.ts | 21 +- .../routes/api+/branding.logo.team.$teamId.ts | 21 +- apps/remix/app/routes/api+/locale.tsx | 3 +- apps/remix/app/routes/embed+/_v0+/_layout.tsx | 39 +- .../app/routes/embed+/_v0+/direct.$token.tsx | 37 +- .../app/routes/embed+/_v0+/sign.$token.tsx | 63 +- apps/remix/app/routes/embed+/playground.tsx | 705 + .../routes/embed+/v1+/authoring+/_layout.tsx | 44 +- .../embed+/v1+/authoring+/document.create.tsx | 37 +- .../v1+/authoring+/document.edit.$id.tsx | 46 +- .../embed+/v1+/authoring+/template.create.tsx | 23 +- .../v1+/authoring+/template.edit.$id.tsx | 51 +- .../v1+/authoring_.completed.create.tsx | 9 +- .../routes/embed+/v1+/multisign+/_index.tsx | 62 +- .../routes/embed+/v2+/authoring+/_layout.tsx | 201 + .../v2+/authoring+/envelope.create._index.tsx | 422 + .../v2+/authoring+/envelope.edit.$id.tsx | 370 + apps/remix/app/storage/lang-cookie.server.ts | 3 +- .../remix/app/storage/theme-session.server.ts | 3 +- apps/remix/app/utils/css-vars.ts | 72 +- .../app/utils/field-signing/checkbox-field.ts | 18 +- .../app/utils/field-signing/dropdown-field.ts | 3 +- .../app/utils/field-signing/email-field.ts | 3 +- .../app/utils/field-signing/initial-field.ts | 3 +- .../app/utils/field-signing/name-field.ts | 3 +- .../app/utils/field-signing/number-field.ts | 3 +- .../utils/field-signing/signature-field.ts | 12 +- .../app/utils/field-signing/text-field.ts | 3 +- apps/remix/app/utils/meta.ts | 5 +- apps/remix/app/utils/nonce.ts | 38 + .../utils/polyfills/promise-with-resolvers.ts | 2 +- apps/remix/app/utils/super-json-loader.ts | 11 +- apps/remix/package.json | 10 +- apps/remix/public/robots.txt | 4 + apps/remix/rollup.config.mjs | 2 +- .../server/api/ai/detect-fields.client.ts | 5 +- apps/remix/server/api/ai/detect-fields.ts | 7 +- .../server/api/ai/detect-fields.types.ts | 6 +- .../server/api/ai/detect-recipients.client.ts | 5 +- apps/remix/server/api/ai/detect-recipients.ts | 7 +- .../server/api/ai/detect-recipients.types.ts | 3 +- apps/remix/server/api/download/download.ts | 206 +- .../server/api/download/download.types.ts | 13 +- apps/remix/server/api/files/files.helpers.ts | 245 +- apps/remix/server/api/files/files.ts | 175 +- apps/remix/server/api/files/files.types.ts | 21 +- .../routes/get-envelope-item-pdf-by-token.ts | 80 + .../api/files/routes/get-envelope-item-pdf.ts | 156 + apps/remix/server/context.ts | 10 +- apps/remix/server/load-context.ts | 33 + apps/remix/server/main.js | 3 +- apps/remix/server/middleware.ts | 3 +- apps/remix/server/router.ts | 116 +- apps/remix/server/security-headers.ts | 180 + apps/remix/server/trpc/hono-trpc-open-api.ts | 8 +- apps/remix/server/trpc/hono-trpc-remix.ts | 3 +- apps/remix/tailwind.config.ts | 5 +- apps/remix/vite-env.d.ts | 4 +- apps/remix/vite.config.ts | 36 +- assets/a4-size.pdf | 51 + assets/field-overflow.pdf | Bin 0 -> 19545 bytes assets/letter-size.pdf | 51 + assets/tabloid-landscape.pdf | 51 + biome.json | 138 + build.log | 769 - docker/README.md | 7 +- docker/development/compose.yml | 9 + docker/production/compose.yml | 5 + lingui.config.ts | 4 +- lint-staged.config.cjs | 12 +- package-lock.json | 15676 +++++----------- package.json | 41 +- packages/api/hono.ts | 5 +- packages/api/package.json | 4 +- packages/api/tsconfig.json | 2 +- packages/api/v1/contract.ts | 3 +- packages/api/v1/implementation.ts | 423 +- packages/api/v1/middleware/authenticated.ts | 7 +- packages/api/v1/openapi.ts | 3 +- packages/api/v1/schema.ts | 84 +- .../constants/field-alignment-pdf.ts | 24 +- .../app-tests/constants/field-meta-pdf.ts | 3 +- .../app-tests/constants/field-overflow-pdf.ts | 789 + .../update-organisation-member-role.spec.ts | 3 +- .../e2e/api/trpc/search-documents.spec.ts | 463 + .../e2e/api/trpc/search-templates.spec.ts | 256 + .../e2e/api/v1/document-sending.spec.ts | 12 +- .../e2e/api/v1/template-field-prefill.spec.ts | 21 +- .../v1/test-unauthorized-api-access.spec.ts | 48 +- .../e2e/api/v2/distribute-validation.spec.ts | 13 +- .../e2e/api/v2/embedding-presign.spec.ts | 53 +- .../e2e/api/v2/envelopes-api.spec.ts | 88 +- .../e2e/api/v2/find-documents.spec.ts | 1562 ++ .../e2e/api/v2/find-envelopes.spec.ts | 1057 ++ .../v2/partial-signed-pdf-download.spec.ts | 244 + .../e2e/api/v2/placeholder-fields-api.spec.ts | 28 +- .../e2e/api/v2/template-field-prefill.spec.ts | 21 +- .../v2/test-unauthorized-api-access.spec.ts | 1178 +- .../api-access-envelope-attachments.spec.ts | 55 +- .../api-access-envelope-bulk.spec.ts | 684 +- .../e2e/api/v2/update-envelope-items.spec.ts | 508 + .../auto-place-fields-document.spec.ts | 67 +- .../e2e/command-menu/document-search.spec.ts | 5 +- .../e2e/document-auth/access-auth.spec.ts | 3 +- .../e2e/document-auth/action-auth.spec.ts | 59 +- .../assistant-signing-auth.spec.ts | 163 + .../next-recipient-dictation.spec.ts | 27 +- .../autosave-fields-step.spec.ts | 54 +- .../autosave-settings-step.spec.ts | 7 +- .../autosave-signers-step.spec.ts | 19 +- .../autosave-subject-step.spec.ts | 54 +- .../duplicate-recipients-simple.spec.ts | 8 +- .../duplicate-recipients.spec.ts | 65 +- .../e2e/document-flow/settings-step.spec.ts | 9 +- .../e2e/document-flow/signers-step.spec.ts | 3 +- .../document-flow/stepper-component.spec.ts | 74 +- .../documents/bulk-document-actions.spec.ts | 3 +- .../e2e/documents/delete-documents.spec.ts | 25 +- .../e2e/documents/find-documents.spec.ts | 1167 ++ .../test-unauthorized-document-access.spec.ts | 9 +- .../envelope-actions.spec.ts | 430 + .../envelope-attachments.spec.ts | 321 + .../envelope-editor-embedded.spec.ts | 436 + .../envelope-fields.spec.ts | 836 + .../envelope-item-edit-dialog.spec.ts | 311 + .../envelope-editor-v2/envelope-items.spec.ts | 378 + .../envelope-recipients.spec.ts | 267 + .../envelope-replace-pdf.spec.ts | 516 + .../envelope-save-as-template.spec.ts | 487 + .../envelope-settings.spec.ts | 468 + .../envelopes/cert-page-dimensions.spec.ts | 214 + .../e2e/envelopes/envelope-alignment.spec.ts | 142 +- .../envelope-expiration-send.spec.ts | 286 + .../envelope-expiration-settings.spec.ts | 138 + .../envelope-expiration-signing.spec.ts | 130 + .../e2e/envelopes/envelope-overflow.spec.ts | 531 + .../envelope-v2-field-insertion.spec.ts | 256 + .../include-document-certificate.spec.ts | 19 +- packages/app-tests/e2e/fixtures/api-seeds.ts | 882 + .../app-tests/e2e/fixtures/authentication.ts | 3 +- .../app-tests/e2e/fixtures/envelope-editor.ts | 407 + packages/app-tests/e2e/fixtures/generic.ts | 2 +- packages/app-tests/e2e/fixtures/konva.ts | 18 + .../e2e/folders/team-account-folders.spec.ts | 55 +- .../enterprise-feature-restrictions.spec.ts | 416 +- .../e2e/license/license-status-banner.spec.ts | 508 +- .../organisations/manage-organisation.spec.ts | 129 +- .../organisation-team-preferences.spec.ts | 29 +- .../e2e/pdf-viewer/pdf-viewer.spec.ts | 406 + .../public-profiles/public-profiles.spec.ts | 11 +- .../e2e/scenarios/form-flattening.spec.ts | 92 +- .../e2e/teams/default-recipients.spec.ts | 27 +- .../app-tests/e2e/teams/manage-team.spec.ts | 8 +- .../e2e/teams/search-documents.spec.ts | 27 +- .../e2e/teams/team-documents.spec.ts | 83 +- .../app-tests/e2e/teams/team-email.spec.ts | 13 +- .../e2e/teams/team-signature-settings.spec.ts | 17 +- .../duplicate-recipients.spec.ts | 41 +- .../template-autosave-fields-step.spec.ts | 62 +- .../template-autosave-settings-step.spec.ts | 17 +- .../template-autosave-signers-step.spec.ts | 23 +- .../template-settings-step.spec.ts | 21 +- .../template-signers-step.spec.ts | 3 +- .../templates/bulk-template-actions.spec.ts | 3 +- .../create-document-from-template.spec.ts | 76 +- .../e2e/templates/direct-templates.spec.ts | 23 +- .../e2e/templates/manage-templates.spec.ts | 13 +- .../templates/organisation-templates.spec.ts | 640 + .../test-unauthorized-template-access.spec.ts | 3 +- packages/app-tests/e2e/user/auth-flow.spec.ts | 9 +- .../app-tests/e2e/user/auth-sessions.spec.ts | 17 +- .../app-tests/e2e/user/delete-account.spec.ts | 3 +- packages/app-tests/e2e/user/password.spec.ts | 13 +- .../app-tests/e2e/user/update-name.spec.ts | 3 +- .../e2e/webhooks/webhooks-crud.spec.ts | 22 +- packages/app-tests/package.json | 9 +- .../visual-regression/alignment-pdf-0.png | Bin 142396 -> 362601 bytes .../visual-regression/alignment-pdf-1.png | Bin 104573 -> 272884 bytes .../visual-regression/alignment-pdf-2.png | Bin 114594 -> 316973 bytes .../visual-regression/alignment-pdf-3.png | Bin 119597 -> 251663 bytes .../visual-regression/blank-certificate.png | Bin 166551 -> 6648 bytes .../visual-regression/field-meta-pdf-0.png | Bin 41657 -> 50888 bytes .../visual-regression/field-meta-pdf-1.png | Bin 129985 -> 195306 bytes .../visual-regression/field-meta-pdf-2.png | Bin 92080 -> 228786 bytes .../visual-regression/field-meta-pdf-3.png | Bin 82687 -> 206439 bytes .../visual-regression/field-meta-pdf-4.png | Bin 76524 -> 165527 bytes .../visual-regression/field-meta-pdf-5.png | Bin 92162 -> 229606 bytes .../visual-regression/field-meta-pdf-6.png | Bin 58771 -> 111578 bytes .../visual-regression/field-meta-pdf-7.png | Bin 119597 -> 251663 bytes .../visual-regression/field-overflow-0.png | Bin 0 -> 636935 bytes .../visual-regression/field-overflow-1.png | Bin 0 -> 651473 bytes .../visual-regression/field-overflow-2.png | Bin 0 -> 365752 bytes .../visual-regression/field-overflow-3.png | Bin 0 -> 252360 bytes .../visual-regression/field-overflow-4.png | Bin 0 -> 588777 bytes .../visual-regression/field-overflow-5.png | Bin 0 -> 1343353 bytes .../visual-regression/field-overflow-6.png | Bin 0 -> 518291 bytes .../visual-regression/field-overflow-7.png | Bin 0 -> 154461 bytes .../visual-regression/field-overflow-8.png | Bin 0 -> 272988 bytes packages/auth/client/index.ts | 19 +- packages/auth/package.json | 4 +- packages/auth/server/index.ts | 7 +- .../auth/server/lib/errors/error-codes.ts | 1 + .../server/lib/session/session-cookies.ts | 19 +- packages/auth/server/lib/session/session.ts | 26 +- .../lib/utils/delete-account-provider.ts | 5 +- .../auth/server/lib/utils/get-accounts.ts | 3 +- packages/auth/server/lib/utils/get-session.ts | 9 +- .../lib/utils/handle-oauth-authorize-url.ts | 11 +- .../lib/utils/handle-oauth-callback-url.ts | 53 +- .../handle-oauth-organisation-callback-url.ts | 20 +- .../server/lib/utils/organisation-portal.ts | 6 +- packages/auth/server/routes/callback.ts | 7 +- packages/auth/server/routes/email-password.ts | 169 +- packages/auth/server/routes/passkey.ts | 35 +- packages/auth/server/routes/sign-out.ts | 3 +- packages/auth/server/routes/two-factor.ts | 63 +- .../auth/server/routes/two-factor.types.ts | 4 +- packages/auth/server/types/email-password.ts | 19 +- packages/ee/package.json | 4 +- .../ee/server-only/lib/create-email-domain.ts | 71 +- .../lib/link-organisation-account.ts | 122 +- .../lib/reregister-email-domain.ts | 92 + ...isation-account-link-confirmation-email.ts | 15 +- .../ee/server-only/lib/verify-email-domain.ts | 4 +- packages/ee/server-only/limits/handler.ts | 3 +- .../ee/server-only/limits/provider/client.tsx | 15 + packages/ee/server-only/limits/server.ts | 17 +- .../stripe/create-checkout-session.ts | 4 +- .../stripe/get-internal-claim-plans.ts | 11 +- .../update-subscription-item-quantity.ts | 104 +- .../ee/server-only/stripe/webhook/handler.ts | 24 +- .../stripe/webhook/on-subscription-created.ts | 40 +- .../stripe/webhook/on-subscription-deleted.ts | 75 +- .../stripe/webhook/on-subscription-updated.ts | 17 +- packages/email/mailer.ts | 15 +- packages/email/package.json | 4 +- packages/email/providers/branding.tsx | 5 +- packages/email/render.tsx | 3 +- .../template-access-auth-2fa.tsx | 17 +- .../template-confirmation-email.tsx | 20 +- .../template-custom-message-body.tsx | 5 +- .../template-document-cancel.tsx | 2 +- .../template-document-completed.tsx | 18 +- .../template-document-image.tsx | 2 +- .../template-document-invite.tsx | 18 +- .../template-document-pending.tsx | 16 +- .../template-document-recipient-signed.tsx | 11 +- .../template-document-rejected.tsx | 4 +- .../template-document-rejection-confirmed.tsx | 11 +- .../template-document-reminder.tsx | 74 + .../template-document-self-signed.tsx | 37 +- .../template-document-super-delete.tsx | 20 +- .../template-components/template-footer.tsx | 4 +- .../template-forgot-password.tsx | 11 +- .../template-recipient-expired.tsx | 54 + .../template-reset-password.tsx | 9 +- packages/email/templates/access-auth-2fa.tsx | 8 +- .../email/templates/bulk-send-complete.tsx | 14 +- packages/email/templates/confirm-email.tsx | 13 +- .../email/templates/confirm-team-email.tsx | 50 +- packages/email/templates/document-cancel.tsx | 8 +- .../email/templates/document-completed.tsx | 8 +- .../document-created-from-direct-template.tsx | 17 +- packages/email/templates/document-invite.tsx | 13 +- packages/email/templates/document-pending.tsx | 8 +- .../templates/document-recipient-signed.tsx | 8 +- .../email/templates/document-rejected.tsx | 8 +- .../document-rejection-confirmed.tsx | 8 +- .../email/templates/document-reminder.tsx | 86 + .../email/templates/document-self-signed.tsx | 8 +- .../email/templates/document-super-delete.tsx | 14 +- packages/email/templates/forgot-password.tsx | 13 +- ...organisation-account-link-confirmation.tsx | 43 +- .../email/templates/organisation-invite.tsx | 37 +- .../email/templates/organisation-join.tsx | 18 +- .../email/templates/organisation-leave.tsx | 18 +- .../email/templates/recipient-expired.tsx | 64 + .../recipient-removed-from-document.tsx | 10 +- packages/email/templates/reset-password.tsx | 24 +- packages/email/templates/team-delete.tsx | 21 +- .../email/templates/team-email-removed.tsx | 24 +- packages/email/transports/mailchannels.ts | 15 +- packages/email/tsconfig.json | 4 +- packages/eslint-config/index.cjs | 82 - packages/eslint-config/package.json | 20 - packages/eslint-config/tsconfig.json | 9 - .../validate-checkbox.ts | 11 +- packages/lib/client-only/download-pdf.ts | 26 +- .../client-only/get-bounding-client-rect.ts | 2 +- .../lib/client-only/hooks/use-analytics.ts | 20 +- .../lib/client-only/hooks/use-autosave.ts | 5 +- .../client-only/hooks/use-copy-share-link.ts | 3 +- .../hooks/use-copy-to-clipboard.ts | 4 +- .../client-only/hooks/use-document-element.ts | 55 +- .../client-only/hooks/use-editor-fields.ts | 47 +- .../hooks/use-editor-recipients.ts | 29 +- .../client-only/hooks/use-element-bounds.ts | 11 +- .../hooks/use-element-scale-size.ts | 2 +- .../hooks/use-envelope-autosave.ts | 4 +- .../hooks/use-field-page-coords.ts | 74 +- .../client-only/hooks/use-is-page-in-dom.ts | 35 + .../client-only/hooks/use-page-renderer.ts | 146 +- .../client-only/hooks/use-session-storage.ts | 13 +- .../providers/envelope-editor-provider.tsx | 559 +- .../providers/envelope-render-provider.tsx | 215 +- .../lib/client-only/providers/i18n-server.tsx | 6 +- .../lib/client-only/providers/i18n.client.tsx | 3 +- .../client-only/providers/organisation.tsx | 9 +- .../lib/client-only/providers/session.tsx | 28 +- packages/lib/client-only/recipient-type.ts | 19 +- packages/lib/constants/app.ts | 18 +- packages/lib/constants/auth.ts | 75 +- packages/lib/constants/billing.ts | 16 +- packages/lib/constants/branding.ts | 11 + packages/lib/constants/date-formats.ts | 18 + packages/lib/constants/document-audit-logs.ts | 3 + packages/lib/constants/document-visibility.ts | 3 +- packages/lib/constants/document.ts | 13 +- packages/lib/constants/email.ts | 2 - packages/lib/constants/envelope-expiration.ts | 61 + packages/lib/constants/envelope-reminder.ts | 104 + packages/lib/constants/i18n.ts | 51 +- packages/lib/constants/locales.ts | 13 + .../constants/organisations-translations.ts | 10 +- packages/lib/constants/organisations.ts | 4 +- packages/lib/constants/pdf-viewer-i18n.ts | 22 + packages/lib/constants/pdf-viewer.ts | 17 +- packages/lib/constants/teams-translations.ts | 11 +- packages/lib/constants/teams.ts | 10 +- packages/lib/constants/theme.ts | 58 + packages/lib/errors/app-error.ts | 97 +- packages/lib/jobs/client.ts | 18 + packages/lib/jobs/client/_internal/job.ts | 14 +- packages/lib/jobs/client/base.ts | 10 + packages/lib/jobs/client/bullmq.ts | 382 + packages/lib/jobs/client/client.ts | 13 + packages/lib/jobs/client/inngest.ts | 27 +- packages/lib/jobs/client/local.ts | 177 +- .../emails/send-confirmation-email.ts | 7 +- .../send-document-cancelled-emails.handler.ts | 16 +- .../emails/send-document-cancelled-emails.ts | 2 +- ...ated-from-direct-template-email.handler.ts | 94 + ...ment-created-from-direct-template-email.ts | 33 + ...rganisation-member-joined-email.handler.ts | 69 +- .../send-organisation-member-joined-email.ts | 3 +- ...-organisation-member-left-email.handler.ts | 67 +- ...d-owner-recipient-expired-email.handler.ts | 107 + .../send-owner-recipient-expired-email.ts | 32 + ...nd-password-reset-success-email.handler.ts | 6 +- .../send-recipient-signed-email.handler.ts | 20 +- .../emails/send-recipient-signed-email.ts | 6 +- .../emails/send-rejection-emails.handler.ts | 24 +- .../emails/send-rejection-emails.ts | 2 +- .../emails/send-signing-email.handler.ts | 103 +- .../definitions/emails/send-signing-email.ts | 11 +- .../emails/send-team-deleted-email.handler.ts | 8 +- .../emails/send-team-deleted-email.ts | 4 +- .../backport-subscription-claims.handler.ts | 8 +- .../internal/backport-subscription-claims.ts | 8 +- .../internal/bulk-send-template.handler.ts | 23 +- .../internal/bulk-send-template.ts | 11 +- .../internal/cleanup-rate-limits.handler.ts | 35 + .../internal/cleanup-rate-limits.ts | 25 + .../internal/execute-webhook.handler.ts | 49 +- .../definitions/internal/execute-webhook.ts | 7 +- .../expire-recipients-sweep.handler.ts | 47 + .../internal/expire-recipients-sweep.ts | 28 + .../process-recipient-expired.handler.ts | 83 + .../internal/process-recipient-expired.ts | 29 + .../process-signing-reminder.handler.ts | 207 + .../internal/process-signing-reminder.ts | 29 + .../internal/seal-document-sweep.handler.ts | 102 + .../internal/seal-document-sweep.ts | 25 + .../internal/seal-document.handler.ts | 220 +- .../definitions/internal/seal-document.ts | 7 +- .../send-signing-reminders-sweep.handler.ts | 48 + .../internal/send-signing-reminders-sweep.ts | 30 + .../internal/sync-email-domains.handler.ts | 91 + .../internal/sync-email-domains.ts | 25 + packages/lib/package.json | 29 +- packages/lib/plain/client.ts | 3 +- packages/lib/server-only/2fa/disable-2fa.ts | 8 +- .../2fa/email/send-2fa-token-email.ts | 59 +- packages/lib/server-only/2fa/enable-2fa.ts | 3 +- .../lib/server-only/2fa/get-backup-code.ts | 4 +- .../lib/server-only/2fa/is-2fa-availble.ts | 4 +- packages/lib/server-only/2fa/setup-2fa.ts | 9 +- packages/lib/server-only/2fa/validate-2fa.ts | 5 +- .../lib/server-only/2fa/verify-2fa-token.ts | 4 +- .../lib/server-only/2fa/verify-password.ts | 3 +- .../lib/server-only/2fa/view-backup-codes.ts | 5 +- .../server-only/admin/admin-find-documents.ts | 9 +- .../admin/admin-find-unsealed-documents.ts | 99 + .../admin/admin-super-delete-document.ts | 27 +- .../server-only/admin/get-documents-stats.ts | 3 +- .../server-only/admin/get-entire-document.ts | 3 +- .../get-organisation-detailed-insights.ts | 14 +- .../server-only/admin/get-recipients-stats.ts | 3 +- .../server-only/admin/get-signing-volume.ts | 27 +- .../lib/server-only/admin/get-users-stats.ts | 3 +- .../lib/server-only/admin/update-recipient.ts | 7 +- packages/lib/server-only/admin/update-user.ts | 3 +- .../ai/envelope/detect-fields/index.ts | 22 +- .../ai/envelope/detect-fields/schema.ts | 4 +- .../ai/envelope/detect-recipients/index.ts | 20 +- .../ai/envelope/detect-recipients/schema.ts | 4 +- .../create-passkey-authentication-options.ts | 5 +- .../create-passkey-registration-options.ts | 9 +- .../auth/create-passkey-signin-options.ts | 3 +- .../lib/server-only/auth/create-passkey.ts | 9 +- .../lib/server-only/auth/delete-passkey.ts | 9 +- .../lib/server-only/auth/find-passkeys.ts | 11 +- .../auth/send-confirmation-email.ts | 11 +- .../server-only/auth/send-forgot-password.ts | 6 +- .../server-only/auth/send-reset-password.ts | 3 +- .../lib/server-only/auth/update-passkey.ts | 10 +- .../branding/load-recipient-branding.ts | 55 + .../lib/server-only/captcha/verify-captcha.ts | 107 + packages/lib/server-only/cert/cert-status.ts | 3 +- packages/lib/server-only/crypto/encrypt.ts | 3 +- .../document-data/create-document-data.ts | 14 +- .../document-meta/upsert-document-meta.ts | 12 +- .../document/complete-document-with-token.ts | 208 +- .../server-only/document/delete-document.ts | 46 +- .../document/find-document-audit-logs.ts | 5 +- .../server-only/document/find-documents.ts | 992 +- .../document/get-document-by-access-token.ts | 13 +- .../document/get-document-by-token.ts | 4 +- .../get-document-certificate-audit-logs.ts | 4 +- .../get-document-with-details-by-id.ts | 6 +- ...-recipient-or-sender-by-share-link-slug.ts | 4 +- .../lib/server-only/document/get-stats.ts | 601 +- .../document/is-recipient-authorized.ts | 15 +- .../document/reject-document-with-token.ts | 19 +- .../server-only/document/resend-document.ts | 155 +- .../document/search-documents-with-keyword.ts | 226 +- .../document/send-completed-email.ts | 22 +- .../server-only/document/send-delete-email.ts | 10 +- .../lib/server-only/document/send-document.ts | 90 +- .../document/send-pending-email.ts | 12 +- .../server-only/document/viewed-document.ts | 20 +- .../server-only/email/get-email-context.ts | 24 +- .../create-embedding-presign-token.ts | 3 +- .../verify-embedding-presign-token.ts | 24 +- .../envelope-attachment/create-attachment.ts | 10 +- .../envelope-attachment/delete-attachment.ts | 3 +- .../find-attachments-by-token.ts | 10 +- .../envelope-attachment/update-attachment.ts | 3 +- .../envelope-item/create-envelope-items.ts | 172 + .../envelope-item/delete-envelope-item.ts | 67 + .../replace-envelope-item-pdf.ts | 227 + .../envelope-item/update-envelope-items.ts | 100 + .../server-only/envelope/create-envelope.ts | 152 +- .../envelope/duplicate-envelope.ts | 127 +- .../server-only/envelope/find-envelopes.ts | 337 +- .../envelope/get-editor-envelope-by-id.ts | 104 + .../envelope/get-envelope-by-id.ts | 11 +- ...et-envelope-for-direct-template-signing.ts | 10 +- .../get-envelope-for-recipient-signing.ts | 29 +- .../get-envelope-required-access-data.ts | 3 +- .../envelope/get-envelopes-by-ids.ts | 10 +- .../server-only/envelope/orphan-envelopes.ts | 3 +- .../envelope/transfer-team-envelopes.ts | 5 +- .../server-only/envelope/update-envelope.ts | 78 +- .../field/create-envelope-fields.ts | 14 +- .../field/delete-document-field.ts | 10 +- .../field/delete-template-field.ts | 9 +- .../get-completed-fields-for-document.ts | 7 +- .../field/get-completed-fields-for-token.ts | 3 +- .../lib/server-only/field/get-field-by-id.ts | 10 +- .../server-only/field/get-fields-for-token.ts | 4 +- .../field/remove-signed-field-with-token.ts | 12 +- .../field/set-fields-for-document.ts | 51 +- .../field/set-fields-for-template.ts | 28 +- .../field/sign-field-with-token.ts | 50 +- .../field/update-envelope-fields.ts | 28 +- .../folder/find-folders-internal.ts | 10 +- .../lib/server-only/folder/find-folders.ts | 12 +- .../folder/get-folder-breadcrumbs.ts | 16 +- .../htmltopdf/get-audit-logs-pdf.ts | 6 +- .../htmltopdf/get-certificate-pdf.ts | 6 +- .../lib/server-only/license/license-client.ts | 3 +- .../accept-organisation-invitation.ts | 57 +- .../create-organisation-member-invites.ts | 40 +- .../organisation/create-organisation.ts | 26 +- .../pdf/add-rejection-stamp-to-pdf.ts | 4 +- .../lib/server-only/pdf/auto-place-fields.ts | 18 +- .../server-only/pdf/generate-audit-log-pdf.ts | 21 +- .../pdf/generate-certificate-pdf.ts | 28 +- .../pdf/generate-partial-signed-pdf.ts | 76 + packages/lib/server-only/pdf/get-page-size.ts | 50 +- packages/lib/server-only/pdf/helpers.ts | 39 +- .../server-only/pdf/insert-field-in-pdf-v1.ts | 40 +- .../server-only/pdf/insert-field-in-pdf-v2.ts | 25 +- .../pdf/legacy-insert-field-in-pdf.ts | 41 +- .../lib/server-only/pdf/render-audit-logs.ts | 63 +- .../lib/server-only/pdf/render-certificate.ts | 82 +- .../profile/get-public-profile-by-url.ts | 3 +- .../server-only/profile/set-avatar-image.ts | 7 +- .../public-api/create-api-token.ts | 10 +- .../rate-limit/rate-limit-middleware.ts | 88 + .../lib/server-only/rate-limit/rate-limit.ts | 197 + .../lib/server-only/rate-limit/rate-limits.ts | 99 + .../recipient/create-envelope-recipients.ts | 14 +- .../recipient/delete-envelope-recipient.ts | 12 +- .../recipient/get-is-recipient-turn.ts | 3 +- .../recipient/get-next-pending-recipient.ts | 3 +- .../recipient/get-recipient-by-id.ts | 20 +- .../recipient/get-recipient-suggestions.ts | 13 +- .../recipient/get-recipients-for-assistant.ts | 3 +- .../recipient/get-recipients-for-document.ts | 9 +- .../recipient/set-document-recipients.ts | 55 +- .../recipient/set-template-recipients.ts | 62 +- .../recipient/update-envelope-recipients.ts | 30 +- .../update-recipient-next-reminder.ts | 106 + .../share/create-or-get-share-link.ts | 5 +- .../lib/server-only/site-settings/schema.ts | 5 +- .../site-settings/upsert-site-setting.ts | 9 +- .../get-active-subscriptions-by-user-id.ts | 7 +- .../team/create-team-email-verification.ts | 69 +- packages/lib/server-only/team/create-team.ts | 23 +- .../team/delete-team-email-verification.ts | 5 +- .../lib/server-only/team/delete-team-email.ts | 6 +- packages/lib/server-only/team/delete-team.ts | 69 +- .../lib/server-only/team/find-team-members.ts | 13 +- packages/lib/server-only/team/find-teams.ts | 3 +- .../lib/server-only/team/get-member-roles.ts | 5 +- .../team/get-team-email-by-email.ts | 8 +- .../lib/server-only/team/get-team-members.ts | 5 +- .../team/get-team-public-profile.ts | 3 +- .../lib/server-only/team/get-team-settings.ts | 2 + packages/lib/server-only/team/get-team.ts | 14 +- packages/lib/server-only/team/get-teams.ts | 3 +- .../server-only/team/get-user-team-groups.ts | 43 + .../team/resend-team-email-verification.ts | 41 +- .../lib/server-only/team/update-team-email.ts | 6 +- .../team/update-team-public-profile.ts | 6 +- packages/lib/server-only/team/update-team.ts | 5 +- .../server-only/telemetry/telemetry-client.ts | 17 +- .../create-document-from-direct-template.ts | 223 +- .../template/create-document-from-template.ts | 126 +- .../template/create-template-direct-link.ts | 14 +- .../template/delete-template-direct-link.ts | 3 +- .../server-only/template/delete-template.ts | 23 +- .../template/find-organisation-templates.ts | 83 + .../server-only/template/find-templates.ts | 91 +- .../get-organisation-template-by-id.ts | 131 + .../get-template-by-direct-link-token.ts | 8 +- .../template/get-template-by-id.ts | 3 +- .../template/search-templates-with-keyword.ts | 129 + .../template/toggle-template-direct-link.ts | 3 +- packages/lib/server-only/user/create-user.ts | 21 +- .../user/find-user-security-audit-logs.ts | 3 +- .../lib/server-only/user/forgot-password.ts | 7 +- .../lib/server-only/user/get-all-users.ts | 10 +- .../user/get-monthly-completed-document.ts | 7 +- ...et-most-recent-email-verification-token.ts | 4 +- .../server-only/user/get-signer-conversion.ts | 7 +- .../user/get-user-by-reset-token.ts | 24 + .../user/get-user-monthly-growth.ts | 3 +- .../lib/server-only/user/reset-password.ts | 15 +- .../user/send-confirmation-token.ts | 8 +- .../user/service-accounts/deleted-account.ts | 39 +- .../legacy-service-account.ts | 34 + .../lib/server-only/user/update-password.ts | 18 +- .../lib/server-only/user/update-profile.ts | 10 +- packages/lib/server-only/user/verify-email.ts | 13 +- .../webhooks/assert-webhook-url.test.ts | 111 + .../webhooks/assert-webhook-url.ts | 130 + .../server-only/webhooks/create-webhook.ts | 3 +- .../lib/server-only/webhooks/edit-webhook.ts | 3 +- .../webhooks/execute-webhook-call.ts | 60 + .../get-all-webhooks-by-event-trigger.ts | 9 +- .../webhooks/is-private-url.test.ts | 113 + .../server-only/webhooks/is-private-url.ts | 82 + .../webhooks/trigger-test-webhook.ts | 9 +- .../webhooks/trigger/generate-sample-data.ts | 217 +- .../server-only/webhooks/trigger/handler.ts | 5 +- .../webhooks/zapier/list-documents.ts | 7 +- .../server-only/webhooks/zapier/subscribe.ts | 8 + packages/lib/types/css-vars.ts | 49 + packages/lib/types/default-recipients.ts | 4 +- packages/lib/types/document-audit-logs.ts | 88 +- packages/lib/types/document-auth.ts | 12 +- packages/lib/types/document-email.ts | 39 +- packages/lib/types/document-form-values.ts | 5 +- packages/lib/types/document-meta.ts | 24 +- packages/lib/types/document.ts | 22 +- packages/lib/types/email-domain.ts | 5 +- .../lib}/types/embed-authoring-base-schema.ts | 0 .../lib}/types/embed-base-schemas.ts | 4 +- .../types/embed-direct-template-schema.ts | 3 +- .../lib}/types/embed-document-sign-schema.ts | 3 +- .../types/embed-multisign-document-schema.ts | 3 +- packages/lib/types/envelope-editor.ts | 342 + packages/lib/types/envelope.ts | 5 +- packages/lib/types/field-meta.ts | 44 +- packages/lib/types/field.ts | 18 +- packages/lib/types/license.ts | 1 + packages/lib/types/organisation-email.ts | 3 +- packages/lib/types/organisation.ts | 7 +- packages/lib/types/recipient.ts | 34 +- packages/lib/types/subscription.ts | 25 +- packages/lib/types/template.ts | 9 +- packages/lib/types/webhook-payload.ts | 40 +- .../lib/universal/extract-request-metadata.ts | 2 +- .../calculate-overflow-layout.ts | 338 + .../field-renderer/field-generic-items.ts | 40 +- .../field-renderer/field-renderer.ts | 6 +- .../field-renderer/render-checkbox-field.ts | 53 +- .../field-renderer/render-dropdown-field.ts | 16 +- .../universal/field-renderer/render-field.ts | 13 +- .../render-generic-text-field.ts | 119 +- .../field-renderer/render-grid-lines.ts | 13 +- .../field-renderer/render-radio-field.ts | 53 +- .../field-renderer/render-signature-field.ts | 252 +- .../lib/universal/generate-twitter-intent.ts | 4 +- packages/lib/universal/id.ts | 10 +- .../lib/universal/upload/put-file.server.ts | 17 +- packages/lib/universal/upload/put-file.ts | 37 +- .../lib/universal/upload/server-actions.ts | 28 +- packages/lib/utils/advanced-fields-helpers.ts | 6 +- packages/lib/utils/billing.ts | 8 +- packages/lib/utils/document-audit-logs.ts | 41 +- packages/lib/utils/document-auth.ts | 23 +- packages/lib/utils/document.ts | 26 +- packages/lib/utils/embed-config.ts | 132 + packages/lib/utils/env.ts | 4 +- packages/lib/utils/envelope-download.ts | 58 +- packages/lib/utils/envelope-signing.ts | 24 +- packages/lib/utils/envelope.ts | 95 +- packages/lib/utils/fields.ts | 41 +- packages/lib/utils/images/avatar.ts | 5 +- .../images/resize-image-to-gemini-image.ts | 5 +- packages/lib/utils/logger.ts | 2 +- .../mask-recipient-tokens-for-document.ts | 3 +- .../lib/utils/normalize-branding-colors.ts | 46 + packages/lib/utils/organisations-claims.ts | 3 +- packages/lib/utils/organisations.ts | 26 +- packages/lib/utils/public-profiles.ts | 10 +- packages/lib/utils/recipients.ts | 57 +- .../lib/utils/render-custom-email-template.ts | 5 +- packages/lib/utils/render-email-with-i18n.tsx | 6 +- .../lib/utils/sanitize-branding-css.test.ts | 436 + packages/lib/utils/sanitize-branding-css.ts | 323 + packages/lib/utils/teams.ts | 18 +- packages/lib/utils/templates.ts | 5 +- packages/lib/utils/timeout.ts | 34 + packages/lib/utils/zod.ts | 38 + packages/lib/vitest.config.ts | 7 + packages/prettier-config/index.cjs | 42 - packages/prettier-config/package.json | 15 - packages/prisma/index.ts | 25 +- .../migration.sql | 14 + .../migration.sql | 18 + .../migration.sql | 13 + .../migration.sql | 2 + .../migration.sql | 17 + .../migration.sql | 1 + .../migration.sql | 16 + .../migration.sql | 8 + .../migration.sql | 10 + .../migration.sql | 7 + packages/prisma/package.json | 2 +- packages/prisma/schema.prisma | 110 +- packages/prisma/seed/documents.ts | 42 +- packages/prisma/seed/folders.ts | 6 +- packages/prisma/seed/initial-seed.ts | 165 +- packages/prisma/seed/large-team-seed.ts | 66 + packages/prisma/seed/medium-account-seed.ts | 77 + packages/prisma/seed/organisations.ts | 5 +- packages/prisma/seed/teams.ts | 17 +- packages/prisma/seed/templates.ts | 10 +- packages/prisma/seed/users.ts | 5 +- .../prisma/types/document-legacy-schema.ts | 14 +- .../prisma/types/extended-document-status.ts | 3 +- .../field-with-signature-and-fieldmeta.ts | 3 +- .../prisma/types/template-legacy-schema.ts | 4 +- packages/prisma/types/types.d.ts | 7 +- packages/signing/helpers/tsa.ts | 3 +- packages/signing/index.ts | 10 +- packages/signing/package.json | 2 +- packages/signing/transports/google-cloud.ts | 15 +- packages/signing/transports/local.ts | 3 +- packages/tailwind-config/index.cjs | 7 +- packages/tailwind-config/package.json | 2 +- packages/tailwind-config/tsconfig.json | 2 +- packages/trpc/client/index.ts | 9 +- packages/trpc/package.json | 2 - packages/trpc/react/index.tsx | 5 +- .../admin-router/create-admin-organisation.ts | 3 +- .../admin-router/create-stripe-customer.ts | 26 +- .../create-subscription-claim.types.ts | 3 +- .../server/admin-router/delete-document.ts | 5 +- .../delete-organisation-member.ts | 123 + .../delete-organisation-member.types.ts | 11 + .../server/admin-router/delete-team-member.ts | 101 + .../admin-router/delete-team-member.types.ts | 11 + .../download-document-audit-logs.ts | 81 + .../download-document-audit-logs.types.ts | 13 + .../admin-router/find-admin-organisations.ts | 11 +- .../find-admin-organisations.types.ts | 3 +- .../admin-router/find-document-audit-logs.ts | 11 +- .../find-document-audit-logs.types.ts | 3 +- .../server/admin-router/find-document-jobs.ts | 13 +- .../admin-router/find-document-jobs.types.ts | 3 +- .../admin-router/find-documents.types.ts | 3 +- .../server/admin-router/find-email-domains.ts | 92 + .../admin-router/find-email-domains.types.ts | 35 + .../admin-router/find-subscription-claims.ts | 11 +- .../find-subscription-claims.types.ts | 3 +- .../admin-router/find-unsealed-documents.ts | 16 + .../find-unsealed-documents.types.ts | 30 + .../server/admin-router/find-user-teams.ts | 3 +- .../admin-router/find-user-teams.types.ts | 3 +- .../get-admin-organisation.types.ts | 3 +- .../server/admin-router/get-admin-team.ts | 130 + .../admin-router/get-admin-team.types.ts | 51 + .../server/admin-router/get-email-domain.ts | 39 + .../admin-router/get-email-domain.types.ts | 29 + .../server/admin-router/get-user.types.ts | 3 +- .../admin-router/promote-member-to-owner.ts | 11 +- .../admin-router/reregister-email-domain.ts | 22 + .../reregister-email-domain.types.ts | 10 + .../server/admin-router/reseal-document.ts | 8 +- .../reset-two-factor-authentication.ts | 5 +- packages/trpc/server/admin-router/router.ts | 24 + .../swap-organisation-subscription.ts | 139 + .../swap-organisation-subscription.types.ts | 11 + .../update-organisation-member-role.ts | 15 +- .../update-organisation-member-role.types.ts | 8 +- .../server/admin-router/update-recipient.ts | 9 +- .../admin-router/update-recipient.types.ts | 4 +- .../admin-router/update-site-setting.ts | 5 +- .../admin-router/update-site-setting.types.ts | 3 +- .../admin-router/update-subscription-claim.ts | 37 +- .../server/admin-router/update-user.types.ts | 3 +- .../api-token-router/create-api-token.ts | 5 +- .../api-token-router/delete-api-token.ts | 5 +- .../api-token-router/get-api-tokens.types.ts | 3 +- ...eate-passkey-registration-options.types.ts | 8 +- .../create-passkey-signin-options.types.ts | 8 +- .../trpc/server/auth-router/create-passkey.ts | 3 +- .../auth-router/create-passkey.types.ts | 3 +- .../server/auth-router/find-passkeys.types.ts | 3 +- packages/trpc/server/auth-router/schema.ts | 5 +- packages/trpc/server/context.ts | 14 +- .../access-auth-request-2fa-email.ts | 16 +- .../access-auth-request-2fa-email.types.ts | 8 +- .../attachment/create-attachment.ts | 11 +- .../attachment/delete-attachment.ts | 5 +- .../attachment/find-attachments.ts | 11 +- .../attachment/find-attachments.types.ts | 3 +- .../attachment/update-attachment.ts | 5 +- .../create-document-temporary.ts | 5 +- .../create-document-temporary.types.ts | 22 +- .../server/document-router/create-document.ts | 5 +- .../document-router/create-document.types.ts | 14 +- .../server/document-router/delete-document.ts | 2 +- .../document-router/distribute-document.ts | 4 +- .../distribute-document.types.ts | 6 +- .../download-document-audit-logs.ts | 3 +- .../download-document-audit-logs.types.ts | 8 +- .../document-router/download-document-beta.ts | 13 +- .../download-document-certificate.ts | 3 +- .../download-document-certificate.types.ts | 8 +- .../document-router/download-document.ts | 2 +- .../document-router/duplicate-document.ts | 2 +- .../find-document-audit-logs.ts | 10 +- .../find-document-audit-logs.types.ts | 3 +- .../find-documents-internal.ts | 31 +- .../find-documents-internal.types.ts | 3 +- .../server/document-router/find-documents.ts | 19 +- .../document-router/find-documents.types.ts | 20 +- .../trpc/server/document-router/find-inbox.ts | 5 +- .../document-router/find-inbox.types.ts | 2 +- .../document-router/get-document-by-token.ts | 8 +- .../get-document-by-token.types.ts | 3 +- .../server/document-router/get-document.ts | 6 +- .../document-router/get-document.types.ts | 3 +- .../document-router/get-documents-by-ids.ts | 5 +- .../get-documents-by-ids.types.ts | 3 +- .../server/document-router/get-inbox-count.ts | 3 +- .../document-router/redistribute-document.ts | 2 +- .../redistribute-document.types.ts | 5 +- .../trpc/server/document-router/schema.ts | 14 +- .../server/document-router/search-document.ts | 5 +- .../document-router/search-document.types.ts | 2 +- .../document-router/share-document.types.ts | 3 +- .../server/document-router/update-document.ts | 4 +- .../document-router/update-document.types.ts | 13 +- .../trpc/server/embedding-router/_router.ts | 4 + .../apply-multi-sign-signature.ts | 10 +- .../apply-multi-sign-signature.types.ts | 8 +- .../create-embedding-document.ts | 7 +- .../create-embedding-document.types.ts | 11 +- .../create-embedding-envelope.ts | 41 + .../create-embedding-envelope.types.ts | 5 + .../create-embedding-presign-token.ts | 4 +- .../create-embedding-presign-token.types.ts | 15 +- .../create-embedding-template.ts | 7 +- .../create-embedding-template.types.ts | 10 +- .../get-multi-sign-document.types.ts | 7 +- .../update-embedding-document.ts | 4 +- .../update-embedding-document.types.ts | 10 +- .../update-embedding-envelope.ts | 512 + .../update-embedding-envelope.types.ts | 113 + .../update-embedding-template.ts | 4 +- .../update-embedding-template.types.ts | 9 +- .../verify-embedding-presign-token.ts | 2 +- .../verify-embedding-presign-token.types.ts | 16 +- .../create-organisation-email-domain.types.ts | 11 +- .../create-organisation-email.types.ts | 3 +- ...decline-link-organisation-account.types.ts | 4 +- .../find-organisation-email-domain.ts | 6 +- .../find-organisation-email-domain.types.ts | 9 +- .../find-organisation-emails.ts | 3 +- .../find-organisation-emails.types.ts | 3 +- .../get-organisation-authentication-portal.ts | 2 + ...rganisation-authentication-portal.types.ts | 35 +- .../get-organisation-email-domain.ts | 5 +- .../get-organisation-email-domain.types.ts | 7 +- .../link-organisation-account.ts | 9 + ...date-organisation-authentication-portal.ts | 9 +- ...rganisation-authentication-portal.types.ts | 4 +- .../attachment/create-attachment.ts | 2 +- .../attachment/delete-attachment.ts | 2 +- .../attachment/find-attachments.ts | 2 +- .../attachment/find-attachments.types.ts | 3 +- .../attachment/update-attachment.ts | 2 +- .../envelope-router/bulk-delete-envelopes.ts | 10 +- .../bulk-delete-envelopes.types.ts | 4 +- .../envelope-router/bulk-move-envelopes.ts | 5 +- .../bulk-move-envelopes.types.ts | 8 +- .../envelope-router/create-envelope-items.ts | 158 +- .../create-envelope-items.types.ts | 8 +- .../server/envelope-router/create-envelope.ts | 312 +- .../envelope-router/create-envelope.types.ts | 33 +- .../envelope-router/delete-envelope-item.ts | 59 +- .../server/envelope-router/delete-envelope.ts | 7 +- .../envelope-router/distribute-envelope.ts | 4 +- .../distribute-envelope.types.ts | 3 +- .../envelope-router/download-envelope-item.ts | 2 +- .../download-envelope-item.types.ts | 4 +- .../envelope-router/duplicate-envelope.ts | 2 +- .../envelope-fields/create-envelope-fields.ts | 2 +- .../create-envelope-fields.types.ts | 14 +- .../envelope-fields/delete-envelope-field.ts | 5 +- .../get-envelope-field-signatures.ts | 64 + .../get-envelope-field-signatures.types.ts | 16 + .../envelope-fields/get-envelope-field.ts | 2 +- .../get-envelope-field.types.ts | 3 +- .../envelope-fields/update-envelope-fields.ts | 2 +- .../update-envelope-fields.types.ts | 29 +- .../create-envelope-recipients.ts | 2 +- .../create-envelope-recipients.types.ts | 19 +- .../delete-envelope-recipient.ts | 2 +- .../delete-envelope-recipient.types.ts | 4 +- .../get-envelope-recipient.ts | 2 +- .../get-envelope-recipient.types.ts | 3 +- .../update-envelope-recipients.ts | 2 +- .../update-envelope-recipients.types.ts | 16 +- .../find-envelope-audit-logs.ts | 13 +- .../find-envelope-audit-logs.types.ts | 3 +- .../server/envelope-router/find-envelopes.ts | 20 +- .../envelope-router/find-envelopes.types.ts | 25 +- .../envelope-router/get-editor-envelope.ts | 28 + .../get-editor-envelope.types.ts | 11 + .../get-envelope-items-by-token.ts | 39 +- .../get-envelope-items-by-token.types.ts | 3 +- .../envelope-router/get-envelope-items.ts | 5 +- .../get-envelope-items.types.ts | 3 +- .../server/envelope-router/get-envelope.ts | 6 +- .../envelope-router/get-envelope.types.ts | 3 +- .../envelope-router/get-envelopes-by-ids.ts | 2 +- .../get-envelopes-by-ids.types.ts | 3 +- .../envelope-router/redistribute-envelope.ts | 2 +- .../redistribute-envelope.types.ts | 5 +- .../replace-envelope-item-pdf.ts | 105 + .../replace-envelope-item-pdf.types.ts | 41 + .../trpc/server/envelope-router/router.ts | 10 + .../envelope-router/save-as-template.ts | 36 + .../envelope-router/save-as-template.types.ts | 14 + .../trpc/server/envelope-router/schema.ts | 3 +- .../envelope-router/set-envelope-fields.ts | 10 +- .../set-envelope-fields.types.ts | 15 +- .../set-envelope-recipients.ts | 5 +- .../set-envelope-recipients.types.ts | 23 +- .../envelope-router/sign-envelope-field.ts | 45 +- .../sign-envelope-field.types.ts | 3 +- .../signing-status-envelope.ts | 6 +- .../envelope-router/update-envelope-items.ts | 73 +- .../update-envelope-items.types.ts | 3 +- .../server/envelope-router/update-envelope.ts | 2 +- .../envelope-router/update-envelope.types.ts | 16 +- .../server/envelope-router/use-envelope.ts | 21 +- .../envelope-router/use-envelope.types.ts | 15 +- packages/trpc/server/field-router/router.ts | 39 +- packages/trpc/server/field-router/schema.ts | 9 +- packages/trpc/server/folder-router/schema.ts | 12 +- packages/trpc/server/open-api.ts | 3 +- ...accept-organisation-member-invite.types.ts | 4 +- .../create-organisation-group.ts | 8 +- ...reate-organisation-member-invites.types.ts | 3 +- .../create-organisation.ts | 12 +- .../decline-organisation-member-invite.ts | 3 +- ...ecline-organisation-member-invite.types.ts | 4 +- .../delete-organisation-group.ts | 3 +- .../delete-organisation-member-invites.ts | 43 +- .../delete-organisation-members.ts | 41 +- .../delete-organisation-members.types.ts | 8 +- .../delete-organisation.ts | 5 +- .../find-organisation-groups.ts | 18 +- .../find-organisation-groups.types.ts | 11 +- .../find-organisation-member-invites.ts | 5 +- .../find-organisation-member-invites.types.ts | 9 +- .../find-organisation-members.ts | 26 +- .../find-organisation-members.types.ts | 13 +- .../get-organisation-member-invites.types.ts | 9 +- .../get-organisation-session.ts | 12 +- .../get-organisation-session.types.ts | 5 +- .../organisation-router/get-organisation.ts | 10 +- .../get-organisation.types.ts | 3 +- .../organisation-router/get-organisations.ts | 5 +- .../get-organisations.types.ts | 3 +- .../organisation-router/leave-organisation.ts | 53 +- .../update-organisation-group.ts | 20 +- .../update-organisation-members.ts | 11 +- .../update-organisation-settings.ts | 41 +- .../update-organisation-settings.types.ts | 24 +- .../update-organisation.ts | 5 +- packages/trpc/server/profile-router/router.ts | 82 +- packages/trpc/server/profile-router/schema.ts | 3 +- .../find-recipient-suggestions.types.ts | 11 +- .../trpc/server/recipient-router/router.ts | 39 +- .../trpc/server/recipient-router/schema.ts | 29 +- .../server/team-router/create-team-groups.ts | 42 +- .../server/team-router/create-team-members.ts | 71 +- .../team-router/create-team-members.types.ts | 3 +- .../server/team-router/create-team.types.ts | 4 +- .../server/team-router/delete-team-group.ts | 5 +- .../server/team-router/delete-team-member.ts | 51 +- .../trpc/server/team-router/delete-team.ts | 3 +- .../server/team-router/find-team-groups.ts | 12 +- .../team-router/find-team-groups.types.ts | 5 +- .../server/team-router/find-team-members.ts | 5 +- .../team-router/find-team-members.types.ts | 3 +- .../server/team-router/find-teams.types.ts | 5 +- .../server/team-router/get-team-members.ts | 5 +- .../team-router/get-team-members.types.ts | 3 +- .../trpc/server/team-router/get-team.types.ts | 3 +- packages/trpc/server/team-router/router.ts | 52 +- packages/trpc/server/team-router/schema.ts | 29 +- .../server/team-router/update-team-group.ts | 5 +- .../server/team-router/update-team-member.ts | 12 +- .../team-router/update-team-settings.ts | 56 +- .../team-router/update-team-settings.types.ts | 24 +- .../template-router/get-templates-by-ids.ts | 11 +- .../get-templates-by-ids.types.ts | 3 +- .../trpc/server/template-router/router.ts | 180 +- .../trpc/server/template-router/schema.ts | 51 +- .../server/template-router/search-template.ts | 18 + .../template-router/search-template.types.ts | 16 + packages/trpc/server/trpc.ts | 30 +- .../webhook-router/find-webhook-calls.ts | 8 +- .../find-webhook-calls.types.ts | 5 +- .../webhook-router/resend-webhook-call.ts | 52 +- .../resend-webhook-call.types.ts | 17 +- packages/trpc/server/webhook-router/router.ts | 134 +- packages/trpc/server/webhook-router/schema.ts | 10 +- packages/trpc/tsconfig.json | 2 +- packages/trpc/utils/openapi-fetch-handler.ts | 4 +- packages/trpc/utils/trpc-error-handler.ts | 9 +- packages/trpc/utils/zod-form-data.ts | 16 + packages/tsconfig/base.json | 12 +- packages/tsconfig/package.json | 2 +- packages/tsconfig/process-env.d.ts | 20 +- .../animate/animate-generic-fade-in-out.tsx | 6 +- packages/ui/components/client-only.tsx | 2 +- .../ui/components/common/copy-text-button.tsx | 15 +- .../common/language-switcher-dialog.tsx | 26 +- packages/ui/components/common/local-time.tsx | 119 + .../document/document-email-checkboxes.tsx | 165 +- .../document-global-auth-access-select.tsx | 24 +- .../document-global-auth-action-select.tsx | 38 +- .../document/document-read-only-fields.tsx | 53 +- .../document-send-email-message-helper.tsx | 18 +- .../document/document-share-button.tsx | 46 +- .../document-signature-settings-tooltip.tsx | 9 +- .../document/document-visibility-select.tsx | 37 +- .../envelope-recipient-field-tooltip.tsx | 44 +- .../document/expiration-period-picker.tsx | 137 + .../document/reminder-settings-picker.tsx | 253 + .../field/envelope-field-tooltip.tsx | 30 +- .../ui/components/field/field-tooltip.tsx | 17 +- packages/ui/components/field/field.tsx | 49 +- .../pdf-viewer/pdf-viewer-konva-lazy.tsx | 26 - .../pdf-viewer/pdf-viewer-konva.tsx | 213 - .../recipient-action-auth-select.tsx | 38 +- .../recipient-autocomplete-input.tsx | 12 +- .../recipient/recipient-role-select.tsx | 173 +- packages/ui/components/signing-card.tsx | 55 +- .../template/template-type-select.tsx | 62 + packages/ui/icons/signature.tsx | 12 +- packages/ui/icons/verified.tsx | 51 +- packages/ui/lib/handle-dropzone-rejection.tsx | 15 + packages/ui/lib/recipient-colors.ts | 183 +- packages/ui/package.json | 5 +- packages/ui/primitives/accordion.tsx | 9 +- packages/ui/primitives/alert-dialog.tsx | 40 +- packages/ui/primitives/alert.tsx | 32 +- packages/ui/primitives/auto-sized-text.tsx | 24 +- packages/ui/primitives/avatar.tsx | 30 +- packages/ui/primitives/badge.tsx | 58 +- packages/ui/primitives/button.tsx | 14 +- packages/ui/primitives/calendar.tsx | 8 +- packages/ui/primitives/card.tsx | 33 +- packages/ui/primitives/checkbox.tsx | 7 +- packages/ui/primitives/collapsible.tsx | 2 +- packages/ui/primitives/color-picker.tsx | 21 +- packages/ui/primitives/combobox.tsx | 7 +- packages/ui/primitives/command.tsx | 47 +- packages/ui/primitives/context-menu.tsx | 44 +- .../ui/primitives/data-table-pagination.tsx | 24 +- packages/ui/primitives/data-table.tsx | 13 +- packages/ui/primitives/dialog.tsx | 94 +- packages/ui/primitives/document-dropzone.tsx | 71 +- .../primitives/document-flow/add-fields.tsx | 160 +- .../document-flow/add-fields.types.ts | 3 +- .../primitives/document-flow/add-settings.tsx | 96 +- .../document-flow/add-settings.types.ts | 25 +- .../primitives/document-flow/add-signers.tsx | 189 +- .../document-flow/add-signers.types.ts | 9 +- .../primitives/document-flow/add-subject.tsx | 106 +- .../document-flow/add-subject.types.ts | 14 +- .../document-flow/document-flow-root.tsx | 23 +- .../document-flow/field-content.tsx | 45 +- .../field-item-advanced-settings.tsx | 55 +- .../primitives/document-flow/field-item.tsx | 97 +- .../checkbox-field.tsx | 64 +- .../date-field.tsx | 23 +- .../dropdown-field.tsx | 59 +- .../email-field.tsx | 23 +- .../initials-field.tsx | 14 +- .../name-field.tsx | 22 +- .../number-field.tsx | 46 +- .../radio-field.tsx | 32 +- .../text-field.tsx | 28 +- .../missing-signature-field-dialog.tsx | 14 +- .../send-document-action-dialog.tsx | 20 +- .../signing-order-confirmation.tsx | 10 +- packages/ui/primitives/document-flow/types.ts | 6 +- .../ui/primitives/document-upload-button.tsx | 27 +- packages/ui/primitives/dropdown-menu.tsx | 41 +- packages/ui/primitives/element-visible.tsx | 3 +- packages/ui/primitives/field-selector.tsx | 27 +- .../ui/primitives/form/form-error-message.tsx | 2 +- packages/ui/primitives/form/form.tsx | 139 +- packages/ui/primitives/hover-card.tsx | 7 +- packages/ui/primitives/input.tsx | 34 +- packages/ui/primitives/label.tsx | 9 +- packages/ui/primitives/menubar.tsx | 57 +- .../ui/primitives/multi-select-combobox.tsx | 14 +- packages/ui/primitives/multiselect.tsx | 131 +- packages/ui/primitives/navigation-menu.tsx | 23 +- packages/ui/primitives/password-input.tsx | 52 +- .../ui/primitives/pdf-viewer/base.client.tsx | 10 - packages/ui/primitives/pdf-viewer/base.tsx | 290 - packages/ui/primitives/pdf-viewer/index.ts | 1 - packages/ui/primitives/pdf-viewer/lazy.tsx | 7 - packages/ui/primitives/pin-input.tsx | 59 +- packages/ui/primitives/popover.tsx | 14 +- packages/ui/primitives/progress.tsx | 7 +- packages/ui/primitives/radio-group.tsx | 7 +- packages/ui/primitives/recipient-selector.tsx | 68 +- packages/ui/primitives/scroll-area.tsx | 15 +- packages/ui/primitives/select.tsx | 36 +- packages/ui/primitives/separator.tsx | 9 +- packages/ui/primitives/sheet.tsx | 238 +- .../ui/primitives/signature-pad/canvas.ts | 7 +- packages/ui/primitives/signature-pad/point.ts | 18 +- .../signature-pad-color-picker.tsx | 27 +- .../signature-pad/signature-pad-dialog.tsx | 15 +- .../signature-pad/signature-pad-draw.tsx | 39 +- .../signature-pad/signature-pad-type.tsx | 10 +- .../signature-pad/signature-pad-upload.tsx | 35 +- .../signature-pad/signature-pad.tsx | 21 +- .../signature-pad/signature-render.tsx | 3 +- .../signature-pad/signature-tabs.tsx | 31 +- packages/ui/primitives/skeleton.tsx | 2 +- packages/ui/primitives/slider.tsx | 9 +- packages/ui/primitives/spinner.tsx | 31 +- packages/ui/primitives/stepper.tsx | 2 +- packages/ui/primitives/switch.tsx | 7 +- packages/ui/primitives/table.tsx | 84 +- packages/ui/primitives/tabs.tsx | 11 +- .../template-flow/add-template-fields.tsx | 269 +- .../add-template-fields.types.ts | 3 +- .../add-template-placeholder-recipients.tsx | 189 +- ...d-template-placeholder-recipients.types.ts | 10 +- .../template-flow/add-template-settings.tsx | 180 +- .../add-template-settings.types.tsx | 33 +- packages/ui/primitives/textarea.tsx | 32 +- packages/ui/primitives/theme-switcher.tsx | 17 +- packages/ui/primitives/toast.tsx | 44 +- packages/ui/primitives/toaster.tsx | 31 +- packages/ui/primitives/toggle.tsx | 9 +- packages/ui/primitives/tooltip.tsx | 14 +- packages/ui/primitives/use-toast.ts | 6 +- packages/ui/styles/theme.css | 17 +- packages/ui/tailwind.config.cjs | 11 +- packages/ui/tsconfig.json | 12 +- prettier.config.cjs | 1 - render.yaml | 8 + scripts/create-justification.ts | 3 +- scripts/create-plan.ts | 3 +- scripts/create-scratch.ts | 3 +- scripts/generate-overflow-test-pdf.mjs | 260 + turbo.json | 15 +- 1959 files changed, 93488 insertions(+), 47038 deletions(-) create mode 100644 .agents/plans/bright-emerald-flower-bullmq-background-jobs.md create mode 100644 .agents/plans/calm-violet-tide-envelope-expiration.md create mode 100644 .agents/plans/dark-hazel-beam-swap-subscription-between-orgs.md create mode 100644 .agents/plans/fresh-gold-rock-cert-page-width-mismatch.md create mode 100644 .agents/plans/happy-teal-tree-platform-signing-page-branding.md create mode 100644 .agents/plans/pale-lemon-rock-pnpm-migration.md create mode 100644 .agents/plans/smooth-coral-earth-database-rate-limiting.md create mode 100644 .agents/plans/smooth-ivory-sky-partial-signed-pdf-download.md create mode 100644 .agents/plans/warm-purple-flower-custom-email-domain-sync-and-recovery.md create mode 100644 .agents/plans/wild-teal-wind-add-folder-support-to-v1-api.md create mode 100644 .agents/scratches/search-query-optimization.md create mode 100644 .agents/skills/agent-browser/SKILL.md create mode 100644 .agents/skills/agent-browser/references/authentication.md create mode 100644 .agents/skills/agent-browser/references/commands.md create mode 100644 .agents/skills/agent-browser/references/proxy-support.md create mode 100644 .agents/skills/agent-browser/references/session-management.md create mode 100644 .agents/skills/agent-browser/references/snapshot-refs.md create mode 100644 .agents/skills/agent-browser/references/video-recording.md create mode 100755 .agents/skills/agent-browser/templates/authenticated-session.sh create mode 100755 .agents/skills/agent-browser/templates/capture-workflow.sh create mode 100755 .agents/skills/agent-browser/templates/form-automation.sh create mode 100644 .agents/skills/create-documentation/SKILL.md rename {.opencode/skill => .agents/skills}/create-justification/SKILL.md (100%) rename {.opencode/skill => .agents/skills}/create-plan/SKILL.md (100%) rename {.opencode/skill => .agents/skills}/create-scratch/SKILL.md (100%) create mode 100644 .agents/skills/envelope-editor-v2-e2e/SKILL.md delete mode 100644 .eslintignore delete mode 100644 .eslintrc.cjs create mode 100644 .opencode/commands/create-documentation.md delete mode 100644 .opencode/commands/document.md delete mode 100644 .prettierignore create mode 100644 ARCHITECTURE.md create mode 100644 WRITING_STYLE.md create mode 100644 apps/docs/.gitignore create mode 100644 apps/docs/README.md create mode 100644 apps/docs/cli.json create mode 100644 apps/docs/content/docs/compliance/certifications.mdx create mode 100644 apps/docs/content/docs/compliance/esign.mdx create mode 100644 apps/docs/content/docs/compliance/gdpr.mdx create mode 100644 apps/docs/content/docs/compliance/index.mdx create mode 100644 apps/docs/content/docs/compliance/meta.json create mode 100644 apps/docs/content/docs/compliance/signature-levels.mdx create mode 100644 apps/docs/content/docs/compliance/standards.mdx create mode 100644 apps/docs/content/docs/concepts/document-lifecycle.mdx create mode 100644 apps/docs/content/docs/concepts/field-types.mdx create mode 100644 apps/docs/content/docs/concepts/index.mdx create mode 100644 apps/docs/content/docs/concepts/meta.json create mode 100644 apps/docs/content/docs/concepts/recipient-roles.mdx create mode 100644 apps/docs/content/docs/concepts/signing-certificates.mdx create mode 100644 apps/docs/content/docs/concepts/signing-workflow.mdx create mode 100644 apps/docs/content/docs/developers/api/developer-mode.mdx create mode 100644 apps/docs/content/docs/developers/api/documents.mdx create mode 100644 apps/docs/content/docs/developers/api/fields.mdx create mode 100644 apps/docs/content/docs/developers/api/index.mdx create mode 100644 apps/docs/content/docs/developers/api/meta.json rename apps/{documentation/pages/developers/public-api => docs/content/docs/developers/api}/rate-limits.mdx (79%) create mode 100644 apps/docs/content/docs/developers/api/recipients.mdx create mode 100644 apps/docs/content/docs/developers/api/teams.mdx create mode 100644 apps/docs/content/docs/developers/api/templates.mdx rename apps/{documentation/pages/developers/public-api => docs/content/docs/developers/api}/versioning.mdx (80%) rename apps/{documentation/pages => docs/content/docs}/developers/contributing/contributing-translations.mdx (60%) rename apps/{documentation/pages => docs/content/docs}/developers/contributing/index.mdx (80%) create mode 100644 apps/docs/content/docs/developers/contributing/meta.json create mode 100644 apps/docs/content/docs/developers/demo-environment/index.mdx create mode 100644 apps/docs/content/docs/developers/embedding/authoring/index.mdx create mode 100644 apps/docs/content/docs/developers/embedding/authoring/meta.json create mode 100644 apps/docs/content/docs/developers/embedding/authoring/v1.mdx create mode 100644 apps/docs/content/docs/developers/embedding/authoring/v2.mdx create mode 100644 apps/docs/content/docs/developers/embedding/css-variables.mdx create mode 100644 apps/docs/content/docs/developers/embedding/direct-links.mdx create mode 100644 apps/docs/content/docs/developers/embedding/index.mdx create mode 100644 apps/docs/content/docs/developers/embedding/meta.json create mode 100644 apps/docs/content/docs/developers/embedding/sdks/angular.mdx create mode 100644 apps/docs/content/docs/developers/embedding/sdks/index.mdx create mode 100644 apps/docs/content/docs/developers/embedding/sdks/meta.json create mode 100644 apps/docs/content/docs/developers/embedding/sdks/preact.mdx create mode 100644 apps/docs/content/docs/developers/embedding/sdks/react.mdx create mode 100644 apps/docs/content/docs/developers/embedding/sdks/solid.mdx create mode 100644 apps/docs/content/docs/developers/embedding/sdks/svelte.mdx create mode 100644 apps/docs/content/docs/developers/embedding/sdks/vue.mdx create mode 100644 apps/docs/content/docs/developers/examples/common-workflows.mdx create mode 100644 apps/docs/content/docs/developers/examples/index.mdx create mode 100644 apps/docs/content/docs/developers/examples/meta.json create mode 100644 apps/docs/content/docs/developers/getting-started/authentication.mdx create mode 100644 apps/docs/content/docs/developers/getting-started/first-api-call.mdx create mode 100644 apps/docs/content/docs/developers/getting-started/index.mdx create mode 100644 apps/docs/content/docs/developers/getting-started/meta.json create mode 100644 apps/docs/content/docs/developers/index.mdx rename apps/{documentation/pages => docs/content/docs}/developers/local-development/gitpod.mdx (61%) rename apps/{documentation/pages => docs/content/docs}/developers/local-development/index.mdx (84%) rename apps/{documentation/pages => docs/content/docs}/developers/local-development/manual.mdx (63%) create mode 100644 apps/docs/content/docs/developers/local-development/meta.json rename apps/{documentation/pages => docs/content/docs}/developers/local-development/quickstart.mdx (73%) rename apps/{documentation/pages => docs/content/docs}/developers/local-development/signing-certificate.mdx (74%) rename apps/{documentation/pages => docs/content/docs}/developers/local-development/translations.mdx (93%) create mode 100644 apps/docs/content/docs/developers/meta.json create mode 100644 apps/docs/content/docs/developers/webhooks/events.mdx create mode 100644 apps/docs/content/docs/developers/webhooks/index.mdx create mode 100644 apps/docs/content/docs/developers/webhooks/meta.json create mode 100644 apps/docs/content/docs/developers/webhooks/setup.mdx create mode 100644 apps/docs/content/docs/developers/webhooks/verification.mdx create mode 100644 apps/docs/content/docs/index.mdx create mode 100644 apps/docs/content/docs/meta.json create mode 100644 apps/docs/content/docs/policies/community-edition.mdx create mode 100644 apps/docs/content/docs/policies/enterprise-edition.mdx create mode 100644 apps/docs/content/docs/policies/fair-use.mdx create mode 100644 apps/docs/content/docs/policies/index.mdx create mode 100644 apps/docs/content/docs/policies/licenses.mdx create mode 100644 apps/docs/content/docs/policies/meta.json create mode 100644 apps/docs/content/docs/policies/privacy.mdx create mode 100644 apps/docs/content/docs/policies/security.mdx create mode 100644 apps/docs/content/docs/policies/support.mdx create mode 100644 apps/docs/content/docs/policies/terms.mdx rename apps/{documentation/pages/developers/self-hosting => docs/content/docs/self-hosting/configuration/advanced}/ai-features.mdx (55%) create mode 100644 apps/docs/content/docs/self-hosting/configuration/advanced/index.mdx create mode 100644 apps/docs/content/docs/self-hosting/configuration/advanced/meta.json create mode 100644 apps/docs/content/docs/self-hosting/configuration/advanced/oauth-providers.mdx create mode 100644 apps/docs/content/docs/self-hosting/configuration/background-jobs.mdx create mode 100644 apps/docs/content/docs/self-hosting/configuration/database.mdx create mode 100644 apps/docs/content/docs/self-hosting/configuration/email.mdx create mode 100644 apps/docs/content/docs/self-hosting/configuration/environment.mdx create mode 100644 apps/docs/content/docs/self-hosting/configuration/index.mdx create mode 100644 apps/docs/content/docs/self-hosting/configuration/meta.json create mode 100644 apps/docs/content/docs/self-hosting/configuration/signing-certificate/google-cloud-hsm.mdx create mode 100644 apps/docs/content/docs/self-hosting/configuration/signing-certificate/index.mdx create mode 100644 apps/docs/content/docs/self-hosting/configuration/signing-certificate/local.mdx create mode 100644 apps/docs/content/docs/self-hosting/configuration/signing-certificate/meta.json create mode 100644 apps/docs/content/docs/self-hosting/configuration/signing-certificate/timestamp-server.mdx create mode 100644 apps/docs/content/docs/self-hosting/configuration/signing-certificate/troubleshooting.mdx create mode 100644 apps/docs/content/docs/self-hosting/configuration/storage.mdx rename apps/{documentation/pages/developers/self-hosting => docs/content/docs/self-hosting/configuration}/telemetry.mdx (58%) create mode 100644 apps/docs/content/docs/self-hosting/deployment/docker-compose.mdx create mode 100644 apps/docs/content/docs/self-hosting/deployment/docker.mdx create mode 100644 apps/docs/content/docs/self-hosting/deployment/index.mdx create mode 100644 apps/docs/content/docs/self-hosting/deployment/kubernetes.mdx create mode 100644 apps/docs/content/docs/self-hosting/deployment/manual.mdx create mode 100644 apps/docs/content/docs/self-hosting/deployment/meta.json create mode 100644 apps/docs/content/docs/self-hosting/deployment/railway.mdx create mode 100644 apps/docs/content/docs/self-hosting/getting-started/index.mdx create mode 100644 apps/docs/content/docs/self-hosting/getting-started/meta.json create mode 100644 apps/docs/content/docs/self-hosting/getting-started/quick-start.mdx create mode 100644 apps/docs/content/docs/self-hosting/getting-started/requirements.mdx create mode 100644 apps/docs/content/docs/self-hosting/getting-started/tips.mdx create mode 100644 apps/docs/content/docs/self-hosting/index.mdx create mode 100644 apps/docs/content/docs/self-hosting/maintenance/backups.mdx create mode 100644 apps/docs/content/docs/self-hosting/maintenance/index.mdx create mode 100644 apps/docs/content/docs/self-hosting/maintenance/meta.json create mode 100644 apps/docs/content/docs/self-hosting/maintenance/troubleshooting.mdx create mode 100644 apps/docs/content/docs/self-hosting/maintenance/upgrades.mdx create mode 100644 apps/docs/content/docs/self-hosting/meta.json create mode 100644 apps/docs/content/docs/users/documents/add-fields.mdx create mode 100644 apps/docs/content/docs/users/documents/add-recipients.mdx create mode 100644 apps/docs/content/docs/users/documents/advanced/ai-detection.mdx create mode 100644 apps/docs/content/docs/users/documents/advanced/default-recipients.mdx create mode 100644 apps/docs/content/docs/users/documents/advanced/document-visibility.mdx create mode 100644 apps/docs/content/docs/users/documents/advanced/index.mdx create mode 100644 apps/docs/content/docs/users/documents/advanced/meta.json rename apps/{documentation/pages/users/documents => docs/content/docs/users/documents/advanced}/pdf-placeholders.mdx (80%) create mode 100644 apps/docs/content/docs/users/documents/advanced/recipient-expiration.mdx create mode 100644 apps/docs/content/docs/users/documents/advanced/signing-reminders.mdx create mode 100644 apps/docs/content/docs/users/documents/direct-links.mdx create mode 100644 apps/docs/content/docs/users/documents/index.mdx create mode 100644 apps/docs/content/docs/users/documents/meta.json create mode 100644 apps/docs/content/docs/users/documents/send.mdx create mode 100644 apps/docs/content/docs/users/documents/upload.mdx create mode 100644 apps/docs/content/docs/users/getting-started/create-account.mdx create mode 100644 apps/docs/content/docs/users/getting-started/index.mdx create mode 100644 apps/docs/content/docs/users/getting-started/meta.json create mode 100644 apps/docs/content/docs/users/getting-started/send-first-document.mdx create mode 100644 apps/docs/content/docs/users/index.mdx create mode 100644 apps/docs/content/docs/users/meta.json rename apps/{documentation/pages => docs/content/docs}/users/organisations/billing.mdx (61%) create mode 100644 apps/docs/content/docs/users/organisations/create-team.mdx rename apps/{documentation/pages/users => docs/content/docs/users/organisations}/email-domains.mdx (71%) create mode 100644 apps/docs/content/docs/users/organisations/groups.mdx create mode 100644 apps/docs/content/docs/users/organisations/index.mdx create mode 100644 apps/docs/content/docs/users/organisations/members.mdx create mode 100644 apps/docs/content/docs/users/organisations/meta.json create mode 100644 apps/docs/content/docs/users/organisations/overview.mdx create mode 100644 apps/docs/content/docs/users/organisations/preferences/branding.mdx create mode 100644 apps/docs/content/docs/users/organisations/preferences/document.mdx create mode 100644 apps/docs/content/docs/users/organisations/preferences/email.mdx create mode 100644 apps/docs/content/docs/users/organisations/preferences/index.mdx create mode 100644 apps/docs/content/docs/users/organisations/preferences/meta.json create mode 100644 apps/docs/content/docs/users/organisations/single-sign-on/configuration.mdx create mode 100644 apps/docs/content/docs/users/organisations/single-sign-on/index.mdx create mode 100644 apps/docs/content/docs/users/organisations/single-sign-on/meta.json create mode 100644 apps/docs/content/docs/users/organisations/single-sign-on/microsoft-entra-id.mdx create mode 100644 apps/docs/content/docs/users/settings/api-tokens.mdx create mode 100644 apps/docs/content/docs/users/settings/delete-account.mdx create mode 100644 apps/docs/content/docs/users/settings/index.mdx create mode 100644 apps/docs/content/docs/users/settings/meta.json create mode 100644 apps/docs/content/docs/users/settings/profile.mdx create mode 100644 apps/docs/content/docs/users/settings/public-profile.mdx create mode 100644 apps/docs/content/docs/users/settings/security.mdx create mode 100644 apps/docs/content/docs/users/settings/sessions.mdx create mode 100644 apps/docs/content/docs/users/templates/create.mdx create mode 100644 apps/docs/content/docs/users/templates/index.mdx create mode 100644 apps/docs/content/docs/users/templates/meta.json create mode 100644 apps/docs/content/docs/users/templates/organisation-templates.mdx create mode 100644 apps/docs/content/docs/users/templates/use.mdx create mode 100644 apps/docs/next.config.mjs create mode 100644 apps/docs/package.json create mode 100644 apps/docs/postcss.config.mjs rename apps/{documentation => docs}/public/apple-touch-icon.png (100%) rename apps/{documentation => docs}/public/default-recipients/organisation-default-recipients-role-step.webp (100%) rename apps/{documentation => docs}/public/default-recipients/organisation-default-recipients-select-step.webp (100%) rename apps/{documentation => docs}/public/default-recipients/team-default-recipients.webp (100%) create mode 100644 apps/docs/public/developer-mode/field-coordinates-legacy-editor.webp create mode 100644 apps/docs/public/developer-mode/field-coordinates-new-editor.webp rename apps/{documentation => docs}/public/direct-links/choose-direct-link-recipient-documenso.webp (100%) rename apps/{documentation => docs}/public/direct-links/documenso-profile.webp (100%) rename apps/{documentation => docs}/public/direct-links/document-direct-link-documenso.webp (100%) rename apps/{documentation => docs}/public/direct-links/enable-document-direct-link-modal.webp (100%) rename apps/{documentation => docs}/public/document-signing/ai-field-detection-button.webp (100%) rename apps/{documentation => docs}/public/document-signing/ai-field-detection-dialog.webp (100%) rename apps/{documentation => docs}/public/document-signing/ai-recipient-detect-button.webp (100%) rename apps/{documentation => docs}/public/document-signing/checkbox-field-document-editor-view.webp (100%) rename apps/{documentation => docs}/public/document-signing/date-field-document-editor-view.webp (100%) rename apps/{documentation => docs}/public/document-signing/documenso-document-email-settings.webp (100%) rename apps/{documentation => docs}/public/document-signing/documenso-document-fields.webp (100%) rename apps/{documentation => docs}/public/document-signing/documenso-documents-dashboard.webp (100%) rename apps/{documentation => docs}/public/document-signing/documenso-editor-email-settings.webp (100%) rename apps/{documentation => docs}/public/document-signing/documenso-editor-general-settings.webp (100%) rename apps/{documentation => docs}/public/document-signing/documenso-editor-preview.webp (100%) rename apps/{documentation => docs}/public/document-signing/documenso-editor-security-settings.webp (100%) rename apps/{documentation => docs}/public/document-signing/documenso-sign-email.webp (100%) rename apps/{documentation => docs}/public/document-signing/documenso-signing-links.webp (100%) rename apps/{documentation => docs}/public/document-signing/dropdown-field-document-editor-view.webp (100%) rename apps/{documentation => docs}/public/document-signing/editor-overview.webp (100%) rename apps/{documentation => docs}/public/document-signing/editor-upload-recipients.webp (100%) rename apps/{documentation => docs}/public/document-signing/email-field-document-editor-view.webp (100%) rename apps/{documentation => docs}/public/document-signing/initials-field-document-editor-view.webp (100%) rename apps/{documentation => docs}/public/document-signing/name-field-document-editor-view.webp (100%) rename apps/{documentation => docs}/public/document-signing/number-field-document-editor-view.webp (100%) rename apps/{documentation => docs}/public/document-signing/radio-field-document-editor-view.webp (100%) rename apps/{documentation => docs}/public/document-signing/signature-field-document-editor-view.webp (100%) rename apps/{documentation => docs}/public/document-signing/text-field-document-editor-view.webp (100%) rename apps/{documentation => docs}/public/email-domains/email-domain-sync.webp (100%) rename apps/{documentation => docs}/public/email-domains/email-domains-manage-create-email.webp (100%) rename apps/{documentation => docs}/public/email-domains/email-domains-manage.webp (100%) rename apps/{documentation => docs}/public/email-domains/email-domains-record.webp (100%) rename apps/{documentation => docs}/public/email-domains/email-domains-settings-page.webp (100%) rename apps/{documentation => docs}/public/embedding/copy-recipient-token.png (100%) rename apps/{documentation => docs}/public/embedding/enable-direct-link.png (100%) rename apps/{documentation => docs}/public/embedding/team-templates.png (100%) rename apps/{documentation => docs}/public/favicon-16x16.png (100%) rename apps/{documentation => docs}/public/favicon-32x32.png (100%) create mode 100644 apps/docs/public/fonts/inter-bold.ttf create mode 100644 apps/docs/public/fonts/inter-regular.ttf create mode 100644 apps/docs/public/fonts/inter-semibold.ttf rename apps/{documentation => docs}/public/get-started-images/documenso-account-security-page.webp (100%) rename apps/{documentation => docs}/public/get-started-images/documenso-add-passkey-box.webp (100%) rename apps/{documentation => docs}/public/get-started-images/documenso-enable-2-factor-authentication.webp (100%) rename apps/{documentation => docs}/public/get-started-images/documenso-passkeys-page.webp (100%) create mode 100644 apps/docs/public/logo.png rename apps/{documentation => docs}/public/organisations/organisation-branding.webp (100%) rename apps/{documentation => docs}/public/organisations/organisation-document-preferences.webp (100%) rename apps/{documentation => docs}/public/organisations/organisation-document-visibility.webp (100%) rename apps/{documentation => docs}/public/organisations/organisation-email-preferences.webp (100%) rename apps/{documentation => docs}/public/organisations/organisation-group-assignment.webp (100%) rename apps/{documentation => docs}/public/organisations/organisation-group-create.webp (100%) rename apps/{documentation => docs}/public/organisations/organisation-group-manage.webp (100%) rename apps/{documentation => docs}/public/organisations/organisations-basic-diagram.webp (100%) rename apps/{documentation => docs}/public/organisations/organisations-billing.webp (100%) rename apps/{documentation => docs}/public/organisations/organisations-create.webp (100%) rename apps/{documentation => docs}/public/organisations/organisations-member-invite.webp (100%) rename apps/{documentation => docs}/public/organisations/organisations-sso-settings.webp (100%) rename apps/{documentation => docs}/public/public-api-images/api-tokens-page-documenso.webp (100%) rename apps/{documentation => docs}/public/public-api-images/documenso-api-key-blurred.webp (100%) rename apps/{documentation => docs}/public/public-api-images/documenso-user-dropdown-menu.webp (100%) rename apps/{documentation => docs}/public/public-profile/documenso-enable-public-profile-settings.webp (100%) rename apps/{documentation => docs}/public/public-profile/documenso-public-profile-settings.webp (100%) create mode 100644 apps/docs/public/recipient-expiration/configure-expiration.webp create mode 100644 apps/docs/public/recipient-expiration/recipient-expired.webp rename apps/{documentation => docs}/public/teams/document-visibility-settings.webp (100%) rename apps/{documentation => docs}/public/teams/team-create-dialog.webp (100%) rename apps/{documentation => docs}/public/teams/team-create.webp (100%) rename apps/{documentation => docs}/public/templates/documenso-template-page-uploaded-document.webp (100%) rename apps/{documentation => docs}/public/templates/documenso-template-page.webp (100%) rename apps/{documentation => docs}/public/templates/documenso-template-recipients.webp (100%) rename apps/{documentation => docs}/public/templates/documenso-use-template.webp (100%) rename apps/{documentation => docs}/public/webhook-images/create-webhook-dialog.webp (100%) rename apps/{documentation => docs}/public/webhook-images/documenso-main-page.webp (100%) rename apps/{documentation => docs}/public/webhook-images/webhook-detail-page.webp (100%) rename apps/{documentation => docs}/public/webhook-images/webhook-run-page.webp (100%) rename apps/{documentation => docs}/public/webhook-images/webhook-test-trigger.webp (100%) rename apps/{documentation => docs}/public/webhook-images/webhooks-main-page.webp (100%) rename apps/{documentation => docs}/public/webhook-images/webhooks-page.webp (100%) create mode 100644 apps/docs/source.config.ts create mode 100644 apps/docs/src/app/(home)/layout.tsx create mode 100644 apps/docs/src/app/(home)/page.tsx create mode 100644 apps/docs/src/app/api/search/route.ts create mode 100644 apps/docs/src/app/apple-icon.png create mode 100644 apps/docs/src/app/docs/[[...slug]]/page.tsx create mode 100644 apps/docs/src/app/docs/layout.tsx create mode 100644 apps/docs/src/app/favicon.ico create mode 100644 apps/docs/src/app/global.css create mode 100644 apps/docs/src/app/layout.tsx create mode 100644 apps/docs/src/app/llms-full.txt/route.ts create mode 100644 apps/docs/src/app/llms.mdx/docs/[[...slug]]/route.ts create mode 100644 apps/docs/src/app/llms.txt/route.ts create mode 100644 apps/docs/src/app/not-found.tsx create mode 100644 apps/docs/src/app/og/docs/[...slug]/route.tsx create mode 100644 apps/docs/src/app/robots.ts create mode 100644 apps/docs/src/app/sitemap.ts create mode 100644 apps/docs/src/components/ai/page-actions.tsx create mode 100644 apps/docs/src/components/mdx/mermaid.tsx create mode 100644 apps/docs/src/lib/cn.ts create mode 100644 apps/docs/src/lib/layout.shared.tsx create mode 100644 apps/docs/src/lib/merge-refs.ts create mode 100644 apps/docs/src/lib/source.ts create mode 100644 apps/docs/src/mdx-components.tsx rename apps/{documentation => docs}/tsconfig.json (55%) delete mode 100644 apps/documentation/.gitignore delete mode 100644 apps/documentation/README.md delete mode 100644 apps/documentation/components/call-to-action.tsx delete mode 100644 apps/documentation/next-sitemap.config.js delete mode 100644 apps/documentation/next.config.ts delete mode 100644 apps/documentation/package.json delete mode 100644 apps/documentation/pages/_app.tsx delete mode 100644 apps/documentation/pages/_meta.js delete mode 100644 apps/documentation/pages/developers/_meta.js delete mode 100644 apps/documentation/pages/developers/contributing/_meta.js delete mode 100644 apps/documentation/pages/developers/developer-mode/field-coordinates.mdx delete mode 100644 apps/documentation/pages/developers/embedded-authoring.mdx delete mode 100644 apps/documentation/pages/developers/embedding/_meta.js delete mode 100644 apps/documentation/pages/developers/embedding/angular.mdx delete mode 100644 apps/documentation/pages/developers/embedding/css-variables.mdx delete mode 100644 apps/documentation/pages/developers/embedding/index.mdx delete mode 100644 apps/documentation/pages/developers/embedding/preact.mdx delete mode 100644 apps/documentation/pages/developers/embedding/react.mdx delete mode 100644 apps/documentation/pages/developers/embedding/solid.mdx delete mode 100644 apps/documentation/pages/developers/embedding/svelte.mdx delete mode 100644 apps/documentation/pages/developers/embedding/vue.mdx delete mode 100644 apps/documentation/pages/developers/index.mdx delete mode 100644 apps/documentation/pages/developers/local-development/_meta.js delete mode 100644 apps/documentation/pages/developers/public-api/_meta.js delete mode 100644 apps/documentation/pages/developers/public-api/authentication.mdx delete mode 100644 apps/documentation/pages/developers/public-api/index.mdx delete mode 100644 apps/documentation/pages/developers/public-api/reference.mdx delete mode 100644 apps/documentation/pages/developers/self-hosting/_meta.js delete mode 100644 apps/documentation/pages/developers/self-hosting/how-to.mdx delete mode 100644 apps/documentation/pages/developers/self-hosting/index.mdx delete mode 100644 apps/documentation/pages/developers/self-hosting/setting-up-oauth-providers.mdx delete mode 100644 apps/documentation/pages/developers/self-hosting/signing-certificate.mdx delete mode 100644 apps/documentation/pages/developers/webhooks.mdx delete mode 100644 apps/documentation/pages/index.mdx delete mode 100644 apps/documentation/pages/users/_meta.js delete mode 100644 apps/documentation/pages/users/branding.mdx delete mode 100644 apps/documentation/pages/users/compliance/_meta.js delete mode 100644 apps/documentation/pages/users/compliance/signature-levels.mdx delete mode 100644 apps/documentation/pages/users/compliance/standards-and-regulations.mdx delete mode 100644 apps/documentation/pages/users/direct-links.mdx delete mode 100644 apps/documentation/pages/users/documents/_meta.js delete mode 100644 apps/documentation/pages/users/documents/ai-detection.mdx delete mode 100644 apps/documentation/pages/users/documents/default-recipients.mdx delete mode 100644 apps/documentation/pages/users/documents/document-preferences.mdx delete mode 100644 apps/documentation/pages/users/documents/document-visibility.mdx delete mode 100644 apps/documentation/pages/users/documents/email-preferences.mdx delete mode 100644 apps/documentation/pages/users/documents/fields.mdx delete mode 100644 apps/documentation/pages/users/documents/sending-documents.mdx delete mode 100644 apps/documentation/pages/users/fair-use.mdx delete mode 100644 apps/documentation/pages/users/get-started/account-creation.mdx delete mode 100644 apps/documentation/pages/users/get-started/account-security.mdx delete mode 100644 apps/documentation/pages/users/index.mdx delete mode 100644 apps/documentation/pages/users/licenses/_meta.js delete mode 100644 apps/documentation/pages/users/licenses/community-edition.mdx delete mode 100644 apps/documentation/pages/users/licenses/enterprise-edition.mdx delete mode 100644 apps/documentation/pages/users/licenses/index.mdx delete mode 100644 apps/documentation/pages/users/organisations/_meta.js delete mode 100644 apps/documentation/pages/users/organisations/groups.mdx delete mode 100644 apps/documentation/pages/users/organisations/index.mdx delete mode 100644 apps/documentation/pages/users/organisations/members.mdx delete mode 100644 apps/documentation/pages/users/organisations/sso/_meta.js delete mode 100644 apps/documentation/pages/users/organisations/sso/index.mdx delete mode 100644 apps/documentation/pages/users/organisations/sso/microsoft-entra-id.mdx delete mode 100644 apps/documentation/pages/users/organisations/teams.mdx delete mode 100644 apps/documentation/pages/users/profile.mdx delete mode 100644 apps/documentation/pages/users/support.mdx delete mode 100644 apps/documentation/pages/users/templates.mdx delete mode 100644 apps/documentation/postcss.config.cjs delete mode 100644 apps/documentation/postcss.config.js delete mode 100644 apps/documentation/providers/plausible.tsx delete mode 100644 apps/documentation/public/developer-mode/field-coordinates-legacy-editor.webp delete mode 100644 apps/documentation/public/developer-mode/field-coordinates-new-editor.webp delete mode 100644 apps/documentation/public/images/admin-license-status.webp delete mode 100644 apps/documentation/styles.css delete mode 100644 apps/documentation/styles/globals.css delete mode 100644 apps/documentation/tailwind.config.cjs delete mode 100644 apps/documentation/theme.config.tsx create mode 100644 apps/remix/app/components/dialogs/admin-organisation-member-delete-dialog.tsx create mode 100644 apps/remix/app/components/dialogs/admin-swap-subscription-dialog.tsx create mode 100644 apps/remix/app/components/dialogs/admin-team-member-delete-dialog.tsx delete mode 100644 apps/remix/app/components/dialogs/document-duplicate-dialog.tsx rename apps/remix/app/components/dialogs/{document-delete-dialog.tsx => envelope-delete-dialog.tsx} (65%) create mode 100644 apps/remix/app/components/dialogs/envelope-item-edit-dialog.tsx create mode 100644 apps/remix/app/components/dialogs/envelope-rename-dialog.tsx create mode 100644 apps/remix/app/components/dialogs/envelope-save-as-template-dialog.tsx delete mode 100644 apps/remix/app/components/dialogs/template-delete-dialog.tsx delete mode 100644 apps/remix/app/components/dialogs/template-duplicate-dialog.tsx create mode 100644 apps/remix/app/components/embed/embed-recipient-expired.tsx create mode 100644 apps/remix/app/components/general/admin-details.tsx create mode 100644 apps/remix/app/components/general/admin-global-settings-section.tsx create mode 100644 apps/remix/app/components/general/document/embedded-editor-attachment-popover.tsx create mode 100644 apps/remix/app/components/general/envelope-editor/envelope-editor-renderer-provider-wrapper.tsx create mode 100644 apps/remix/app/components/general/organisation-groups-multiselect-combobox.tsx create mode 100644 apps/remix/app/components/general/organisation-members-multiselect-combobox.tsx create mode 100644 apps/remix/app/components/general/pdf-viewer/envelope-pdf-viewer.tsx create mode 100644 apps/remix/app/components/general/pdf-viewer/pdf-viewer-lazy.tsx create mode 100644 apps/remix/app/components/general/pdf-viewer/pdf-viewer-page-image.tsx create mode 100644 apps/remix/app/components/general/pdf-viewer/pdf-viewer-states.tsx create mode 100644 apps/remix/app/components/general/pdf-viewer/pdf-viewer.tsx create mode 100644 apps/remix/app/components/general/pdf-viewer/use-scroll-to-page.ts create mode 100644 apps/remix/app/components/general/recipient-branding.tsx delete mode 100644 apps/remix/app/components/general/refresh-on-focus.tsx create mode 100644 apps/remix/app/components/general/virtual-list/use-virtual-list.ts create mode 100644 apps/remix/app/routes/_authenticated+/admin+/email-domains.$id.tsx create mode 100644 apps/remix/app/routes/_authenticated+/admin+/email-domains._index.tsx create mode 100644 apps/remix/app/routes/_authenticated+/admin+/teams.$id.tsx create mode 100644 apps/remix/app/routes/_authenticated+/admin+/unsealed-documents._index.tsx create mode 100644 apps/remix/app/routes/_recipient+/sign.$token+/expired.tsx create mode 100644 apps/remix/app/routes/embed+/playground.tsx create mode 100644 apps/remix/app/routes/embed+/v2+/authoring+/_layout.tsx create mode 100644 apps/remix/app/routes/embed+/v2+/authoring+/envelope.create._index.tsx create mode 100644 apps/remix/app/routes/embed+/v2+/authoring+/envelope.edit.$id.tsx create mode 100644 apps/remix/app/utils/nonce.ts create mode 100644 apps/remix/public/robots.txt create mode 100644 apps/remix/server/api/files/routes/get-envelope-item-pdf-by-token.ts create mode 100644 apps/remix/server/api/files/routes/get-envelope-item-pdf.ts create mode 100644 apps/remix/server/load-context.ts create mode 100644 apps/remix/server/security-headers.ts create mode 100644 assets/a4-size.pdf create mode 100644 assets/field-overflow.pdf create mode 100644 assets/letter-size.pdf create mode 100644 assets/tabloid-landscape.pdf create mode 100644 biome.json delete mode 100644 build.log create mode 100644 packages/app-tests/constants/field-overflow-pdf.ts create mode 100644 packages/app-tests/e2e/api/trpc/search-documents.spec.ts create mode 100644 packages/app-tests/e2e/api/trpc/search-templates.spec.ts create mode 100644 packages/app-tests/e2e/api/v2/find-documents.spec.ts create mode 100644 packages/app-tests/e2e/api/v2/find-envelopes.spec.ts create mode 100644 packages/app-tests/e2e/api/v2/partial-signed-pdf-download.spec.ts create mode 100644 packages/app-tests/e2e/api/v2/update-envelope-items.spec.ts create mode 100644 packages/app-tests/e2e/document-auth/assistant-signing-auth.spec.ts create mode 100644 packages/app-tests/e2e/documents/find-documents.spec.ts create mode 100644 packages/app-tests/e2e/envelope-editor-v2/envelope-actions.spec.ts create mode 100644 packages/app-tests/e2e/envelope-editor-v2/envelope-attachments.spec.ts create mode 100644 packages/app-tests/e2e/envelope-editor-v2/envelope-editor-embedded.spec.ts create mode 100644 packages/app-tests/e2e/envelope-editor-v2/envelope-fields.spec.ts create mode 100644 packages/app-tests/e2e/envelope-editor-v2/envelope-item-edit-dialog.spec.ts create mode 100644 packages/app-tests/e2e/envelope-editor-v2/envelope-items.spec.ts create mode 100644 packages/app-tests/e2e/envelope-editor-v2/envelope-recipients.spec.ts create mode 100644 packages/app-tests/e2e/envelope-editor-v2/envelope-replace-pdf.spec.ts create mode 100644 packages/app-tests/e2e/envelope-editor-v2/envelope-save-as-template.spec.ts create mode 100644 packages/app-tests/e2e/envelope-editor-v2/envelope-settings.spec.ts create mode 100644 packages/app-tests/e2e/envelopes/cert-page-dimensions.spec.ts create mode 100644 packages/app-tests/e2e/envelopes/envelope-expiration-send.spec.ts create mode 100644 packages/app-tests/e2e/envelopes/envelope-expiration-settings.spec.ts create mode 100644 packages/app-tests/e2e/envelopes/envelope-expiration-signing.spec.ts create mode 100644 packages/app-tests/e2e/envelopes/envelope-overflow.spec.ts create mode 100644 packages/app-tests/e2e/envelopes/envelope-v2-field-insertion.spec.ts create mode 100644 packages/app-tests/e2e/fixtures/api-seeds.ts create mode 100644 packages/app-tests/e2e/fixtures/envelope-editor.ts create mode 100644 packages/app-tests/e2e/fixtures/konva.ts create mode 100644 packages/app-tests/e2e/pdf-viewer/pdf-viewer.spec.ts create mode 100644 packages/app-tests/e2e/templates/organisation-templates.spec.ts create mode 100644 packages/app-tests/visual-regression/field-overflow-0.png create mode 100644 packages/app-tests/visual-regression/field-overflow-1.png create mode 100644 packages/app-tests/visual-regression/field-overflow-2.png create mode 100644 packages/app-tests/visual-regression/field-overflow-3.png create mode 100644 packages/app-tests/visual-regression/field-overflow-4.png create mode 100644 packages/app-tests/visual-regression/field-overflow-5.png create mode 100644 packages/app-tests/visual-regression/field-overflow-6.png create mode 100644 packages/app-tests/visual-regression/field-overflow-7.png create mode 100644 packages/app-tests/visual-regression/field-overflow-8.png create mode 100644 packages/ee/server-only/lib/reregister-email-domain.ts create mode 100644 packages/email/template-components/template-document-reminder.tsx create mode 100644 packages/email/template-components/template-recipient-expired.tsx create mode 100644 packages/email/templates/document-reminder.tsx create mode 100644 packages/email/templates/recipient-expired.tsx delete mode 100644 packages/eslint-config/index.cjs delete mode 100644 packages/eslint-config/package.json delete mode 100644 packages/eslint-config/tsconfig.json create mode 100644 packages/lib/client-only/hooks/use-is-page-in-dom.ts create mode 100644 packages/lib/constants/branding.ts create mode 100644 packages/lib/constants/envelope-expiration.ts create mode 100644 packages/lib/constants/envelope-reminder.ts create mode 100644 packages/lib/constants/locales.ts create mode 100644 packages/lib/constants/pdf-viewer-i18n.ts create mode 100644 packages/lib/constants/theme.ts create mode 100644 packages/lib/jobs/client/bullmq.ts create mode 100644 packages/lib/jobs/definitions/emails/send-document-created-from-direct-template-email.handler.ts create mode 100644 packages/lib/jobs/definitions/emails/send-document-created-from-direct-template-email.ts create mode 100644 packages/lib/jobs/definitions/emails/send-owner-recipient-expired-email.handler.ts create mode 100644 packages/lib/jobs/definitions/emails/send-owner-recipient-expired-email.ts create mode 100644 packages/lib/jobs/definitions/internal/cleanup-rate-limits.handler.ts create mode 100644 packages/lib/jobs/definitions/internal/cleanup-rate-limits.ts create mode 100644 packages/lib/jobs/definitions/internal/expire-recipients-sweep.handler.ts create mode 100644 packages/lib/jobs/definitions/internal/expire-recipients-sweep.ts create mode 100644 packages/lib/jobs/definitions/internal/process-recipient-expired.handler.ts create mode 100644 packages/lib/jobs/definitions/internal/process-recipient-expired.ts create mode 100644 packages/lib/jobs/definitions/internal/process-signing-reminder.handler.ts create mode 100644 packages/lib/jobs/definitions/internal/process-signing-reminder.ts create mode 100644 packages/lib/jobs/definitions/internal/seal-document-sweep.handler.ts create mode 100644 packages/lib/jobs/definitions/internal/seal-document-sweep.ts create mode 100644 packages/lib/jobs/definitions/internal/send-signing-reminders-sweep.handler.ts create mode 100644 packages/lib/jobs/definitions/internal/send-signing-reminders-sweep.ts create mode 100644 packages/lib/jobs/definitions/internal/sync-email-domains.handler.ts create mode 100644 packages/lib/jobs/definitions/internal/sync-email-domains.ts create mode 100644 packages/lib/server-only/admin/admin-find-unsealed-documents.ts create mode 100644 packages/lib/server-only/branding/load-recipient-branding.ts create mode 100644 packages/lib/server-only/captcha/verify-captcha.ts create mode 100644 packages/lib/server-only/envelope-item/create-envelope-items.ts create mode 100644 packages/lib/server-only/envelope-item/delete-envelope-item.ts create mode 100644 packages/lib/server-only/envelope-item/replace-envelope-item-pdf.ts create mode 100644 packages/lib/server-only/envelope-item/update-envelope-items.ts create mode 100644 packages/lib/server-only/envelope/get-editor-envelope-by-id.ts create mode 100644 packages/lib/server-only/pdf/generate-partial-signed-pdf.ts create mode 100644 packages/lib/server-only/rate-limit/rate-limit-middleware.ts create mode 100644 packages/lib/server-only/rate-limit/rate-limit.ts create mode 100644 packages/lib/server-only/rate-limit/rate-limits.ts create mode 100644 packages/lib/server-only/recipient/update-recipient-next-reminder.ts create mode 100644 packages/lib/server-only/team/get-user-team-groups.ts create mode 100644 packages/lib/server-only/template/find-organisation-templates.ts create mode 100644 packages/lib/server-only/template/get-organisation-template-by-id.ts create mode 100644 packages/lib/server-only/template/search-templates-with-keyword.ts create mode 100644 packages/lib/server-only/user/get-user-by-reset-token.ts create mode 100644 packages/lib/server-only/user/service-accounts/legacy-service-account.ts create mode 100644 packages/lib/server-only/webhooks/assert-webhook-url.test.ts create mode 100644 packages/lib/server-only/webhooks/assert-webhook-url.ts create mode 100644 packages/lib/server-only/webhooks/execute-webhook-call.ts create mode 100644 packages/lib/server-only/webhooks/is-private-url.test.ts create mode 100644 packages/lib/server-only/webhooks/is-private-url.ts create mode 100644 packages/lib/types/css-vars.ts rename {apps/remix/app => packages/lib}/types/embed-authoring-base-schema.ts (100%) rename {apps/remix/app => packages/lib}/types/embed-base-schemas.ts (60%) rename {apps/remix/app => packages/lib}/types/embed-direct-template-schema.ts (89%) rename {apps/remix/app => packages/lib}/types/embed-document-sign-schema.ts (87%) rename {apps/remix/app => packages/lib}/types/embed-multisign-document-schema.ts (86%) create mode 100644 packages/lib/types/envelope-editor.ts create mode 100644 packages/lib/universal/field-renderer/calculate-overflow-layout.ts create mode 100644 packages/lib/utils/embed-config.ts create mode 100644 packages/lib/utils/normalize-branding-colors.ts create mode 100644 packages/lib/utils/sanitize-branding-css.test.ts create mode 100644 packages/lib/utils/sanitize-branding-css.ts create mode 100644 packages/lib/utils/timeout.ts create mode 100644 packages/lib/utils/zod.ts create mode 100644 packages/lib/vitest.config.ts delete mode 100644 packages/prettier-config/index.cjs delete mode 100644 packages/prettier-config/package.json create mode 100644 packages/prisma/migrations/20251101000330_add_new_webhook_events/migration.sql create mode 100644 packages/prisma/migrations/20260219091107_add_recipient_expirations/migration.sql create mode 100644 packages/prisma/migrations/20260219141233_add_rate_limit_table/migration.sql create mode 100644 packages/prisma/migrations/20260224000000_add_email_domain_last_verified_at/migration.sql create mode 100644 packages/prisma/migrations/20260302223702_optimize_recipient_indexes/migration.sql create mode 100644 packages/prisma/migrations/20260311000000_add_organisation_template_type/migration.sql create mode 100644 packages/prisma/migrations/20260401000000_add_reminder_settings/migration.sql create mode 100644 packages/prisma/migrations/20260408052212_add_set_null_for_audit_log_foreign_key/migration.sql create mode 100644 packages/prisma/migrations/20260504000000_add_allow_personal_organisations_to_auth_portal/migration.sql create mode 100644 packages/prisma/migrations/20260507043737_add_custom_css_branding/migration.sql create mode 100644 packages/prisma/seed/large-team-seed.ts create mode 100644 packages/prisma/seed/medium-account-seed.ts create mode 100644 packages/trpc/server/admin-router/delete-organisation-member.ts create mode 100644 packages/trpc/server/admin-router/delete-organisation-member.types.ts create mode 100644 packages/trpc/server/admin-router/delete-team-member.ts create mode 100644 packages/trpc/server/admin-router/delete-team-member.types.ts create mode 100644 packages/trpc/server/admin-router/download-document-audit-logs.ts create mode 100644 packages/trpc/server/admin-router/download-document-audit-logs.types.ts create mode 100644 packages/trpc/server/admin-router/find-email-domains.ts create mode 100644 packages/trpc/server/admin-router/find-email-domains.types.ts create mode 100644 packages/trpc/server/admin-router/find-unsealed-documents.ts create mode 100644 packages/trpc/server/admin-router/find-unsealed-documents.types.ts create mode 100644 packages/trpc/server/admin-router/get-admin-team.ts create mode 100644 packages/trpc/server/admin-router/get-admin-team.types.ts create mode 100644 packages/trpc/server/admin-router/get-email-domain.ts create mode 100644 packages/trpc/server/admin-router/get-email-domain.types.ts create mode 100644 packages/trpc/server/admin-router/reregister-email-domain.ts create mode 100644 packages/trpc/server/admin-router/reregister-email-domain.types.ts create mode 100644 packages/trpc/server/admin-router/swap-organisation-subscription.ts create mode 100644 packages/trpc/server/admin-router/swap-organisation-subscription.types.ts create mode 100644 packages/trpc/server/embedding-router/create-embedding-envelope.ts create mode 100644 packages/trpc/server/embedding-router/create-embedding-envelope.types.ts create mode 100644 packages/trpc/server/embedding-router/update-embedding-envelope.ts create mode 100644 packages/trpc/server/embedding-router/update-embedding-envelope.types.ts create mode 100644 packages/trpc/server/envelope-router/envelope-fields/get-envelope-field-signatures.ts create mode 100644 packages/trpc/server/envelope-router/envelope-fields/get-envelope-field-signatures.types.ts create mode 100644 packages/trpc/server/envelope-router/get-editor-envelope.ts create mode 100644 packages/trpc/server/envelope-router/get-editor-envelope.types.ts create mode 100644 packages/trpc/server/envelope-router/replace-envelope-item-pdf.ts create mode 100644 packages/trpc/server/envelope-router/replace-envelope-item-pdf.types.ts create mode 100644 packages/trpc/server/envelope-router/save-as-template.ts create mode 100644 packages/trpc/server/envelope-router/save-as-template.types.ts create mode 100644 packages/trpc/server/template-router/search-template.ts create mode 100644 packages/trpc/server/template-router/search-template.types.ts create mode 100644 packages/ui/components/common/local-time.tsx create mode 100644 packages/ui/components/document/expiration-period-picker.tsx create mode 100644 packages/ui/components/document/reminder-settings-picker.tsx delete mode 100644 packages/ui/components/pdf-viewer/pdf-viewer-konva-lazy.tsx delete mode 100644 packages/ui/components/pdf-viewer/pdf-viewer-konva.tsx create mode 100644 packages/ui/components/template/template-type-select.tsx create mode 100644 packages/ui/lib/handle-dropzone-rejection.tsx delete mode 100644 packages/ui/primitives/pdf-viewer/base.client.tsx delete mode 100644 packages/ui/primitives/pdf-viewer/base.tsx delete mode 100644 packages/ui/primitives/pdf-viewer/index.ts delete mode 100644 packages/ui/primitives/pdf-viewer/lazy.tsx delete mode 100644 prettier.config.cjs create mode 100644 scripts/generate-overflow-test-pdf.mjs diff --git a/.agents/plans/bright-emerald-flower-bullmq-background-jobs.md b/.agents/plans/bright-emerald-flower-bullmq-background-jobs.md new file mode 100644 index 000000000..04438bfc8 --- /dev/null +++ b/.agents/plans/bright-emerald-flower-bullmq-background-jobs.md @@ -0,0 +1,239 @@ +--- +date: 2026-03-26 +title: Bullmq Background Jobs +--- + +## Context + +The codebase has a well-designed background job provider abstraction (`BaseJobProvider`) with two existing implementations: + +- **InngestJobProvider** — cloud/SaaS provider, externally hosted +- **LocalJobProvider** — database-backed (Postgres via Prisma), uses HTTP self-calls to dispatch + +The goal is to add a third provider backed by a proper job queue library for self-hosted deployments that need more reliability than the Local provider offers. + +### Current Architecture + +All code lives in `packages/lib/jobs/`: + +- `client/base.ts` — Abstract `BaseJobProvider` with 4 methods: `defineJob()`, `triggerJob()`, `getApiHandler()`, `startCron()` +- `client/client.ts` — `JobClient` facade, selects provider via `NEXT_PRIVATE_JOBS_PROVIDER` env var +- `client/inngest.ts` — Inngest implementation +- `client/local.ts` — Local/Postgres implementation +- `client/_internal/job.ts` — Core types: `JobDefinition`, `JobRunIO`, `SimpleTriggerJobOptions` +- `definitions/` — 19 job definitions (15 event-triggered, 4 cron) + +The `JobRunIO` interface provided to handlers includes: + +- `runTask(cacheKey, callback)` — idempotent task execution (cached via `BackgroundJobTask` table) +- `triggerJob(cacheKey, options)` — chain jobs from within handlers +- `wait(cacheKey, ms)` — delay/sleep (not implemented in Local provider) +- `logger` — structured logging + +### Local Provider Limitations + +The current Local provider has several issues that motivate this work: + +1. `io.wait()` throws "Not implemented" +2. HTTP self-call with 150ms fire-and-forget `Promise.race` is fragile +3. No concurrency control — jobs run in the web server process +4. No real retry backoff (immediate re-dispatch) +5. No monitoring/visibility into job status +6. Jobs compete for resources with HTTP request handling + +--- + +## Provider Evaluation + +Three alternatives were evaluated against the existing provider interface and project requirements. + +### BullMQ (Redis-backed) — Recommended + +| Attribute | Detail | +| ------------------- | -------------------------- | +| Backend | Redis 7.x | +| npm downloads/month | ~15M | +| TypeScript | Native | +| Delayed jobs | Yes (ms precision) | +| Cron/repeatable | Yes (`upsertJobScheduler`) | +| Retries + backoff | Yes (exponential, custom) | +| Concurrency control | Yes (per-worker) | +| Rate limiting | Yes (per-queue, per-group) | +| Dashboard | Bull Board (mature) | +| New infrastructure | Yes — Redis required | + +**Why BullMQ**: Most mature and widely-adopted Node.js queue. Native delayed jobs solve the `io.wait()` gap. Redis is purpose-built for queue workloads and keeps Postgres clean for application data. Bull Board gives immediate operational visibility. The provider abstraction already exists so wrapping BullMQ is straightforward. + +**Trade-off**: Requires Redis, which is additional infrastructure. However, Redis is a single Docker Compose service or a free Upstash tier, and the operational benefit is significant. + +### pg-boss (PostgreSQL-backed) — Strong Alternative + +| Attribute | Detail | +| ------------------- | ----------------------------- | +| Backend | PostgreSQL (existing) | +| npm downloads/month | ~1.4M | +| TypeScript | Native | +| Delayed jobs | Yes (`startAfter`) | +| Cron/repeatable | Yes (`schedule()`) | +| New infrastructure | No — reuses existing Postgres | + +**Why it could work**: Zero new infrastructure since the project already uses Postgres. API maps well to existing patterns. + +**Why it's second choice**: Polling-based (no LISTEN/NOTIFY), adds write amplification to the primary database, smaller ecosystem, no dashboard. At scale, queue operations on the primary database become a concern. + +### Graphile Worker (PostgreSQL-backed) — Less Suitable + +Uses LISTEN/NOTIFY for instant pickup but has a file-based task convention and separate schema that don't mesh well with the existing Prisma-centric architecture. Would require more adapter work. + +### Improving the Local Provider — Not Recommended + +Fixing the Local provider's issues (wait support, replacing HTTP self-calls, adding concurrency control, backoff) essentially means rebuilding a queue library from scratch with less robustness and no community maintenance. + +--- + +## Recommendation + +**Proceed with BullMQ.** It's the most capable option, maps cleanly to the existing provider interface, and is the standard choice for production Node.js applications. Redis is lightweight infrastructure with managed options available at every cloud provider. + +**If Redis is a hard blocker**, pg-boss is the clear fallback — but the plan below assumes BullMQ. + +--- + +## Implementation Plan + +### Phase 1: BullMQ Provider Core + +**File: `packages/lib/jobs/client/bullmq.ts`** + +Create `BullMQJobProvider extends BaseJobProvider` with singleton pattern matching the existing providers. + +Key implementation details: + +1. **Constructor / `getInstance()`** + - Initialize a Redis `IORedis` connection using new env var: `NEXT_PRIVATE_REDIS_URL` + - Create a single `Queue` instance for dispatching jobs, using `NEXT_PRIVATE_REDIS_PREFIX` as the BullMQ `prefix` option (defaults to `documenso` if unset). This namespaces all Redis keys so multiple environments (worktrees, branches, developers) sharing the same Redis instance don't collide. + - Create a single `Worker` instance for processing jobs (in-process, same prefix) + - Store job definitions in a `_jobDefinitions` record (same pattern as Local provider) + +2. **`defineJob()`** + - Store definition in `_jobDefinitions` keyed by ID + - If the definition has a `trigger.cron`, register it via `queue.upsertJobScheduler()` with the cron expression + +3. **`triggerJob(options)`** + - Find eligible definitions by `trigger.name` (same lookup as Local provider) + - For each, call `queue.add(jobDefinitionId, payload)` with appropriate options + - Support `options.id` for deduplication via BullMQ's `jobId` option + +4. **`getApiHandler()`** + - Return a minimal health-check / queue-status handler. Unlike the Local provider, BullMQ workers don't need an HTTP endpoint to receive jobs — they pull from Redis directly. The API handler can return queue metrics for monitoring. + +5. **`startCron()`** + - No-op — cron is handled by BullMQ's `upsertJobScheduler` registered during `defineJob()` + +6. **Worker setup** + - Single worker processes all job types by dispatching to the correct handler from `_jobDefinitions` + - Configure concurrency with a default of 10 (overridable via `NEXT_PRIVATE_BULLMQ_CONCURRENCY` env var for those who need to tune it) + - Configure retry with exponential backoff: `backoff: { type: 'exponential', delay: 1000 }` + - Default 3 retries (matching current Local provider behavior) + +7. **`createJobRunIO(jobId)`** — Implement `JobRunIO`: + - `runTask()`: Reuse the existing `BackgroundJobTask` Prisma table for idempotent task tracking (same pattern as Local provider) + - `triggerJob()`: Delegate to `this.triggerJob()` + - `wait()`: Throw "Not implemented" (same as Local provider). No handler uses `io.wait()` so this has zero impact + - `logger`: Same console-based logger pattern as Local provider + +### Phase 2: Provider Registration + +**File: `packages/lib/jobs/client/client.ts`** + +Add `'bullmq'` case to the provider match: + +```typescript +this._provider = match(env('NEXT_PRIVATE_JOBS_PROVIDER')) + .with('inngest', () => InngestJobProvider.getInstance()) + .with('bullmq', () => BullMQJobProvider.getInstance()) + .otherwise(() => LocalJobProvider.getInstance()); +``` + +**File: `packages/tsconfig/process-env.d.ts`** + +Add `'bullmq'` to the `NEXT_PRIVATE_JOBS_PROVIDER` type union and add Redis env var types: + +```typescript +NEXT_PRIVATE_JOBS_PROVIDER?: 'inngest' | 'local' | 'bullmq'; +NEXT_PRIVATE_REDIS_URL?: string; +NEXT_PRIVATE_REDIS_PREFIX?: string; +NEXT_PRIVATE_BULLMQ_CONCURRENCY?: string; +``` + +**File: `.env.example`** + +Add Redis configuration examples: + +```env +NEXT_PRIVATE_JOBS_PROVIDER="local" # Options: local, inngest, bullmq +NEXT_PRIVATE_REDIS_URL="redis://localhost:63790" +NEXT_PRIVATE_REDIS_PREFIX="documenso" # Namespace for Redis keys (useful when sharing a Redis instance) +``` + +**File: `turbo.json`** + +Add `NEXT_PRIVATE_REDIS_URL`, `NEXT_PRIVATE_REDIS_PREFIX`, and `NEXT_PRIVATE_BULLMQ_CONCURRENCY` to the env vars list for cache invalidation. + +### Phase 3: Infrastructure & Dependencies + +**File: `packages/lib/package.json`** + +Add dependencies: + +- `bullmq` — the queue library +- `ioredis` — Redis client (peer dependency of BullMQ, but explicit is better) + +**File: `docker-compose.yml` (or equivalent)** + +Add Redis service for local development: + +```yaml +redis: + image: redis:7-alpine + ports: + - '6379:6379' +``` + +### Phase 4: Optional Enhancements + +These are not required for the initial implementation but worth considering for follow-up: + +1. **Bull Board integration** — Add a `/api/jobs/dashboard` route that serves Bull Board UI for monitoring. Gate behind an admin auth check. + +2. **Separate worker process** — Add an `apps/worker` entry point that runs BullMQ workers without the web server, for deployments that want to isolate job processing from request handling. + +3. **Graceful shutdown** — Register `SIGTERM`/`SIGINT` handlers to call `worker.close()` and `queue.close()` for clean shutdown. + +4. **BackgroundJob table integration** — Optionally continue writing to the `BackgroundJob` Prisma table for audit/history, using BullMQ events (`completed`, `failed`) to update status. This preserves the existing database-level visibility. + +--- + +## Files to Create/Modify + +| File | Action | Description | +| ------------------------------------ | ---------- | ---------------------------------------- | +| `packages/lib/jobs/client/bullmq.ts` | **Create** | BullMQ provider implementation | +| `packages/lib/jobs/client/client.ts` | Modify | Add `'bullmq'` provider case | +| `packages/tsconfig/process-env.d.ts` | Modify | Add type for `'bullmq'` + Redis env vars | +| `.env.example` | Modify | Add Redis config example | +| `turbo.json` | Modify | Add Redis env var to cache keys | +| `packages/lib/package.json` | Modify | Add `bullmq` + `ioredis` dependencies | +| `docker-compose.yml` | Modify | Add Redis service | + +--- + +## Open Questions + +1. **Should the BullMQ provider also write to the `BackgroundJob` Prisma table?** This would maintain audit history and allow existing admin tooling to query job status. Trade-off is dual-write complexity. + +2. **Redis connection resilience**: Should the provider gracefully degrade if Redis is unavailable (e.g., fall back to Local provider), or fail hard? Failing hard is simpler and more predictable. + +## Resolved Questions + +- **`io.wait()`**: Not a concern. Only Inngest implements it (via `step.sleep`), the Local provider throws "Not implemented", and no job handler calls `io.wait()`. The BullMQ provider can throw "Not implemented" identically to the Local provider. diff --git a/.agents/plans/calm-violet-tide-envelope-expiration.md b/.agents/plans/calm-violet-tide-envelope-expiration.md new file mode 100644 index 000000000..b2e8506ec --- /dev/null +++ b/.agents/plans/calm-violet-tide-envelope-expiration.md @@ -0,0 +1,519 @@ +--- +date: 2026-02-10 +title: Envelope Expiration +--- + +## Summary + +Envelopes (documents sent for signing) should automatically expire after a configurable period, preventing recipients from completing stale documents. Expiration is tracked **per-recipient** — when a recipient's signing window lapses, the document owner is notified and can resend (extending the deadline) or cancel. The document itself stays PENDING so other recipients can continue signing. + +**Settings cascade**: Organisation → Team → Document (each level can override the prior). +**Default**: 1 month from when the envelope is sent (transitions to PENDING). + +--- + +## 1. Database Schema Changes + +### 1.1 Expiration period data shape + +Store expiration as a structured JSON object rather than an enum or raw milliseconds. This avoids the enum treadmill (adding `FOUR_MONTHS` later requires a migration) while keeping values validated and meaningful. + +**Zod schema** (defined in `packages/lib/constants/envelope-expiration.ts`): + +```typescript +export const ZEnvelopeExpirationPeriod = z.union([ + z.object({ unit: z.enum(['day', 'week', 'month', 'year']), amount: z.number().int().min(1) }), + z.object({ disabled: z.literal(true) }), +]); + +export type TEnvelopeExpirationPeriod = z.infer; +``` + +Semantics: + +- `null` on `DocumentMeta` / `TeamGlobalSettings` = inherit from parent +- `{ disabled: true }` = explicitly never expires +- `{ unit: 'month', amount: 1 }` = expires in 1 month + +No Prisma enum is needed — the period is stored as `Json?` on the relevant models (see sections 1.3 and 1.4). + +### 1.2 Add expiration fields to `Recipient` + +```prisma +model Recipient { + // ... existing fields + expiresAt DateTime? + expirationNotifiedAt DateTime? // null = not yet notified; set when owner notification sent + + @@index([expiresAt]) +} +``` + +`expiresAt` is a computed timestamp set when the envelope transitions to PENDING (at send time). It is calculated from the effective expiration period. Storing the concrete timestamp rather than a relative duration means: + +- Sweep queries are simple (`WHERE expiresAt <= NOW() AND expirationNotifiedAt IS NULL`) +- No need to re-resolve the settings cascade at query time +- The sender can see the exact deadline in the UI +- The index on `expiresAt` ensures the expiration sweep query is efficient + +`expirationNotifiedAt` tracks whether the owner has already been notified about this recipient's expiration, making the notification job idempotent. + +### 1.3 Add expiration period to settings models + +**OrganisationGlobalSettings** (JSON, application-level default): + +```prisma +model OrganisationGlobalSettings { + // ... existing fields + envelopeExpirationPeriod Json? +} +``` + +Prisma `@default` doesn't work for `Json` columns, so the application-level default (`{ unit: 'month', amount: 1 }`) is applied in `extractDerivedTeamSettings` / `extractDerivedDocumentMeta` when the value is null. The migration should backfill existing rows with `{ "unit": "month", "amount": 1 }`. + +**TeamGlobalSettings** (nullable, null = inherit from org): + +```prisma +model TeamGlobalSettings { + // ... existing fields + envelopeExpirationPeriod Json? +} +``` + +### 1.4 Add expiration period to DocumentMeta + +This allows per-document override during the document editing flow: + +```prisma +model DocumentMeta { + // ... existing fields + envelopeExpirationPeriod Json? +} +``` + +When null on DocumentMeta, the resolved team/org setting is used at send time. Validated at write time using `ZEnvelopeExpirationPeriod.nullable()`. + +**Important**: `envelopeExpirationPeriod` on `DocumentMeta` is a user-facing preference that may be set during the draft editing flow. It does NOT determine the final expiration — that is resolved at send time (see section 2.3). The value stored here is just the user's selection in the document editor. + +--- + +## 2. Expiration Period Resolution + +### 2.1 Duration mapping + +Add to `packages/lib/constants/envelope-expiration.ts` alongside the Zod schema: + +```typescript +import { Duration } from 'luxon'; + +const UNIT_TO_LUXON_KEY: Record = { + day: 'days', + week: 'weeks', + month: 'months', + year: 'years', +}; + +export const DEFAULT_ENVELOPE_EXPIRATION_PERIOD: TEnvelopeExpirationPeriod = { + unit: 'month', + amount: 1, +}; + +export const getEnvelopeExpirationDuration = (period: TEnvelopeExpirationPeriod): Duration => { + return Duration.fromObject({ [UNIT_TO_LUXON_KEY[period.unit]]: period.amount }); +}; +``` + +### 2.2 Settings cascade integration + +`extractDerivedTeamSettings()` in `packages/lib/utils/teams.ts` needs **no code changes** — it iterates `Object.keys(derivedSettings)` and overrides with non-null team values at runtime. The new `envelopeExpirationPeriod` field on both `OrganisationGlobalSettings` and `TeamGlobalSettings` will be automatically picked up. + +Update `extractDerivedDocumentMeta()` in `packages/lib/utils/document.ts` to include the new field: + +```typescript +envelopeExpirationPeriod: meta.envelopeExpirationPeriod ?? settings.envelopeExpirationPeriod, +``` + +### 2.3 Compute `expiresAt` at send time + +The expiration period is **locked at send time** — when the envelope transitions to PENDING. The concrete `expiresAt` timestamp is computed for each recipient when the document is actually sent. + +In `packages/lib/server-only/document/send-document.ts`: + +```typescript +// Resolve effective period: document meta -> team/org settings -> default +const rawPeriod = + envelope.documentMeta?.envelopeExpirationPeriod ?? settings.envelopeExpirationPeriod; + +const expiresAt = resolveExpiresAt(rawPeriod); + +// Inside the $transaction, for each recipient: +await tx.recipient.updateMany({ + where: { envelopeId: envelope.id }, + data: { expiresAt }, +}); +``` + +### 2.4 Compute `expiresAt` in the direct template flow + +`create-document-from-direct-template.ts` creates envelopes directly as PENDING and then calls `sendDocument` afterward. Since `sendDocument` handles setting `expiresAt` on recipients, the direct template flow doesn't need to set it directly — `sendDocument` handles it. + +--- + +## 3. Cron Job Infrastructure (New) + +The current job system is purely event-triggered. Inngest natively supports cron-triggered functions, but the local provider (used in dev and by self-hosters who don't want a third-party dependency) has no scheduling capability. This section adds cron support to the local provider to maintain feature parity. + +### 3.1 Extend `JobDefinition` with cron support + +Add an optional `cron` field to the trigger type in `packages/lib/jobs/client/_internal/job.ts`: + +```typescript +export type JobDefinition = { + id: string; + name: string; + version: string; + enabled?: boolean; + optimizeParallelism?: boolean; + trigger: { + name: Name; + schema?: z.ZodType; + /** Cron expression (e.g. "* * * * *"). When set, the job runs on a schedule. */ + cron?: string; + }; + handler: (options: { payload: Schema; io: JobRunIO }) => Promise; +}; +``` + +### 3.2 Inngest provider: wire up native cron + +In `packages/lib/jobs/client/inngest.ts`, when defining a function, check for `cron`: + +```typescript +defineJob(job) { + if (job.trigger.cron) { + this._functions.push( + this._client.createFunction( + { id: job.id, name: job.name }, + { cron: job.trigger.cron }, + async ({ step, logger }) => { + const io = convertInngestIoToJobRunIo(step, logger, this); + await job.handler({ payload: {} as any, io }); + }, + ), + ); + } else { + // Existing event-triggered logic (unchanged) + } +} +``` + +### 3.3 Local provider: poller + deterministic `BackgroundJob` IDs + +Use the existing `BackgroundJob` table for multi-instance dedupe instead of advisory locks. This approach keeps implementation Prisma-only (no raw SQL), works for single-instance and multi-instance deployments, and preserves existing retry/visibility behavior. + +**On `defineJob()`**: If the job has a `cron` field, register an in-process scheduler entry and start a lightweight poller (every 30s with jitter). + +**Each poll tick**: + +1. Evaluate whether the cron schedule has one or more due run slots since the last tick (use a real cron parser, e.g. `cron-parser`) +2. For each due slot, build a deterministic run ID from job ID + scheduled slot time +3. Create a `BackgroundJob` row with that deterministic ID using Prisma +4. If insert succeeds → enqueue via the existing local job pipeline +5. If insert fails with Prisma `P2002` (unique violation) → another node already enqueued that run, skip + +### 3.4 Summary of changes to the job system + +| File | Change | +| ------------------------------------------- | ---------------------------------------------------------------- | +| `packages/lib/jobs/client/_internal/job.ts` | Add optional `cron` field to `trigger` type | +| `packages/lib/jobs/client/local.ts` | Add cron poller + deterministic `BackgroundJob.id` dedupe | +| `packages/lib/jobs/client/inngest.ts` | Wire up `{ cron: ... }` in `createFunction` for cron jobs | +| `packages/lib/jobs/client/_internal/*` | Add cron helper utilities (`getDueCronSlots`, run ID generation) | + +--- + +## 4. Expiration Processing + +### 4.1 Two-job architecture + +Expiration uses two jobs: a **sweep dispatcher** that runs on a cron schedule and finds expired recipients, and an **individual notification job** that handles the audit log, owner notification email, and webhook for a single recipient. This separation means: + +- The sweep is lightweight and fast (just a query + N job triggers) +- Each recipient's expiration notification is independently retryable +- The individual jobs are idempotent — they check `expirationNotifiedAt IS NULL` before processing + +### 4.2 Sweep job: `EXPIRE_RECIPIENTS_SWEEP_JOB` + +A cron-triggered job that runs every minute to find and dispatch notifications for expired recipients. + +**Definition:** `packages/lib/jobs/definitions/internal/expire-recipients-sweep.ts` + +**Handler:** `packages/lib/jobs/definitions/internal/expire-recipients-sweep.handler.ts` + +```typescript +const expiredRecipients = await prisma.recipient.findMany({ + where: { + expiresAt: { lte: new Date() }, + expirationNotifiedAt: null, + signingStatus: { notIn: [SigningStatus.SIGNED, SigningStatus.REJECTED] }, + envelope: { status: DocumentStatus.PENDING }, + }, + select: { id: true }, + take: 100, +}); + +for (const recipient of expiredRecipients) { + await jobs.triggerJob({ + name: 'internal.notify-recipient-expired', + payload: { recipientId: recipient.id }, + }); +} +``` + +### 4.3 Individual notification job: `NOTIFY_RECIPIENT_EXPIRED_JOB` + +An event-triggered job that handles a single recipient's expiration. + +**Definition:** `packages/lib/jobs/definitions/internal/notify-recipient-expired.ts` + +**Handler:** `packages/lib/jobs/definitions/internal/notify-recipient-expired.handler.ts` + +The handler: + +1. Fetches the recipient (with guard: `expirationNotifiedAt IS NULL` + not signed/rejected) +2. Sets `recipient.expirationNotifiedAt = now()` (idempotency) +3. Creates audit log entry with `DOCUMENT_RECIPIENT_EXPIRED` type +4. Sends email notification to the **document owner** (inline — no separate email job) +5. The document stays PENDING — the owner decides whether to resend or cancel + +### 4.4 Register in job client + +Add `EXPIRE_RECIPIENTS_SWEEP_JOB_DEFINITION` and `NOTIFY_RECIPIENT_EXPIRED_JOB_DEFINITION` to the job registry in `packages/lib/jobs/client.ts`. + +### 4.5 Email template: Recipient Expired + +Target the **document owner**: + +- Subject: `Signing window expired for "{recipientName}" on "{documentTitle}"` +- Body: "The signing window for {recipientName} ({recipientEmail}) on document {title} has expired. You can resend the document to extend their deadline or cancel the document." +- Include a "View Document" link to the document page in the app + +Template files: + +- `packages/email/templates/recipient-expired.tsx` — wrapper +- `packages/email/template-components/template-recipient-expired.tsx` — body + +### 4.6 Recipient signing guard + +In the signing flow, check `recipient.expiresAt` before allowing any signing action. Note that the document stays PENDING even after recipient expiration, so the existing `status !== PENDING` guard does not block expired recipients — an explicit expiration check is required: + +```typescript +if (recipient.expiresAt && recipient.expiresAt <= new Date()) { + throw new AppError(AppErrorCode.RECIPIENT_EXPIRED, { + message: 'Recipient signing window has expired', + }); +} +``` + +**Files to update:** + +- `packages/lib/server-only/document/complete-document-with-token.ts` +- `packages/lib/server-only/field/sign-field-with-token.ts` +- `packages/lib/server-only/field/remove-signed-field-with-token.ts` +- `packages/lib/server-only/document/reject-document-with-token.ts` + +--- + +## 5. UI Design + +### 5.1 Expiration Period Selector Component + +Use a number input + unit selector combo. This gives organisations full flexibility to configure any duration without needing schema changes for new options. + +**Layout**: A horizontal group with: + +- A number `` (min 1, integer) +- A `` instead of `react-colorful`, which +was removed) in a 2-col grid, plus a free-text radius input and an +`` revealing a mono `