ez_logs_agent 0.1.8 → 0.1.10
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 +4 -4
- data/CHANGELOG.md +36 -0
- data/lib/ez_logs_agent/sanitizer.rb +60 -0
- data/lib/ez_logs_agent/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 2a7479b12ee7dd0814929516f0474d7e05e393410d86a1c6d56117c854945809
|
|
4
|
+
data.tar.gz: 54af5890799ca5614373dae0e66d1b422b3abab3dee7d9d0f95c7f23039ffdd7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a68790e445b19ba92f2df2d0733fe6ae7e6d9c43f2ff854eed01fced091cb7d62aa1c0377429c44d3250abc515d5a1bb45056f1087eb0e2b8d491461fdd94843
|
|
7
|
+
data.tar.gz: f4208dc88f566f28e1ec24288533468fb3f99d268a77d4f3030da19fc4fc77fe8e36a39052516ddc94def977f03012d8bc157fccb319161a06d4889f52cd37e5
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,42 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## [0.1.10] — 2026-06-05
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- `Sanitizer` no longer collapses ActiveJob keyword-argument hashes
|
|
9
|
+
(those tagged with `_aj_ruby2_keywords`) to `"[Object]"` at the
|
|
10
|
+
depth-3 cap. ActionMailer puts kwargs at two wrapper layers — an
|
|
11
|
+
outer `{"args" => [kwargs_hash], "_aj_ruby2_keywords" => ["args"]}`
|
|
12
|
+
payload and the kwargs hash itself, also marked. Each layer is
|
|
13
|
+
framework noise; the depth budget now skips them so real kwargs
|
|
14
|
+
survive the wire (e.g. `CompanyMailer.deleted(admin_email:, ...)`
|
|
15
|
+
now ships `admin_email`/`company_name`/`deleted_at` instead of a
|
|
16
|
+
single `"[Object]"`).
|
|
17
|
+
|
|
18
|
+
The carve-out is narrow: only hashes that actually carry the
|
|
19
|
+
`_aj_ruby2_keywords` marker are exempt. Customer-data hashes
|
|
20
|
+
without the marker still hit the depth cap unchanged, and
|
|
21
|
+
sensitive-key filtering (passwords, tokens, …) still runs on the
|
|
22
|
+
real kwargs entries — the wrapper is free to descend into, but
|
|
23
|
+
nothing inside it is exempt from masking. No wire-format change.
|
|
24
|
+
|
|
25
|
+
## [0.1.9] — 2026-06-05
|
|
26
|
+
|
|
27
|
+
### Fixed
|
|
28
|
+
- `Sanitizer` no longer collapses ActiveJob record references
|
|
29
|
+
(`{"_aj_globalid" => "gid://app/Model/id"}`) to `"[Object]"` at the
|
|
30
|
+
depth-3 cap. These one-key wrapper hashes pass through verbatim so
|
|
31
|
+
the server can display *which* record a job ran on
|
|
32
|
+
(e.g. ActionMailer's `Record 1` field now reads `User #42` instead
|
|
33
|
+
of `[Object]`).
|
|
34
|
+
|
|
35
|
+
The carve-out is narrow: only the exact `{"_aj_globalid" => "gid://..."}`
|
|
36
|
+
shape is exempt. Multi-key hashes, non-GID values, and any other
|
|
37
|
+
nested structure still hit the existing graph-protection rules
|
|
38
|
+
(depth cap, array truncation, non-primitive collapse) unchanged. No
|
|
39
|
+
wire-format change.
|
|
40
|
+
|
|
5
41
|
## [0.1.8] — 2026-05-29
|
|
6
42
|
|
|
7
43
|
### Changed
|
|
@@ -96,6 +96,23 @@ module EzLogsAgent
|
|
|
96
96
|
private
|
|
97
97
|
|
|
98
98
|
def sanitize_nested_object(hash, depth)
|
|
99
|
+
# ActiveJob serializes record refs as `{"_aj_globalid" => "gid://..."}`.
|
|
100
|
+
# Preserve these even past the depth limit so a record reference
|
|
101
|
+
# survives the [Object] collapse and the server can display WHICH
|
|
102
|
+
# record the job ran on. Display formatting (gid → "User #42") is
|
|
103
|
+
# the server's job; the agent's job is to keep the data on the wire.
|
|
104
|
+
return hash if global_id_hash?(hash)
|
|
105
|
+
|
|
106
|
+
# ActiveJob wraps keyword args at TWO layers: the outer mailer
|
|
107
|
+
# payload `{"args" => [kwargs_hash], "_aj_ruby2_keywords" => ["args"]}`
|
|
108
|
+
# and the inner kwargs hash itself, also tagged `_aj_ruby2_keywords`.
|
|
109
|
+
# Each wrapper layer is framework noise — recursing into it without
|
|
110
|
+
# spending depth budget keeps the real kwargs from collapsing to
|
|
111
|
+
# "[Object]" at depth 3. Sensitive-key filtering still runs on the
|
|
112
|
+
# real entries (passwords don't leak; the wrapper just doesn't cost
|
|
113
|
+
# a depth level).
|
|
114
|
+
return sanitize_ruby2_keywords_wrapper(hash, depth) if ruby2_keywords_wrapper?(hash)
|
|
115
|
+
|
|
99
116
|
return "[Object]" if depth >= MAX_NESTING_DEPTH
|
|
100
117
|
return {} if hash.empty?
|
|
101
118
|
|
|
@@ -104,6 +121,24 @@ module EzLogsAgent
|
|
|
104
121
|
end
|
|
105
122
|
end
|
|
106
123
|
|
|
124
|
+
# Sanitize the entries of an _aj_ruby2_keywords wrapper at the SAME
|
|
125
|
+
# depth as the wrapper itself, then re-attach the marker. This is what
|
|
126
|
+
# lets kwargs survive past the depth-3 cap when they're wrapped at
|
|
127
|
+
# depth 2-3 by the outer mailer payload.
|
|
128
|
+
def sanitize_ruby2_keywords_wrapper(hash, depth)
|
|
129
|
+
result = {}
|
|
130
|
+
hash.each do |key, value|
|
|
131
|
+
if ruby2_keywords_marker_key?(key)
|
|
132
|
+
# Preserve the marker verbatim — it's used to identify the
|
|
133
|
+
# wrapper on the receiving side, not to display.
|
|
134
|
+
result[key] = value
|
|
135
|
+
else
|
|
136
|
+
result[key] = sanitize_value(key, value, depth)
|
|
137
|
+
end
|
|
138
|
+
end
|
|
139
|
+
result
|
|
140
|
+
end
|
|
141
|
+
|
|
107
142
|
def sanitize_array_value(array, depth)
|
|
108
143
|
return [] if array.empty?
|
|
109
144
|
|
|
@@ -145,6 +180,31 @@ module EzLogsAgent
|
|
|
145
180
|
value.is_a?(TrueClass) ||
|
|
146
181
|
value.is_a?(FalseClass)
|
|
147
182
|
end
|
|
183
|
+
|
|
184
|
+
# True iff `hash` is the exact one-key shape ActiveJob uses to serialize
|
|
185
|
+
# an ActiveRecord (or any GlobalID::Identification) argument:
|
|
186
|
+
# `{"_aj_globalid" => "gid://..."}`. Used to exempt these hashes from
|
|
187
|
+
# the depth-limit collapse so the wire still carries the record ref.
|
|
188
|
+
def global_id_hash?(hash)
|
|
189
|
+
return false unless hash.is_a?(Hash) && hash.size == 1
|
|
190
|
+
gid = hash["_aj_globalid"] || hash[:_aj_globalid]
|
|
191
|
+
gid.is_a?(String) && gid.start_with?("gid://")
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
# True iff `hash` carries the `_aj_ruby2_keywords` marker. ActiveJob
|
|
195
|
+
# uses this marker on any hash that originated as a keyword-argument
|
|
196
|
+
# splat (so the framework can re-splat on deserialize). Used to skip
|
|
197
|
+
# the depth penalty for these framework wrappers — the marker's
|
|
198
|
+
# presence is the unambiguous signal we're inside an ActiveJob
|
|
199
|
+
# serialization layer, not customer data.
|
|
200
|
+
def ruby2_keywords_wrapper?(hash)
|
|
201
|
+
return false unless hash.is_a?(Hash)
|
|
202
|
+
hash.key?("_aj_ruby2_keywords") || hash.key?(:_aj_ruby2_keywords)
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def ruby2_keywords_marker_key?(key)
|
|
206
|
+
key.to_s == "_aj_ruby2_keywords"
|
|
207
|
+
end
|
|
148
208
|
end
|
|
149
209
|
end
|
|
150
210
|
end
|
metadata
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: ez_logs_agent
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.10
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- dezsirazvan
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
|
-
date: 2026-05
|
|
10
|
+
date: 2026-06-05 00:00:00.000000000 Z
|
|
11
11
|
dependencies:
|
|
12
12
|
- !ruby/object:Gem::Dependency
|
|
13
13
|
name: request_store
|