CodeVetter · Repo Unpack · Data flow
rails/rails
Three boundaries dominate. HTTP enters as a Rack env, passes DefaultMiddlewareStack, and is recognized by Journey into a controller action whose callbacks and render produce a Rack triple. Records enter through Active Record attribute hashes, are validated and callback-wrapped, then inserted or updated on a leased connection. Secrets enter as ENV or a key file, are decrypted with AES-128-GCM, and feed secret_key_base, which signs and encrypts cookies and messages. Jobs, uploads, and filtered logs are side channels off those paths.
- RouteSet#call builds a request, normalizes path_info with Journey::Router::Utils.normalize_path, and calls @router.serve. Journey::Router#serve yields each match to route.app.serve and returns the response unless the X_CASCADE header is pass; otherwise it returns 404.
- RouteSet::Dispatcher#serve reads path parameters, instantiates the controller response, and calls controller.dispatch. On RoutingError it re-raises only when @raise_on_name_error is set; otherwise it returns a 404 cascade triple.
- ActionController::Metal#dispatch assigns the request and response, calls process(name), commits the flash, and returns to_a. AbstractController::Base#process sets @_action_name, raises ActionNotFound when _find_action_name fails, and calls process_action. Callbacks#process_action wraps super in run_callbacks(:process_action).
- Journey path captures are CGI.unescapeURIComponent'd when they contain % and then forced to UTF-8 before being merged with route defaults. recognize_path separately binary-encodes and URI-unescapes string params and raises RoutingError when the controller constant is missing.
- Persistence#save calls create_or_update and returns false on RecordInvalid. create_or_update raises if the record is readonly, returns false if destroyed, and chooses _create_record or _update_record. _create_record filters attributes_for_create, opens with_connection, calls _insert_record with _returning_columns_for_insert, writes returned columns, and clears @new_record.
- ActiveRecord::Base.establish_connection resolves a symbol or hash via resolve_config_for_connection and delegates to connection_handler.establish_connection with owner_name, current_role, and current_shard. connects_to accepts database: or shards: but not both, and only on Base or abstract classes. ConnectionPool#lease_connection checks out a connection once per thread and marks the lease sticky.
- secret_key_base prefers ENV[SECRET_KEY_BASE_DUMMY] (a generated local secret), then ENV[SECRET_KEY_BASE], then credentials.secret_key_base, then a generated secret when Rails.env.local?. A missing non-local secret raises ArgumentError naming bin/rails credentials:edit. Application#key_generator memoizes an ActiveSupport::CachingKeyGenerator per secret, used for MessageVerifier and MessageEncryptor including cookies.
- ActiveSupport::EncryptedFile uses cipher aes-128-gcm. #key reads the env var named by env_key, then the key file, then raises MissingKeyError if raise_if_missing_key. #read decrypts content_path.binread. generate_key is SecureRandom.hex of MessageEncryptor.key_len, and a key of any other length raises InvalidKeyLengthError.
- Application#creds returns ActiveSupport::CombinedConfiguration. In development the lookup order is envs, then dotenv, then encrypted credentials; in other environments dotenv is omitted. The documented API is creds.require and creds.option.
- ActiveJob::Enqueuing::ClassMethods#perform_later instantiates the job and calls enqueue. The class attribute enqueue_after_transaction_commit defaults to false in the module, but load_defaults 8.2 sets active_job.enqueue_after_transaction_commit = true so new 8.2 apps defer enqueue until the outermost transaction commits.
- ActionDispatch::Http::FilterParameters#filtered_parameters runs ActiveSupport::ParameterFilter over the request parameters and substitutes matches with the mask [FILTERED]. ParseError yields an empty hash so a bad body does not leak into logs via the filter path.
- sanitize_sql_for_conditions sends Arrays through sanitize_sql_array and quotes bound values, but returns a bare String unchanged. The comment states the helper is not schema-aware and that MySQL numeric binds are quoted as strings.
- An upload enters ActiveStorage::Service#upload(key, io, checksum:) and, when a checksum is given, must raise ActiveStorage::IntegrityError on mismatch. Disk, S3, GCS, and Mirror are selected by the service: key in the configuration passed to Service.configure, not by a hardcoded global.