Upstream syncs repeatedly re-introduce DocuSeal's freemium gates, delete
fork code, overwrite brand assets, and drop AGPL attribution; recovery took
~7 repair commits after the 3.0.2 sync. rebrand-check only catches surviving
DocuSeal *text*, and the REBRANDING.md post-merge checklist was manual and
not run reliably (two regressions it claims were fixed were still live).
Add bin/fork-check, a stdlib-only runner driven by config/fork_invariants.yml,
asserting: must-exist fork files/brand assets, must-not-exist placeholders /
console_redirect / lib/docuseal.rb (Zeitwerk guard), must-contain attribution
+ renamed identifiers + SDK tokens, path-scoped must-not-contain gate markers,
forbidden global markers, forbidden i18n keys, no dangling partial renders,
and PRESERVE<->ALLOW_PATTERNS consistency between rebrand-sync/rebrand-check.
Wired into CI as the 'Fork invariants' job. Allowlist the new guard + manifest
in rebrand-check and deny them in rebrand-sync so the sweep can't corrupt them.
Baseline cleanup so the new gate-absence checks pass (both documented as
removed in REBRANDING.md but live on master): remove the ENTERPRISE_PATHS
'Pro Edition' export paywall from errors_controller.rb, and the multitenant?
reminder-duration gate from _reminder_form.html.erb.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
RuboCop (9 offenses, 5 files):
- embed_scripts_controller: drop redundant .freeze (frozen_string_literal on)
- sessions_controller: use modifier if for redir return
- feature_toggles/signing_flow/template_crud specs: convert flaky
`pending 'desc: reason' do` to `it 'desc', skip: 'reason' do`
- signing_flow_edge_cases: break over-long execute_script line
Erblint (2 offenses):
- sso_settings: replace inline `rescue` modifier with precomputed
begin/rescue local for the OAuth callback URI
- sms_settings: remove leading blank line in the multi-statement <% %> block
Assets precompile:
- config/initializers/migrate.rb runs DatabaseTasks.migrate when
RAILS_ENV=production and RUN_MIGRATIONS!=false. The precompile CI job has
no postgres service, so it failed on a refused DB connection. Set
RUN_MIGRATIONS=false for the precompile step so no DB is touched.
All pre-existing on master before the SMS work; none are SMS-related.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- bin/sync-upstream: automation script for upstream tag sync with
logo file restoration from ORIG_HEAD after merge
- CI: setup-node@v1->@v4, set-output->$GITHUB_OUTPUT,
docuseal_test->wabosign_test, add rebrand-check and
assets-precompile jobs
- Docker: checkout@v3->@v4, metadata-action@v4->@v5,
login-action@v3->@v6, images->wabolabs/wabosign, add PR build test
- rebrand-sync: add logo paths to DENY_PATHS
- .gitattributes: add -merge for brand logo files
- REBRANDING.md: update per-sync workflow with logo restoration step
- Rubocop Style/RedundantRegexpEscape: remove unnecessary \- in two
character classes in FULL_EMAIL_REGEXP (user.rb:59)
- Brakeman LinkToHref XSS: add fingerprint to brakeman.ignore — the
filter_path guard (start_with?('/')) prevents javascript: and
absolute-URL attacks; Brakeman still tracks params[:path] taint
through the conditional assignment
- RSpec install: switch pdfium binary source from the deleted
docusealco/pdfium-binaries to bblanchon/pdfium-binaries (same
tarball layout: lib/libpdfium.so)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Patch release covering the security findings from the repo's first
CodeQL scan against 1.3.0:
- Sanitise params[:path] before it flows into form action / link href
in submissions_filters/_filter_modal (reflected XSS).
- Slice required_params to email/phone before passing to find_by! /
find_or_initialize_by in start_form_controller (column-name
injection via template-owner-controlled link_form_fields preference).
- Rewrite FULL_EMAIL_REGEXP local-part to remove the nested quantifier
(ReDoS).
- Replace the Bearer-token regex in mcp_controller with a string
prefix check (polynomial ReDoS).
- Swap Math.random()-based attachment UUIDs for crypto.randomUUID()
in the submission-form Vue dropzone / signature / initials steps.
- Add a workflow-level permissions: read-all block to ci.yml.
See CHANGELOG.md [1.3.1] for the full per-alert breakdown and the
list of CodeQL findings that are false positives in context.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds a deterministic rebrand sweep so each upstream sync is a scripted
transformation rather than a manual sweep:
- bin/rebrand-sync — idempotent Ruby script that rewrites DocuSeal →
WaboSign tokens across the tree (Ruby module, AATL cert name, DB
names, Docker user, registry/repo URLs, DOM-ID/localStorage prefix,
daisyUI theme name, hardcoded UI strings). Sentinel-protects AGPL
§7(b) attribution phrases, SDK custom-element identifiers, the
@docuseal/* npm packages, and the docusealco/{fields-detection,
pdfium-binaries,turbo} binary URLs. Deny-lists NOTICE, LICENSE_*,
README, the AGPL attribution partials, calculator.js's DocuSeal LLC
copyright, lib/wabosign.rb's UPSTREAM constants, and the
docuseal_aatl migration that searches by the legacy name.
- bin/rebrand-check — fails CI when an unintended DocuSeal reference
survives in the tree. Wired in as the new `Rebrand check` job in
.github/workflows/ci.yml.
- REBRANDING.md gains a "Sync workflow" section documenting the
per-sync steps, rerere setup, and how to keep the two scripts'
allow/preserve lists in sync.
- .gitattributes marks Gemfile.lock and yarn.lock as -merge — they get
regenerated post-merge rather than diffed.
- Latent rebrand leftovers fixed: public/service-worker.js no longer
logs "DocuSeal App installed/activated"; .dockerignore and
.gitignore now ignore /wabosign (the actual runtime data dir mount)
rather than the stale /docuseal path.
Strategy detail lives at .claude/plans/come-up-with-a-foamy-flask.md.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
- actions/checkout@v3 -> @v4 in docker.yml
- actions/setup-node@v1 -> @v4 in ci.yml (both jobs that use it)
- Replace deprecated `::set-output` with $GITHUB_OUTPUT in the
ESLint yarn-cache-dir step
The remaining Node 20 deprecation warnings on actions/cache@v4,
actions/checkout@v4, and the docker/* actions will resolve once
upstream ships Node 24 builds; not blocking, the runtime won't
flip until 2026-06.
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>