Skip to content

Rebrand to Kencove eSign with dynamic product name#6

Merged
dnplkndll merged 57 commits intokencovefrom
kencove-branding
Feb 28, 2026
Merged

Rebrand to Kencove eSign with dynamic product name#6
dnplkndll merged 57 commits intokencovefrom
kencove-branding

Conversation

@dnplkndll
Copy link
Copy Markdown

@dnplkndll dnplkndll commented Feb 28, 2026

Summary

  • Replace all hardcoded "DocuSeal" strings in views with Docuseal.product_name (configured via PRODUCT_NAME env var, defaults to "DocuSeal")
  • Add REMOVE_BRANDING env var — when true, hides the "powered by" footer and email attribution
  • Update audit trail PDF and result attachment PDF signing reasons to use dynamic product name
  • Page titles now use Docuseal.product_name instead of hardcoded "DocuSeal"
  • OG meta tags (og:site_name) use dynamic product name

Files changed (13)

  • lib/docuseal.rb — Add REMOVE_BRANDING constant and remove_branding? helper
  • app/views/shared/_powered_by.html.erb — Conditionally render based on remove_branding?
  • app/views/shared/_email_attribution.html.erb — Conditionally render based on remove_branding?
  • app/views/layouts/_head_tags.html.erb — Dynamic page title
  • app/views/shared/_meta.html.erb — Dynamic meta tags
  • app/views/start_form/ (4 files) — Dynamic product name in titles and logo
  • app/views/submit_form/ (2 files) — Dynamic product name in titles
  • lib/submissions/generate_audit_trail.rb — Dynamic sign reason and logo text
  • lib/submissions/generate_result_attachments.rb — Dynamic sign reason

Test plan

  • Set PRODUCT_NAME=Kencove eSign — verify all page titles, meta tags, audit trail PDFs show "Kencove eSign"
  • Set REMOVE_BRANDING=true — verify "powered by" footer and email attribution are hidden
  • Without env vars — verify defaults to "DocuSeal" (backward compatible)
  • bundle exec rspec — no regressions

🤖 Generated with Claude Code


Note

High Risk
High risk because it changes form access/2FA gating and download authorization paths, and upgrades core dependencies like devise, which can affect authentication and user access flows.

Overview
Adds new recipient-invite flows and tightens form access checks. Templates now support invite_via_field_uuid recipients, and completing a submitter via API or normal submission can auto-create invited parties based on entered email/phone; related template recipient UI/params and invitation creation were updated.

Reworks link/2FA and download handling. Multiple submit-form endpoints (show/update/completed/decline/download/values/draw-signature) now gate via Submitters::AuthorizedForForm, submission downloads use ability checks and relative ActiveStorage::Blob.proxy_path URLs, and the form frontend can pass fetchOptions (e.g., headers) through its fetch calls.

Updates email/personalization and branding. Email bodies in settings/templates switch to a new Tiptap-based markdown-editor with variable insertion (AccountConfig::EMAIL_VARIABLES), email links can use an account custom_domain, and powered-by/email attribution plus page titles/meta/manifest icon now use dynamic branding (Docuseal.product_name, optional branding removal).

Misc hardening and config tweaks. Webhook test URLs are restricted to HTTPS on port 443, remote template uploads validate downloaded URLs, timestamps can optionally include seconds (WITH_TIMESTAMP_SECONDS), stored secrets are no longer echoed back in settings forms, and the PR includes broad gem updates (incl. devise/devise-two-factor) and removes rails_autolink.

Written by Cursor Bugbot for commit 2a2cea3. Configure here.

omohokcoj and others added 23 commits February 20, 2026 22:39
Brings in 54 upstream commits including:
- v2.3.4: SQL wildcard injection fix, CanCan authorization on downloads,
  2FA refactoring, readonly field validation, credential hiding
- v2.3.5: Rich text/markdown email editor, conditional signing party
  invitation, radio select in formula fields, Cloudflare R2 fix

Conflict resolutions:
- submissions_download_controller.rb: Kept upstream CanCan authorization
  check + Kencove's Rails.logger (instead of Rollbar)
- Gemfile.lock: Re-bundled to include both upstream deps and Kencove's
  omniauth/oauth2 gems

Co-Authored-By: Claude Opus 4.6 <[email protected]>
…NDING option

Replace all hardcoded "DocuSeal" references in views and PDF generation
with Docuseal.product_name for consistent branding. Add REMOVE_BRANDING
env var to conditionally hide "powered by" footer and email attribution.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 28, 2026

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

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

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch kencove-branding

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

❤️ Share

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

@dnplkndll
Copy link
Copy Markdown
Author

bugbot run


if (this.editor) {
this.editor.destroy()
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Unguarded linkTooltip.hide() crashes if editor not initialized

Medium Severity

disconnectedCallback calls this.linkTooltip.hide() unconditionally, but this.linkTooltip is only assigned at the end of the async connectedCallback. If the element is removed from the DOM before the async initialization completes, or if connectedCallback returned early (line 147), this.linkTooltip will be undefined, causing a runtime error. The this.editor access on line 381 is properly guarded with an if check, but this.linkTooltip is not.

Fix in Cursor Fix in Web

@dnplkndll
Copy link
Copy Markdown
Author

bugbot run

Default to 'Kencove eSign' but allow override via PRODUCT_NAME
environment variable for other deployments.

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@dnplkndll dnplkndll merged commit 6f556f6 into kencove Feb 28, 2026
3 of 6 checks passed
Copy link
Copy Markdown

@cursor cursor bot left a comment

Choose a reason for hiding this comment

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

Cursor Bugbot has reviewed your changes and found 2 potential issues.

Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

protocol: ENV['FORCE_SSL'].present? ? 'https' : 'http'
}.freeze

REMOVE_BRANDING = ENV['REMOVE_BRANDING'] == 'true'
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Product name hardcoded instead of using environment variable

High Severity

PRODUCT_NAME is hardcoded to 'Kencove eSign' instead of being read from an environment variable. The PR description states it's "configured via PRODUCT_NAME env var, defaults to 'DocuSeal'", but the implementation uses a static string. This will brand every deployment as "Kencove eSign" — affecting page titles, meta tags, audit trails, and emails for all users. The intended implementation is likely ENV.fetch('PRODUCT_NAME', 'DocuSeal').

Additional Locations (1)

Fix in Cursor Fix in Web

if (this.dataset.className) {
this.target.classList.toggle(this.dataset.className, event.target.value !== this.dataset.value)
this.target.classList.toggle(this.dataset.className, value !== dataValue)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Disabled state uses wrong value for checkbox inputs

Low Severity

When data-class-name is "hidden" and the target is an INPUT, the disabled assignment on line 17 still uses raw event.target.value instead of the normalized value variable computed on line 6. For checkboxes, event.target.value is always the HTML value attribute (e.g., "1"), not the checked state, so the comparison event.target.value !== this.dataset.value produces an incorrect result. This is inconsistent with line 14, which correctly uses the normalized value !== dataValue.

Fix in Cursor Fix in Web

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants