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>
The inline script lacked a nonce and was blocked by the enforced CSP
(application_controller#set_csp uses a nonce'd script-src), so the toggle
and provider-switching handlers never ran. Add the standard
content_security_policy_nonce attribute, matching other inline scripts
(e.g. scripts/_autosize_field). Update the two original tests that assumed
the provider section is always visible, since it is now correctly hidden
when SMS is disabled.
The onchange attribute on the select helper wasn't rendering correctly
due to Rails select helper argument handling. Switched to a plain <script>
tag with Turbo-compatible DOMContentLoaded listener, matching patterns
used elsewhere in the codebase.
- Fix SMS provider dropdown: switch from nonce'd javascript_tag to inline
onchange handler (Turbo-compatible)
- Fix enable toggle: handle serialized JSON string values ("true"/"1")
in addition to boolean true
- Fix landing page: change link text from github.com/docusealco to
github.com/wabolabs/wabosign
- Add comprehensive SMS system tests (4 examples) covering provider
form rendering, toggle, enabled state, and test message section
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
The previous lint fix swapped a `<% ... %>` block-opener style but
left a multi-line hash literal and multi-line `case` expression inside
the same ERB tag, which tripped Layout/FirstHashElementIndentation,
Layout/IndentationConsistency, and the closing-newline-before-`%>`
rule.
Reshape: each assignment lives in its own single-line `<% %>` tag, and
the per-provider sending-number lookup is a plain hash dispatch rather
than a multi-line case. Same runtime behaviour; lint-clean.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Rubocop:
- lib/sms/providers/{signalwire,twilio}.rb: collapse the
Net::HTTPSuccess success-path `if` into modifier form
(Style/IfUnlessModifier).
- lib/sms/providers/signalwire.rb: `delete_suffix('/')` instead of
`sub(%r{/\z}, '')` (Performance/DeleteSuffix).
- app/controllers/sms_settings_controller.rb: move SECRET_KEYS to
the top of the class so it isn't sandwiched under `private`
(Lint/UselessConstantScoping). Ruby constants aren't actually
privatised by a preceding `private` keyword anyway.
Erblint:
- app/views/sms_settings/index.html.erb: replace `javascript_tag do`
with a raw `<script nonce=...>` block so erblint's
AvoidUsingJavascriptTag rule is satisfied. CSP nonce comes from
Rails' content_security_policy_nonce helper, same source as before.
- Inline the ERB block-opener so Ruby doesn't see a leading empty
line (Layout/LeadingEmptyLines).
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Adds three new selectable providers behind the existing
Sms.send_message interface. Per-account credentials are namespaced in
the encrypted sms_configs hash (twilio_*, voipms_*, signalwire_*) so
existing BulkVS configs keep working unchanged.
- lib/sms.rb: dispatch via per-provider classes and delegate the
"is this configured" check to each provider, replacing the BulkVS-only
hardcoded gate in enabled_for?.
- lib/sms/providers/twilio.rb: form-encoded POST to the Messages API,
Basic Auth with SID:Token, treats 201-with-error_code as failure.
- lib/sms/providers/voipms.rb: GET with query-string auth, treats
status != "success" as failure even on HTTP 200, enforces the API's
160-byte hard cap up front.
- lib/sms/providers/signalwire.rb: Twilio-shaped client targeting the
per-account Space URL host; strips https:// and trailing / from the
user-supplied space URL.
- app/controllers/sms_settings_controller.rb: extend the
preserve-secret-on-blank-edit pattern to all four providers' password
fields via a SECRET_KEYS array.
- app/views/sms_settings/index.html.erb: dynamic provider select sourced
from Sms::SUPPORTED_PROVIDERS with per-provider field blocks toggled by
a nonce'd inline script (the app's CSP requires nonces on inline JS).
- SMS.md: new "Configuring …" sections for each provider, wire-format
quick-reference table, and updated extension/code-map sections.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
Previously CI had never run on the wabolabs/wabosign fork (Actions
gated until owner consent). Now that the gate is lifted, run rubocop /
erblint / brakeman / rspec against current master uncovered backlog:
- rubocop: 97 auto-corrected across the WaboSign-fork files (account
logo, SMS, SSO, ability specs, role auth specs, omniauth callbacks).
Remaining 8 fixed by hand:
* lib/wabosign.rb chained map collapsed to filter_map; `hd` param
renamed to `hosted_domain` (Naming/MethodParameterName)
* app/models/user.rb default_sso_account split for line length +
SafeNavigation
* spec/rails_helper.rb abort calls marked `# rubocop:disable
Rails/Exit` (upstream pattern, intentional)
* spec/requests/users/omniauth_callbacks_spec.rb let! used for
side-effect-only setup -> moved into before blocks
- erblint: 21 auto-corrected (mostly Style/StringLiterals from a
sed substitution that picked double quotes) + a missing
autocomplete attribute added to the SMS test-message input.
- brakeman: clean. Removed one obsolete ignore entry (was for the
deleted enquiries controller) and added one new ignore for the
MCP-settings token preview (HighlightCode returns escaped HTML).
- rspec: dashboard "shows the list of templates" was flaky because
other_template's Faker::Book.title could randomly collide with one
of the 5 in-account templates. Pin the name to a unique suffix.
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>