Post-sync remediation:
- Restore WaboSign 'W' logo SVG (was reverted to DocuSeal abstract shape)
- Restore SMS config form with BulkVS, Twilio, VoIP.ms, SignalWire providers
- Add AGPL §7(b) upstream attribution to footer (DocuSeal link alongside WaboSign)
- Remove Console feature entirely (controller deleted, routes/constants removed)
- Remove all Pro/Plan/Upgrade gating — features now freely available
- Make all user roles selectable (editor/viewer no longer disabled)
- Remove upgrade button from navbar, plans link from settings nav
- Remove console redirect from sessions controller
- Add _logo.html.erb to rebrand-sync DENY_PATHS to prevent future overwrites
First exercise of the bin/rebrand-sync workflow. Upstream 3.0.0
(merge-base 528a1216, 15 commits) brought:
Auto-merged cleanly (no conflict):
- New controllers/routes: submissions_resend_email (route added by
hand to config/routes.rb since fork's routes diverged elsewhere),
template_documents, templates_clone_and_replace, templates_folders,
templates_restore, templates_versions, submissions_unarchive
- PDF optimizations and signing-form completion-button refactor
(e378025a, 04129ded, 7fe56941)
- Percent formatting (99ca0136), area-box clamping (41604008),
validation message rephrasings (abd498dd)
Conflicts resolved (rerere now caches these for next sync):
- "take ours" for files where the fork stripped freemium gates
(Plans/Console/Upgrade, ENTERPRISE_PATHS, multitenant guards on
esign default sig, reminder durations, decline/delegate toggles,
BCC and send-on-completion, Pro upsell placeholders for SMS/SSO/
bulk-send/payment/conditions/formula/phone-field)
- "take ours" for per-account branding helpers
(Wabosign.branded_product_name vs Wabosign.product_name) across
mailers, MFA, MCP, audit-trail PDFs, page titles
- "take ours" for fork brand URLs (sign.wabo.cc, Wabosign::PRODUCT_URL,
Wabosign::GITHUB_URL) over upstream's hardcoded wabosign.com
- "take ours" for the webhook User-Agent ("WaboSign Webhook" not
"WaboSign.com Webhook") and X-Wabosign-Signature header
- "take theirs" for submitters_send_email's defensive authorize!(:update)
(security improvement from upstream commit e52830c9)
- Hybrid resolution in lib/send_webhook_request.rb — keep fork's
USER_AGENT, take upstream's "don't override custom webhook header"
blank-check (a7891f89)
- 22 "deleted by us" files (Pro upsell controllers/views, removed
docs/api/*, deleted newsletter feature) confirmed deleted
Known gaps to fix as follow-ups:
- config/locales/i18n.yml — taken ours wholesale; missing upstream's
three new resend-email keys (re_send_emails,
are_you_sure_you_want_to_re_send_email_to_n_recipients,
emails_have_been_sent_to_n_recipients) across all 14 languages.
English fallback works for those strings until translated.
- Gemfile.lock — taken ours; needs `bundle install` to regenerate
with upstream's gem updates from 37d4a8e8.
- yarn.lock — same; needs `yarn install`.
- bin/rebrand-sync — the `\bdocuseal_` rule misses `_docuseal_` inside
identifiers (e.g. `unlock_with_docuseal_pro` i18n keys). Widening
to `docuseal_` (no leading word boundary) would catch those. Tracked
as a script refinement before the next sync.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Output of bin/rebrand-sync against the upstream 3.0.0 tree. Renames
lib/docuseal.rb → lib/wabosign.rb, rewrites the Docuseal/DocuSeal
identifiers to Wabosign/WaboSign across controllers, jobs, mailers,
views, JS/Vue, locales, specs, and infrastructure (Dockerfile,
docker-compose, CI workflows, env-file path, AATL cert name).
This commit is the sync branch's contribution to the merge — it does
NOT carry the fork's features (SSO, SMS, per-account branding, etc.)
or the bin/rebrand-* scripts themselves; those arrive via the
subsequent merge into master.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replaces the disabled "logo upload not bundled in OSS" placeholder
with a real upload flow. Logos attach to the Account via ActiveStorage
(`has_one_attached :logo`) and replace the default WaboSign mark at
every render site that previously rendered `shared/_logo`.
Accepted formats: PNG, JPEG, and SVG. SVGs go through
`AccountLogo.sanitize_upload` before storage:
- `<script>` and `<foreignObject>` elements removed
- every `on*` attribute stripped (onclick, onload, onerror, …)
- `href` / `xlink:href` dropped unless the value starts with `#`
(in-doc fragment) or `data:` (inert in <img> context)
Raster uploads pass through unchanged. 2 MB upload cap on all formats.
Dispatch is a new `shared/_account_logo.html.erb` partial — takes an
optional `account:` local and emits either `<img>` (logo attached) or
falls back to the existing inline `shared/_logo.html.erb` SVG. All
swapped render sites pass the right account expression:
- shared/_title.html.erb → current_account
- start_form/_brand_logo.html.erb → @template.account
- submit_form/_brand_logo.html.erb → @submitter.submission.account
- templates_uploads/show.html.erb → current_account
- submissions/_logo.html.erb → @submission || @submitter accounts
- templates_share_link_qr/_logo.html.erb → @template.account
The landing page stays on the default mark (no account context).
Static favicon/PWA manifest/preview.png stay on the default brand.
Audit-trail PDF (`lib/submissions/generate_audit_trail.rb#add_logo`)
now calls `PdfIcons.account_logo_io(submission.account)`. SVG logos
are rasterized to PNG via ActiveStorage variants (libvips + librsvg,
both present in the production image via the `vips` Alpine pkg). On
any failure path the helper logs and falls back to `PdfIcons.logo_io`
so audit-trail generation never crashes on a bad logo.
Routes: `resource :account_logo, only: %i[create destroy]` nested
under `/settings`. AccountLogoController authorizes via
`authorize!(:manage, current_account)` and routes the form back to
`/settings/personalization` on success or failure.
Specs (11/11 pass in the Ruby 4.0.1 + Postgres-14 container):
- spec/lib/account_logo_spec.rb — 6 sanitizer unit cases
- spec/requests/account_logo_controller_spec.rb — 5 request cases
Smoke-tested end-to-end in the built image:
- PNG round-trips through attach/download.
- Malicious SVG (`<script>` + onload + alert) saves with all three
payloads scrubbed from the stored bytes.
- SVG → PNG rasterization for the PDF path produces a 18 KB PNG
with valid PNG magic — confirms libvips/librsvg is actually
wired in the production Alpine image.
- After purge, `PdfIcons.account_logo_io` is byte-identical to
`PdfIcons.logo_io` (clean fallback).
- /settings/personalization renders the new form with all expected
fields.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Replaces the SMS placeholder with an actual provider integration. v1
ships BulkVS only; the architecture leaves room for additional
providers behind the same Sms.send_message interface.
Storage:
- EncryptedConfig key `sms_configs` (added to CONFIG_KEYS):
{ provider, enabled, basic_auth_token, from_number,
delivery_webhook_url }
- AccountConfig key `submitter_invitation_sms` for the per-account
SMS body template override.
Service layer:
- lib/sms.rb — Sms.enabled_for?(account), Sms.send_message
(account:, to:, text:), Sms.normalize_phone
- lib/sms/providers/bulkvs.rb — POST to
https://portal.bulkvs.com/api/v1.0/messageSend with the
pre-encoded Basic Auth header from the BulkVS portal. Surfaces
non-2xx responses as Sms::ProviderError with the upstream message.
Background sending:
- app/jobs/send_submitter_invitation_sms_job.rb — mirrors
SendSubmitterInvitationEmailJob; substitutes account-template
variables via the existing ReplaceEmailVariables module so
{account.name} / {submitter.link} / etc. work in the SMS body.
- submitters_controller#maybe_resend_email_sms already enqueues
this job when params[:send_sms] == '1', so the existing
"Send SMS" toggle in the submitter edit form now does what it
says on the tin.
Controllers/routes:
- SmsSettingsController gains create + test_message; the test_message
action lets an admin verify their config with a one-off SMS
against any phone number.
- SubmittersSendSmsController#create powers the per-submitter
"Send SMS" button (mirrors SubmittersSendEmailController).
- Routes: resources :sms with create + test_message; submitters
nested resources :send_sms.
Views:
- app/views/sms_settings/index.html.erb — real form replacing the
"not bundled" placeholder. Status banner reflects live config.
Test-send card renders only when SMS is enabled.
- app/views/submissions/_send_sms_button.html.erb — was a permanently
disabled stub; now button_to the new send_sms endpoint when SMS
is configured and the submitter has a phone number. Falls back to
a tooltip explaining what's missing otherwise.
- app/views/submissions/_send_sms.html.erb — was a placeholder render;
now shows a real "send SMS on save" toggle when SMS is configured.
- app/views/personalization_settings/_signature_request_sms_form.html.erb
+ show.html.erb — per-account SMS body override with variable
documentation.
Smoke-tested in a built image:
- /settings/sms renders 200, all form fields present.
- /settings/personalization renders the SMS body field.
- With saved (bogus) creds, Sms.send_message hits BulkVS over HTTPS
and surfaces the real 401 as Sms::ProviderError — proves the
transport is wired, not just the boot path.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Renames the product to WaboSign across UI, mailers, locales, assets, and
internal Ruby module. Keeps the upstream DocuSeal attribution required by
AGPLv3 §7(b) in the powered-by footer, email attribution, README, and a
new NOTICE file. Migration renames the AATL cert identifier in encrypted
configs from docuseal_aatl to wabosign_aatl.
Removes multitenant-gated Pro upsell UI (Plans/Console/Upgrade links,
SMS/SSO/bulk-send/logo placeholders, reminder-duration restriction, the
"DocuSeal Pro" email-attribution toggle, conditions/formula/payment
pricing links) so every shipped feature is reachable on a self-hosted
deployment. Multitenant routing logic is preserved.
Drops Discord, Twitter, and ChatGPT/AI-assistant chrome. Embedding
modal keeps the upstream <docuseal-form> / @docuseal/* SDK contract so
existing embedded forms continue to work; documented in NOTICE.
REBRANDING.md captures the change inventory for future maintainers.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>