fiber_audit 0.2.0 → 0.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1c20b77ea07f9fedfc345f994798c6d58ffe14853dbf63bd46a1328cdf486271
4
- data.tar.gz: c71285e1a636ebf514251634a8202b40a1459e2bb7de36b71f7459313afb72d8
3
+ metadata.gz: f76c5789a7f5490e2e568cb6ea912520ae1350cc5a0de15053b3b30fd271e10d
4
+ data.tar.gz: aac0a9b350682e2c1abb167057ab4ea9ba912f277efa8818dd7269cee8d71058
5
5
  SHA512:
6
- metadata.gz: 86784bb39bb1d300324ef74e4ffce7e087a00567633c0645d8a0eed15fbb83cda38ec422ab07bcc49a1546c4d72614089b3af3ca78081abcd75eb08a15cb511b
7
- data.tar.gz: 672e6b9cdd0da82c01e2ef4f2377ac82905b8656d5e545db234d55e0ebf6a36c854ca6f3bbc3c784b97363bae320fcceddfad34075cc885c9e91898dde255e14
6
+ metadata.gz: 9d1cbe6bca9cc0363a483f9c2902a13c0389fc1fc0b833023d923342c23e8ea01b884e71233ddc2ba5b6f802cb83f7af6c5bb17ae67ef1b01d96958517ea5bca
7
+ data.tar.gz: f14db18581138d051937fbb788b4c3d6a8ec8970647fa82612d5911d2809b55918adfd27e02ec790500e86ae80c8cdeec112a60515d8cc22eb1f52da07ffcf89
data/ARCHITECTURE.md CHANGED
@@ -20,7 +20,7 @@ produces hypotheses, while observational runtime sessions provide bounded eviden
20
20
  without establishing complete coverage. FiberAudit never claims unconditional
21
21
  `PASS`.
22
22
 
23
- > **Repository status:** v0.2.0 includes the v0.1.0 static pipeline end to end:
23
+ > **Repository status:** v0.2.1 includes the v0.1.0 static pipeline end to end:
24
24
  > project discovery, configuration, semantic and syntax analysis, execution
25
25
  > contexts, FA1001–FA1007, suppressions, status derivation, text/JSON reports,
26
26
  > and the CLI. The v0.2 runtime contracts, bounded JSONL recorder, explicit
data/CHANGELOG.md CHANGED
@@ -2,6 +2,17 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 0.2.1 (2026-08-12)
6
+
7
+ ### Fixed
8
+
9
+ - Rails 8 and Zeitwerk compatibility during runtime boot: avoid reentrant
10
+ application initialization and premature constant autoloads, preserve
11
+ Zeitwerk directory autoload semantics, and avoid duplicate insertion into a
12
+ copied or frozen middleware stack.
13
+ - Install the runtime context middleware at the outer edge of the Rails stack so
14
+ application middleware operations are classified as `middleware`.
15
+
5
16
  ## 0.2.0 (2026-08-12)
6
17
 
7
18
  ### Added
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # FiberAudit
2
2
 
3
3
  FiberAudit audits Ruby and Rails code for operations that can block the thread
4
- running a Fiber scheduler. Version 0.2.0 includes static analysis and an explicit,
4
+ running a Fiber scheduler. Version 0.2.1 includes static analysis and an explicit,
5
5
  observational runtime audit.
6
6
 
7
7
  > **Safety disclaimer:** FiberAudit does not prove that an application is
@@ -10,7 +10,7 @@ observational runtime audit.
10
10
 
11
11
  ## Requirements and installation
12
12
 
13
- FiberAudit v0.2.0 supports Ruby 3.3 and 3.4.
13
+ FiberAudit v0.2.1 supports Ruby 3.3 and 3.4.
14
14
 
15
15
  ```sh
16
16
  gem install fiber_audit
@@ -190,7 +190,7 @@ Missing reasons and invalid configuration return exit code 2.
190
190
  - `PASS_WITH_WARNINGS` — only low or informational findings.
191
191
  - `NO_FINDINGS` — no findings at the configured threshold.
192
192
 
193
- FiberAudit never emits unconditional `PASS` in v0.2.0.
193
+ FiberAudit never emits unconditional `PASS` in v0.2.1.
194
194
 
195
195
  ## Exit codes
196
196
 
@@ -199,7 +199,7 @@ FiberAudit never emits unconditional `PASS` in v0.2.0.
199
199
  | 0 | No active finding at or above the configured threshold |
200
200
  | 1 | One or more active findings at or above the threshold |
201
201
  | 2 | Invalid options, configuration, analysis, or report output |
202
- | 3 | Reserved; never emitted by v0.2.0 |
202
+ | 3 | Reserved; never emitted by v0.2.1 |
203
203
 
204
204
  Source parse errors are included in report data while analysis continues on
205
205
  other files.
@@ -125,6 +125,15 @@ module FiberAudit
125
125
  def install_require_hook
126
126
  return if @require_hook_installed
127
127
 
128
+ # Zeitwerk replaces Kernel#require. Load its optional integration before
129
+ # prepending FiberAudit so later Rails autoloads retain Zeitwerk's require
130
+ # semantics. This remains a no-op when Zeitwerk is not installed.
131
+ begin
132
+ require 'zeitwerk'
133
+ rescue LoadError
134
+ nil
135
+ end
136
+
128
137
  # Install narrow guarded require hook for late Rails loading
129
138
  # Independent of probe registry
130
139
  ::Kernel.prepend(RequireHook) unless ::Kernel.ancestors.include?(RequireHook)
@@ -132,33 +141,57 @@ module FiberAudit
132
141
  end
133
142
 
134
143
  def install_controller_hook
135
- return unless defined?(::ActionController::Metal)
144
+ namespace = loaded_constant(Object, :ActionController)
145
+ target = loaded_constant(namespace, :Metal)
146
+ return unless target
136
147
 
137
- ::ActionController::Metal.prepend(ControllerHook) unless ::ActionController::Metal.ancestors.include?(ControllerHook)
148
+ target.prepend(ControllerHook) unless target.ancestors.include?(ControllerHook)
138
149
  end
139
150
 
140
151
  def install_job_hook
141
- return unless defined?(::ActiveJob::Base)
152
+ namespace = loaded_constant(Object, :ActiveJob)
153
+ target = loaded_constant(namespace, :Base)
154
+ return unless target
142
155
 
143
- ::ActiveJob::Base.prepend(JobHook) unless ::ActiveJob::Base.ancestors.include?(JobHook)
156
+ target.prepend(JobHook) unless target.ancestors.include?(JobHook)
144
157
  end
145
158
 
146
159
  def install_cable_hook
147
- return unless defined?(::ActionCable::Channel::Base)
160
+ namespace = loaded_constant(Object, :ActionCable)
161
+ channel = loaded_constant(namespace, :Channel)
162
+ target = loaded_constant(channel, :Base)
163
+ return unless target
164
+
165
+ target.prepend(CableHook) unless target.ancestors.include?(CableHook)
166
+ end
167
+
168
+ def loaded_constant(namespace, name)
169
+ return unless namespace.is_a?(Module)
170
+ return if namespace.autoload?(name)
171
+ return unless namespace.const_defined?(name, false)
148
172
 
149
- ::ActionCable::Channel::Base.prepend(CableHook) unless ::ActionCable::Channel::Base.ancestors.include?(CableHook)
173
+ namespace.const_get(name, false)
174
+ rescue NameError
175
+ nil
150
176
  end
151
177
 
152
178
  def try_install_middleware_hook
153
- return unless defined?(::Rails) && ::Rails.respond_to?(:application) && ::Rails.application
179
+ rails = loaded_constant(Object, :Rails)
180
+ return unless rails
154
181
 
155
- stack = ::Rails.application.config.middleware
156
- return if @middleware_stack.equal?(stack)
182
+ # Rails.application may instantiate the application class. Calling it
183
+ # from a require hook while Rails itself is loading can re-enter a
184
+ # partially initialized application, so only inspect an existing instance.
185
+ application = rails.instance_variable_get(:@application)
186
+ return unless application
187
+
188
+ stack = application.config.middleware
189
+ return if @middleware_stack.equal?(stack) || middleware_installed_in?(stack)
157
190
 
158
191
  # Try to insert middleware into Rails stack. A replacement stack (for
159
192
  # example after a Rails reload) is eligible for installation again.
160
193
  begin
161
- stack.use(Middleware)
194
+ stack.insert_before(0, Middleware)
162
195
  @middleware_stack = stack
163
196
  rescue StandardError => e
164
197
  # Stack may be finalized - that's okay, middleware is optional
@@ -166,6 +199,14 @@ module FiberAudit
166
199
  end
167
200
  end
168
201
 
202
+ def middleware_installed_in?(stack)
203
+ return false unless stack.respond_to?(:any?)
204
+
205
+ stack.any? do |entry|
206
+ entry.equal?(Middleware) || (entry.respond_to?(:klass) && entry.klass.equal?(Middleware))
207
+ end
208
+ end
209
+
169
210
  # Require hook for late Rails loading - independent of probe registry
170
211
  # Narrow, guarded, behavior-preserving
171
212
  module RequireHook
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module FiberAudit
4
- VERSION = '0.2.0'
4
+ VERSION = '0.2.1'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fiber_audit
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - FiberAudit Contributors