diff --git a/.agents/plans/sharp-gold-mountain-custom-brand-logo-url.md b/.agents/plans/sharp-gold-mountain-custom-brand-logo-url.md
new file mode 100644
index 000000000..e1b573c3e
--- /dev/null
+++ b/.agents/plans/sharp-gold-mountain-custom-brand-logo-url.md
@@ -0,0 +1,122 @@
+---
+date: 2026-05-28
+title: Custom Brand Logo Url
+---
+
+# Problem
+
+`brandingUrl` (the configured "Brand Website") is persisted and editable in branding
+settings, but historically it was never consumed anywhere. It flowed into the database,
+the settings form, and the admin read-only view, but never affected any rendered output.
+
+We want `brandingUrl` to actually do something, with deliberately different behavior per
+surface.
+
+# Relationship we're going for
+
+`brandingUrl` is an **email-only** linking concept. It is intentionally **not** used on
+in-app signing surfaces.
+
+| Surface | Custom branding logo configured | `brandingUrl` behavior |
+| --- | --- | --- |
+| Transactional emails (logo) | Logo shown | Logo links to `brandingUrl` when it is a safe http(s) URL; otherwise plain image |
+| Transactional emails (footer) | n/a | `brandingUrl` rendered as a link in the footer when it is a safe http(s) URL |
+| Signing pages (V1 + V2, normal + direct-template) | Logo shown | Ignored — logo is a plain image with no link |
+| Signing pages (no custom logo) | Documenso fallback shown | Fallback keeps its internal `/` link |
+| Embedded signing | Logo shown | Ignored (logo not linked) |
+| Embedded authoring/editor | Logo shown | Ignored |
+| Settings / admin branding previews | n/a | Unchanged (display only) |
+
+Rationale:
+
+- On signing pages the recipient is mid-task; sending them off to an external marketing
+ site via the logo is undesirable, so the custom logo is a plain image there.
+- In emails the logo and a footer link to the brand's own site are a normal, expected
+ pattern and reinforce that the email is legitimately from that brand.
+
+# Decisions
+
+## Scope
+
+- Use `brandingUrl` only in transactional email rendering:
+ - The shared email logo component links the custom branding logo to `brandingUrl`.
+ - The shared email footer renders `brandingUrl` as a link.
+- On signing surfaces, render a configured custom branding logo as a plain image with no
+ link wrapper. Leave the Documenso fallback logo's internal `/` link untouched.
+- Do not change embedded signing, embedded authoring/editor, or settings/admin previews.
+- No Prisma schema or database migration. `brandingUrl` already exists and is editable.
+
+## URL safety
+
+Rendering must be defensive because old/imported data can bypass the branding form's URL
+validation. Only treat the stored value as a usable Brand Website when it parses as an
+absolute `http:` or `https:` URL.
+
+- Empty, missing, invalid, relative, or non-http(s) values are treated as "no Brand
+ Website" and produce a plain logo / no footer link.
+- Do not mutate stored settings or run a cleanup migration.
+- Factored into a single shared helper so both email logo and footer apply identical rules:
+ - `packages/email/utils/branding-url.ts` -> `getSafeBrandingUrl(value): string | null`.
+
+## Email rendering
+
+- New shared component `packages/email/template-components/template-branding-logo.tsx`
+ (`TemplateBrandingLogo`) renders either:
+ - the custom branding logo, wrapped in a `Link` to the safe `brandingUrl` with
+ `target="_blank"` when one exists, or a plain `Img` when not; or
+ - the Documenso fallback logo (`/static/logo.png`) when custom branding is disabled or
+ no logo is set.
+- This component replaced the duplicated `brandingEnabled && brandingLogo ? :
`. `brandingUrl` is not read; the local branding type
+ and loader payload no longer carry it.
+- `apps/remix/app/components/general/envelope-signing/envelope-signer-header.tsx` (V2,
+ shared by normal and direct-template signing): custom logo renders as a bare `
`; the
+ Documenso fallback keeps its ``.
+- `apps/remix/app/routes/_recipient+/sign.$token+/_index.tsx`: V1 loader branding payload no
+ longer includes `brandingUrl`.
+- `packages/lib/server-only/envelope/get-envelope-for-recipient-signing.ts` and
+ `get-envelope-for-direct-template-signing.ts`: `brandingUrl` removed from the V2
+ `EnvelopeForSigningResponse.settings` schema/payload since it is not consumed there.
+
+# History
+
+An earlier iteration of this plan wired `brandingUrl` into the in-app signing pages so a
+custom logo linked to the Brand Website (external ``, internal `/`
+fallback otherwise) and added `brandingUrl` to the V1/V2 signing payloads. That direction
+was reversed: signing-page logos are now plain images and `brandingUrl` is email-only. The
+signing payload additions were removed.
+
+# Test coverage
+
+`packages/app-tests/e2e/signing-branding.spec.ts`:
+
+- V1 normal `/sign/:token`: custom logo is a plain image, not inside a link, and no
+ `brandingUrl` link is present.
+- V2 normal `/sign/:token` and V2 direct-template: same plain-image assertions.
+- V2 with no custom logo: Documenso fallback still links to `/`.
+- Embedded signing: no custom-logo Brand Website link is rendered.
+
+# Acceptance criteria
+
+- A custom branding logo on any signing surface (V1, V2 normal, V2 direct-template, embedded)
+ renders as a plain image with no link, and `brandingUrl` is never rendered as a link there.
+- Documenso fallback logos continue linking to `/`.
+- In transactional emails, when a custom logo and a safe `brandingUrl` are configured, the
+ email logo links to `brandingUrl` (new tab) and the footer shows the Brand Website link.
+- In transactional emails, when `brandingUrl` is empty/invalid/relative/non-http(s), the logo
+ is a plain image and no footer Brand Website link is shown.
+- URL safety is enforced through the single shared `getSafeBrandingUrl` helper.
+- Settings/admin branding previews are unchanged.
+- No schema or migration changes.
diff --git a/.env.example b/.env.example
index f723e1c66..5f3da7c1f 100644
--- a/.env.example
+++ b/.env.example
@@ -48,7 +48,7 @@ NEXT_PRIVATE_DATABASE_URL="postgres://documenso:password@127.0.0.1:54320/documen
NEXT_PRIVATE_DIRECT_DATABASE_URL="postgres://documenso:password@127.0.0.1:54320/documenso"
# [[SIGNING]]
-# The transport to use for document signing. Available options: local (default) | gcloud-hsm
+# The transport to use for document signing. Available options: local (default) | gcloud-hsm | csc
NEXT_PRIVATE_SIGNING_TRANSPORT="local"
# OPTIONAL: The passphrase to use for the local file-based signing transport.
NEXT_PRIVATE_SIGNING_PASSPHRASE=
@@ -70,6 +70,14 @@ NEXT_PRIVATE_SIGNING_GCLOUD_HSM_CERT_CHAIN_FILE_PATH=
NEXT_PRIVATE_SIGNING_GCLOUD_HSM_CERT_CHAIN_CONTENTS=
# OPTIONAL: The Google Secret Manager path to retrieve the certificate for the gcloud-hsm signing transport.
NEXT_PRIVATE_SIGNING_GCLOUD_HSM_SECRET_MANAGER_CERT_PATH=
+# OPTIONAL: The base URL of the Cloud Signature Consortium (CSC) provider for the csc signing transport.
+NEXT_PRIVATE_SIGNING_CSC_PROVIDER_BASE_URL=
+# OPTIONAL: The OAuth client ID registered with the CSC provider for the csc signing transport.
+NEXT_PRIVATE_SIGNING_CSC_OAUTH_CLIENT_ID=
+# OPTIONAL: The OAuth client secret registered with the CSC provider for the csc signing transport.
+NEXT_PRIVATE_SIGNING_CSC_OAUTH_CLIENT_SECRET=
+# OPTIONAL: Default signature level for envelopes created on a CSC instance when the caller doesn't specify one. Available options: AES (default) | QES. Explicit AES/QES requests always pass through unchanged.
+NEXT_PRIVATE_SIGNING_CSC_SIGNATURE_LEVEL=
# OPTIONAL: Comma-separated list of timestamp authority URLs for PDF signing (enables LTV and archival timestamps).
NEXT_PRIVATE_SIGNING_TIMESTAMP_AUTHORITY=
# OPTIONAL: Contact info to embed in PDF signatures. Defaults to the webapp URL.
@@ -95,7 +103,7 @@ NEXT_PRIVATE_UPLOAD_ACCESS_KEY_ID="documenso"
NEXT_PRIVATE_UPLOAD_SECRET_ACCESS_KEY="password"
# [[SMTP]]
-# OPTIONAL: Defines the transport to use for sending emails. Available options: smtp-auth (default) | smtp-api | mailchannels
+# OPTIONAL: Defines the transport to use for sending emails. Available options: smtp-auth (default) | smtp-api | resend | mailchannels
NEXT_PRIVATE_SMTP_TRANSPORT="smtp-auth"
# OPTIONAL: Defines the host to use for sending emails.
NEXT_PRIVATE_SMTP_HOST="127.0.0.1"
@@ -172,6 +180,20 @@ NEXT_PUBLIC_DISABLE_MICROSOFT_SIGNUP=
NEXT_PUBLIC_DISABLE_OIDC_SIGNUP=
# OPTIONAL: Comma-separated list of email domains allowed to sign up (e.g., example.com,acme.org).
NEXT_PRIVATE_ALLOWED_SIGNUP_DOMAINS=
+# OPTIONAL: Set to "true" to disable all signin methods (email, Google, Microsoft, OIDC).
+NEXT_PUBLIC_DISABLE_SIGNIN=
+# OPTIONAL: Set to "true" to disable email/password signin only. Also closes /forgot-password and /reset-password.
+NEXT_PUBLIC_DISABLE_EMAIL_PASSWORD_SIGNIN=
+# OPTIONAL: Set to "true" to hide the Google signin button.
+NEXT_PUBLIC_DISABLE_GOOGLE_SIGNIN=
+# OPTIONAL: Set to "true" to hide the Microsoft signin button.
+NEXT_PUBLIC_DISABLE_MICROSOFT_SIGNIN=
+# OPTIONAL: Set to "true" to hide the OIDC signin button.
+NEXT_PUBLIC_DISABLE_OIDC_SIGNIN=
+# OPTIONAL: When OIDC is the only enabled signin transport, /signin auto-redirects
+# to the OIDC provider (rendering only a spinner). Set to "true" to disable this
+# and keep showing the signin page.
+NEXT_PUBLIC_DISABLE_OIDC_AUTO_REDIRECT=
# OPTIONAL: Set to true to use internal webapp url in browserless requests.
NEXT_PUBLIC_USE_INTERNAL_URL_BROWSERLESS=false
diff --git a/.github/ISSUE_TEMPLATE/bug-report.yml b/.github/ISSUE_TEMPLATE/bug-report.yml
index 4fcde0ea3..ceee6933e 100644
--- a/.github/ISSUE_TEMPLATE/bug-report.yml
+++ b/.github/ISSUE_TEMPLATE/bug-report.yml
@@ -34,7 +34,7 @@ body:
label: Browser [e.g., Chrome, Firefox]
- type: input
attributes:
- label: Version [e.g., 2.0.1]
+ label: Version [e.g., 2.13.0]
- type: checkboxes
attributes:
label: Please check the boxes that apply to this issue report.
@@ -44,4 +44,3 @@ body:
- label: I have included relevant environment information.
- label: I have included any relevant screenshots.
- label: I understand that this is a voluntary contribution and that there is no guarantee of resolution.
- - label: I want to work on creating a PR for this issue if approved
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
new file mode 100644
index 000000000..4be27fb49
--- /dev/null
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -0,0 +1,11 @@
+blank_issues_enabled: false
+contact_links:
+ - name: Security vulnerability
+ url: https://github.com/documenso/documenso/security/advisories/new
+ about: Please report security vulnerabilities privately via GitHub Security Advisories. Do not open a public issue.
+ - name: Questions & Discussions
+ url: https://github.com/documenso/documenso/discussions
+ about: Ask questions, share ideas, and discuss Documenso with the community.
+ - name: Discord
+ url: https://documen.so/discord
+ about: Chat with the community and the team.
diff --git a/.github/ISSUE_TEMPLATE/feature-request.yml b/.github/ISSUE_TEMPLATE/feature-request.yml
index ffb788c23..ab21e8828 100644
--- a/.github/ISSUE_TEMPLATE/feature-request.yml
+++ b/.github/ISSUE_TEMPLATE/feature-request.yml
@@ -33,4 +33,3 @@ body:
- label: I have explained the use case or scenario for this feature.
- label: I have included any relevant technical details or design suggestions.
- label: I understand that this is a suggestion and that there is no guarantee of implementation.
- - label: I want to work on creating a PR for this issue if approved
diff --git a/.github/ISSUE_TEMPLATE/improvement.yml b/.github/ISSUE_TEMPLATE/improvement.yml
index de2983b67..424d54a53 100644
--- a/.github/ISSUE_TEMPLATE/improvement.yml
+++ b/.github/ISSUE_TEMPLATE/improvement.yml
@@ -15,17 +15,6 @@ body:
description: 'Are there any additional context or information that might be relevant to the improvement suggestion.'
validations:
required: false
- - type: dropdown
- id: assignee
- attributes:
- label: 'Do you want to work on this improvement?'
- multiple: false
- options:
- - 'No'
- - 'Yes'
- default: 0
- validations:
- required: true
- type: checkboxes
attributes:
label: 'Please check the boxes that apply to this improvement suggestion.'
diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md
index 66602d12b..4e6151b34 100644
--- a/.github/PULL_REQUEST_TEMPLATE.md
+++ b/.github/PULL_REQUEST_TEMPLATE.md
@@ -1,3 +1,14 @@
+
+
## Description
diff --git a/.github/PULL_REQUEST_TEMPLATE/test-addition.md b/.github/PULL_REQUEST_TEMPLATE/test-addition.md
deleted file mode 100644
index f93c81493..000000000
--- a/.github/PULL_REQUEST_TEMPLATE/test-addition.md
+++ /dev/null
@@ -1,40 +0,0 @@
----
-name: Test Addition
-about: Submit a new test, either unit or end-to-end (E2E), for review and inclusion
----
-
-## Description
-
-
-
-
-## Related Issue
-
-
-
-
-## Test Details
-
-
-
-
-- Test Name: Name of the test
-- Type: [Unit / E2E]
-- Description: Brief description of what the test checks
-- Inputs: What inputs the test uses (if applicable)
-- Expected Output: What output or behavior the test expects
-
-## Checklist
-
-
-
-
-- [ ] I have written the new test and ensured it works as intended.
-- [ ] I have added necessary documentation to explain the purpose of the test.
-- [ ] I have followed the project's testing guidelines and coding style.
-- [ ] I have addressed any review feedback from previous submissions, if applicable.
-
-## Additional Notes
-
-
-
diff --git a/.github/workflows/first-interaction.yml b/.github/workflows/first-interaction.yml
index 5f53eb280..a4d7c8a54 100644
--- a/.github/workflows/first-interaction.yml
+++ b/.github/workflows/first-interaction.yml
@@ -1,13 +1,10 @@
name: 'Welcome New Contributors'
on:
- pull_request:
- types: ['opened']
issues:
types: ['opened']
permissions:
- pull-requests: write
issues: write
jobs:
@@ -20,10 +17,7 @@ jobs:
- uses: actions/first-interaction@v1
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
- pr-message: |
- Thank you for creating your first Pull Request and for being a part of the open signing revolution! 💚🚀
-
Feel free to hop into our community in [Discord](https://documen.so/discord)
issue-message: |
Thank you for opening your first issue and for being a part of the open signing revolution!
-
One of our team members will review it and get back to you as soon as it possible 💚
+
One of our team members will review it and get back to you as soon as possible 💚
Meanwhile, please feel free to hop into our community in [Discord](https://documen.so/discord)
diff --git a/.github/workflows/issue-assignee-check.yml b/.github/workflows/issue-assignee-check.yml
deleted file mode 100644
index de53564ec..000000000
--- a/.github/workflows/issue-assignee-check.yml
+++ /dev/null
@@ -1,62 +0,0 @@
-name: 'Issue Assignee Check'
-
-on:
- issues:
- types: ['assigned']
-
-permissions:
- issues: write
-
-jobs:
- countIssues:
- if: ${{ github.event.issue.assignee }} && github.event.action == 'assigned' && github.event.sender.type == 'User'
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- with:
- fetch-depth: 2
- - name: Set up Node.js
- uses: actions/setup-node@v4
- with:
- node-version: '18'
-
- - name: Install Octokit
- run: npm install @octokit/rest@18
-
- - name: Check Assigned User's Issue Count
- id: parse-comment
- uses: actions/github-script@v6
- with:
- github-token: ${{ secrets.GITHUB_TOKEN }}
- script: |
- const { Octokit } = require("@octokit/rest");
- const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
-
- const username = context.payload.issue.assignee.login;
- console.log(`Username Extracted: ${username}`);
-
- const { data: issues } = await octokit.issues.listForRepo({
- owner: context.repo.owner,
- repo: context.repo.repo,
- assignee: username,
- state: 'open'
- });
-
- const issueCount = issues.length;
- console.log(`Issue Count For ${username}: ${issueCount}`);
-
- if (issueCount > 3) {
- let issueCountMessage = `### 🚨 Documenso Police 🚨`;
- issueCountMessage += `\n@${username} has ${issueCount} open issues assigned already. Consider whether this issue should be assigned to them or left open for another contributor.`;
-
- await octokit.request('POST /repos/{owner}/{repo}/issues/{issue_number}/comments', {
- owner: context.repo.owner,
- repo: context.repo.repo,
- issue_number: context.issue.number,
- body: issueCountMessage,
- headers: {
- 'Authorization': `token ${{ secrets.GITHUB_TOKEN }}`,
- }
- });
- }
diff --git a/.github/workflows/pr-review-reminder.yml b/.github/workflows/pr-review-reminder.yml
deleted file mode 100644
index 67dc32f34..000000000
--- a/.github/workflows/pr-review-reminder.yml
+++ /dev/null
@@ -1,63 +0,0 @@
-name: 'PR Review Reminder'
-
-on:
- pull_request:
- types: ['opened', 'ready_for_review']
-
-permissions:
- pull-requests: write
-
-jobs:
- checkPRs:
- if: ${{ github.event.pull_request.user.login }} && github.event.action == ('opened' || 'ready_for_review')
- runs-on: ubuntu-latest
- steps:
- - name: Checkout
- uses: actions/checkout@v4
- with:
- fetch-depth: 2
- - name: Set up Node.js
- uses: actions/setup-node@v4
- with:
- node-version: '18'
-
- - name: Install Octokit
- run: npm install @octokit/rest@18
-
- - name: Check user's PRs awaiting review
- id: parse-prs
- uses: actions/github-script@v5
- with:
- github-token: ${{ secrets.GITHUB_TOKEN }}
- script: |
- const { Octokit } = require("@octokit/rest");
- const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN });
-
- const username = context.payload.pull_request.user.login;
- console.log(`Username Extracted: ${username}`);
-
- const { data: pullRequests } = await octokit.pulls.list({
- owner: context.repo.owner,
- repo: context.repo.repo,
- state: 'open',
- sort: 'created',
- direction: 'asc',
- });
-
- const userPullRequests = pullRequests.filter(pr => pr.user.login === username && (pr.state === 'open' || pr.state === 'ready_for_review'));
- const prCount = userPullRequests.length;
- console.log(`PR Count for ${username}: ${prCount}`);
-
- if (prCount > 3) {
- let prReminderMessage = `🚨 @${username} has ${prCount} pull requests awaiting review. Please consider reviewing them when possible. 🚨`;
-
- await octokit.request('POST /repos/{owner}/{repo}/issues/{issue_number}/comments', {
- owner: context.repo.owner,
- repo: context.repo.repo,
- issue_number: context.payload.pull_request.number,
- body: prReminderMessage,
- headers: {
- 'Authorization': `token ${{ secrets.GITHUB_TOKEN }}`,
- }
- });
- }
diff --git a/.github/workflows/semantic-pull-requests.yml b/.github/workflows/semantic-pull-requests.yml
index 76a1b2f42..0dab3392d 100644
--- a/.github/workflows/semantic-pull-requests.yml
+++ b/.github/workflows/semantic-pull-requests.yml
@@ -16,24 +16,6 @@ jobs:
name: Validate PR title
runs-on: ubuntu-latest
steps:
- - name: Check PR creator's previous activity
- id: check_activity
- run: |
- CREATOR=$(curl -s "https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}" | jq -r '.user.login')
- ACTIVITY=$(curl -s "https://api.github.com/search/commits?q=author:${CREATOR}+repo:${{ github.repository }}" | jq -r '.total_count')
- if [ "$ACTIVITY" -eq 0 ]; then
- echo "::set-output name=is_new::true"
- else
- echo "::set-output name=is_new::false"
- fi
-
- - name: Count PRs created by user
- id: count_prs
- run: |
- CREATOR=$(curl -s "https://api.github.com/repos/${{ github.repository }}/pulls/${{ github.event.pull_request.number }}" | jq -r '.user.login')
- PR_COUNT=$(curl -s "https://api.github.com/search/issues?q=type:pr+is:open+author:${CREATOR}+repo:${{ github.repository }}" | jq -r '.total_count')
- echo "::set-output name=pr_count::$PR_COUNT"
-
- uses: amannn/action-semantic-pull-request@v5
id: lint_pr_title
env:
@@ -44,8 +26,6 @@ jobs:
with:
header: pr-title-lint-error
message: |
- Hey There! and thank you for opening this pull request! 📝👋🏼
-
We require pull request titles to follow the [Conventional Commits Spec](https://www.conventionalcommits.org/en/v1.0.0/) and it looks like your proposed title needs to be adjusted.
Details:
@@ -53,10 +33,3 @@ jobs:
```
${{ steps.lint_pr_title.outputs.error_message }}
```
-
- - if: ${{ steps.lint_pr_title.outputs.error_message == null && steps.check_activity.outputs.is_new == 'false' && steps.count_prs.outputs.pr_count < 2}}
- uses: marocchino/sticky-pull-request-comment@v2
- with:
- header: pr-title-lint-error
- message: |
- Thank you for following the naming conventions for pull request titles! 💚🚀
diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml
index a18e33f87..c9c12ce59 100644
--- a/.github/workflows/stale.yml
+++ b/.github/workflows/stale.yml
@@ -21,4 +21,4 @@ jobs:
stale-pr-message: 'This PR has not seen activitiy for a while. It will be closed in 30 days unless further activity is detected.'
close-pr-message: 'This PR has been closed because of inactivity.'
exempt-pr-labels: 'WIP,on-hold,needs review'
- exempt-issue-labels: 'WIP,on-hold,needs review,roadmap,assigned,needs triage'
+ exempt-issue-labels: 'WIP,on-hold,needs review,roadmap,status: assigned,status: triage'
diff --git a/.gitpod.yml b/.gitpod.yml
index 261f8c96b..883ac5bb3 100644
--- a/.gitpod.yml
+++ b/.gitpod.yml
@@ -31,8 +31,7 @@ vscode:
extensions:
- aaron-bond.better-comments
- bradlc.vscode-tailwindcss
- - dbaeumer.vscode-eslint
- - esbenp.prettier-vscode
+ - biomejs.biome
- mikestead.dotenv
- unifiedjs.vscode-mdx
- GitHub.vscode-pull-request-github
diff --git a/.vscode/settings.json b/.vscode/settings.json
index 7ef2f1a5a..15c6dc877 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -29,6 +29,6 @@
"editor.defaultFormatter": "biomejs.biome"
},
"[json]": {
- "editor.defaultFormatter": "biomejs.biome"
+ "editor.defaultFormatter": "vscode.json-language-features"
}
}
diff --git a/.well-known/security.txt b/.well-known/security.txt
index 1a3f685e5..f96fce0f0 100644
--- a/.well-known/security.txt
+++ b/.well-known/security.txt
@@ -1,7 +1,14 @@
-# General Issues
+# Report security vulnerabilities privately via GitHub Security Advisories (preferred).
+Contact: https://github.com/documenso/documenso/security/advisories/new
+
+# Alternatively, report critical issues privately by email.
+Contact: mailto:security@documenso.com
+
+# Security policy
+Policy: https://github.com/documenso/documenso/security/policy
+
+# General (non-security) issues
Contact: https://github.com/documenso/documenso/issues/new?assignees=&labels=bug&projects=&template=bug-report.yml
-# Report critical issues privately to let us take appropriate action before publishing.
-Contact: mailto:security@documenso.com
Preferred-Languages: en
-Canonical: https://documenso.com/.well-known/security.txt
\ No newline at end of file
+Canonical: https://documenso.com/.well-known/security.txt
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 5cd7a6887..7260cdfe2 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -1,13 +1,27 @@
# Contributing to Documenso
-If you plan to contribute to Documenso, please take a moment to feel awesome ✨ People like you are what open source is about ♥. Any contributions, no matter how big or small, are highly appreciated.
+> **We are no longer accepting external pull requests.**
+>
+> Aside from a small group of trusted contributors we reach out to directly, we no longer merge external PRs. New pull requests will usually be closed with a request to open an issue instead. This is a security decision, not a judgement on your work. Read [Why We're Pausing External Pull Requests](https://documenso.com/blog/why-we-re-pausing-external-pull-requests) for the full reasoning.
+>
+> Documenso stays open source. You can still read, audit, run, and fork the code. The best way to contribute is through detailed issues.
-## Before getting started
+## How to contribute now
-- Before jumping into a PR be sure to search [existing PRs](https://github.com/documenso/documenso/pulls) or [issues](https://github.com/documenso/documenso/issues) for an open or closed item that relates to your submission.
-- Select an issue from [here](https://github.com/documenso/documenso/issues) or create a new one
-- Consider the results from the discussion on the issue
-- Accept the [Contributor License Agreement](https://documen.so/cla) to ensure we can accept your contributions.
+The most useful contribution is a detailed issue. Treat it like a spec. The more detail, the better:
+
+- The problem you're trying to solve, and who it affects
+- How you expect the feature or change to behave
+- Edge cases, constraints, and anything you've already considered
+- Examples, mockups, or references where they help
+
+Before opening an issue, search [existing issues](https://github.com/documenso/documenso/issues) and [discussions](https://github.com/documenso/documenso/discussions) for related items. If a proposal is detailed and fits where Documenso is heading, we'll pick it up and build against it.
+
+For security vulnerabilities, do not open a public issue. Follow our [Security Policy](./SECURITY.md) instead.
+
+---
+
+The sections below are for trusted contributors working with us directly, and for anyone running Documenso locally or maintaining a fork.
## English only PRs and Issues
diff --git a/README.md b/README.md
index f5117abd0..642a285eb 100644
--- a/README.md
+++ b/README.md
@@ -51,16 +51,18 @@ Join us in creating the next generation of open trust infrastructure.
## Community and Next Steps 🎯
-- Check out the first source code release in this repository and test it.
+- Try Documenso by self-hosting it or signing up at [documenso.com](https://documenso.com).
- Tell us what you think in the [Discussions](https://github.com/documenso/documenso/discussions).
-- Join the [Discord server](https://documen.so/discord) for any questions and getting to know to other community members.
+- Join the [Discord server](https://documen.so/discord) for any questions and getting to know other community members.
- ⭐ the repository to help us raise awareness.
-- Spread the word on Twitter that Documenso is working towards a more open signing tool.
-- Fix or create [issues](https://github.com/documenso/documenso/issues), that are needed for the first production release.
+- Open detailed [issues](https://github.com/documenso/documenso/issues) to report bugs or propose features.
## Contributing
-- To contribute, please see our [contribution guide](https://github.com/documenso/documenso/blob/main/CONTRIBUTING.md).
+> **Note**: We no longer accept external pull requests, aside from a small group of trusted contributors we reach out to directly. The best way to contribute is through detailed issues. Read [Why We're Pausing External Pull Requests](https://documenso.com/blog/why-we-re-pausing-external-pull-requests) for the reasoning.
+
+- Documenso stays open source. You can read, audit, run, and fork the code.
+- To report issues or propose changes, see our [contribution guide](https://github.com/documenso/documenso/blob/main/CONTRIBUTING.md).
## Contact us
@@ -81,17 +83,21 @@ Contact us if you are interested in our Enterprise plan for large organizations
diff --git a/apps/docs/content/docs/users/settings/delete-account.mdx b/apps/docs/content/docs/users/settings/delete-account.mdx
index 569dc1bc2..77640db70 100644
--- a/apps/docs/content/docs/users/settings/delete-account.mdx
+++ b/apps/docs/content/docs/users/settings/delete-account.mdx
@@ -7,14 +7,14 @@ import { Callout } from 'fumadocs-ui/components/callout';
import { Step, Steps } from 'fumadocs-ui/components/steps';