$ cat rails/week/2026-09-14.log
the week in review · Sep 14 – Sep 20, 2026
Active Storage gets a direct-upload kill switch
By RepoJournal · composed from the cited sources · human-reviewed weekly · methodology
Active Record also fixed Postgres primary key and schema introspection bugs that misread covering indexes and shadowed table names.
Introduce `config.active_storage.draw_direct_upload_route` rails/rails
Setting config.active_storage.draw_direct_upload_route to false removes the direct upload endpoint while leaving the rest of the Active Storage routes in place, so apps that never use direct uploads can shrink their attack surface without opting out of Active Storage entirely.
Read PostgreSQL indexes and constraints from the table a name resolves to rails/rails
fetch_indexes, fetch_foreign_keys, fetch_check_constraints, fetch_unique_constraints and fetch_exclusion_constraints matched an unqualified name against every schema on the search path, so a name two schemas both carry returned both tables' objects. The schema statements now read from the table the name actually resolves to.
Fix PostgreSQL primary key introspection for covering indexes rails/rails
Postgres primary key indexes can carry non-key columns via INCLUDE, and Active Record was reading pg_index.indkey, which lists both key and included columns, so included columns were reported as part of the primary key. Bulk upserts could then treat writable columns as read-only.
Jail agent commands in their own namespaces rails/lemans
The LeMans sandbox agent could read the harness's own secrets, including a DeepSeek model that pulled OPENROUTER_API_KEY from its environment and called OpenRouter with it, which the allowlist permits because lemans itself talks to OpenRouter. Every agent command now runs jailed, with a read-only system and no env vars leaked.
Replace the `mysql5` fallback in `ActiveRecord.database_cli` with `mariadb` rails/rails
The mysql5 fallback in ActiveRecord.database_cli dates to 2008 and pointed at a MacPorts client binary whose port is long gone, so dbconsole now falls back to mariadb instead. MySQL installs whose client binaries are named mysql or mysql5 are unaffected by name lookup unless the fallback was actually being used.
Deprecate `ActiveRecord::Callbacks::CALLBACKS` rails/rails
CALLBACKS has been stale for years and is only referenced in tests. It is missing several transaction callbacks added since, including before_commit, after_save_commit, after_create_commit and after_destroy_commit, so any code reaching for the constant should switch to the individual callback constants.
Speed up TimeWithZone#xmlschema, #to_s and TimeZone.seconds_to_utc_offset rails/rails
TimeWithZone#xmlschema, its iso8601 and rfc3339 aliases, and to_s now build non-UTC output with getlocal(utc_offset) and Time#iso8601 rather than formatting with C iso8601 and patching the offset back in with a regexp, which also speeds up TimeZone.seconds_to_utc_offset.
Skip leaky ractor tests rails/rails
The skipped tests called require inside a Ractor, which breaks any gem that aliases Kernel#require, a list that includes Zeitwerk, Bootsnap and Rubygems. The skips were later trimmed back rather than dropped outright, so Ractor coverage narrows without losing the suite's signal.
$ ls rails/week/ # the briefings behind this review
Keep up with Rails in about 3 minutes: what actually shipped — the commits, pull requests, releases, and security advisories that matter.
fair warning: these emails are deeply technical. diffs, version numbers, CVEs, benchmark deltas. if that's not your idea of a good read, this isn't your newsletter.
Folds into your digest — weekly by default, monthly if you prefer. Unsubscribe in one click.