From 8ae6afe395e0abfe344ee552b8615417a31c2b96 Mon Sep 17 00:00:00 2001 From: Stefanni Brasil Date: Thu, 18 Jun 2026 14:02:37 -0600 Subject: [PATCH 01/13] bundle update rails --- Gemfile | 2 +- Gemfile.lock | 121 ++++++++++++++++++++++++++------------------------- 2 files changed, 63 insertions(+), 60 deletions(-) diff --git a/Gemfile b/Gemfile index bbd8fef141..4692aeb653 100644 --- a/Gemfile +++ b/Gemfile @@ -3,7 +3,7 @@ source "https://rubygems.org" ruby "4.0.3" -gem "rails", "~> 8.0" +gem "rails", "~> 8.1" gem "after_party" # Post-deployment tasks gem "amazing_print" # Easier console reading diff --git a/Gemfile.lock b/Gemfile.lock index 9dc8e88f5d..8fb46adf4b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,29 +1,31 @@ GEM remote: https://rubygems.org/ specs: - actioncable (8.0.5) - actionpack (= 8.0.5) - activesupport (= 8.0.5) + action_text-trix (2.1.19) + railties + actioncable (8.1.3) + actionpack (= 8.1.3) + activesupport (= 8.1.3) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) - actionmailbox (8.0.5) - actionpack (= 8.0.5) - activejob (= 8.0.5) - activerecord (= 8.0.5) - activestorage (= 8.0.5) - activesupport (= 8.0.5) + actionmailbox (8.1.3) + actionpack (= 8.1.3) + activejob (= 8.1.3) + activerecord (= 8.1.3) + activestorage (= 8.1.3) + activesupport (= 8.1.3) mail (>= 2.8.0) - actionmailer (8.0.5) - actionpack (= 8.0.5) - actionview (= 8.0.5) - activejob (= 8.0.5) - activesupport (= 8.0.5) + actionmailer (8.1.3) + actionpack (= 8.1.3) + actionview (= 8.1.3) + activejob (= 8.1.3) + activesupport (= 8.1.3) mail (>= 2.8.0) rails-dom-testing (~> 2.2) - actionpack (8.0.5) - actionview (= 8.0.5) - activesupport (= 8.0.5) + actionpack (8.1.3) + actionview (= 8.1.3) + activesupport (= 8.1.3) nokogiri (>= 1.8.5) rack (>= 2.2.4) rack-session (>= 1.0.1) @@ -31,46 +33,47 @@ GEM rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) useragent (~> 0.16) - actiontext (8.0.5) - actionpack (= 8.0.5) - activerecord (= 8.0.5) - activestorage (= 8.0.5) - activesupport (= 8.0.5) + actiontext (8.1.3) + action_text-trix (~> 2.1.15) + actionpack (= 8.1.3) + activerecord (= 8.1.3) + activestorage (= 8.1.3) + activesupport (= 8.1.3) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (8.0.5) - activesupport (= 8.0.5) + actionview (8.1.3) + activesupport (= 8.1.3) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - activejob (8.0.5) - activesupport (= 8.0.5) + activejob (8.1.3) + activesupport (= 8.1.3) globalid (>= 0.3.6) - activemodel (8.0.5) - activesupport (= 8.0.5) + activemodel (8.1.3) + activesupport (= 8.1.3) activemodel-serializers-xml (1.0.3) activemodel (>= 5.0.0.a) activesupport (>= 5.0.0.a) builder (~> 3.1) - activerecord (8.0.5) - activemodel (= 8.0.5) - activesupport (= 8.0.5) + activerecord (8.1.3) + activemodel (= 8.1.3) + activesupport (= 8.1.3) timeout (>= 0.4.0) - activestorage (8.0.5) - actionpack (= 8.0.5) - activejob (= 8.0.5) - activerecord (= 8.0.5) - activesupport (= 8.0.5) + activestorage (8.1.3) + actionpack (= 8.1.3) + activejob (= 8.1.3) + activerecord (= 8.1.3) + activesupport (= 8.1.3) marcel (~> 1.0) - activesupport (8.0.5) + activesupport (8.1.3) base64 - benchmark (>= 0.3) bigdecimal concurrent-ruby (~> 1.0, >= 1.3.1) connection_pool (>= 2.2.5) drb i18n (>= 1.6, < 2) + json logger (>= 1.4.2) minitest (>= 5.1) securerandom (>= 0.3) @@ -463,20 +466,20 @@ GEM rack (>= 1.3) rackup (2.3.1) rack (>= 3) - rails (8.0.5) - actioncable (= 8.0.5) - actionmailbox (= 8.0.5) - actionmailer (= 8.0.5) - actionpack (= 8.0.5) - actiontext (= 8.0.5) - actionview (= 8.0.5) - activejob (= 8.0.5) - activemodel (= 8.0.5) - activerecord (= 8.0.5) - activestorage (= 8.0.5) - activesupport (= 8.0.5) + rails (8.1.3) + actioncable (= 8.1.3) + actionmailbox (= 8.1.3) + actionmailer (= 8.1.3) + actionpack (= 8.1.3) + actiontext (= 8.1.3) + actionview (= 8.1.3) + activejob (= 8.1.3) + activemodel (= 8.1.3) + activerecord (= 8.1.3) + activestorage (= 8.1.3) + activesupport (= 8.1.3) bundler (>= 1.15.0) - railties (= 8.0.5) + railties (= 8.1.3) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1) @@ -488,9 +491,9 @@ GEM rails-html-sanitizer (1.7.0) loofah (~> 2.25) nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) - railties (8.0.5) - actionpack (= 8.0.5) - activesupport (= 8.0.5) + railties (8.1.3) + actionpack (= 8.1.3) + activesupport (= 8.1.3) irb (~> 1.13) rackup (>= 1.0.0) rake (>= 12.2) @@ -541,9 +544,9 @@ GEM json-schema (>= 2.2, < 7.0) railties (>= 5.2, < 8.2) rspec-core (>= 2.14) - rswag-ui (2.16.0) - actionpack (>= 5.2, < 8.1) - railties (>= 5.2, < 8.1) + rswag-ui (2.17.0) + actionpack (>= 5.2, < 8.2) + railties (>= 5.2, < 8.2) rubocop (1.84.2) json (~> 2.3) language_server-protocol (~> 3.17.0.2) @@ -690,7 +693,7 @@ GEM crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) websocket (1.2.11) - websocket-driver (0.8.0) + websocket-driver (0.8.1) base64 websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) @@ -767,7 +770,7 @@ DEPENDENCIES pundit rack-attack rack-cors - rails (~> 8.0) + rails (~> 8.1) rails-controller-testing request_store rexml From e1b7e262c66aa6b9de4f83ec42fb09c999419d98 Mon Sep 17 00:00:00 2001 From: Stefanni Brasil Date: Thu, 18 Jun 2026 14:11:52 -0600 Subject: [PATCH 02/13] reviewed files we want to keep --- bin/bundler-audit | 6 ++ config/bundler-audit.yml | 5 ++ config/environments/development.rb | 3 + .../initializers/content_security_policy.rb | 4 + config/initializers/inflections.rb | 2 +- .../new_framework_defaults_8_1.rb | 74 +++++++++++++++++++ config/puma.rb | 5 +- 7 files changed, 96 insertions(+), 3 deletions(-) create mode 100755 bin/bundler-audit create mode 100644 config/bundler-audit.yml create mode 100644 config/initializers/new_framework_defaults_8_1.rb diff --git a/bin/bundler-audit b/bin/bundler-audit new file mode 100755 index 0000000000..e2ef22690c --- /dev/null +++ b/bin/bundler-audit @@ -0,0 +1,6 @@ +#!/usr/bin/env ruby +require_relative "../config/boot" +require "bundler/audit/cli" + +ARGV.concat %w[ --config config/bundler-audit.yml ] if ARGV.empty? || ARGV.include?("check") +Bundler::Audit::CLI.start diff --git a/config/bundler-audit.yml b/config/bundler-audit.yml new file mode 100644 index 0000000000..e74b3af949 --- /dev/null +++ b/config/bundler-audit.yml @@ -0,0 +1,5 @@ +# Audit all gems listed in the Gemfile for known security problems by running bin/bundler-audit. +# CVEs that are not relevant to the application can be enumerated on the ignore list below. + +ignore: + - CVE-THAT-DOES-NOT-APPLY diff --git a/config/environments/development.rb b/config/environments/development.rb index 493e6fc73c..ac7c230e0a 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -77,6 +77,9 @@ config.action_controller.forgery_protection_origin_check = false end + # Uncomment if you wish to allow Action Cable access from any origin. + # config.action_cable.disable_request_forgery_protection = true + # Raise error when a before_action's only/except options reference missing actions. config.action_controller.raise_on_missing_callback_actions = false diff --git a/config/initializers/content_security_policy.rb b/config/initializers/content_security_policy.rb index b3076b38fe..d51d713979 100644 --- a/config/initializers/content_security_policy.rb +++ b/config/initializers/content_security_policy.rb @@ -20,6 +20,10 @@ # config.content_security_policy_nonce_generator = ->(request) { request.session.id.to_s } # config.content_security_policy_nonce_directives = %w(script-src style-src) # +# # Automatically add `nonce` to `javascript_tag`, `javascript_include_tag`, and `stylesheet_link_tag` +# # if the corresponding directives are specified in `content_security_policy_nonce_directives`. +# # config.content_security_policy_nonce_auto = true +# # # Report violations without enforcing the policy. # # config.content_security_policy_report_only = true # end diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb index e2fdd60539..0ce5929819 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -15,5 +15,5 @@ # inflect.acronym "RESTful" # end ActiveSupport::Inflector.inflections(:en) do |inflect| - inflect.acronym "DSS" # TODO what is this for? + inflect.acronym "DSS" end diff --git a/config/initializers/new_framework_defaults_8_1.rb b/config/initializers/new_framework_defaults_8_1.rb new file mode 100644 index 0000000000..5cc706343c --- /dev/null +++ b/config/initializers/new_framework_defaults_8_1.rb @@ -0,0 +1,74 @@ +# Be sure to restart your server when you modify this file. +# +# This file eases your Rails 8.1 framework defaults upgrade. +# +# Uncomment each configuration one by one to switch to the new default. +# Once your application is ready to run with all new defaults, you can remove +# this file and set the `config.load_defaults` to `8.1`. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. +# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html + +### +# Skips escaping HTML entities and line separators. When set to `false`, the +# JSON renderer no longer escapes these to improve performance. +# +# Example: +# class PostsController < ApplicationController +# def index +# render json: { key: "\u2028\u2029<>&" } +# end +# end +# +# Renders `{"key":"\u2028\u2029\u003c\u003e\u0026"}` with the previous default, but `{"key":"

<>&"}` with the config +# set to `false`. +# +# Applications that want to keep the escaping behavior can set the config to `true`. +#++ +Rails.configuration.action_controller.escape_json_responses = false + +### +# Skips escaping LINE SEPARATOR (U+2028) and PARAGRAPH SEPARATOR (U+2029) in JSON. +# +# Historically these characters were not valid inside JavaScript literal strings but that changed in ECMAScript 2019. +# As such it's no longer a concern in modern browsers: https://caniuse.com/mdn-javascript_builtins_json_json_superset. +#++ +Rails.configuration.active_support.escape_js_separators_in_json = false + +### +# Raises an error when order dependent finder methods (e.g. `#first`, `#second`) are called without `order` values +# on the relation, and the model does not have any order columns (`implicit_order_column`, `query_constraints`, or +# `primary_key`) to fall back on. +# +# The current behavior of not raising an error has been deprecated, and this configuration option will be removed in +# Rails 8.2. +#++ +Rails.configuration.active_record.raise_on_missing_required_finder_order_columns = true + +### +# Controls how Rails handles path relative URL redirects. +# When set to `:raise`, Rails will raise an `ActionController::Redirecting::UnsafeRedirectError` +# for relative URLs without a leading slash, which can help prevent open redirect vulnerabilities. +# +# Example: +# redirect_to "example.com" # Raises UnsafeRedirectError +# redirect_to "@attacker.com" # Raises UnsafeRedirectError +# redirect_to "/safe/path" # Works correctly +# +# Applications that want to allow these redirects can set the config to `:log` (previous default) +# to only log warnings, or `:notify` to send ActiveSupport notifications. +#++ +Rails.configuration.action_controller.action_on_path_relative_redirect = :raise + +### +# Use a Ruby parser to track dependencies between Action View templates +#++ +Rails.configuration.action_view.render_tracker = :ruby + +### +# When enabled, hidden inputs generated by `form_tag`, `token_tag`, `method_tag`, and the hidden parameter fields +# included in `button_to` forms will omit the `autocomplete="off"` attribute. +# +# Applications that want to keep generating the `autocomplete` attribute for those tags can set it to `false`. +#++ +Rails.configuration.action_view.remove_hidden_field_autocomplete = true diff --git a/config/puma.rb b/config/puma.rb index a248513b24..38c4b86596 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -7,7 +7,8 @@ # # You can control the number of workers using ENV["WEB_CONCURRENCY"]. You # should only set this value when you want to run 2 or more workers. The -# default is already 1. +# default is already 1. You can set it to `auto` to automatically start a worker +# for each available processor. # # The ideal number of threads per worker depends both on how much time the # application spends waiting for IO operations and on how much you wish to @@ -33,7 +34,7 @@ # Allow puma to be restarted by `bin/rails restart` command. plugin :tmp_restart -# Run the Solid Queue supervisor inside of Puma for single-server deployments +# Run the Solid Queue supervisor inside of Puma for single-server deployments. plugin :solid_queue if ENV["SOLID_QUEUE_IN_PUMA"] # Specify the PID file. Defaults to tmp/pids/server.pid in development. From cb20c14ec521f1bded62789403b6a452507de0f6 Mon Sep 17 00:00:00 2001 From: Stefanni Brasil Date: Thu, 18 Jun 2026 14:12:08 -0600 Subject: [PATCH 03/13] commit all to view changes in the browser, easier to compare --- config/environments/development.rb | 41 +++++++------------ config/environments/production.rb | 63 +++++++++++++----------------- config/environments/test.rb | 36 +++++------------ 3 files changed, 51 insertions(+), 89 deletions(-) diff --git a/config/environments/development.rb b/config/environments/development.rb index ac7c230e0a..885961f81a 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -20,33 +20,29 @@ if Rails.root.join("tmp/caching-dev.txt").exist? config.action_controller.perform_caching = true config.action_controller.enable_fragment_cache_logging = true - config.cache_store = :memory_store - config.public_file_server.headers = {"cache-control" => "public, max-age=#{2.days.to_i}"} + config.public_file_server.headers = { "cache-control" => "public, max-age=#{2.days.to_i}" } else config.action_controller.perform_caching = false - config.cache_store = :null_store end + # Change to :null_store to avoid any caching. + config.cache_store = :memory_store + # Store uploaded files on the local file system (see config/storage.yml for options). config.active_storage.service = :local # Don't care if the mailer can't send. - config.action_mailer.default_url_options = {host: "localhost", port: 3000} # Set localhost to be used by links generated in mailer templates. - config.action_mailer.delivery_method = :letter_opener - config.action_mailer.perform_deliveries = true + config.action_mailer.raise_delivery_errors = false + # Make template changes take effect immediately. config.action_mailer.perform_caching = false - config.action_mailer.raise_delivery_errors = false + + # Set localhost to be used by links generated in mailer templates. + config.action_mailer.default_url_options = { host: "localhost", port: 3000 } # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log - # Raise exceptions for disallowed deprecations. - config.active_support.disallowed_deprecation = :raise - - # Tell Active Support which deprecation messages to disallow. - config.active_support.disallowed_deprecation_warnings = [] - # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load @@ -59,29 +55,20 @@ # Highlight code that enqueued background job in logs. config.active_job.verbose_enqueue_logs = true - # Suppress logger output for asset requests. - config.assets.quiet = true - config.assets.digest = false + # Highlight code that triggered redirect in logs. + config.action_dispatch.verbose_redirect_logs = true - # Prosopite N+1 query detection - config.prosopite_enabled = true - config.prosopite_min_n_queries = 5 # More lenient for development + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true # Annotate rendered view with file names. config.action_view.annotate_rendered_view_with_filenames = true - config.hosts << ENV["DEV_HOSTS"] - config.hosts << ".app.github.dev" - - if ENV["CODESPACES"] === "true" - config.action_controller.forgery_protection_origin_check = false - end - # Uncomment if you wish to allow Action Cable access from any origin. # config.action_cable.disable_request_forgery_protection = true # Raise error when a before_action's only/except options reference missing actions. - config.action_controller.raise_on_missing_callback_actions = false + config.action_controller.raise_on_missing_callback_actions = true # Apply autocorrection by RuboCop to files generated by `bin/rails generate`. # config.generators.apply_rubocop_autocorrect_after_generate! diff --git a/config/environments/production.rb b/config/environments/production.rb index f7d6140383..887af96a7e 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,25 +1,8 @@ +require "active_support/core_ext/integer/time" + Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. - # Set host to be used by links generated in mailer templates. - config.action_mailer.default_url_options = {host: ENV["DOMAIN"]} - # Ignore bad email addresses and do not raise email delivery errors. - # Set this to true and configure the email server for immediate delivery to raise delivery errors. - config.action_mailer.raise_delivery_errors = true - config.action_mailer.show_previews = ENV["APP_ENVIRONMENT"] != "production" - # Do not send emails in staging or qa - config.action_mailer.perform_deliveries = ENV["APP_ENVIRONMENT"] == "production" - config.action_mailer.delivery_method = :smtp - # Specify outgoing SMTP server. - config.action_mailer.smtp_settings = { - address: "smtp-relay.sendinblue.com", - port: 587, - user_name: ENV["SENDINBLUE_EMAIL"], - password: ENV["SENDINBLUE_PASSWORD"], - authentication: "login", - enable_starttls_auto: true - } - # Code is not reloaded between requests. config.enable_reloading = false @@ -32,12 +15,8 @@ # Turn on fragment caching in view templates. config.action_controller.perform_caching = true - # Ensures that a master key has been made available in ENV["RAILS_MASTER_KEY"], config/master.key, or an environment - # key such as config/credentials/production.key. This key is used to decrypt credentials (and other encrypted files). - config.require_master_key = true - - # Enable static file serving from the `/public` folder (turn off if using NGINX/Apache for it). - config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? + # Cache assets for far-future expiry since they are all digest stamped. + config.public_file_server.headers = { "cache-control" => "public, max-age=#{1.year.to_i}" } # Enable serving of images, stylesheets, and JavaScripts from an asset server. # config.asset_host = "http://assets.example.com" @@ -46,19 +25,22 @@ config.assets.compile = false # Store uploaded files on the local file system (see config/storage.yml for options). - config.active_storage.service = :microsoft + config.active_storage.service = :local + + # Assume all access to the app is happening through a SSL-terminating reverse proxy. + # config.assume_ssl = true # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. - config.force_ssl = true + # config.force_ssl = true # Skip http-to-https redirect for the default health check endpoint. # config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } } # Log to STDOUT with the current request id as a default log tag. - config.log_tags = [:request_id] - config.logger = ActiveSupport::TaggedLogging.logger($stdout) + config.log_tags = [ :request_id ] + config.logger = ActiveSupport::TaggedLogging.logger(STDOUT) - # Change to "debug" to log everything (including potentially personally-identifiable information!) + # Change to "debug" to log everything (including potentially personally-identifiable information!). config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info") # Prevent health checks from clogging up the logs. @@ -73,10 +55,21 @@ # Replace the default in-process and non-durable queuing backend for Active Job. # config.active_job.queue_adapter = :resque - # Use a real queuing backend for Active Job (and separate queues per environment). - config.active_job.queue_adapter = :delayed_job + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + # config.action_mailer.raise_delivery_errors = false + + # Set host to be used by links generated in mailer templates. + config.action_mailer.default_url_options = { host: "example.com" } - config.action_mailer.perform_caching = false + # Specify outgoing SMTP server. Remember to add smtp/* credentials via bin/rails credentials:edit. + # config.action_mailer.smtp_settings = { + # user_name: Rails.application.credentials.dig(:smtp, :user_name), + # password: Rails.application.credentials.dig(:smtp, :password), + # address: "smtp.example.com", + # port: 587, + # authentication: :plain + # } # Enable locale fallbacks for I18n (makes lookups for any locale fall back to # the I18n.default_locale when a translation cannot be found). @@ -85,8 +78,8 @@ # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false - # Inspect all attributes in production. New default is :id. - config.active_record.attributes_for_inspect = [:all] + # Only use :id for inspections in production. + config.active_record.attributes_for_inspect = [ :id ] # Enable DNS rebinding protection and other `Host` header attacks. # config.hosts = [ diff --git a/config/environments/test.rb b/config/environments/test.rb index 1b61cc7031..c2095b1174 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -7,9 +7,7 @@ # Settings specified here will take precedence over those in config/application.rb. # While tests run files are not watched, reloading is not necessary. - config.enable_reloading = ENV["CI"].blank? - - config.action_view.cache_template_loading = true + config.enable_reloading = false # Eager loading loads your entire application. When running a single test locally, # this is usually not necessary, and can slow down your test suite. However, it's @@ -18,15 +16,11 @@ config.eager_load = ENV["CI"].present? # Configure public file server for tests with cache-control for performance. - config.public_file_server.enabled = true - config.public_file_server.headers = { - "Cache-Control" => "public, max-age=#{1.hour.to_i}" - } + config.public_file_server.headers = { "cache-control" => "public, max-age=3600" } # Show full error reports. config.consider_all_requests_local = true - - config.action_controller.perform_caching = false + config.cache_store = :null_store # Render exception templates for rescuable exceptions and raise for other exceptions. config.action_dispatch.show_exceptions = :rescuable @@ -37,35 +31,23 @@ # Store uploaded files on the local file system in a temporary directory. config.active_storage.service = :test - config.action_mailer.perform_caching = false - # Tell Action Mailer not to deliver emails to the real world. # The :test delivery method accumulates sent emails in the # ActionMailer::Base.deliveries array. config.action_mailer.delivery_method = :test # Set host to be used by links generated in mailer templates. - config.action_mailer.default_url_options = {host: "localhost", port: 3000} + config.action_mailer.default_url_options = { host: "example.com" } # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr - # Rack Attack configuration - # Set IP_BLOCKLIST for testing. Can't stub in spec since environment variable - # gets read during application initialization. - ENV["IP_BLOCKLIST"] = "4.5.6.7, 9.8.7.6,100.101.102.103" - - # Raise exceptions for disallowed deprecations. - config.active_support.disallowed_deprecation = :raise - - # Tell Active Support which deprecation messages to disallow. - config.active_support.disallowed_deprecation_warnings = [] - # Raises error for missing translations. - config.i18n.raise_on_missing_translations = true + # config.i18n.raise_on_missing_translations = true - # Raise error when a before_action's only/except options reference missing actions. - config.action_controller.raise_on_missing_callback_actions = false + # Annotate rendered view with file names. + # config.action_view.annotate_rendered_view_with_filenames = true - config.secret_key_base = ENV["SECRET_KEY_BASE"] || "dummy_test_secret_key" + # Raise error when a before_action's only/except options reference missing actions. + config.action_controller.raise_on_missing_callback_actions = true end From 370ac0fc65b290790bad190548da6f63851330b6 Mon Sep 17 00:00:00 2001 From: Stefanni Brasil Date: Thu, 18 Jun 2026 14:24:54 -0600 Subject: [PATCH 04/13] keep previous config --- config/environments/development.rb | 39 +++++++++++++++++----- config/environments/production.rb | 52 ++++++++++++++++++++---------- config/environments/test.rb | 38 ++++++++++++++++++---- 3 files changed, 97 insertions(+), 32 deletions(-) diff --git a/config/environments/development.rb b/config/environments/development.rb index 885961f81a..d4fc67b336 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -20,29 +20,34 @@ if Rails.root.join("tmp/caching-dev.txt").exist? config.action_controller.perform_caching = true config.action_controller.enable_fragment_cache_logging = true + config.cache_store = :memory_store config.public_file_server.headers = { "cache-control" => "public, max-age=#{2.days.to_i}" } else config.action_controller.perform_caching = false + config.cache_store = :null_store end - # Change to :null_store to avoid any caching. - config.cache_store = :memory_store - # Store uploaded files on the local file system (see config/storage.yml for options). config.active_storage.service = :local # Don't care if the mailer can't send. config.action_mailer.raise_delivery_errors = false + config.action_mailer.default_url_options = {host: "localhost", port: 3000} # Set localhost to be used by links generated in mailer templates. + config.action_mailer.delivery_method = :letter_opener + config.action_mailer.perform_deliveries = true # Make template changes take effect immediately. config.action_mailer.perform_caching = false - # Set localhost to be used by links generated in mailer templates. - config.action_mailer.default_url_options = { host: "localhost", port: 3000 } - # Print deprecation notices to the Rails logger. config.active_support.deprecation = :log + # Raise exceptions for disallowed deprecations. + config.active_support.disallowed_deprecation = :raise + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] + # Raise an error on page load if there are pending migrations. config.active_record.migration_error = :page_load @@ -59,16 +64,34 @@ config.action_dispatch.verbose_redirect_logs = true # Raises error for missing translations. - # config.i18n.raise_on_missing_translations = true + config.i18n.raise_on_missing_translations = true + + # Suppress logger output for asset requests. + config.assets.quiet = true + config.assets.digest = false # Annotate rendered view with file names. config.action_view.annotate_rendered_view_with_filenames = true + # Prosopite N+1 query detection + config.prosopite_enabled = true + config.prosopite_min_n_queries = 5 # More lenient for development + # Uncomment if you wish to allow Action Cable access from any origin. # config.action_cable.disable_request_forgery_protection = true # Raise error when a before_action's only/except options reference missing actions. - config.action_controller.raise_on_missing_callback_actions = true + config.action_controller.raise_on_missing_callback_actions = false + + # Uncomment if you wish to allow Action Cable access from any origin. + # config.action_cable.disable_request_forgery_protection = true + + config.hosts << ENV["DEV_HOSTS"] + config.hosts << ".app.github.dev" + + if ENV["CODESPACES"] === "true" + config.action_controller.forgery_protection_origin_check = false + end # Apply autocorrection by RuboCop to files generated by `bin/rails generate`. # config.generators.apply_rubocop_autocorrect_after_generate! diff --git a/config/environments/production.rb b/config/environments/production.rb index 887af96a7e..9c3c2e3ad9 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -3,6 +3,25 @@ Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. + # Set host to be used by links generated in mailer templates. + config.action_mailer.default_url_options = {host: ENV["DOMAIN"]} + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + config.action_mailer.raise_delivery_errors = true + config.action_mailer.show_previews = ENV["APP_ENVIRONMENT"] != "production" + # Do not send emails in staging or qa + config.action_mailer.perform_deliveries = ENV["APP_ENVIRONMENT"] == "production" + config.action_mailer.delivery_method = :smtp + # Specify outgoing SMTP server. + config.action_mailer.smtp_settings = { + address: "smtp-relay.sendinblue.com", + port: 587, + user_name: ENV["SENDINBLUE_EMAIL"], + password: ENV["SENDINBLUE_PASSWORD"], + authentication: "login", + enable_starttls_auto: true + } + # Code is not reloaded between requests. config.enable_reloading = false @@ -15,6 +34,13 @@ # Turn on fragment caching in view templates. config.action_controller.perform_caching = true + # Ensures that a master key has been made available in ENV["RAILS_MASTER_KEY"], config/master.key, or an environment + # key such as config/credentials/production.key. This key is used to decrypt credentials (and other encrypted files). + config.require_master_key = true + + # Enable static file serving from the `/public` folder (turn off if using NGINX/Apache for it). + config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? + # Cache assets for far-future expiry since they are all digest stamped. config.public_file_server.headers = { "cache-control" => "public, max-age=#{1.year.to_i}" } @@ -25,20 +51,20 @@ config.assets.compile = false # Store uploaded files on the local file system (see config/storage.yml for options). - config.active_storage.service = :local + config.active_storage.service = :microsoft # Assume all access to the app is happening through a SSL-terminating reverse proxy. # config.assume_ssl = true # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. - # config.force_ssl = true + config.force_ssl = true # Skip http-to-https redirect for the default health check endpoint. # config.ssl_options = { redirect: { exclude: ->(request) { request.path == "/up" } } } # Log to STDOUT with the current request id as a default log tag. - config.log_tags = [ :request_id ] - config.logger = ActiveSupport::TaggedLogging.logger(STDOUT) + config.log_tags = [:request_id] + config.logger = ActiveSupport::TaggedLogging.logger($stdout) # Change to "debug" to log everything (including potentially personally-identifiable information!). config.log_level = ENV.fetch("RAILS_LOG_LEVEL", "info") @@ -59,17 +85,9 @@ # Set this to true and configure the email server for immediate delivery to raise delivery errors. # config.action_mailer.raise_delivery_errors = false - # Set host to be used by links generated in mailer templates. - config.action_mailer.default_url_options = { host: "example.com" } - - # Specify outgoing SMTP server. Remember to add smtp/* credentials via bin/rails credentials:edit. - # config.action_mailer.smtp_settings = { - # user_name: Rails.application.credentials.dig(:smtp, :user_name), - # password: Rails.application.credentials.dig(:smtp, :password), - # address: "smtp.example.com", - # port: 587, - # authentication: :plain - # } + # Ignore bad email addresses and do not raise email delivery errors. + # Set this to true and configure the email server for immediate delivery to raise delivery errors. + # config.action_mailer.raise_delivery_errors = false # Enable locale fallbacks for I18n (makes lookups for any locale fall back to # the I18n.default_locale when a translation cannot be found). @@ -78,8 +96,8 @@ # Do not dump schema after migrations. config.active_record.dump_schema_after_migration = false - # Only use :id for inspections in production. - config.active_record.attributes_for_inspect = [ :id ] + # Inspect all attributes in production. New default is :id. + config.active_record.attributes_for_inspect = [:all] # Enable DNS rebinding protection and other `Host` header attacks. # config.hosts = [ diff --git a/config/environments/test.rb b/config/environments/test.rb index c2095b1174..ed97c38a6e 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -6,8 +6,8 @@ Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. - # While tests run files are not watched, reloading is not necessary. - config.enable_reloading = false + config.enable_reloading = ENV["CI"].blank? + config.action_view.cache_template_loading = true # Eager loading loads your entire application. When running a single test locally, # this is usually not necessary, and can slow down your test suite. However, it's @@ -16,12 +16,17 @@ config.eager_load = ENV["CI"].present? # Configure public file server for tests with cache-control for performance. - config.public_file_server.headers = { "cache-control" => "public, max-age=3600" } + config.public_file_server.enabled = true + config.public_file_server.headers = { + "Cache-Control" => "public, max-age=#{1.hour.to_i}" + } # Show full error reports. config.consider_all_requests_local = true config.cache_store = :null_store + config.action_controller.perform_caching = false + # Render exception templates for rescuable exceptions and raise for other exceptions. config.action_dispatch.show_exceptions = :rescuable @@ -31,23 +36,42 @@ # Store uploaded files on the local file system in a temporary directory. config.active_storage.service = :test + config.action_mailer.perform_caching = false + # Tell Action Mailer not to deliver emails to the real world. # The :test delivery method accumulates sent emails in the # ActionMailer::Base.deliveries array. config.action_mailer.delivery_method = :test # Set host to be used by links generated in mailer templates. - config.action_mailer.default_url_options = { host: "example.com" } + config.action_mailer.default_url_options = {host: "localhost", port: 3000} # Print deprecation notices to the stderr. config.active_support.deprecation = :stderr + # Rack Attack configuration + # Set IP_BLOCKLIST for testing. Can't stub in spec since environment variable + # gets read during application initialization. + ENV["IP_BLOCKLIST"] = "4.5.6.7, 9.8.7.6,100.101.102.103" + + # Raise exceptions for disallowed deprecations. + config.active_support.disallowed_deprecation = :raise + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] + # Raises error for missing translations. - # config.i18n.raise_on_missing_translations = true + config.i18n.raise_on_missing_translations = true + + # Raise error when a before_action's only/except options reference missing actions. + + config.action_controller.raise_on_missing_callback_actions = true # Annotate rendered view with file names. - # config.action_view.annotate_rendered_view_with_filenames = true + config.action_view.annotate_rendered_view_with_filenames = true # Raise error when a before_action's only/except options reference missing actions. - config.action_controller.raise_on_missing_callback_actions = true + config.action_controller.raise_on_missing_callback_actions = false + + config.secret_key_base = ENV["SECRET_KEY_BASE"] || "dummy_test_secret_key" end From 23281c8b7c049b3fd1f57b5a4c08fcd63abda2c8 Mon Sep 17 00:00:00 2001 From: Stefanni Brasil Date: Thu, 18 Jun 2026 14:28:44 -0600 Subject: [PATCH 05/13] Rails 8: schema update (no functional change, reorder columns alphabetically) --- db/schema.rb | 406 +++++++++++++++++++++++++-------------------------- 1 file changed, 203 insertions(+), 203 deletions(-) diff --git a/db/schema.rb b/db/schema.rb index 1af5b4dbd0..bcfba65765 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,38 +10,38 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[8.0].define(version: 2026_07_21_120000) do +ActiveRecord::Schema[8.1].define(version: 2026_07_21_120000) do # These are extensions that must be enabled in order to support this database enable_extension "pg_catalog.plpgsql" create_table "action_text_rich_texts", force: :cascade do |t| - t.string "name", null: false t.text "body" - t.string "record_type", null: false - t.bigint "record_id", null: false t.datetime "created_at", null: false + t.string "name", null: false + t.bigint "record_id", null: false + t.string "record_type", null: false t.datetime "updated_at", null: false t.index ["record_type", "record_id", "name"], name: "index_action_text_rich_texts_uniqueness", unique: true end create_table "active_storage_attachments", force: :cascade do |t| - t.string "name", null: false - t.string "record_type", null: false - t.bigint "record_id", null: false t.bigint "blob_id", null: false t.datetime "created_at", precision: nil, null: false + t.string "name", null: false + t.bigint "record_id", null: false + t.string "record_type", null: false t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true end create_table "active_storage_blobs", force: :cascade do |t| - t.string "key", null: false - t.string "filename", null: false - t.string "content_type" - t.text "metadata" t.bigint "byte_size", null: false t.string "checksum" + t.string "content_type" t.datetime "created_at", precision: nil, null: false + t.string "filename", null: false + t.string "key", null: false + t.text "metadata" t.string "service_name", null: false t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true end @@ -54,18 +54,18 @@ create_table "additional_expenses", force: :cascade do |t| t.bigint "case_contact_id", null: false + t.datetime "created_at", null: false t.decimal "other_expense_amount" t.string "other_expenses_describe" - t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["case_contact_id"], name: "index_additional_expenses_on_case_contact_id" end create_table "addresses", force: :cascade do |t| t.string "content" - t.bigint "user_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.bigint "user_id", null: false t.string "line_1" t.string "line_2" t.string "city" @@ -75,49 +75,49 @@ end create_table "all_casa_admins", force: :cascade do |t| + t.datetime "created_at", null: false t.string "email", default: "", null: false t.string "encrypted_password", default: "", null: false - t.string "reset_password_token" - t.datetime "reset_password_sent_at", precision: nil - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.string "invitation_token" - t.datetime "invitation_created_at", precision: nil - t.datetime "invitation_sent_at", precision: nil t.datetime "invitation_accepted_at", precision: nil + t.datetime "invitation_created_at", precision: nil t.integer "invitation_limit" + t.datetime "invitation_sent_at", precision: nil + t.string "invitation_token" t.integer "invited_by_id" t.string "invited_by_type" + t.datetime "reset_password_sent_at", precision: nil + t.string "reset_password_token" + t.datetime "updated_at", null: false t.index ["email"], name: "index_all_casa_admins_on_email", unique: true t.index ["invitation_token"], name: "index_all_casa_admins_on_invitation_token", unique: true t.index ["reset_password_token"], name: "index_all_casa_admins_on_reset_password_token", unique: true end create_table "api_credentials", force: :cascade do |t| - t.bigint "user_id", null: false - t.datetime "token_expires_at", default: -> { "(now() + 'PT7H'::interval)" } - t.datetime "refresh_token_expires_at", default: -> { "(now() + 'P30D'::interval)" } t.string "api_token_digest" - t.string "refresh_token_digest" t.datetime "created_at", null: false + t.string "refresh_token_digest" + t.datetime "refresh_token_expires_at", default: -> { "(now() + 'P30D'::interval)" } + t.datetime "token_expires_at", default: -> { "(now() + 'PT7H'::interval)" } t.datetime "updated_at", null: false + t.bigint "user_id", null: false t.index ["api_token_digest"], name: "index_api_credentials_on_api_token_digest", unique: true, where: "(api_token_digest IS NOT NULL)" t.index ["refresh_token_digest"], name: "index_api_credentials_on_refresh_token_digest", unique: true, where: "(refresh_token_digest IS NOT NULL)" end create_table "banners", force: :cascade do |t| - t.bigint "casa_org_id", null: false - t.bigint "user_id", null: false - t.string "name" t.boolean "active", default: false + t.bigint "casa_org_id", null: false t.datetime "created_at", null: false - t.datetime "updated_at", null: false t.datetime "expires_at" + t.string "name" + t.datetime "updated_at", null: false + t.bigint "user_id", null: false end create_table "casa_case_contact_types", force: :cascade do |t| - t.bigint "contact_type_id", null: false t.bigint "casa_case_id", null: false + t.bigint "contact_type_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["casa_case_id"], name: "index_casa_case_contact_types_on_casa_case_id" @@ -126,67 +126,67 @@ create_table "casa_case_emancipation_categories", force: :cascade do |t| t.bigint "casa_case_id", null: false - t.bigint "emancipation_category_id", null: false t.datetime "created_at", null: false + t.bigint "emancipation_category_id", null: false t.datetime "updated_at", null: false t.index ["casa_case_id"], name: "index_casa_case_emancipation_categories_on_casa_case_id" end create_table "casa_case_emancipation_options", force: :cascade do |t| t.bigint "casa_case_id", null: false - t.bigint "emancipation_option_id", null: false t.datetime "created_at", null: false + t.bigint "emancipation_option_id", null: false t.datetime "updated_at", null: false t.index ["casa_case_id", "emancipation_option_id"], name: "index_case_options_on_case_id_and_option_id", unique: true end create_table "casa_cases", force: :cascade do |t| - t.string "case_number", null: false - t.boolean "transition_aged_youth", default: false - t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.bigint "casa_org_id", null: false + t.boolean "active", default: true, null: false t.datetime "birth_month_year_youth", precision: nil + t.bigint "casa_org_id", null: false + t.string "case_number", null: false t.datetime "court_report_due_date", precision: nil - t.boolean "active", default: true, null: false - t.datetime "court_report_submitted_at", precision: nil t.integer "court_report_status", default: 0 - t.string "slug" + t.datetime "court_report_submitted_at", precision: nil + t.datetime "created_at", null: false t.datetime "date_in_care" + t.string "slug" + t.boolean "transition_aged_youth", default: false + t.datetime "updated_at", null: false t.index ["casa_org_id"], name: "index_casa_cases_on_casa_org_id" t.index ["case_number", "casa_org_id"], name: "index_casa_cases_on_case_number_and_casa_org_id", unique: true t.index ["slug"], name: "index_casa_cases_on_slug" end create_table "casa_orgs", force: :cascade do |t| - t.string "name", null: false + t.boolean "additional_expenses_enabled", default: false + t.string "address" t.datetime "created_at", null: false - t.datetime "updated_at", null: false t.string "display_name" - t.string "address" t.string "footer_links", default: [], array: true - t.string "slug" + t.boolean "learning_topic_active", default: false + t.string "name", null: false + t.boolean "other_duties_enabled", default: true t.boolean "show_driving_reimbursement", default: true t.boolean "show_fund_request", default: false - t.string "twilio_phone_number" + t.string "slug" t.string "twilio_account_sid" - t.string "twilio_api_key_sid" t.string "twilio_api_key_secret" + t.string "twilio_api_key_sid" t.boolean "twilio_enabled", default: false - t.boolean "additional_expenses_enabled", default: false - t.boolean "learning_topic_active", default: false - t.boolean "other_duties_enabled", default: true + t.string "twilio_phone_number" + t.datetime "updated_at", null: false t.index ["slug"], name: "index_casa_orgs_on_slug", unique: true end create_table "case_assignments", force: :cascade do |t| - t.bigint "casa_case_id", null: false - t.bigint "volunteer_id", null: false t.boolean "active", default: true, null: false + t.boolean "allow_reimbursement", default: true + t.bigint "casa_case_id", null: false t.datetime "created_at", null: false - t.datetime "updated_at", null: false t.boolean "hide_old_contacts", default: false - t.boolean "allow_reimbursement", default: true + t.datetime "updated_at", null: false + t.bigint "volunteer_id", null: false t.index ["casa_case_id"], name: "index_case_assignments_on_casa_case_id" t.index ["volunteer_id"], name: "index_case_assignments_on_volunteer_id" end @@ -201,23 +201,23 @@ end create_table "case_contacts", force: :cascade do |t| - t.bigint "creator_id", null: false t.bigint "casa_case_id" - t.integer "duration_minutes" - t.datetime "occurred_at", precision: nil - t.datetime "created_at", null: false - t.datetime "updated_at", null: false t.boolean "contact_made", default: false + t.datetime "created_at", null: false + t.bigint "creator_id", null: false + t.datetime "deleted_at", precision: nil + t.integer "draft_case_ids", default: [], array: true + t.integer "duration_minutes" t.string "medium_type" + t.jsonb "metadata", default: {} t.integer "miles_driven", default: 0, null: false - t.boolean "want_driving_reimbursement", default: false t.string "notes" - t.datetime "deleted_at", precision: nil + t.datetime "occurred_at", precision: nil t.boolean "reimbursement_complete", default: false t.string "status", default: "started" - t.integer "draft_case_ids", default: [], array: true + t.datetime "updated_at", null: false t.string "volunteer_address" - t.jsonb "metadata", default: {} + t.boolean "want_driving_reimbursement", default: false t.index ["casa_case_id"], name: "index_case_contacts_on_casa_case_id" t.index ["creator_id"], name: "index_case_contacts_on_creator_id" t.check_constraint "miles_driven IS NOT NULL OR NOT want_driving_reimbursement", name: "want_driving_reimbursement_only_when_miles_driven" @@ -225,381 +225,381 @@ create_table "case_court_orders", force: :cascade do |t| t.bigint "casa_case_id", null: false + t.bigint "court_date_id" t.datetime "created_at", null: false - t.datetime "updated_at", null: false t.integer "implementation_status" - t.bigint "court_date_id" t.string "text" + t.datetime "updated_at", null: false t.index ["casa_case_id"], name: "index_case_court_orders_on_casa_case_id" t.index ["court_date_id"], name: "index_case_court_orders_on_court_date_id" end create_table "case_group_memberships", force: :cascade do |t| - t.bigint "case_group_id", null: false t.bigint "casa_case_id", null: false + t.bigint "case_group_id", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false end create_table "case_groups", force: :cascade do |t| t.bigint "casa_org_id", null: false - t.string "name" t.datetime "created_at", null: false + t.string "name" t.datetime "updated_at", null: false end create_table "checklist_items", force: :cascade do |t| - t.integer "hearing_type_id" - t.text "description", null: false t.string "category", null: false - t.boolean "mandatory", default: false, null: false t.datetime "created_at", null: false + t.text "description", null: false + t.integer "hearing_type_id" + t.boolean "mandatory", default: false, null: false t.datetime "updated_at", null: false end create_table "contact_topic_answers", force: :cascade do |t| - t.text "value" t.bigint "case_contact_id", null: false t.bigint "contact_topic_id" - t.boolean "selected", default: false, null: false t.datetime "created_at", null: false - t.datetime "updated_at", null: false t.datetime "deleted_at" + t.boolean "selected", default: false, null: false + t.datetime "updated_at", null: false + t.text "value" t.index ["case_contact_id"], name: "index_contact_topic_answers_on_case_contact_id" end create_table "contact_topics", force: :cascade do |t| - t.bigint "casa_org_id", null: false t.boolean "active", default: true, null: false - t.boolean "soft_delete", default: false, null: false + t.bigint "casa_org_id", null: false + t.datetime "created_at", null: false t.text "details" + t.boolean "exclude_from_court_report", default: false, null: false t.string "question" - t.datetime "created_at", null: false + t.boolean "soft_delete", default: false, null: false t.datetime "updated_at", null: false - t.boolean "exclude_from_court_report", default: false, null: false end create_table "contact_type_groups", force: :cascade do |t| + t.boolean "active", default: true t.bigint "casa_org_id", null: false - t.string "name", null: false t.datetime "created_at", null: false + t.string "name", null: false t.datetime "updated_at", null: false - t.boolean "active", default: true end create_table "contact_types", force: :cascade do |t| + t.boolean "active", default: true t.bigint "contact_type_group_id", null: false - t.string "name", null: false t.datetime "created_at", null: false + t.string "name", null: false t.datetime "updated_at", null: false - t.boolean "active", default: true t.index ["contact_type_group_id"], name: "index_contact_types_on_contact_type_group_id" end create_table "court_dates", force: :cascade do |t| - t.datetime "date", precision: nil, null: false t.bigint "casa_case_id", null: false + t.datetime "court_report_due_date", precision: nil t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.datetime "date", precision: nil, null: false t.bigint "hearing_type_id" t.bigint "judge_id" - t.datetime "court_report_due_date", precision: nil + t.datetime "updated_at", null: false t.index ["casa_case_id"], name: "index_court_dates_on_casa_case_id" end create_table "custom_org_links", force: :cascade do |t| - t.bigint "casa_org_id", null: false - t.string "text", null: false - t.string "url", null: false t.boolean "active", default: true, null: false + t.bigint "casa_org_id", null: false t.datetime "created_at", null: false + t.string "text", null: false t.datetime "updated_at", null: false + t.string "url", null: false t.index ["casa_org_id"], name: "index_custom_org_links_on_casa_org_id" end create_table "delayed_jobs", force: :cascade do |t| - t.integer "priority", default: 0, null: false t.integer "attempts", default: 0, null: false + t.datetime "created_at" + t.datetime "failed_at", precision: nil t.text "handler", null: false t.text "last_error" - t.datetime "run_at", precision: nil t.datetime "locked_at", precision: nil - t.datetime "failed_at", precision: nil t.string "locked_by" + t.integer "priority", default: 0, null: false t.string "queue" - t.datetime "created_at" + t.datetime "run_at", precision: nil t.datetime "updated_at" end create_table "emancipation_categories", force: :cascade do |t| - t.string "name", null: false - t.boolean "mutually_exclusive", null: false t.datetime "created_at", null: false + t.boolean "mutually_exclusive", null: false + t.string "name", null: false t.datetime "updated_at", null: false t.index ["name"], name: "index_emancipation_categories_on_name", unique: true end create_table "emancipation_options", force: :cascade do |t| + t.datetime "created_at", null: false t.bigint "emancipation_category_id", null: false t.string "name", null: false - t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["emancipation_category_id", "name"], name: "index_emancipation_options_on_emancipation_category_id_and_name", unique: true end create_table "flipper_features", force: :cascade do |t| - t.string "key", null: false t.datetime "created_at", null: false + t.string "key", null: false t.datetime "updated_at", null: false t.index ["key"], name: "index_flipper_features_on_key", unique: true end create_table "flipper_gates", force: :cascade do |t| + t.datetime "created_at", null: false t.string "feature_key", null: false t.string "key", null: false - t.text "value" - t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.text "value" t.index ["feature_key", "key", "value"], name: "index_flipper_gates_on_feature_key_and_key_and_value", unique: true end create_table "followups", force: :cascade do |t| t.bigint "case_contact_id" - t.bigint "creator_id" - t.integer "status", default: 0 t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.text "note" + t.bigint "creator_id" t.bigint "followupable_id" t.string "followupable_type" + t.text "note" + t.integer "status", default: 0 + t.datetime "updated_at", null: false t.index ["case_contact_id"], name: "index_followups_on_case_contact_id" end create_table "fund_requests", force: :cascade do |t| - t.text "submitter_email" - t.text "youth_name" - t.text "payment_amount" t.text "deadline" - t.text "request_purpose" + t.text "extra_information" + t.text "impact" + t.text "other_funding_source_sought" t.text "payee_name" + t.text "payment_amount" + t.text "request_purpose" t.text "requested_by_and_relationship" - t.text "other_funding_source_sought" - t.text "impact" - t.text "extra_information" + t.text "submitter_email" t.text "timestamps" + t.text "youth_name" end create_table "healths", force: :cascade do |t| + t.datetime "created_at", null: false t.datetime "latest_deploy_time", precision: nil t.integer "singleton_guard" - t.datetime "created_at", null: false t.datetime "updated_at", null: false t.index ["singleton_guard"], name: "index_healths_on_singleton_guard", unique: true end create_table "hearing_types", force: :cascade do |t| - t.bigint "casa_org_id", null: false - t.string "name", null: false t.boolean "active", default: true, null: false + t.bigint "casa_org_id", null: false t.string "checklist_updated_date", default: "None", null: false + t.string "name", null: false end create_table "judges", force: :cascade do |t| + t.boolean "active", default: true t.bigint "casa_org_id", null: false t.datetime "created_at", null: false - t.datetime "updated_at", null: false - t.boolean "active", default: true t.string "name" + t.datetime "updated_at", null: false end create_table "languages", force: :cascade do |t| - t.string "name" t.bigint "casa_org_id", null: false t.datetime "created_at", null: false + t.string "name" t.datetime "updated_at", null: false end create_table "learning_hour_topics", force: :cascade do |t| - t.string "name", null: false t.bigint "casa_org_id", null: false - t.integer "position", default: 1 t.datetime "created_at", null: false + t.string "name", null: false + t.integer "position", default: 1 t.datetime "updated_at", null: false end create_table "learning_hour_types", force: :cascade do |t| + t.boolean "active", default: true t.bigint "casa_org_id", null: false + t.datetime "created_at", null: false t.string "name" - t.boolean "active", default: true t.integer "position", default: 1 - t.datetime "created_at", null: false t.datetime "updated_at", null: false end create_table "learning_hours", force: :cascade do |t| - t.bigint "user_id", null: false - t.string "name", null: false - t.integer "duration_minutes", null: false + t.datetime "created_at", null: false t.integer "duration_hours", null: false + t.integer "duration_minutes", null: false + t.bigint "learning_hour_topic_id" + t.bigint "learning_hour_type_id" + t.string "name", null: false t.datetime "occurred_at", precision: nil, null: false - t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.bigint "learning_hour_type_id" - t.bigint "learning_hour_topic_id" + t.bigint "user_id", null: false t.index ["user_id"], name: "index_learning_hours_on_user_id" end create_table "login_activities", force: :cascade do |t| - t.string "scope" - t.string "strategy" - t.string "identity" - t.boolean "success" - t.string "failure_reason" - t.string "user_type" - t.bigint "user_id" - t.string "context" - t.string "ip" - t.text "user_agent" - t.text "referrer" t.string "city" - t.string "region" + t.string "context" t.string "country" + t.datetime "created_at" + t.string "failure_reason" + t.string "identity" + t.string "ip" t.float "latitude" t.float "longitude" - t.datetime "created_at" + t.text "referrer" + t.string "region" + t.string "scope" + t.string "strategy" + t.boolean "success" + t.text "user_agent" + t.bigint "user_id" + t.string "user_type" end create_table "mileage_rates", force: :cascade do |t| t.decimal "amount" + t.bigint "casa_org_id", null: false + t.datetime "created_at", null: false t.date "effective_date" t.boolean "is_active", default: true - t.bigint "user_id" - t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.bigint "casa_org_id", null: false + t.bigint "user_id" end create_table "notes", force: :cascade do |t| t.string "content" + t.datetime "created_at", null: false t.bigint "creator_id" - t.string "notable_type" t.bigint "notable_id" - t.datetime "created_at", null: false + t.string "notable_type" t.datetime "updated_at", null: false end create_table "noticed_events", force: :cascade do |t| - t.string "type" - t.string "record_type" - t.bigint "record_id" - t.jsonb "params" t.datetime "created_at", null: false - t.datetime "updated_at", null: false t.integer "notifications_count" + t.jsonb "params" + t.bigint "record_id" + t.string "record_type" + t.string "type" + t.datetime "updated_at", null: false end create_table "noticed_notifications", force: :cascade do |t| - t.string "type" + t.datetime "created_at", null: false t.bigint "event_id", null: false - t.string "recipient_type", null: false - t.bigint "recipient_id", null: false t.datetime "read_at", precision: nil + t.bigint "recipient_id", null: false + t.string "recipient_type", null: false t.datetime "seen_at", precision: nil - t.datetime "created_at", null: false + t.string "type" t.datetime "updated_at", null: false t.index ["recipient_type", "recipient_id"], name: "index_noticed_notifications_on_recipient" end create_table "notifications", force: :cascade do |t| - t.string "recipient_type", null: false - t.bigint "recipient_id", null: false - t.string "type", null: false + t.datetime "created_at", null: false t.jsonb "params" t.datetime "read_at", precision: nil - t.datetime "created_at", null: false + t.bigint "recipient_id", null: false + t.string "recipient_type", null: false + t.string "type", null: false t.datetime "updated_at", null: false end create_table "other_duties", force: :cascade do |t| + t.datetime "created_at", null: false t.bigint "creator_id", null: false t.string "creator_type" - t.datetime "occurred_at", precision: nil t.bigint "duration_minutes" t.text "notes" - t.datetime "created_at", null: false + t.datetime "occurred_at", precision: nil t.datetime "updated_at", null: false end create_table "patch_note_groups", force: :cascade do |t| - t.string "value", null: false t.datetime "created_at", null: false t.datetime "updated_at", null: false + t.string "value", null: false t.index ["value"], name: "index_patch_note_groups_on_value", unique: true end create_table "patch_note_types", force: :cascade do |t| - t.string "name", null: false t.datetime "created_at", null: false + t.string "name", null: false t.datetime "updated_at", null: false t.index ["name"], name: "index_patch_note_types_on_name", unique: true end create_table "patch_notes", force: :cascade do |t| + t.datetime "created_at", null: false t.text "note", null: false - t.bigint "patch_note_type_id", null: false t.bigint "patch_note_group_id", null: false - t.datetime "created_at", null: false + t.bigint "patch_note_type_id", null: false t.datetime "updated_at", null: false end create_table "placement_types", force: :cascade do |t| - t.string "name", null: false t.bigint "casa_org_id", null: false t.datetime "created_at", null: false + t.string "name", null: false t.datetime "updated_at", null: false end create_table "placements", force: :cascade do |t| + t.bigint "casa_case_id", null: false + t.datetime "created_at", null: false + t.bigint "creator_id", null: false t.datetime "placement_started_at", null: false t.bigint "placement_type_id", null: false - t.bigint "creator_id", null: false - t.datetime "created_at", null: false t.datetime "updated_at", null: false - t.bigint "casa_case_id", null: false end create_table "preference_sets", force: :cascade do |t| - t.bigint "user_id" t.jsonb "case_volunteer_columns", default: "{}", null: false t.datetime "created_at", null: false - t.datetime "updated_at", null: false t.jsonb "table_state", default: {} + t.datetime "updated_at", null: false + t.bigint "user_id" t.index ["user_id"], name: "index_preference_sets_on_user_id" end create_table "sent_emails", force: :cascade do |t| - t.bigint "user_id" t.bigint "casa_org_id", null: false - t.string "mailer_type" t.string "category" - t.string "sent_address" t.datetime "created_at", null: false + t.string "mailer_type" + t.string "sent_address" t.datetime "updated_at", null: false + t.bigint "user_id" end create_table "sms_notification_events", force: :cascade do |t| - t.string "name" - t.string "user_type" t.datetime "created_at", null: false + t.string "name" t.datetime "updated_at", null: false + t.string "user_type" end create_table "supervisor_volunteers", force: :cascade do |t| - t.bigint "supervisor_id", null: false - t.bigint "volunteer_id", null: false t.datetime "created_at", null: false - t.datetime "updated_at", null: false t.boolean "is_active", default: true + t.bigint "supervisor_id", null: false + t.datetime "updated_at", null: false + t.bigint "volunteer_id", null: false t.index ["supervisor_id"], name: "index_supervisor_volunteers_on_supervisor_id" t.index ["volunteer_id"], name: "index_supervisor_volunteers_on_volunteer_id" end @@ -609,64 +609,64 @@ end create_table "user_languages", force: :cascade do |t| - t.bigint "user_id" - t.bigint "language_id" t.datetime "created_at", null: false + t.bigint "language_id" t.datetime "updated_at", null: false + t.bigint "user_id" t.index ["language_id", "user_id"], name: "index_user_languages_on_language_id_and_user_id", unique: true end create_table "user_reminder_times", force: :cascade do |t| - t.bigint "user_id", null: false t.datetime "case_contact_types" - t.datetime "no_contact_made" t.datetime "created_at", null: false + t.datetime "no_contact_made" t.datetime "updated_at", null: false + t.bigint "user_id", null: false t.index ["user_id"], name: "index_user_reminder_times_on_user_id" end create_table "user_sms_notification_events", force: :cascade do |t| - t.bigint "user_id", null: false - t.bigint "sms_notification_event_id", null: false t.datetime "created_at", null: false + t.bigint "sms_notification_event_id", null: false t.datetime "updated_at", null: false + t.bigint "user_id", null: false end create_table "users", force: :cascade do |t| - t.string "email", default: "", null: false - t.string "encrypted_password", default: "", null: false - t.string "reset_password_token" - t.datetime "reset_password_sent_at", precision: nil - t.datetime "created_at", null: false - t.datetime "updated_at", null: false + t.boolean "active", default: true t.bigint "casa_org_id", null: false + t.datetime "confirmation_sent_at" + t.string "confirmation_token" + t.datetime "confirmed_at" + t.datetime "created_at", null: false + t.datetime "current_sign_in_at", precision: nil + t.string "current_sign_in_ip" + t.datetime "date_of_birth" t.string "display_name", default: "", null: false - t.string "invitation_token" - t.datetime "invitation_created_at", precision: nil - t.datetime "invitation_sent_at", precision: nil + t.string "email", default: "", null: false + t.string "encrypted_password", default: "", null: false t.datetime "invitation_accepted_at", precision: nil + t.datetime "invitation_created_at", precision: nil t.integer "invitation_limit" - t.string "invited_by_type" - t.bigint "invited_by_id" + t.datetime "invitation_sent_at", precision: nil + t.string "invitation_token" t.integer "invitations_count", default: 0 - t.string "type" - t.boolean "active", default: true - t.integer "sign_in_count", default: 0, null: false - t.datetime "current_sign_in_at", precision: nil + t.bigint "invited_by_id" + t.string "invited_by_type" t.datetime "last_sign_in_at", precision: nil - t.string "current_sign_in_ip" t.string "last_sign_in_ip" + t.boolean "monthly_learning_hours_report", default: false, null: false + t.string "old_emails", default: [], array: true t.string "phone_number", default: "" - t.boolean "receive_sms_notifications", default: false, null: false t.boolean "receive_email_notifications", default: true - t.string "confirmation_token" - t.datetime "confirmed_at" - t.datetime "confirmation_sent_at" - t.string "unconfirmed_email" - t.string "old_emails", default: [], array: true t.boolean "receive_reimbursement_email", default: false - t.boolean "monthly_learning_hours_report", default: false, null: false - t.datetime "date_of_birth" + t.boolean "receive_sms_notifications", default: false, null: false + t.datetime "reset_password_sent_at", precision: nil + t.string "reset_password_token" + t.integer "sign_in_count", default: 0, null: false + t.string "type" + t.string "unconfirmed_email" + t.datetime "updated_at", null: false t.index ["casa_org_id"], name: "index_users_on_casa_org_id" t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true t.index ["email"], name: "index_users_on_email", unique: true From d31465a1231e389d57429527d52a5aef15bf84bb Mon Sep 17 00:00:00 2001 From: Stefanni Brasil Date: Thu, 18 Jun 2026 14:39:37 -0600 Subject: [PATCH 06/13] bring these back --- config/environments/development.rb | 2 +- config/environments/production.rb | 5 +++++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/config/environments/development.rb b/config/environments/development.rb index d4fc67b336..cd8e628947 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -21,7 +21,7 @@ config.action_controller.perform_caching = true config.action_controller.enable_fragment_cache_logging = true config.cache_store = :memory_store - config.public_file_server.headers = { "cache-control" => "public, max-age=#{2.days.to_i}" } + config.public_file_server.headers = {"cache-control" => "public, max-age=#{2.days.to_i}"} else config.action_controller.perform_caching = false config.cache_store = :null_store diff --git a/config/environments/production.rb b/config/environments/production.rb index 9c3c2e3ad9..4160369e91 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -81,6 +81,11 @@ # Replace the default in-process and non-durable queuing backend for Active Job. # config.active_job.queue_adapter = :resque + # Use a real queuing backend for Active Job (and separate queues per environment). + config.active_job.queue_adapter = :delayed_job + + config.action_mailer.perform_caching = false + # Ignore bad email addresses and do not raise email delivery errors. # Set this to true and configure the email server for immediate delivery to raise delivery errors. # config.action_mailer.raise_delivery_errors = false From 0708a13732422ff6047f0735600816dc49ea3625 Mon Sep 17 00:00:00 2001 From: Stefanni Brasil Date: Thu, 18 Jun 2026 15:10:38 -0600 Subject: [PATCH 07/13] Keep random date simple After the upgrade, this test was raising this error: ``` Failure/Error: ActiveRecord::Tasks::DatabaseTasks.load_seed ArgumentError: cannot load complex into simple # ./db/seeds/db_populator.rb:143:in 'block in DbPopulator#create_cases' # ./db/seeds/db_populator.rb:137:in 'Integer#times' # ./db/seeds/db_populator.rb:137:in 'DbPopulator#create_cases' ``` Keeping the date to a simpler rand generation solves the problem. --- db/seeds/db_populator.rb | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/db/seeds/db_populator.rb b/db/seeds/db_populator.rb index a5080cd4a7..f4fccbc067 100644 --- a/db/seeds/db_populator.rb +++ b/db/seeds/db_populator.rb @@ -139,7 +139,6 @@ def create_cases(casa_org, options) court_date = generate_court_date court_report_submitted = index.even? - new_casa_case = CasaCase.find_by(case_number: case_number) birth_month_year_youth = @case_fourteen_years_old ? ((Date.today - 18.year)..(Date.today - CasaCase::TRANSITION_AGE.year)).to_a.sample : ((Date.today - 18.year)..(Date.today - 1.year)).to_a.sample new_casa_case ||= CasaCase.find_or_create_by!( casa_org_id: casa_org.id, @@ -147,7 +146,7 @@ def create_cases(casa_org, options) court_report_submitted_at: court_report_submitted ? Date.today : nil, court_report_status: court_report_submitted ? :submitted : :not_submitted, birth_month_year_youth: birth_month_year_youth, - date_in_care: Date.today - (rand * 1500) + date_in_care: Date.today - rand(1500) ) new_court_date = CourtDate.find_or_create_by!( casa_case: new_casa_case, From a3789b3dd337417c4fd9098319f6d40a55dff631 Mon Sep 17 00:00:00 2001 From: Stefanni Brasil Date: Thu, 18 Jun 2026 15:23:28 -0600 Subject: [PATCH 08/13] linter --- config/environments/production.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/environments/production.rb b/config/environments/production.rb index 4160369e91..efe43cde55 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -42,7 +42,7 @@ config.public_file_server.enabled = ENV["RAILS_SERVE_STATIC_FILES"].present? # Cache assets for far-future expiry since they are all digest stamped. - config.public_file_server.headers = { "cache-control" => "public, max-age=#{1.year.to_i}" } + config.public_file_server.headers = {"cache-control" => "public, max-age=#{1.year.to_i}"} # Enable serving of images, stylesheets, and JavaScripts from an asset server. # config.asset_host = "http://assets.example.com" From 087a05e5a439c12358c286b75d5be24d434ff9de Mon Sep 17 00:00:00 2001 From: Stefanni Brasil Date: Mon, 22 Jun 2026 17:19:19 -0600 Subject: [PATCH 09/13] we do not use rubocop --- config/environments/development.rb | 3 --- 1 file changed, 3 deletions(-) diff --git a/config/environments/development.rb b/config/environments/development.rb index cd8e628947..03ea247338 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -92,7 +92,4 @@ if ENV["CODESPACES"] === "true" config.action_controller.forgery_protection_origin_check = false end - - # Apply autocorrection by RuboCop to files generated by `bin/rails generate`. - # config.generators.apply_rubocop_autocorrect_after_generate! end From e0564a60ea891d2b5d4bd0ddef8f2999083004bd Mon Sep 17 00:00:00 2001 From: Stefanni Brasil Date: Mon, 22 Jun 2026 17:22:01 -0600 Subject: [PATCH 10/13] bring comment back --- config/environments/test.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/environments/test.rb b/config/environments/test.rb index ed97c38a6e..33b0b360f9 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -6,7 +6,9 @@ Rails.application.configure do # Settings specified here will take precedence over those in config/application.rb. + # While tests run files are not watched, reloading is not necessary. config.enable_reloading = ENV["CI"].blank? + config.action_view.cache_template_loading = true # Eager loading loads your entire application. When running a single test locally, From 7d8c087cfad567e0a632e1018e8e1f069b8fe1f5 Mon Sep 17 00:00:00 2001 From: Stefanni Brasil Date: Thu, 2 Jul 2026 16:12:54 -0600 Subject: [PATCH 11/13] Fully enable Rails 8.1 config defaults This version new defaults do not seem to impact this app. --- config/application.rb | 2 +- .../new_framework_defaults_8_1.rb | 74 ------------------- 2 files changed, 1 insertion(+), 75 deletions(-) delete mode 100644 config/initializers/new_framework_defaults_8_1.rb diff --git a/config/application.rb b/config/application.rb index 28ccbd75b7..9f31c0766b 100644 --- a/config/application.rb +++ b/config/application.rb @@ -9,7 +9,7 @@ module Casa class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. - config.load_defaults 8.0 + config.load_defaults 8.1 # Please, add to the `ignore` list any other `lib` subdirectories that do # not contain `.rb` files, or that should not be reloaded or eager loaded. diff --git a/config/initializers/new_framework_defaults_8_1.rb b/config/initializers/new_framework_defaults_8_1.rb deleted file mode 100644 index 5cc706343c..0000000000 --- a/config/initializers/new_framework_defaults_8_1.rb +++ /dev/null @@ -1,74 +0,0 @@ -# Be sure to restart your server when you modify this file. -# -# This file eases your Rails 8.1 framework defaults upgrade. -# -# Uncomment each configuration one by one to switch to the new default. -# Once your application is ready to run with all new defaults, you can remove -# this file and set the `config.load_defaults` to `8.1`. -# -# Read the Guide for Upgrading Ruby on Rails for more info on each option. -# https://guides.rubyonrails.org/upgrading_ruby_on_rails.html - -### -# Skips escaping HTML entities and line separators. When set to `false`, the -# JSON renderer no longer escapes these to improve performance. -# -# Example: -# class PostsController < ApplicationController -# def index -# render json: { key: "\u2028\u2029<>&" } -# end -# end -# -# Renders `{"key":"\u2028\u2029\u003c\u003e\u0026"}` with the previous default, but `{"key":"

<>&"}` with the config -# set to `false`. -# -# Applications that want to keep the escaping behavior can set the config to `true`. -#++ -Rails.configuration.action_controller.escape_json_responses = false - -### -# Skips escaping LINE SEPARATOR (U+2028) and PARAGRAPH SEPARATOR (U+2029) in JSON. -# -# Historically these characters were not valid inside JavaScript literal strings but that changed in ECMAScript 2019. -# As such it's no longer a concern in modern browsers: https://caniuse.com/mdn-javascript_builtins_json_json_superset. -#++ -Rails.configuration.active_support.escape_js_separators_in_json = false - -### -# Raises an error when order dependent finder methods (e.g. `#first`, `#second`) are called without `order` values -# on the relation, and the model does not have any order columns (`implicit_order_column`, `query_constraints`, or -# `primary_key`) to fall back on. -# -# The current behavior of not raising an error has been deprecated, and this configuration option will be removed in -# Rails 8.2. -#++ -Rails.configuration.active_record.raise_on_missing_required_finder_order_columns = true - -### -# Controls how Rails handles path relative URL redirects. -# When set to `:raise`, Rails will raise an `ActionController::Redirecting::UnsafeRedirectError` -# for relative URLs without a leading slash, which can help prevent open redirect vulnerabilities. -# -# Example: -# redirect_to "example.com" # Raises UnsafeRedirectError -# redirect_to "@attacker.com" # Raises UnsafeRedirectError -# redirect_to "/safe/path" # Works correctly -# -# Applications that want to allow these redirects can set the config to `:log` (previous default) -# to only log warnings, or `:notify` to send ActiveSupport notifications. -#++ -Rails.configuration.action_controller.action_on_path_relative_redirect = :raise - -### -# Use a Ruby parser to track dependencies between Action View templates -#++ -Rails.configuration.action_view.render_tracker = :ruby - -### -# When enabled, hidden inputs generated by `form_tag`, `token_tag`, `method_tag`, and the hidden parameter fields -# included in `button_to` forms will omit the `autocomplete="off"` attribute. -# -# Applications that want to keep generating the `autocomplete` attribute for those tags can set it to `false`. -#++ -Rails.configuration.action_view.remove_hidden_field_autocomplete = true From a0169409b8538b7b0b8205f8bfcd6d52cdf31571 Mon Sep 17 00:00:00 2001 From: Stefanni Brasil Date: Thu, 30 Jul 2026 15:22:51 -0600 Subject: [PATCH 12/13] Upgrade to 8.1.3.1 These are security patches addressing 1 security issues: - A possible arbitrary file read and remote code execution in Active Storage variant processing We strongly recommend upgrading as soon as possible. https://rubyonrails.org/2026/7/29/Rails-Versions-7-2-3-2-8-0-5-1-and-8-1-3-1-have-been-released --- Gemfile.lock | 141 ++++++++++++++++++++++++++------------------------- 1 file changed, 71 insertions(+), 70 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 8fb46adf4b..04e892cdd9 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,29 +3,29 @@ GEM specs: action_text-trix (2.1.19) railties - actioncable (8.1.3) - actionpack (= 8.1.3) - activesupport (= 8.1.3) + actioncable (8.1.3.1) + actionpack (= 8.1.3.1) + activesupport (= 8.1.3.1) nio4r (~> 2.0) websocket-driver (>= 0.6.1) zeitwerk (~> 2.6) - actionmailbox (8.1.3) - actionpack (= 8.1.3) - activejob (= 8.1.3) - activerecord (= 8.1.3) - activestorage (= 8.1.3) - activesupport (= 8.1.3) + actionmailbox (8.1.3.1) + actionpack (= 8.1.3.1) + activejob (= 8.1.3.1) + activerecord (= 8.1.3.1) + activestorage (= 8.1.3.1) + activesupport (= 8.1.3.1) mail (>= 2.8.0) - actionmailer (8.1.3) - actionpack (= 8.1.3) - actionview (= 8.1.3) - activejob (= 8.1.3) - activesupport (= 8.1.3) + actionmailer (8.1.3.1) + actionpack (= 8.1.3.1) + actionview (= 8.1.3.1) + activejob (= 8.1.3.1) + activesupport (= 8.1.3.1) mail (>= 2.8.0) rails-dom-testing (~> 2.2) - actionpack (8.1.3) - actionview (= 8.1.3) - activesupport (= 8.1.3) + actionpack (8.1.3.1) + actionview (= 8.1.3.1) + activesupport (= 8.1.3.1) nokogiri (>= 1.8.5) rack (>= 2.2.4) rack-session (>= 1.0.1) @@ -33,40 +33,40 @@ GEM rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) useragent (~> 0.16) - actiontext (8.1.3) + actiontext (8.1.3.1) action_text-trix (~> 2.1.15) - actionpack (= 8.1.3) - activerecord (= 8.1.3) - activestorage (= 8.1.3) - activesupport (= 8.1.3) + actionpack (= 8.1.3.1) + activerecord (= 8.1.3.1) + activestorage (= 8.1.3.1) + activesupport (= 8.1.3.1) globalid (>= 0.6.0) nokogiri (>= 1.8.5) - actionview (8.1.3) - activesupport (= 8.1.3) + actionview (8.1.3.1) + activesupport (= 8.1.3.1) builder (~> 3.1) erubi (~> 1.11) rails-dom-testing (~> 2.2) rails-html-sanitizer (~> 1.6) - activejob (8.1.3) - activesupport (= 8.1.3) + activejob (8.1.3.1) + activesupport (= 8.1.3.1) globalid (>= 0.3.6) - activemodel (8.1.3) - activesupport (= 8.1.3) + activemodel (8.1.3.1) + activesupport (= 8.1.3.1) activemodel-serializers-xml (1.0.3) activemodel (>= 5.0.0.a) activesupport (>= 5.0.0.a) builder (~> 3.1) - activerecord (8.1.3) - activemodel (= 8.1.3) - activesupport (= 8.1.3) + activerecord (8.1.3.1) + activemodel (= 8.1.3.1) + activesupport (= 8.1.3.1) timeout (>= 0.4.0) - activestorage (8.1.3) - actionpack (= 8.1.3) - activejob (= 8.1.3) - activerecord (= 8.1.3) - activesupport (= 8.1.3) + activestorage (8.1.3.1) + actionpack (= 8.1.3.1) + activejob (= 8.1.3.1) + activerecord (= 8.1.3.1) + activesupport (= 8.1.3.1) marcel (~> 1.0) - activesupport (8.1.3) + activesupport (8.1.3.1) base64 bigdecimal concurrent-ruby (~> 1.0, >= 1.3.1) @@ -151,7 +151,7 @@ GEM logger (~> 1.5) cliver (0.3.2) coderay (1.1.3) - concurrent-ruby (1.3.7) + concurrent-ruby (1.3.8) connection_pool (3.0.2) crack (1.0.1) bigdecimal @@ -201,7 +201,7 @@ GEM htmlentities (~> 4.3) launchy (>= 2.1, < 4.0) mail (~> 2.7) - erb (6.0.4) + erb (6.0.6) erb_lint (0.9.0) activesupport better_html (>= 2.0.1) @@ -261,7 +261,7 @@ GEM sanitize (< 8) friendly_id (5.7.0) activerecord (>= 4.0.0) - globalid (1.3.0) + globalid (1.4.0) activesupport (>= 6.1) google-protobuf (4.34.1) bigdecimal @@ -301,7 +301,7 @@ GEM activesupport (>= 7.0.0) jsbundling-rails (1.3.1) railties (>= 6.0.0) - json (2.19.8) + json (2.21.1) json-schema (6.2.0) addressable (~> 2.8) bigdecimal (>= 3.1, < 5) @@ -321,10 +321,10 @@ GEM activesupport (>= 4) railties (>= 4) request_store (~> 1.0) - loofah (2.25.1) + loofah (2.25.2) crass (~> 1.0.2) nokogiri (>= 1.12.0) - mail (2.9.0) + mail (2.9.1) logger mini_mime (>= 0.1.1) net-imap @@ -348,7 +348,7 @@ GEM multipart-post (2.4.1) net-http-persistent (4.0.8) connection_pool (>= 2.2.4, < 4) - net-imap (0.6.4.1) + net-imap (0.6.6) date net-protocol net-pop (0.1.2) @@ -426,7 +426,7 @@ GEM google-protobuf (>= 3.25.3) pghero (3.8.0) activerecord (>= 7.2) - pp (0.6.3) + pp (0.6.4) prettyprint pretender (1.0.0) actionpack (>= 7.2) @@ -440,9 +440,6 @@ GEM pry-byebug (3.12.0) byebug (~> 13.0) pry (>= 0.13, < 0.17) - psych (5.4.0) - date - stringio public_suffix (7.0.5) puma (8.0.2) nio4r (~> 2.0) @@ -466,20 +463,20 @@ GEM rack (>= 1.3) rackup (2.3.1) rack (>= 3) - rails (8.1.3) - actioncable (= 8.1.3) - actionmailbox (= 8.1.3) - actionmailer (= 8.1.3) - actionpack (= 8.1.3) - actiontext (= 8.1.3) - actionview (= 8.1.3) - activejob (= 8.1.3) - activemodel (= 8.1.3) - activerecord (= 8.1.3) - activestorage (= 8.1.3) - activesupport (= 8.1.3) + rails (8.1.3.1) + actioncable (= 8.1.3.1) + actionmailbox (= 8.1.3.1) + actionmailer (= 8.1.3.1) + actionpack (= 8.1.3.1) + actiontext (= 8.1.3.1) + actionview (= 8.1.3.1) + activejob (= 8.1.3.1) + activemodel (= 8.1.3.1) + activerecord (= 8.1.3.1) + activestorage (= 8.1.3.1) + activesupport (= 8.1.3.1) bundler (>= 1.15.0) - railties (= 8.1.3) + railties (= 8.1.3.1) rails-controller-testing (1.0.5) actionpack (>= 5.0.1.rc1) actionview (>= 5.0.1.rc1) @@ -488,12 +485,12 @@ GEM activesupport (>= 5.0.0) minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.7.0) - loofah (~> 2.25) + rails-html-sanitizer (1.7.1) + loofah (~> 2.25, >= 2.25.2) nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0) - railties (8.1.3) - actionpack (= 8.1.3) - activesupport (= 8.1.3) + railties (8.1.3.1) + actionpack (= 8.1.3.1) + activesupport (= 8.1.3.1) irb (~> 1.13) rackup (>= 1.0.0) rake (>= 12.2) @@ -502,9 +499,14 @@ GEM zeitwerk (~> 2.6) rainbow (3.1.1) rake (13.4.2) - rdoc (7.2.0) + rbs (4.1.1) + logger + prism (>= 1.6.0) + tsort + rdoc (8.0.0) erb - psych (>= 4.0.0) + prism (>= 1.6.0) + rbs (>= 4.0.0) tsort regexp_parser (2.12.0) reline (0.6.3) @@ -656,7 +658,6 @@ GEM rubocop-rails (~> 2.34.0) stimulus-rails (1.3.4) railties (>= 6.0.0) - stringio (3.2.0) strong_migrations (2.8.0) activerecord (>= 7.2) thor (1.5.0) @@ -693,7 +694,7 @@ GEM crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) websocket (1.2.11) - websocket-driver (0.8.1) + websocket-driver (0.8.2) base64 websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) From e09caa50a175c081bce72b152ae9e79bdcc7bb96 Mon Sep 17 00:00:00 2001 From: Stefanni Brasil Date: Thu, 30 Jul 2026 15:24:46 -0600 Subject: [PATCH 13/13] Ignore file without test to fix CI --- .allow_skipping_tests | 1 + 1 file changed, 1 insertion(+) diff --git a/.allow_skipping_tests b/.allow_skipping_tests index d4c169f8f7..d1574dfb52 100644 --- a/.allow_skipping_tests +++ b/.allow_skipping_tests @@ -7,6 +7,7 @@ controllers/users/confirmations_controller.rb helpers/metrics_helper.rb helpers/table_helper.rb models/concerns/name_presentation.rb +policies/mileage_rate_policy.rb services/admin_dashboard.rb services/volunteer_dashboard.rb