diff --git a/.annotaterb.yml b/.annotaterb.yml
new file mode 100644
index 00000000..3b53dce0
--- /dev/null
+++ b/.annotaterb.yml
@@ -0,0 +1,58 @@
+---
+:position: before
+:position_in_additional_file_patterns: before
+:position_in_class: before
+:position_in_factory: before
+:position_in_fixture: before
+:position_in_routes: before
+:position_in_serializer: before
+:position_in_test: before
+:classified_sort: true
+:exclude_controllers: true
+:exclude_factories: true
+:exclude_fixtures: false
+:exclude_helpers: true
+:exclude_scaffolds: true
+:exclude_serializers: false
+:exclude_sti_subclasses: false
+:exclude_tests: false
+:force: false
+:format_markdown: false
+:format_rdoc: false
+:format_yard: false
+:frozen: false
+:ignore_model_sub_dir: false
+:ignore_unknown_models: false
+:include_version: false
+:show_check_constraints: false
+:show_complete_foreign_keys: false
+:show_foreign_keys: true
+:show_indexes: true
+:simple_indexes: false
+:sort: false
+:timestamp: false
+:trace: false
+:with_comment: true
+:with_column_comments: true
+:with_table_comments: true
+:active_admin: false
+:command:
+:debug: false
+:hide_default_column_types: ''
+:hide_limit_column_types: ''
+:ignore_columns:
+:ignore_routes:
+:models: true
+:routes: false
+:skip_on_db_migrate: false
+:target_action: :do_annotations
+:wrapper:
+:wrapper_close:
+:wrapper_open:
+:classes_default_to_s: []
+:additional_file_patterns: []
+:model_dir:
+- app/models
+:require: []
+:root_dir:
+- ''
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 1a28aa8e..ae1b667c 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -77,6 +77,33 @@ jobs:
         run: |
           ./node_modules/eslint/bin/eslint.js "app/javascript/**/*.js"
 
+  brakeman:
+    name: Brakeman
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v4
+      - name: Install Ruby
+        uses: ruby/setup-ruby@v1
+        with:
+          ruby-version: 3.4.1
+      - name: Cache gems
+        uses: actions/cache@v4
+        with:
+          path: vendor/bundle
+          key: ${{ runner.os }}-gem-${{ hashFiles('**/Gemfile.lock') }}
+          restore-keys: |
+            ${{ runner.os }}-gem-
+      - name: Install gems
+        run: |
+          gem install bundler
+          bundle config path vendor/bundle
+          bundle install --jobs 4 --retry 4
+          yarn install
+          sudo apt-get update
+          sudo apt-get install libvips
+      - name: Run Brakeman
+        run: bundle exec brakeman -q --exit-on-warn
+
   rspec:
     name: RSpec
     runs-on: ubuntu-latest
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 2315d2b1..3250e475 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -7,7 +7,7 @@ on:
 
 jobs:
   build:
-    runs-on: ubuntu-latest
+    runs-on: ubuntu-24.04-arm
 
     steps:
     - name: Checkout code
diff --git a/Dockerfile b/Dockerfile
index cfabc332..23fa1ad7 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM ruby:3.4.1-alpine as fonts
+FROM ruby:3.4.1-alpine AS fonts
 
 WORKDIR /fonts
 
@@ -6,7 +6,7 @@ RUN apk --no-cache add fontforge wget && wget https://github.com/satbyy/go-noto-
 
 RUN fontforge -lang=py -c 'font1 = fontforge.open("FreeSans.ttf"); font2 = fontforge.open("NotoSansSymbols2-Regular.ttf"); font1.mergeFonts(font2); font1.generate("FreeSans.ttf")'
 
-FROM ruby:3.4.1-alpine as webpack
+FROM ruby:3.4.1-alpine AS webpack
 
 ENV RAILS_ENV=production
 ENV NODE_ENV=production
@@ -32,7 +32,7 @@ COPY ./app/views ./app/views
 
 RUN echo "gem 'shakapacker'" > Gemfile && ./bin/shakapacker
 
-FROM ruby:3.4.1-alpine as app
+FROM ruby:3.4.1-alpine AS app
 
 ENV RAILS_ENV=production
 ENV BUNDLE_WITHOUT="development:test"
diff --git a/Gemfile b/Gemfile
index 39cf1bea..6961ac80 100644
--- a/Gemfile
+++ b/Gemfile
@@ -46,7 +46,6 @@ gem 'twitter_cldr', require: false
 gem 'tzinfo-data'
 
 group :development, :test do
-  gem 'annotate'
   gem 'better_html'
   gem 'bullet'
   gem 'debug'
@@ -63,6 +62,9 @@ group :development, :test do
 end
 
 group :development do
+  gem 'annotaterb'
+  gem 'brakeman', require: false
+  gem 'foreman', require: false
   gem 'letter_opener_web'
   gem 'web-console'
 end
diff --git a/Gemfile.lock b/Gemfile.lock
index de6e71b3..984b23c4 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -74,9 +74,7 @@ GEM
       uri (>= 0.13.1)
     addressable (2.8.7)
       public_suffix (>= 2.0.2, < 7.0)
-    annotate (2.6.5)
-      activerecord (>= 2.3.0)
-      rake (>= 0.8.7)
+    annotaterb (4.14.0)
     arabic-letter-connector (0.1.1)
     ast (2.4.2)
     aws-eventstream (1.3.0)
@@ -120,6 +118,8 @@ GEM
     bindex (0.8.1)
     bootsnap (1.18.4)
       msgpack (~> 1.2)
+    brakeman (7.0.0)
+      racc
     builder (3.3.0)
     bullet (8.0.0)
       activesupport (>= 3.0.0)
@@ -229,6 +229,7 @@ GEM
     ffi (1.17.1-arm64-darwin)
     ffi (1.17.1-x86_64-linux-gnu)
     ffi (1.17.1-x86_64-linux-musl)
+    foreman (0.88.1)
     geom2d (0.4.1)
     globalid (1.2.1)
       activesupport (>= 6.1)
@@ -337,18 +338,18 @@ GEM
     net-smtp (0.5.0)
       net-protocol
     nio4r (2.7.4)
-    nokogiri (1.18.2)
+    nokogiri (1.18.3)
       mini_portile2 (~> 2.8.2)
       racc (~> 1.4)
-    nokogiri (1.18.2-aarch64-linux-gnu)
+    nokogiri (1.18.3-aarch64-linux-gnu)
       racc (~> 1.4)
-    nokogiri (1.18.2-aarch64-linux-musl)
+    nokogiri (1.18.3-aarch64-linux-musl)
       racc (~> 1.4)
-    nokogiri (1.18.2-arm64-darwin)
+    nokogiri (1.18.3-arm64-darwin)
       racc (~> 1.4)
-    nokogiri (1.18.2-x86_64-linux-gnu)
+    nokogiri (1.18.3-x86_64-linux-gnu)
       racc (~> 1.4)
-    nokogiri (1.18.2-x86_64-linux-musl)
+    nokogiri (1.18.3-x86_64-linux-musl)
       racc (~> 1.4)
     oj (3.16.8)
       bigdecimal (>= 3.0)
@@ -588,13 +589,14 @@ PLATFORMS
   x86_64-linux-musl
 
 DEPENDENCIES
-  annotate
+  annotaterb
   arabic-letter-connector
   aws-sdk-s3
   aws-sdk-secretsmanager
   azure-storage-blob
   better_html
   bootsnap
+  brakeman
   bullet
   cancancan
   capybara
@@ -610,6 +612,7 @@ DEPENDENCIES
   faker
   faraday
   faraday-follow_redirects
+  foreman
   google-cloud-storage
   hexapdf
   image_processing
diff --git a/app/controllers/account_configs_controller.rb b/app/controllers/account_configs_controller.rb
index 02aee521..21c380a2 100644
--- a/app/controllers/account_configs_controller.rb
+++ b/app/controllers/account_configs_controller.rb
@@ -39,7 +39,7 @@ class AccountConfigsController < ApplicationController
   end
 
   def account_config_params
-    params.required(:account_config).permit!.tap do |attrs|
+    params.required(:account_config).permit(:key, :value, { value: {} }, { value: [] }).tap do |attrs|
       attrs[:value] = attrs[:value] == '1' if attrs[:value].in?(%w[1 0])
     end
   end
diff --git a/app/controllers/api/submitters_controller.rb b/app/controllers/api/submitters_controller.rb
index f85e2f60..1fd06d74 100644
--- a/app/controllers/api/submitters_controller.rb
+++ b/app/controllers/api/submitters_controller.rb
@@ -146,9 +146,15 @@ module Api
 
       if attrs[:completed]
         submitter.values = Submitters::SubmitValues.merge_default_values(submitter)
-        submitter.values = Submitters::SubmitValues.merge_formula_values(submitter)
         submitter.values = Submitters::SubmitValues.maybe_remove_condition_values(submitter)
 
+        formula_values = Submitters::SubmitValues.build_formula_values(submitter)
+
+        if formula_values.present?
+          submitter.values = submitter.values.merge(formula_values)
+          submitter.values = Submitters::SubmitValues.maybe_remove_condition_values(submitter)
+        end
+
         submitter.values = submitter.values.transform_values do |v|
           v == '{{date}}' ? Time.current.in_time_zone(submitter.account.timezone).to_date.to_s : v
         end
diff --git a/app/controllers/notifications_settings_controller.rb b/app/controllers/notifications_settings_controller.rb
index 57b030fc..f03f09c8 100644
--- a/app/controllers/notifications_settings_controller.rb
+++ b/app/controllers/notifications_settings_controller.rb
@@ -39,7 +39,7 @@ class NotificationsSettingsController < ApplicationController
   end
 
   def email_config_params
-    params.require(:account_config).permit!.tap do |attrs|
+    params.require(:account_config).permit(:key, :value, { value: {} }, { value: [] }).tap do |attrs|
       attrs[:key] = nil unless attrs[:key].in?([AccountConfig::BCC_EMAILS, AccountConfig::SUBMITTER_REMINDERS])
     end
   end
diff --git a/app/controllers/personalization_settings_controller.rb b/app/controllers/personalization_settings_controller.rb
index 76d3f886..9812aaee 100644
--- a/app/controllers/personalization_settings_controller.rb
+++ b/app/controllers/personalization_settings_controller.rb
@@ -50,7 +50,7 @@ class PersonalizationSettingsController < ApplicationController
   end
 
   def account_config_params
-    attrs = params.require(:account_config).permit!
+    attrs = params.require(:account_config).permit(:key, :value, { value: {} }, { value: [] })
 
     return attrs if attrs[:value].is_a?(String)
 
diff --git a/app/controllers/submissions_preview_controller.rb b/app/controllers/submissions_preview_controller.rb
index 1df14e21..7986e799 100644
--- a/app/controllers/submissions_preview_controller.rb
+++ b/app/controllers/submissions_preview_controller.rb
@@ -20,7 +20,7 @@ class SubmissionsPreviewController < ApplicationController
 
     @submission ||= Submission.find_by!(slug: params[:slug])
 
-    raise ActionController::RoutingError if @submission.account.archived_at?
+    raise ActionController::RoutingError, I18n.t('not_found') if @submission.account.archived_at?
 
     if !@submission.submitters.all?(&:completed_at?) && !signature_valid &&
        (!current_user || !current_ability.can?(:read, @submission))
diff --git a/app/controllers/user_configs_controller.rb b/app/controllers/user_configs_controller.rb
index 834cc1d9..09b7e6c5 100644
--- a/app/controllers/user_configs_controller.rb
+++ b/app/controllers/user_configs_controller.rb
@@ -26,7 +26,7 @@ class UserConfigsController < ApplicationController
   end
 
   def user_config_params
-    params.required(:user_config).permit!.tap do |attrs|
+    params.required(:user_config).permit(:key, :value, { value: {} }, { value: [] }).tap do |attrs|
       attrs[:value] = attrs[:value] == '1' if attrs[:value].in?(%w[1 0])
     end
   end
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 4a195104..47a88e05 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -45,17 +45,16 @@ class UsersController < ApplicationController
     return redirect_to settings_users_path, notice: I18n.t('unable_to_update_user') if Docuseal.demo?
 
     attrs = user_params.compact_blank.merge(user_params.slice(:archived_at))
-    attrs.delete(:role) if !role_valid?(attrs[:role]) || current_user == @user
 
     if params.dig(:user, :account_id).present?
-      account = Account.accessible_by(current_ability).find(params[:user][:account_id])
+      account = Account.accessible_by(current_ability).find(params.dig(:user, :account_id))
 
       authorize!(:manage, account)
 
       @user.account = account
     end
 
-    if @user.update(attrs)
+    if @user.update(attrs.except(current_user == @user ? :role : nil))
       redirect_back fallback_location: settings_users_path, notice: I18n.t('user_has_been_updated')
     else
       render turbo_stream: turbo_stream.replace(:modal, template: 'users/edit'), status: :unprocessable_entity
@@ -84,8 +83,11 @@ class UsersController < ApplicationController
 
   def user_params
     if params.key?(:user)
-      params.require(:user).permit(:email, :first_name, :last_name, :password,
-                                   :role, :archived_at, :account_id)
+      permitted_params = %i[email first_name last_name password archived_at]
+
+      permitted_params << :role if role_valid?(params.dig(:user, :role))
+
+      params.require(:user).permit(permitted_params)
     else
       {}
     end
diff --git a/app/javascript/submission_form/form.vue b/app/javascript/submission_form/form.vue
index b7d17e27..addf7570 100644
--- a/app/javascript/submission_form/form.vue
+++ b/app/javascript/submission_form/form.vue
@@ -1037,7 +1037,7 @@ export default {
       }, [])
     },
     formulaFields () {
-      return this.fields.filter((f) => f.preferences?.formula && f.type !== 'payment')
+      return this.fields.filter((f) => f.preferences?.formula && f.type !== 'payment' && this.checkFieldConditions(f) && this.checkFieldDocumentsConditions(f))
     },
     attachmentsIndex () {
       return this.attachments.reduce((acc, a) => {
diff --git a/app/models/submitter.rb b/app/models/submitter.rb
index 97a93773..45e38292 100644
--- a/app/models/submitter.rb
+++ b/app/models/submitter.rb
@@ -55,6 +55,7 @@ class Submitter < ApplicationRecord
   has_many_attached :attachments
   has_many_attached :preview_documents
   has_many :template_accesses, through: :template
+  has_many :email_events, as: :emailable, dependent: (Docuseal.multitenant? ? nil : :destroy)
 
   has_many :document_generation_events, dependent: :destroy
   has_many :submission_events, dependent: :destroy
@@ -63,6 +64,8 @@ class Submitter < ApplicationRecord
 
   scope :completed, -> { where.not(completed_at: nil) }
 
+  after_destroy :anonymize_email_events, if: -> { Docuseal.multitenant? }
+
   def status
     if declined_at?
       'declined'
@@ -108,4 +111,12 @@ class Submitter < ApplicationRecord
       fields.any? { |f| f['submitter_uuid'] == uuid && signature_field_types.include?(f['type']) }
     end
   end
+
+  private
+
+  def anonymize_email_events
+    email_events.each do |event|
+      event.update!(email: Digest::MD5.base64digest(event.email))
+    end
+  end
 end
diff --git a/app/views/templates_preferences/show.html.erb b/app/views/templates_preferences/show.html.erb
index 54532ad0..12c020b1 100644
--- a/app/views/templates_preferences/show.html.erb
+++ b/app/views/templates_preferences/show.html.erb
@@ -285,12 +285,12 @@
                 
                   <%= ff.text_field :name, class: 'w-full outline-none border-transparent focus:border-transparent focus:ring-0 bg-base-100 px-1 peer mb-2', autocomplete: 'off', placeholder: "#{index + 1}#{(index + 1).ordinal} Party", required: true %>
                   <% if @template.submitters.size == 2 %>
-                    <%= ff.email_field :email, class: 'base-input', autocomplete: 'off', placeholder: t('default_email'), disabled: ff.object.is_requester || ff.object.invite_by_uuid.present? || ff.object.optional_invite_by_uuid.present?, id: field_uuid = SecureRandom.uuid %>
+                    <%= tag.input name: ff.field_name(:email), value: ff.object.email, type: :email, class: 'base-input', multiple: true, autocomplete: 'off', placeholder: t('default_email'), disabled: ff.object.is_requester || ff.object.invite_by_uuid.present? || ff.object.optional_invite_by_uuid.present?, id: field_uuid = SecureRandom.uuid %>
                   <% else %>
                     
                       <%= ff.select :option, [[t('not_specified'), 'not_set'], [t('submission_requester'), 'is_requester'], [t('specified_email'), 'email'], *(@template.submitters - [submitter]).flat_map { |e| [[t('invite_by_name', name: e['name']), "invite_by_#{e['uuid']}"], [t('invite_by_name', name: e['name']) + " (#{t(:optional).capitalize})", "optional_invite_by_#{e['uuid']}"]] }, *(@template.submitters - [submitter]).map { |e| [t('same_as_name', name: e['name']), "linked_to_#{e['uuid']}"] }], {}, class: 'base-select mb-3' %>
                     
-                    <%= ff.email_field :email, class: "base-input #{'hidden' if item.option != 'email'}", autocomplete: 'off', placeholder: t('default_email'), id: email_field_uuid %>
+                    <%= tag.input name: ff.field_name(:email), type: :email, value: ff.object.email, multiple: true, class: "base-input #{'hidden' if item.option != 'email'}", autocomplete: 'off', placeholder: t('default_email'), id: email_field_uuid %>
                   <% end %>
                 
                 <% if @template.submitters.size == 2 %>
diff --git a/config/brakeman.ignore b/config/brakeman.ignore
new file mode 100644
index 00000000..0b0632ab
--- /dev/null
+++ b/config/brakeman.ignore
@@ -0,0 +1,8 @@
+{
+  "ignored_warnings": [
+    {
+      "fingerprint": "25f4ce5fee1e1180fa1919dc4ee78db3ab3457a956e4679503aa745771a43836",
+      "note": "Permitted parameters are necessary for creating submitters via API"
+    }
+  ]
+}
diff --git a/db/migrate/20250225111255_create_console1984_tables.console1984.rb b/db/migrate/20250225111255_create_console1984_tables.console1984.rb
new file mode 100644
index 00000000..fe6a454a
--- /dev/null
+++ b/db/migrate/20250225111255_create_console1984_tables.console1984.rb
@@ -0,0 +1,37 @@
+# frozen_string_literal: true
+
+class CreateConsole1984Tables < ActiveRecord::Migration[7.0]
+  def change
+    create_table :console1984_sessions do |t|
+      t.text :reason
+      t.references :user, null: false, index: false
+      t.timestamps
+
+      t.index :created_at
+      t.index %i[user_id created_at]
+    end
+
+    create_table :console1984_users do |t|
+      t.string :username, null: false
+      t.timestamps
+
+      t.index [:username]
+    end
+
+    create_table :console1984_commands do |t|
+      t.text :statements
+      t.references :sensitive_access
+      t.references :session, null: false, index: false
+      t.timestamps
+
+      t.index %i[session_id created_at sensitive_access_id], name: 'on_session_and_sensitive_chronologically'
+    end
+
+    create_table :console1984_sensitive_accesses do |t|
+      t.text :justification
+      t.references :session, null: false
+
+      t.timestamps
+    end
+  end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 89cf0fae..34aaa8bf 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
 #
 # It's strongly recommended that you check this file into your version control system.
 
-ActiveRecord::Schema[7.2].define(version: 2024_12_07_172237) do
+ActiveRecord::Schema[8.0].define(version: 2025_02_25_111255) do
   # These are extensions that must be enabled in order to support this database
   enable_extension "plpgsql"
 
@@ -112,6 +112,40 @@ ActiveRecord::Schema[7.2].define(version: 2024_12_07_172237) do
     t.index ["submitter_id"], name: "index_completed_submitters_on_submitter_id", unique: true
   end
 
+  create_table "console1984_commands", force: :cascade do |t|
+    t.text "statements"
+    t.bigint "sensitive_access_id"
+    t.bigint "session_id", null: false
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+    t.index ["sensitive_access_id"], name: "index_console1984_commands_on_sensitive_access_id"
+    t.index ["session_id", "created_at", "sensitive_access_id"], name: "on_session_and_sensitive_chronologically"
+  end
+
+  create_table "console1984_sensitive_accesses", force: :cascade do |t|
+    t.text "justification"
+    t.bigint "session_id", null: false
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+    t.index ["session_id"], name: "index_console1984_sensitive_accesses_on_session_id"
+  end
+
+  create_table "console1984_sessions", force: :cascade do |t|
+    t.text "reason"
+    t.bigint "user_id", null: false
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+    t.index ["created_at"], name: "index_console1984_sessions_on_created_at"
+    t.index ["user_id", "created_at"], name: "index_console1984_sessions_on_user_id_and_created_at"
+  end
+
+  create_table "console1984_users", force: :cascade do |t|
+    t.string "username", null: false
+    t.datetime "created_at", null: false
+    t.datetime "updated_at", null: false
+    t.index ["username"], name: "index_console1984_users_on_username"
+  end
+
   create_table "document_generation_events", force: :cascade do |t|
     t.bigint "submitter_id", null: false
     t.string "event_name", null: false
diff --git a/lib/download_utils.rb b/lib/download_utils.rb
index 3fc32950..78316b80 100644
--- a/lib/download_utils.rb
+++ b/lib/download_utils.rb
@@ -8,19 +8,20 @@ module DownloadUtils
   module_function
 
   def call(url)
-    uri = Addressable::URI.parse(url)
+    uri = begin
+      URI(url)
+    rescue URI::Error
+      Addressable::URI.parse(url).normalize
+    end
 
     if Docuseal.multitenant?
-      raise UnableToDownload, "Error loading: #{uri.display_uri}. Only HTTPS is allowed." if uri.scheme != 'https'
-
-      if uri.host.in?(LOCALHOSTS)
-        raise UnableToDownload, "Error loading: #{uri.display_uri}. Can't download from localhost."
-      end
+      raise UnableToDownload, "Error loading: #{uri}. Only HTTPS is allowed." if uri.scheme != 'https'
+      raise UnableToDownload, "Error loading: #{uri}. Can't download from localhost." if uri.host.in?(LOCALHOSTS)
     end
 
-    resp = conn.get(uri.display_uri.to_s)
+    resp = conn.get(uri)
 
-    raise UnableToDownload, "Error loading: #{uri.display_uri}" if resp.status >= 400
+    raise UnableToDownload, "Error loading: #{uri}" if resp.status >= 400
 
     resp
   end
diff --git a/lib/replace_email_variables.rb b/lib/replace_email_variables.rb
index 430b5757..a78cedf9 100644
--- a/lib/replace_email_variables.rb
+++ b/lib/replace_email_variables.rb
@@ -15,7 +15,10 @@ module ReplaceEmailVariables
   SUBMITTER_SLUG = /\{+submitter\.slug\}+/i
   SUBMISSION_LINK = /\{+submission\.link\}+/i
   SUBMISSION_ID = /\{+submission\.id\}+/i
-  SUBMISSION_SUBMITTERS = /\{+submission\.submitters\}+/i
+  SUBMITTERS = /\{+(?:submission\.)?submitters\}+/i
+  SUBMITTERS_N_EMAIL = /\{+submitters\[(?\d+)\]\.email\}+/i
+  SUBMITTERS_N_NAME = /\{+submitters\[(?\d+)\]\.name\}+/i
+  SUBMITTERS_N_FIRST_NAME = /\{+submitters\[(?\d+)\]\.first_name\}+/i
   DOCUMENTS_LINKS = /\{+documents\.links\}+/i
   DOCUMENTS_LINK = /\{+documents\.link\}+/i
 
@@ -37,13 +40,25 @@ module ReplaceEmailVariables
     text = replace(text, SUBMISSION_LINK, html_escape:) do
       submitter.submission ? build_submission_link(submitter.submission) : ''
     end
-    text = replace(text, SUBMISSION_SUBMITTERS, html_escape:) { build_submission_submitters(submitter.submission) }
+    text = replace(text, SUBMITTERS, html_escape:) { build_submission_submitters(submitter.submission) }
     text = replace(text, DOCUMENTS_LINKS, html_escape:) { build_documents_links_text(submitter, sig) }
     text = replace(text, DOCUMENTS_LINK, html_escape:) { build_documents_links_text(submitter, sig) }
     text = replace(text, ACCOUNT_NAME, html_escape:) { submitter.submission.account.name }
     text = replace(text, SENDER_NAME, html_escape:) { submitter.submission.created_by_user&.full_name }
     text = replace(text, SENDER_FIRST_NAME, html_escape:) { submitter.submission.created_by_user&.first_name }
 
+    text = replace(text, SUBMITTERS_N_NAME, html_escape:) do |match|
+      build_submitters_n_field(submitter.submission, match[:index].to_i - 1, :name)
+    end
+
+    text = replace(text, SUBMITTERS_N_EMAIL, html_escape:) do |match|
+      build_submitters_n_field(submitter.submission, match[:index].to_i - 1, :email)
+    end
+
+    text = replace(text, SUBMITTERS_N_FIRST_NAME, html_escape:) do |match|
+      build_submitters_n_field(submitter.submission, match[:index].to_i - 1, :first_name)
+    end
+
     replace(text, SENDER_EMAIL, html_escape:) { submitter.submission.created_by_user&.email.to_s.sub(/\+\w+@/, '@') }
   end
   # rubocop:enable Metrics
@@ -54,12 +69,18 @@ module ReplaceEmailVariables
     )
   end
 
+  def build_submitters_n_field(submission, index, field_name)
+    uuid = (submission.template_submitters || submission.template.submitters).dig(index, 'uuid')
+
+    submission.submitters.find { |s| s.uuid == uuid }.try(field_name)
+  end
+
   def replace(text, var, html_escape: false)
     text.gsub(var) do
       if html_escape
-        ERB::Util.html_escape(yield)
+        ERB::Util.html_escape(yield(Regexp.last_match))
       else
-        yield
+        yield(Regexp.last_match)
       end
     end
   end
diff --git a/lib/send_webhook_request.rb b/lib/send_webhook_request.rb
index d2e6ebf4..96442441 100644
--- a/lib/send_webhook_request.rb
+++ b/lib/send_webhook_request.rb
@@ -3,10 +3,28 @@
 module SendWebhookRequest
   USER_AGENT = 'DocuSeal.com Webhook'
 
+  LOCALHOSTS = %w[0.0.0.0 127.0.0.1 localhost].freeze
+
+  HttpsError = Class.new(StandardError)
+  LocalhostError = Class.new(StandardError)
+
   module_function
 
   def call(webhook_url, event_type:, data:)
-    Faraday.post(webhook_url.url) do |req|
+    uri = begin
+      URI(webhook_url.url)
+    rescue URI::Error
+      Addressable::URI.parse(webhook_url.url).normalize
+    end
+
+    if Docuseal.multitenant?
+      raise HttpsError, 'Only HTTPS is allowed.' if uri.scheme != 'https' &&
+                                                    !AccountConfig.exists?(key: :allow_http,
+                                                                           account_id: webhook_url.account_id)
+      raise LocalhostError, "Can't send to localhost." if uri.host.in?(LOCALHOSTS)
+    end
+
+    Faraday.post(uri) do |req|
       req.headers['Content-Type'] = 'application/json'
       req.headers['User-Agent'] = USER_AGENT
       req.headers.merge!(webhook_url.secret.to_h) if webhook_url.secret.present?
diff --git a/lib/submissions.rb b/lib/submissions.rb
index 8a89aaa6..9843fd0f 100644
--- a/lib/submissions.rb
+++ b/lib/submissions.rb
@@ -107,6 +107,7 @@ module Submissions
 
   def normalize_email(email)
     return if email.blank?
+    return if email.is_a?(Numeric)
 
     return email.downcase if email.to_s.include?(',') ||
                              email.to_s.match?(/\.(?:gob|om|mm|cm|et|mo|nz|za|ie)\z/) ||
diff --git a/lib/submissions/create_from_submitters.rb b/lib/submissions/create_from_submitters.rb
index c2144ad8..083c3573 100644
--- a/lib/submissions/create_from_submitters.rb
+++ b/lib/submissions/create_from_submitters.rb
@@ -225,9 +225,15 @@ module Submissions
 
     def assign_completed_attributes(submitter)
       submitter.values = Submitters::SubmitValues.merge_default_values(submitter)
-      submitter.values = Submitters::SubmitValues.merge_formula_values(submitter)
       submitter.values = Submitters::SubmitValues.maybe_remove_condition_values(submitter)
 
+      formula_values = Submitters::SubmitValues.build_formula_values(submitter)
+
+      if formula_values.present?
+        submitter.values = submitter.values.merge(formula_values)
+        submitter.values = Submitters::SubmitValues.maybe_remove_condition_values(submitter)
+      end
+
       submitter.values = submitter.values.transform_values do |v|
         v == '{{date}}' ? Time.current.in_time_zone(submitter.submission.account.timezone).to_date.to_s : v
       end
diff --git a/lib/submitters/submit_values.rb b/lib/submitters/submit_values.rb
index b23e7005..15f2da02 100644
--- a/lib/submitters/submit_values.rb
+++ b/lib/submitters/submit_values.rb
@@ -53,9 +53,17 @@ module Submitters
       submitter.completed_at = Time.current
       submitter.ip = request.remote_ip
       submitter.ua = request.user_agent
+
       submitter.values = merge_default_values(submitter)
       submitter.values = maybe_remove_condition_values(submitter)
-      submitter.values = merge_formula_values(submitter)
+
+      formula_values = build_formula_values(submitter)
+
+      if formula_values.present?
+        submitter.values = submitter.values.merge(formula_values)
+        submitter.values = maybe_remove_condition_values(submitter)
+      end
+
       submitter.values = submitter.values.transform_values do |v|
         v == '{{date}}' ? Time.current.in_time_zone(submitter.account.timezone).to_date.to_s : v
       end
@@ -149,7 +157,7 @@ module Submitters
       default_values.compact_blank.merge(submitter.values)
     end
 
-    def merge_formula_values(submitter)
+    def build_formula_values(submitter)
       computed_values = submitter.submission.template_fields.each_with_object({}) do |field, acc|
         next if field['submitter_uuid'] != submitter.uuid
         next if field['type'] == 'payment'
@@ -161,7 +169,7 @@ module Submitters
         acc[field['uuid']] = calculate_formula_value(formula, submitter.values.merge(acc.compact_blank))
       end
 
-      submitter.values.merge(computed_values.compact_blank)
+      computed_values.compact_blank
     end
 
     def calculate_formula_value(_formula, _values)
diff --git a/lib/tasks/annotate_rb.rake b/lib/tasks/annotate_rb.rake
new file mode 100644
index 00000000..e8368b2e
--- /dev/null
+++ b/lib/tasks/annotate_rb.rake
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+# This rake task was added by annotate_rb gem.
+
+# Can set `ANNOTATERB_SKIP_ON_DB_TASKS` to be anything to skip this
+if Rails.env.development? && ENV['ANNOTATERB_SKIP_ON_DB_TASKS'].nil?
+  require 'annotate_rb'
+
+  AnnotateRb::Core.load_rake_tasks
+end
diff --git a/lib/tasks/auto_annotate_models.rake b/lib/tasks/auto_annotate_models.rake
deleted file mode 100644
index d4cb5881..00000000
--- a/lib/tasks/auto_annotate_models.rake
+++ /dev/null
@@ -1,57 +0,0 @@
-# frozen_string_literal: true
-
-if Rails.env.development?
-  require 'annotate'
-
-  task set_annotation_options: :environment do
-    Annotate.set_defaults(
-      'active_admin' => 'false',
-      'additional_file_patterns' => [],
-      'routes' => 'false',
-      'models' => 'true',
-      'position_in_routes' => 'before',
-      'position_in_class' => 'before',
-      'position_in_test' => 'before',
-      'position_in_fixture' => 'before',
-      'position_in_factory' => 'before',
-      'position_in_serializer' => 'before',
-      'show_foreign_keys' => 'true',
-      'show_complete_foreign_keys' => 'false',
-      'show_indexes' => 'true',
-      'simple_indexes' => 'false',
-      'model_dir' => 'app/models',
-      'root_dir' => '',
-      'include_version' => 'false',
-      'require' => '',
-      'exclude_tests' => 'true',
-      'exclude_fixtures' => 'true',
-      'exclude_factories' => 'true',
-      'exclude_serializers' => 'false',
-      'exclude_scaffolds' => 'true',
-      'exclude_controllers' => 'true',
-      'exclude_helpers' => 'true',
-      'exclude_sti_subclasses' => 'false',
-      'ignore_model_sub_dir' => 'false',
-      'ignore_columns' => nil,
-      'ignore_routes' => nil,
-      'ignore_unknown_models' => 'false',
-      'hide_limit_column_types' => 'integer,bigint,boolean',
-      'hide_default_column_types' => 'json,jsonb,hstore',
-      'skip_on_db_migrate' => 'false',
-      'format_bare' => 'true',
-      'format_rdoc' => 'false',
-      'format_yard' => 'false',
-      'format_markdown' => 'false',
-      'sort' => 'false',
-      'force' => 'false',
-      'frozen' => 'false',
-      'classified_sort' => 'true',
-      'trace' => 'false',
-      'wrapper_open' => nil,
-      'wrapper_close' => nil,
-      'with_comment' => 'true'
-    )
-  end
-
-  Annotate.load_tasks
-end
diff --git a/lib/templates/clone.rb b/lib/templates/clone.rb
index 6210354d..2c15858f 100644
--- a/lib/templates/clone.rb
+++ b/lib/templates/clone.rb
@@ -9,7 +9,6 @@ module Templates
 
       template.external_id = external_id
       template.author = author
-      template.preferences = original_template.preferences.deep_dup
       template.name = name.presence || "#{original_template.name} (#{I18n.t('clone')})"
 
       if folder_name.present?
@@ -18,10 +17,11 @@ module Templates
         template.folder_id = original_template.folder_id
       end
 
-      template.submitters, template.fields, template.schema =
+      template.submitters, template.fields, template.schema, template.preferences =
         update_submitters_and_fields_and_schema(original_template.submitters.deep_dup,
                                                 original_template.fields.deep_dup,
-                                                original_template.schema.deep_dup)
+                                                original_template.schema.deep_dup,
+                                                original_template.preferences.deep_dup)
 
       if name.present? && template.schema.size == 1 &&
          original_template.schema.first['name'] == original_template.name &&
@@ -33,7 +33,7 @@ module Templates
     end
 
     # rubocop:disable Metrics, Style/CombinableLoops
-    def update_submitters_and_fields_and_schema(cloned_submitters, cloned_fields, cloned_schema)
+    def update_submitters_and_fields_and_schema(cloned_submitters, cloned_fields, cloned_schema, cloned_preferences)
       submitter_uuids_replacements = {}
       field_uuids_replacements = {}
 
@@ -58,6 +58,10 @@ module Templates
         end
       end
 
+      cloned_preferences['submitters'].to_a.each do |submitter|
+        submitter['uuid'] = submitter_uuids_replacements[submitter['uuid']]
+      end
+
       cloned_fields.each do |field|
         new_field_uuid = SecureRandom.uuid
 
@@ -88,7 +92,7 @@ module Templates
         end
       end
 
-      [cloned_submitters, cloned_fields, cloned_schema]
+      [cloned_submitters, cloned_fields, cloned_schema, cloned_preferences]
     end
     # rubocop:enable Metrics, Style/CombinableLoops
   end
diff --git a/lib/templates/find_acro_fields.rb b/lib/templates/find_acro_fields.rb
index 69bc462a..11c319c7 100644
--- a/lib/templates/find_acro_fields.rb
+++ b/lib/templates/find_acro_fields.rb
@@ -101,7 +101,7 @@ module Templates
 
         {
           uuid: SecureRandom.uuid,
-          required: false,
+          required: field.flags.include?(:required),
           preferences: {},
           areas:,
           **field_properties