iugu_logger 0.10.0 → 0.11.0

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: 9f3b99e1a559a5f178c6b1912682683904d257c4f951f33ea5dce7f61e8c3e0d
4
- data.tar.gz: 3eae5a9150343a4a467d422eb87956fe7995a0f83cd0636304559ba767fda055
3
+ metadata.gz: '015286b1afd6fc355f095a1ef61578d4b5d46e2015caa8604a1cb731e3c6cc74'
4
+ data.tar.gz: 21cc16a5dca1aab380d0e65be5f276c291213f733f4c3a089988412e5ae45c88
5
5
  SHA512:
6
- metadata.gz: 4db9c2d097eb568762a8e931f7d484ca3b294d25a926f84b1031f75ef0bc6d27cf50c466a9d2049cccfe9221396d541608f73f65cade6af3d68f3efc2be56fe0
7
- data.tar.gz: a1e4f13b8b04c6be87b5cacf2dbac6c09b1370906b2e83a7427eb3a63197a45033069085d148c78b5b582424b9441021ca22f1a71aedf09661ae0156e353903a
6
+ metadata.gz: 37b668182fbb6523ec9b69b9854637cc9d0b5b838bc8ccf0a554b0e664081ea8ee64d98d82446738d82ea401096013ea1af1c24a504841fb04eff35a0f8e297d
7
+ data.tar.gz: eab988738a54515f2f993a153a47a570b0d2f7689dcd93c34bb1e19edded0ba4e910e308c55a00bb955c6f8347d297d1fccef555bc844db4a4d1c60f2b19c2d6
data/CHANGELOG.md ADDED
@@ -0,0 +1,564 @@
1
+ # Changelog
2
+
3
+ All notable changes to `iugu_logger` are documented here.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [0.11.0](https://github.com/iugu-private/iugu-logger-ruby/compare/v0.10.0...v0.11.0) (2026-07-01)
9
+
10
+
11
+ ### Features
12
+
13
+ * schema-sync guardrails (auto-sync, freshness gate, version manifest) ([#32](https://github.com/iugu-private/iugu-logger-ruby/issues/32)) ([3175f4a](https://github.com/iugu-private/iugu-logger-ruby/commit/3175f4a7fb44f5666bddd0aea2df522162e8ada3))
14
+
15
+ ## [0.10.0](https://github.com/iugu-private/iugu-logger-ruby/compare/v0.9.0...v0.10.0) (2026-06-01)
16
+
17
+
18
+ ### Features
19
+
20
+ * add automated schema conformance gate to CI ([#31](https://github.com/iugu-private/iugu-logger-ruby/issues/31)) ([f3f3dfb](https://github.com/iugu-private/iugu-logger-ruby/commit/f3f3dfba18e1f6af126f16123b4b3c3e80e653b9))
21
+ * single-line default, trace context OTEL-aware e service.instance opt-in ([#28](https://github.com/iugu-private/iugu-logger-ruby/issues/28)) ([e9f1f88](https://github.com/iugu-private/iugu-logger-ruby/commit/e9f1f88d0f73bb166f395e3082cd733c02ee6778))
22
+
23
+ ## [0.9.0](https://github.com/iugu-private/iugu-logger-ruby/compare/v0.8.1...v0.9.0) (2026-05-13)
24
+
25
+
26
+ ### Features
27
+
28
+ * configurable log size cap + conformance suite runner ([c1d1be3](https://github.com/iugu-private/iugu-logger-ruby/commit/c1d1be3f3b5c98c1af37504649691d916d80bb7b))
29
+ * configurable log size cap + conformance suite runner ([5d4bf82](https://github.com/iugu-private/iugu-logger-ruby/commit/5d4bf824c639567fb6c85bb6c64601f31f25b9d6))
30
+
31
+ ## [0.9.0] — Unreleased
32
+
33
+ ### Added — `Configuration#max_log_size_kb` + automatic params truncation
34
+
35
+ Operational logs in iugu carry the full request payload (`request.params`)
36
+ since v0.8.0 — great for ops/support/fraud but it can blow up the
37
+ emitted log size for endpoints with large bodies (uploads with base64
38
+ attachments, batched PIX, etc.).
39
+
40
+ `Configuration#max_log_size_kb` (default 64) caps the encoded payload.
41
+ When the JSON-encoded log would exceed the cap, the `Logger#emit` path:
42
+
43
+ - Replaces `request.params` with the string `"[TRUNCATED]"`
44
+ - Sets `request.params_truncated: true` so consumers know
45
+ - Preserves every other canonical field (trace, iugu, http, rails, pii,
46
+ service, etc.) — observability and audit stay intact
47
+
48
+ Set to `nil` to disable.
49
+
50
+ ### Added — Conformance suite runner
51
+
52
+ `spec/conformance/conformance_spec.rb` exercises the YAML fixtures
53
+ mirrored from `iugu-logging-schema/conformance/`. When the Go / Node
54
+ SDKs are implemented, they should run the same fixtures and produce
55
+ identical `pii.scanned`/`detected`/`redacted` and post-scan content —
56
+ guaranteeing cross-language behavior parity.
57
+
58
+ 11 fixtures covering CPF, CNPJ, CC (Luhn-valid + Luhn-rejected CNPJ),
59
+ email, phone, AWS key, Bearer, `iugu.account_id` SAFE_PATTERN, password
60
+ Layer 1 filter, and multiple-PII independence.
61
+
62
+ ### Compatibility
63
+
64
+ No breaking change. New configuration option defaults conservatively
65
+ (64 KB cap, well above typical request sizes). API surface unchanged.
66
+ PII strategies unchanged from v0.8 (data-completeness-first preserved).
67
+
68
+ ## [0.8.1](https://github.com/iugu-private/iugu-logger-ruby/compare/v0.8.0...v0.8.1) (2026-05-13)
69
+
70
+
71
+ ### Bug Fixes
72
+
73
+ * cc Luhn + format empty-string + view/db runtime via subscriber ([911fe13](https://github.com/iugu-private/iugu-logger-ruby/commit/911fe13f728387c2bc409844b32f3822fc50d6f0))
74
+ * CC Luhn + format empty-string + view/db runtime via subscriber ([a18eea9](https://github.com/iugu-private/iugu-logger-ruby/commit/a18eea9db8346dd9300478793c4506bd037f2289))
75
+ * **railtie:** wrap rescue in explicit begin/end for Ruby 2.4 compat ([7811822](https://github.com/iugu-private/iugu-logger-ruby/commit/78118225a6a4b8e4c3fb007166e4bfd18bd5b8b6))
76
+
77
+ ## [0.8.1] — Unreleased
78
+
79
+ ### Fixed — CNPJ values being redacted as credit cards (production false positive)
80
+
81
+ The CC regex matched any 13–19 digit sequence (the format only validates
82
+ length and optional separators). In fraud-payout's v0.8.0 production
83
+ deploy this redacted CNPJ values like `54565372000194` as
84
+ `"**** **** **** 0194"` — losing operational signal AND inflating the
85
+ `pii.detected: [cc]` count incorrectly.
86
+
87
+ Fixed by adding a **Luhn (mod-10) checksum validation** before treating
88
+ a match as a card. Real CC numbers pass Luhn; CPF / CNPJ / arbitrary
89
+ numeric identifiers fail.
90
+
91
+ `Pii::Scanner#safe_match?` now takes the type as a second argument and
92
+ short-circuits CC matches that fail `luhn_valid?`.
93
+
94
+ ### Fixed — `request.format` emitting `""` for ActionController::API endpoints
95
+
96
+ `extract_request_format` returned `Mime#symbol.to_s` even when the
97
+ underlying symbol was `nil` (the `Mime::ALL` case for content-type-less
98
+ API endpoints), producing `"format": ""` in production. Now we fall
99
+ through to `Mime#to_s`, then `HTTP_ACCEPT`, then omit the key entirely.
100
+
101
+ ### Fixed — `rails.view_runtime_ms` / `rails.db_runtime_ms` missing for ActionController::API
102
+
103
+ The `action_dispatch.view_runtime` / `db_runtime` env keys are only set
104
+ by Rails' full-stack ActionController::Base; ActionController::API
105
+ (used by fraud-payout and most iugu services) leaves them unset.
106
+
107
+ The Railtie now subscribes to `process_action.action_controller` —
108
+ canonical notification fired at the end of every action regardless of
109
+ controller class — and stashes the `view_runtime` / `db_runtime`
110
+ payload values in `Buffer.current.rails_runtime`. The middleware reads
111
+ from there when building the `rails.*` block.
112
+
113
+ Specs added covering all three fixes (Luhn rejection of CNPJ, format
114
+ nil-symbol fallback, Buffer-sourced runtimes).
115
+
116
+ ### Compatibility
117
+
118
+ - Hosts not using Rails: untouched (Buffer.rails_runtime stays empty).
119
+ - Hosts using ActionController::Base (full-stack Rails view rendering):
120
+ unchanged behavior — env keys still take precedence over Buffer.
121
+ - No public API change.
122
+
123
+ ## [0.8.0](https://github.com/iugu-private/iugu-logger-ruby/compare/v0.7.0...v0.8.0) (2026-05-13)
124
+
125
+
126
+ ### Features
127
+
128
+ * **request_logger:** enrich canonical event for legacy rails_semantic_logger parity ([c1599aa](https://github.com/iugu-private/iugu-logger-ruby/commit/c1599aa6543261eab1359a8b383e172d375f27dc))
129
+ * **request_logger:** enrich canonical event for legacy rails_semantic_logger parity ([8c48c95](https://github.com/iugu-private/iugu-logger-ruby/commit/8c48c95a6688ffd010378d2e9a597c3974bd8488))
130
+
131
+ ## [0.8.0] — Unreleased
132
+
133
+ ### Added — `RequestLogger` enriquece o evento canônico com paridade ao legacy `rails_semantic_logger`
134
+
135
+ `http.request.completed` (e `.failed`) agora carrega:
136
+
137
+ - `request.params` — payload do request com `config.filter_parameters`
138
+ do host Rails já aplicado (pix_key, cards, password etc. chegam como
139
+ `[FILTERED]`). Lido de `env['action_dispatch.request.parameters']`.
140
+ - `request.format` — formato negociado da resposta. Lido de
141
+ `env['action_dispatch.request.formats']` (Rails Mime) com fallback
142
+ no header `HTTP_ACCEPT` pra apps Rack puro.
143
+ - `http.status_message` — `"OK" / "Not Found" / ...` via
144
+ `Rack::Utils::HTTP_STATUS_CODES`.
145
+ - `rails.controller`, `rails.action`, `rails.view_runtime_ms`,
146
+ `rails.db_runtime_ms` — bloco novo populado quando o dispatcher Rails
147
+ expõe `env['action_controller.instance']` e os runtimes
148
+ `action_dispatch.view_runtime` / `db_runtime`. Ausente em hosts
149
+ não-Rails (Sinatra, Rack puro, Jets/Lambda hoje).
150
+
151
+ Motivação: fechar o gap operacional com o `Completed #...` do
152
+ `rails_semantic_logger` que ops/suporte/fraude/ML pipelines da iugu
153
+ consomem hoje. Com v0.7 (defaults `:detect_only` em PII) + v0.8
154
+ (enriquecimento), um único evento canônico carrega:
155
+
156
+ - Tudo que o legacy carrega (controller, action, params, runtimes…)
157
+ - Mais o valor adicionado iugu (event.action, service.version,
158
+ service.instance, iugu.account_id, pii.detected, trace.*)
159
+
160
+ Resultado: a próxima Phase C (PR's de migração `Rails.logger.info →
161
+ IuguLogger.event` em fraud-payout etc.) pode finalmente REMOVER a
162
+ linha legada, em vez de manter coexistência indefinida.
163
+
164
+ ### Compatibility
165
+
166
+ - Sem mudança de API pública. Mesma surface; só campos novos no payload
167
+ emitido.
168
+ - Sem mudança em hosts não-Rails — os blocos `rails.*` e
169
+ `request.params/format` simplesmente não aparecem.
170
+ - Defensivo: cada extração tem `rescue StandardError` — instrumentação
171
+ nunca quebra a request.
172
+
173
+ ## [0.7.0](https://github.com/iugu-private/iugu-logger-ruby/compare/v0.6.3...v0.7.0) (2026-05-13)
174
+
175
+
176
+ ### ⚠ BREAKING CHANGES
177
+
178
+ * default PII strategies for cpf / cnpj / phone / address changed from :full_redact to :detect_only. Apps that depend on '[CPF_REDACTED]'-style markers in log content will start seeing raw values. Migration is mechanical: either accept the new default or pin specific types back to :full_redact via the override pattern.
179
+
180
+ ### Features
181
+
182
+ * flip default PII strategies to :detect_only (data-completeness-first) ([c44be0c](https://github.com/iugu-private/iugu-logger-ruby/commit/c44be0c88a378a51314d5607beb09fe7f2985070))
183
+
184
+ ## [0.6.3](https://github.com/iugu-private/iugu-logger-ruby/compare/v0.6.2...v0.6.3) (2026-05-12)
185
+
186
+
187
+ ### Bug Fixes
188
+
189
+ * **request_logger:** re-read tenant after [@app](https://github.com/app).call ([b77805f](https://github.com/iugu-private/iugu-logger-ruby/commit/b77805f5f7dca7a721834f99d2bb38effd2d8bc7))
190
+ * **request_logger:** re-read tenant after [@app](https://github.com/app).call ([448e43e](https://github.com/iugu-private/iugu-logger-ruby/commit/448e43e35522444a80398fb0fc7ee909d704b8f5))
191
+
192
+ ## [Unreleased]
193
+
194
+ ## [0.7.0] — 2026-05-12
195
+
196
+ ### Changed — Default PII strategies flip to `:detect_only` (data-completeness-first)
197
+
198
+ Aligns the SDK with how iugu operationally consumes logs: ops, support,
199
+ fraud analysts, compliance, and ML pipelines need the raw personal data
200
+ that the legacy `rails_semantic_logger` output already emits today (full
201
+ CPF, CNPJ, phone, email, address, bank account, etc.). The pre-v0.7
202
+ defaults aggressively redacted those values, breaking parity with the
203
+ legacy stream that downstream consumers depend on.
204
+
205
+ New defaults in `IuguLogger::Pii::DEFAULT_STRATEGIES`:
206
+
207
+ | Type | Before (0.6.x) | After (0.7) |
208
+ |---|---|---|
209
+ | `cpf` | `:full_redact` | `:detect_only` |
210
+ | `cnpj` | `:full_redact` | `:detect_only` |
211
+ | `phone` | `:full_redact` | `:detect_only` |
212
+ | `email` | `:detect_only` | `:detect_only` (unchanged) |
213
+ | `address` | (no default) | `:detect_only` |
214
+ | `cc` | `:last4` | `:last4` (KEPT — PCI-DSS) |
215
+ | `aws_key` | `:full_redact` | `:full_redact` (KEPT — credential) |
216
+ | `bearer` | `:full_redact` | `:full_redact` (KEPT — credential) |
217
+ | `url_with_creds` | `:full_redact` | `:full_redact` (KEPT — credential) |
218
+
219
+ `:detect_only` means: **the scanner still scans, still records
220
+ `pii.detected: [cpf, phone, ...]` (so audit / tagging / cardinality
221
+ queries keep working) — but it does NOT modify the content.** LGPD
222
+ compliance is then enforced by access-control and retention on the log
223
+ store (Loki, Datadog), not by removing data at the source.
224
+
225
+ Things explicitly NOT changed:
226
+
227
+ - **PCI-DSS protection** — credit card numbers still redact to last-4.
228
+ - **Credential redaction** — AWS keys, Bearer tokens, URLs with embedded
229
+ creds still fully redacted. These are never user data; they're only
230
+ leak risk.
231
+ - **ILS-002 `iugu.account_id` SAFE_PATTERN** — still preserved.
232
+
233
+ Apps that need stricter redaction can opt in per-type via
234
+ `Configuration#pii_redaction`:
235
+
236
+ ```ruby
237
+ IuguLogger.configure do |c|
238
+ c.pii_redaction = IuguLogger::Pii::DEFAULT_STRATEGIES.merge(
239
+ cpf: :full_redact,
240
+ email: :full_redact
241
+ )
242
+ end
243
+ ```
244
+
245
+ ### Changed — Smoke test renamed `pii_redaction` → `pii_detection`
246
+
247
+ The 6th smoke check now validates detection-without-modification (the
248
+ new default), instead of redaction. `bundle exec rake iugu_logger:smoke`
249
+ shows `✓ pii_detection` instead of `✓ pii_redaction`.
250
+
251
+ ### Changed — Generator template
252
+
253
+ `rails g iugu_logger:install` now emits an initializer that documents the
254
+ new default and the override pattern, and drops the dead
255
+ `HEROKU_SLUG_COMMIT` / `SOURCE_VERSION` fallback chain (use `GIT_SHA`
256
+ only — same fallback the fraud-payout pilot uses).
257
+
258
+ ### Compatibility
259
+
260
+ **Breaking change in default behavior** — code that asserts on
261
+ `'[CPF_REDACTED]'`-style markers will start failing after upgrading.
262
+ The migration is mechanical: either accept the new default (PII stays
263
+ in the log) or pin specific types back to `:full_redact` via the
264
+ override pattern above.
265
+
266
+ No API surface change — same constants, same method signatures.
267
+
268
+ ## [0.6.3] — 2026-05-12
269
+
270
+ ### Fixed — `iugu.*` block always empty in canonical http.request.completed events (production bug)
271
+
272
+ `RequestLogger` extracted tenant context (`TenantContext.from_rack(env)`) at
273
+ the *start* of the request, before `@app.call`. In real apps, tenant
274
+ identifiers (`env['iugu.current_account_id']`, etc.) are populated by a
275
+ controller `before_action` that runs *during* dispatch — so the early
276
+ extraction always saw the env keys missing, and the emitted
277
+ `http.request.completed` event was missing the `iugu.*` block.
278
+
279
+ Caught when fraud-payout (ILS-030 pilot) added the
280
+ `Api::IuguTenantContext` concern in the canonical way (after authenticate,
281
+ populating `request.env['iugu.current_account_id']`): no `iugu` block
282
+ showed up in Datadog despite the env being correctly populated.
283
+
284
+ Fix: re-read tenant *after* `@app.call` in both the success and exception
285
+ paths. The pre-call extraction is kept as a best-effort fallback for hosts
286
+ that prefer to populate tenant in a Rack middleware upstream of
287
+ RequestLogger (still valid; both paths converge on whatever the final
288
+ state of env is).
289
+
290
+ This is the canonical timing for Rack middleware that emits per-request
291
+ events — see `lograge`'s `before_format` hook for the equivalent pattern.
292
+
293
+ No public API change. Existing callers see no behavior difference except
294
+ that `iugu.*` now actually populates when the host app sets the env
295
+ during dispatch.
296
+
297
+ ## [0.6.2] — 2026-05-09
298
+
299
+ ### Fixed — PII false positive on structural identifiers (production bug)
300
+
301
+ The phone regex `/\(?\d{2}\)?\s?9?\d{4}-?\d{4}\b/` matched any 10-11 digit
302
+ run, redacting hex `trace.span_id` / `trace.id` / `request.id` values that
303
+ happened to contain numeric sub-strings as `[PHONE_REDACTED]`. Observed in
304
+ **conector-vtex** (cluster 134, 2026-05-09): 100% of `http.request.completed`
305
+ events had `trace.span_id` redacted to `"000000[PHONE_REDACTED]"`, breaking
306
+ trace correlation downstream.
307
+
308
+ Two-layer defense:
309
+
310
+ - **`Pii::SAFE_KEY_PATHS`** — schema canonical paths (`trace.id`,
311
+ `trace.span_id`, `trace.parent_id`, `request.id`, `service.instance`,
312
+ `service.name`, `service.version`, `service.environment`, `event.action`,
313
+ `event.kind`, `log.level`, `@timestamp`, `http.status_code`,
314
+ `http.duration_ms`) skip the scan entirely. Values at these paths are
315
+ structural identifiers / controlled metadata defined by §2 of the spec
316
+ and never carry user-supplied content.
317
+ - **`Pii::SAFE_PATTERNS` expanded** — added `otel_trace_id` (32-hex),
318
+ `otel_span_id` (16-hex), `uuid` (v4/v7), and made `iugu_account_id` 32-hex
319
+ case-insensitive (modern lowercase + legacy uppercase). Defense-in-depth
320
+ for hex IDs found in arbitrary string content.
321
+ - **`Pii::PATTERNS[:phone]`** — added lookarounds `(?<![\w-])` and `(?![\w-])`
322
+ to require non-identifier flanking. Prevents matches inside dense
323
+ identifier tokens (e.g. `job-1234567890-def`) while still detecting
324
+ plain-text Brazilian phone numbers.
325
+
326
+ ### Added — Human-readable `message` summary in canonical middlewares
327
+
328
+ `message` field now carries an Apache-style summary line so log viewers
329
+ (Loki, Datadog, Grafana, plain `kubectl logs`) show actionable info
330
+ without expanding the JSON. Canonical `event.action` is unchanged in
331
+ attributes for queries.
332
+
333
+ - `RequestLogger` — `"<METHOD> <PATH> <STATUS> [<duration_ms>ms]"` on
334
+ success, `"<METHOD> <PATH> failed [<duration_ms>ms] <ErrorClass>"` on
335
+ exceptions.
336
+ - `JobLogger` — `"<JobClass>#perform [<queue>] ok [<duration_ms>ms]"` on
337
+ success, `"<JobClass>#perform [<queue>] failed [<duration_ms>ms] <ErrorClass>"`
338
+ on exceptions.
339
+ - `Logger#event` — accepts `message:` keyword (already supported); no API
340
+ change required for app code calling `IuguLogger.event(...)`.
341
+
342
+ ### Compatibility
343
+
344
+ Fully backward compatible. No public API change. All call-sites that already
345
+ work with 0.6.1 continue to work; the only observable difference is the
346
+ `message` field now contains a summary instead of repeating `event.action`.
347
+
348
+ ---
349
+
350
+ ### Added — v0.6 Install generator + smoke rake task (zero-puxadinho onboarding)
351
+ Standard "drop in any Rails project" pattern, used by the fraud-payout pilot
352
+ and by every future consumer:
353
+
354
+ ```sh
355
+ rails g iugu_logger:install # generates config/initializers/iugu_logger.rb
356
+ bundle exec rake iugu_logger:smoke # validates the integration end-to-end
357
+ ```
358
+
359
+ - `rails g iugu_logger:install` — `IuguLogger::Generators::InstallGenerator`
360
+ creates `config/initializers/iugu_logger.rb` from an ERB template with
361
+ sensible defaults (service_name auto-derived from `Rails.application.class`,
362
+ format pretty in dev / JSON elsewhere, validator `:warn`, PII defaults).
363
+ Idempotent — re-running asks before overwriting.
364
+ - `rake iugu_logger:smoke` — `IuguLogger::SmokeTest.run` runs 6 end-to-end
365
+ checks against an isolated Logger that mirrors the host app's config:
366
+ 1. `sdk_loaded` — required modules defined
367
+ 2. `configuration_present` — service_name/version/environment set
368
+ 3. `basic_emit` — canonical schema fields populated
369
+ 4. `pii_redaction` — CPF in message → `[CPF_REDACTED]` + `pii.detected`
370
+ 5. `account_id_safe_pattern` — 32-hex preserved (ILS-002)
371
+ 6. `single_line_json` — Loki-friendly one-line output, valid JSON
372
+ Exits non-zero on any failure.
373
+ - Railtie now `load`s `lib/iugu_logger/tasks/iugu_logger.rake` so the rake
374
+ task is available in any Rails app the moment the gem is bundled.
375
+ - Gemspec includes `lib/**/*.rake` and `lib/generators/**/*.tt` in the
376
+ shipped package.
377
+
378
+ ### Changed
379
+ - Bumped to `0.6.0`.
380
+
381
+ ### Added — v0.5 Railtie auto-config (ILS-023 finale)
382
+ - `IuguLogger::Railtie` (loaded only when `::Rails::Railtie` is defined):
383
+ - **Middleware insertion:** `IuguLogger::RequestLogger` is inserted after
384
+ `ActionDispatch::DebugExceptions` automatically. Apps no longer need to
385
+ edit `config/application.rb`.
386
+ - **Sidekiq auto-register:** when Sidekiq is loaded server-side,
387
+ `IuguLogger::JobLogger::Sidekiq` is added to the server middleware chain.
388
+ - **Service name auto-derive:** `Rails.application.class.name` →
389
+ snake_case + dashed (e.g. `PixuguPlatform::Application` → `pixugu-platform`).
390
+ Skipped when `service_name` was already set explicitly.
391
+ - `Rails.logger` is intentionally **not** replaced in this release. Apps
392
+ migrate to `IuguLogger.event(...)` for schema-conforming events; existing
393
+ `Rails.logger.X` calls keep working unchanged. (A future opt-in adapter
394
+ may route `Rails.logger` through the buffer; deferred until the
395
+ fraud-payout pilot validates the migration ergonomics.)
396
+ - 6 RSpec examples for `derive_service_name` heuristic + Railtie load.
397
+ Real Rails integration is verified during the fraud-payout pilot
398
+ (ILS-030).
399
+
400
+ ### Changed
401
+ - Bumped to `0.5.0` (auto-config completes the v0.4 series).
402
+
403
+ ### Added — v0.4.1 JobLogger (Sidekiq + ActiveJob middlewares — ILS-023 part 2)
404
+ - `IuguLogger::JobLogger::Adapter` — shared body around a job execution
405
+ (Buffer reset/drain, request+labels context, completed/failed event emit,
406
+ exception fingerprint, monotonic clock).
407
+ - `IuguLogger::JobLogger::Sidekiq` — server middleware. Register via
408
+ `Sidekiq.configure_server { ... chain.add IuguLogger::JobLogger::Sidekiq }`.
409
+ Compatible with sidekiq, sidekiq-pro, sidekiq-ent (msg payload format
410
+ identical). Maps `msg['retry_count']` → `attempt` (first execution = 1).
411
+ - `IuguLogger::JobLogger::ActiveJob` — mixin. `include` in ApplicationJob.
412
+ Falls back to `attempt: 1` when ActiveJob does not implement
413
+ `#executions` (Rails 4.2 / platform).
414
+ - Each job execution emits one canonical event:
415
+ - `<source>.job.completed` (`sidekiq.job.completed` or `activejob.job.completed`)
416
+ on success — severity `:info`, includes `request`, `labels`, `duration_ms`,
417
+ drained `logs:`.
418
+ - `<source>.job.failed` on exception — severity `:error`, includes
419
+ `error.{type, message, fingerprint}`. Re-raises so other middleware sees
420
+ the original error.
421
+ - `labels` carries low-cardinality dimensions (`job_class`, `queue`,
422
+ `attempt`); per-execution things (`duration_ms`, `job_id`) live elsewhere
423
+ to avoid Loki cardinality blowup.
424
+
425
+ ### Changed
426
+ - Bumped to `0.4.1`.
427
+
428
+ ### Added — v0.4 thread-local Buffer + Rack RequestLogger middleware (ILS-023 part 1)
429
+ - `IuguLogger::Buffer` — per-thread buffer (via `Concurrent::ThreadLocalVar`):
430
+ - `Buffer.current` — lazy-instantiated singleton per thread
431
+ - `Buffer.reset!` — wipes current thread's buffer
432
+ - `#push(severity:, message:, **extras)` — appends a log entry
433
+ - `#drain` — returns and clears entries (used by middleware at request end)
434
+ - `#add_context(**)` / `#context` / `#reset_context!` — request-scoped fields
435
+ - `MAX_ENTRIES = 100` cap to prevent unbounded growth
436
+ - `IuguLogger::RequestLogger` — Rack middleware:
437
+ - Resets buffer at request start, populates context with `trace` (via
438
+ `TraceContext.extract`) and `iugu` (via `TenantContext.from_rack`)
439
+ - Wraps downstream app, captures duration via monotonic clock
440
+ - On success: emits `http.request.completed` with `request`, `http`,
441
+ `trace`, `iugu`, and drained `logs: [...]`. Severity inferred from
442
+ HTTP status (info <400, warn <500, error ≥500)
443
+ - On exception: emits `http.request.failed` with `error.{type, message,
444
+ fingerprint}` (sha256 of normalized message — stable for grouping),
445
+ re-raises so other middleware sees the original error
446
+ - Always resets buffer in `ensure`, even on exception
447
+ - Empty `trace` / `iugu` / `logs` blocks omitted from emitted payload
448
+
449
+ ### Changed
450
+ - `lib/iugu_logger.rb` now requires `buffer` and `request_logger` modules.
451
+ - Bumped to `0.4.0`.
452
+
453
+ ### Added — v0.3.1 trace + tenant context extractors (ILS-023 prep)
454
+ - `IuguLogger::TraceContext.extract(rack_env:)` — chain of sources:
455
+ 1. `OpenTelemetry::Trace.current_span` (when otel-api gem loaded)
456
+ 2. `Datadog::Tracing.active_trace` (when ddtrace loaded — Ruby 2.4 OK)
457
+ 3. W3C `traceparent` header (manual parse, version-agnostic)
458
+ 4. Legacy iugu `X-Request-Id` / `action_dispatch.request_id` (padded to
459
+ 32 hex; correlation only, not a real W3C trace ID — for platform/Ruby 2.4)
460
+ 5. `nil`
461
+ - Ruby 2.4 first-class — defensive `rescue StandardError` around tracing-lib
462
+ calls so any oddity in OTEL/ddtrace can't break logging.
463
+ - `IuguLogger::TenantContext.from_rack(env, key_mapping:)` — extracts
464
+ iugu.* identifiers from Rack env using the convention
465
+ `env['iugu.current_<field>']`. Default mapping covers account_id,
466
+ subaccount_id, organization_id, user_id, tier, feature.
467
+ - 27 new RSpec examples for the two extractor modules (priority chain,
468
+ malformed traceparent rejection, OTEL/Datadog stubbed extraction,
469
+ custom key mappings).
470
+
471
+ These modules are pure utilities — Logger does NOT call them automatically
472
+ yet. Apps integrate manually:
473
+
474
+ ```ruby
475
+ IuguLogger.event('pix.out.requested',
476
+ trace: IuguLogger::TraceContext.extract(rack_env: request.env),
477
+ iugu: IuguLogger::TenantContext.from_rack(request.env),
478
+ pix: { ... })
479
+ ```
480
+
481
+ The `IuguLogger::RequestLogger` Rack middleware (v0.4) will automate this.
482
+
483
+ ### Changed
484
+ - Bumped to `0.3.1`.
485
+
486
+ ### Added — v0.3 event.action registry validator (ILS-022)
487
+ - `IuguLogger::Schema::Validator` with 3 modes:
488
+ - `:strict` — raises `IuguLogger::UnknownEventAction` (with typo suggestions
489
+ via Levenshtein) or `IuguLogger::SchemaViolation` (with missing field list)
490
+ - `:warn` — emits the log with `labels.schema_warning` annotation
491
+ (`unknown_event_action` or `missing_required:<fields>`)
492
+ - `:off` — disabled (default — backward compatible)
493
+ - `IuguLogger::Schema.load_from_file(path)` — loads `dist/registry.json`
494
+ from `iugu-logging-schema` (or any compatible file).
495
+ - `Configuration#event_action_validator` (`:strict`/`:warn`/`:off`)
496
+ - `Configuration#event_action_registry` (Hash from load_from_file or nil)
497
+ - Logger applies registry `event_kind` override when caller does not pass
498
+ explicit `kind:` (e.g. `pix.out.executed` → audit class automatically).
499
+ - Required fields support dot-notation paths (`pix.end_to_end_id`,
500
+ `iugu.account_id`); accepts both string and symbol keys; empty strings
501
+ treated as missing.
502
+ - 16 RSpec examples for Schema + 8 integration tests in Logger.
503
+
504
+ ### Changed
505
+ - `Logger#event` validates against registry BEFORE PII scan (fail fast).
506
+ - `event(action, severity:, kind:, ...)` now defaults severity/kind to nil
507
+ (was `:info`/`'event'`); registry overrides take precedence over defaults
508
+ but caller-provided values still win.
509
+ - Bumped to `0.3.0`.
510
+
511
+ ### Added — v0.2 PII redaction (ILS-021)
512
+ - `IuguLogger::Pii` — 3-layer defense:
513
+ - **Layer 1 (param-name filter):** values of keys matching the blocklist
514
+ (password, secret, token, authorization, api_key, cvv, ssn, pin, etc.)
515
+ replaced with `[FILTERED]` before any content scan. Case-insensitive.
516
+ - **Layer 2 (regex content redaction):** patterns for CPF, CNPJ, email,
517
+ phone (BR), CC, AWS access key, Bearer token, URL with embedded
518
+ credentials. Regex reused from production-validated
519
+ `core/utils/sanitizer.py` (iugu-agents).
520
+ - **Layer 3 (Logger enforcement):** every emitted payload carries
521
+ `pii.scanned=true` populated by Scanner.
522
+ - `Pii::SAFE_PATTERNS` — `iugu.account_id` 32-hex preserved (ILS-002).
523
+ - `Pii::DEFAULT_STRATEGIES` — per-type redaction config:
524
+ - `cpf/cnpj/phone/aws_key/bearer/url_with_creds` → `:full_redact`
525
+ - `cc` → `:last4` (PCI-safe `**** **** **** 1234`)
526
+ - `email` → `:detect_only` (ILS-003 deferred — tech debt)
527
+ - Override per-type via `Configuration#pii_redaction`.
528
+ - `Pii::Result` — frozen object with `payload`, `detected`, `redacted_count`,
529
+ `to_pii_block` for serialization.
530
+ - `Configuration#pii_redaction` and `#pii_param_blocklist` accessors.
531
+ - 23 new RSpec examples for the Pii module + 7 integration tests in Logger.
532
+
533
+ ### Changed
534
+ - `Logger#event` now scans the user-supplied portion (message + fields) via
535
+ `Pii::Scanner` before emitting. SDK-controlled metadata fields
536
+ (`@timestamp`, `service.*`, `pii.*`) bypass scanning.
537
+ - `pii.*` block in emitted payload populated dynamically from scan results
538
+ (was static placeholder in v0.1).
539
+ - Bumped to `0.2.0`.
540
+
541
+ ### Added — v0.1 skeleton (ILS-020)
542
+ - `IuguLogger.configure` DSL with `service_name`, `service_version`,
543
+ `service_environment`, `output`, `format`.
544
+ - `IuguLogger.event(action, **fields)` — emits a JSON line conforming to the
545
+ iugu canonical schema (`@timestamp`, `log.level`, `event.kind`,
546
+ `event.action`, `service.*`, `pii.*`, plus pass-through fields).
547
+ - `IuguLogger::Severity` with custom `:note` level between `:info` and `:warn`.
548
+ - `IuguLogger::Configuration` with `validate!` (raises on missing required
549
+ fields).
550
+ - `IuguLogger::Logger` core — recursive hash key stringification, nil field
551
+ omission, JSON/pretty output formats.
552
+ - Custom error classes: `Error`, `ConfigurationError`, `SchemaViolation`,
553
+ `UnknownEventAction`.
554
+ - 14 RSpec examples covering happy paths and edge cases.
555
+ - CI matrix: Ruby 2.4 / 2.7 / 3.2.
556
+
557
+ ### Pending (next releases)
558
+ - v0.2 — `IuguLogger::Pii` (deep PII redaction, BR regex)
559
+ - v0.3 — `IuguLogger::Schema` (event.action registry validator)
560
+ - v0.4 — `IuguLogger::Transformer` + `TraceContext` + `TenantContext` Rack /
561
+ Sidekiq / ActiveJob middlewares + Railtie auto-config
562
+ - v1.0 — production-ready, conformance suite passing, fraud-payout pilot
563
+
564
+ [Unreleased]: https://github.com/iugu-private/iugu-logger-ruby/compare/v0.1.0...HEAD
data/CODEOWNERS ADDED
@@ -0,0 +1 @@
1
+ * @iugu-private/devops
data/README.md CHANGED
@@ -2,11 +2,13 @@
2
2
 
3
3
  > SDK Ruby do iugu Logging Standard (ILS) — schema canônico, PII detection, trace context, registry de eventos, paridade `rails_semantic_logger`. Funciona de Ruby 2.4 (platform) até 3.x (Rails 8).
4
4
 
5
- SDK Ruby que implementa o **iugu Logging Standard (ILS)**: logging estruturado JSON, schema canônico de eventos, detecção de PII e correlação de trace context.
5
+ 📖 **Conceito do projeto + como funciona o ILS:** [`iugu-logging-schema/README.md`](https://github.com/iugu-private/iugu-logging-schema)
6
+ 🏗️ **Arquitetura técnica detalhada:** [`iugu-logging-schema/ARCHITECTURE.md`](https://github.com/iugu-private/iugu-logging-schema/blob/main/ARCHITECTURE.md)
7
+ 🤖 **Contexto pra agentes de IA continuarem:** [CLAUDE.md](CLAUDE.md)
6
8
 
7
9
  ---
8
10
 
9
- ## Status: **v0.9.0 — em produção**
11
+ ## Status: **v0.9.0 — em produção no fraud-payout (ILS-030 pilot)**
10
12
 
11
13
  Validado em produção em 2026-05-13 com tráfego real. Componentes:
12
14
 
@@ -42,14 +44,59 @@ Validado em produção em 2026-05-13 com tráfego real. Componentes:
42
44
  ### 1. Adicionar a gem ao `Gemfile`
43
45
 
44
46
  ```ruby
45
- gem "iugu_logger", "~> 0.9"
47
+ source "https://rubygems.pkg.github.com/iugu-private" do
48
+ gem "iugu_logger", "~> 0.9"
49
+ end
50
+ ```
51
+
52
+ ### 2. Workflow CI declara `permissions: { contents: read, packages: read }`
53
+
54
+ Pra workflows que rodam `bundle install`:
55
+
56
+ ```yaml
57
+ jobs:
58
+ test:
59
+ permissions:
60
+ contents: read
61
+ packages: read
62
+ steps:
63
+ - uses: iugu-private/workflows-engenharia/.github/actions/setup-ruby@v1
64
+ with:
65
+ ruby-version: 3.3.9
66
+ bundler-cache: true
67
+ ```
68
+
69
+ Pra workflows que buildam Docker image (production deploys), passar opt-in:
70
+
71
+ ```yaml
72
+ build_and_push:
73
+ permissions:
74
+ contents: read
75
+ packages: read
76
+ uses: iugu-private/workflows-engenharia/.github/workflows/build-and-push-workflow.yml@v1
77
+ with:
78
+ BUNDLE_GITHUB_PACKAGES_AUTH: true
79
+ # ... outros inputs
46
80
  ```
47
81
 
48
- Depois rode `bundle install`. A gem é pública na RubyGems.org — sem `source` customizado, autenticação ou secret de build.
82
+ E no `Dockerfile`:
49
83
 
50
- Defina `GIT_SHA` no build/deploy (`service.version` dos eventos): no Dockerfile via `ARG GIT_SHA` + `ENV GIT_SHA=${GIT_SHA}`, ou via env no Deployment.
84
+ ```dockerfile
85
+ # syntax=docker/dockerfile:1.4
51
86
 
52
- ### 2. Gerar initializer + populate Rack tenant + smoke
87
+ FROM ruby:3.3.9
88
+ ARG GIT_SHA=0.0.0
89
+ ENV GIT_SHA=${GIT_SHA}
90
+
91
+ COPY . /app
92
+ WORKDIR /app
93
+
94
+ RUN --mount=type=secret,id=bundle_github_packages_auth \
95
+ BUNDLE_RUBYGEMS__PKG__GITHUB__COM="$(cat /run/secrets/bundle_github_packages_auth)" \
96
+ bundle install
97
+ ```
98
+
99
+ ### 3. Gerar initializer + populate Rack tenant + smoke
53
100
 
54
101
  ```sh
55
102
  rails g iugu_logger:install
@@ -99,7 +146,7 @@ end
99
146
  "message": "PATCH /api/v1/payments 200 [39ms]",
100
147
 
101
148
  "service": {
102
- "name": "payments-api",
149
+ "name": "iugu-fraud-payout",
103
150
  "version": "1db43d1c238229c550a68d44c3be6892fc11d398", // build SHA
104
151
  "environment": "production"
105
152
  // "instance" (= pod name) é opt-in: por padrão NÃO é emitido, pois o
@@ -219,7 +266,7 @@ end
219
266
 
220
267
  ```ruby
221
268
  IuguLogger.configure do |c|
222
- c.service_name = "payments-api" # auto-derived em Rails
269
+ c.service_name = "iugu-fraud-payout" # auto-derived em Rails
223
270
  c.service_version = ENV["GIT_SHA"] || "0.0.0"
224
271
  c.service_environment = Rails.env
225
272
 
@@ -328,10 +375,11 @@ IuguLogger.event("user.processing.failed",
328
375
 
329
376
  ---
330
377
 
331
- ## Decisões aplicadas
378
+ ## Decisões aplicadas (ver [iugu-logging-schema/CONTRIBUTING.md](https://github.com/iugu-private/iugu-logging-schema/blob/main/CONTRIBUTING.md))
332
379
 
333
380
  | ID | Decisão | Implementação |
334
381
  |---|---|---|
382
+ | ILS-001 | 4 repos próprios em `iugu-private` | Este é um deles |
335
383
  | ILS-002 | `iugu.account_id` 32-hex preservado | `Pii::SAFE_PATTERNS` + `SAFE_KEY_PATHS` |
336
384
  | ILS-003 | Email `:detect_only` (deferido — agora **generalizado** em v0.7) | `Pii::DEFAULT_STRATEGIES` |
337
385
  | §13.7 | Ruby 2.4 first-class | `gemspec.required_ruby_version >= 2.4` + CI matrix |
@@ -348,7 +396,9 @@ IuguLogger.event("user.processing.failed",
348
396
 
349
397
  ## Distribuição
350
398
 
351
- Publicada na [RubyGems.org](https://rubygems.org/gems/iugu_logger) `gem "iugu_logger"`, sem autenticação. Versionamento segue [SemVer](https://semver.org) e o `CHANGELOG.md` acompanha cada release.
399
+ Tag `v*` no main dispara `release-please` cria Release PR → ao mergear, tag + workflow `release.yml` rodam automaticamente (via `workflow_call`) e publicam a gem em `https://rubygems.pkg.github.com/iugu-private`. Zero `gh workflow run` manual.
400
+
401
+ Composite `iugu-private/workflows-engenharia/setup-ruby@v1` exporta `BUNDLE_RUBYGEMS__PKG__GITHUB__COM` automaticamente nos consumers.
352
402
 
353
403
  ---
354
404
 
@@ -376,4 +426,4 @@ CI valida matriz Ruby 2.4 + 2.7 + 3.2 em todo PR.
376
426
 
377
427
  ## Ownership
378
428
 
379
- Mantido pela Engenharia de Plataforma da iugu `eng-plataforma@iugu.com`.
429
+ Eng Plataforma. Spec completo: [`devops/docs/IUGU_LOGGING_STANDARD.md`](https://github.com/iugu-private/devops/blob/main/docs/IUGU_LOGGING_STANDARD.md). Workflow de contribuição: [`iugu-logging-schema/CONTRIBUTING.md`](https://github.com/iugu-private/iugu-logging-schema/blob/main/CONTRIBUTING.md).
@@ -21,6 +21,7 @@ module IuguLogger
21
21
  def post_install_summary
22
22
  say "\n iugu_logger #{IuguLogger::VERSION} initializer installed.", :green
23
23
  say ' Run `bundle exec rake iugu_logger:smoke` to validate the setup.', :green
24
+ say ' Spec: https://github.com/iugu-private/devops/blob/main/docs/IUGU_LOGGING_STANDARD.md', :cyan
24
25
  end
25
26
 
26
27
  private
@@ -6,6 +6,8 @@
6
6
  # below cover the canonical case. After changes, validate with:
7
7
  #
8
8
  # bundle exec rake iugu_logger:smoke
9
+ #
10
+ # Spec: https://github.com/iugu-private/devops/blob/main/docs/IUGU_LOGGING_STANDARD.md
9
11
 
10
12
  IuguLogger.configure do |c|
11
13
  c.service_name = '<%= default_service_name %>'
@@ -101,8 +101,9 @@ module IuguLogger
101
101
  error: {
102
102
  'type' => error.class.name,
103
103
  'message' => error.message.to_s,
104
+ 'stack_trace' => clean_backtrace(error),
104
105
  'fingerprint' => fingerprint(error)
105
- },
106
+ }.compact,
106
107
  logs: logs.empty? ? nil : logs
107
108
  )
108
109
  end
@@ -135,6 +136,24 @@ module IuguLogger
135
136
  def normalized_message(msg)
136
137
  msg.to_s.gsub(/\d+/, 'N').gsub(/[a-f0-9]{16,}/i, 'HEX')
137
138
  end
139
+
140
+ # error.stack_trace as an array of frames (schema v2.0.0). Mirrors
141
+ # RequestLogger#clean_backtrace: nil when no backtrace (dropped by
142
+ # `.compact`), Rails BacktraceCleaner when available (gem is standalone),
143
+ # capped at 50 frames.
144
+ STACK_TRACE_LIMIT = 50
145
+
146
+ def clean_backtrace(error)
147
+ frames = error.backtrace
148
+ return nil if frames.nil? || frames.empty?
149
+
150
+ if defined?(::Rails) && ::Rails.respond_to?(:backtrace_cleaner)
151
+ cleaned = ::Rails.backtrace_cleaner.clean(frames)
152
+ frames = cleaned unless cleaned.nil? || cleaned.empty?
153
+ end
154
+
155
+ frames.first(STACK_TRACE_LIMIT)
156
+ end
138
157
  end
139
158
 
140
159
  # Sidekiq server middleware. Compatible with sidekiq, sidekiq-pro,
@@ -46,7 +46,7 @@ module IuguLogger
46
46
 
47
47
  # Captures Rails view/db runtime from the canonical ActiveSupport
48
48
  # notification fired at the end of every controller action. For
49
- # ActionController::API
49
+ # ActionController::API (used by fraud-payout and most iugu services)
50
50
  # the legacy `action_dispatch.view_runtime` / `db_runtime` env keys
51
51
  # aren't populated by Rails — but the `process_action.action_controller`
52
52
  # notification payload always has both. We stash them in Buffer; the
@@ -139,7 +139,9 @@ module IuguLogger
139
139
  # - env['action_dispatch.db_runtime'] → db_runtime_ms (full-stack Rails)
140
140
  # - Buffer.current.rails_runtime → view_ms / db_ms captured by
141
141
  # process_action subscriber
142
- # (ActionController::API path)
142
+ # (ActionController::API path
143
+ # fraud-payout, smart-vault,
144
+ # most iugu services)
143
145
  def extract_rails_info(env)
144
146
  controller = env['action_controller.instance']
145
147
 
@@ -191,8 +193,9 @@ module IuguLogger
191
193
  error: {
192
194
  'type' => error.class.name,
193
195
  'message' => error.message.to_s,
196
+ 'stack_trace' => clean_backtrace(error),
194
197
  'fingerprint' => fingerprint(error)
195
- },
198
+ }.compact,
196
199
  logs: logs.empty? ? nil : logs
197
200
  )
198
201
  end
@@ -253,5 +256,26 @@ module IuguLogger
253
256
  # Strip variable parts (numbers, hex blobs) so similar errors group
254
257
  msg.to_s.gsub(/\d+/, 'N').gsub(/[a-f0-9]{16,}/i, 'HEX')
255
258
  end
259
+
260
+ # error.stack_trace as an array of frames (schema v2.0.0: array, maxItems
261
+ # 50). Returns nil (→ dropped by `.compact`) when there is no backtrace, so
262
+ # we never emit a null into the array-typed field. Uses Rails'
263
+ # BacktraceCleaner to strip framework noise WHEN available — the gem is
264
+ # standalone (Ruby 2.4+, no hard Rails dep), so we degrade to the raw
265
+ # backtrace outside Rails. PII in frames is handled by the scanner
266
+ # downstream (the error block is scanned like any other field).
267
+ STACK_TRACE_LIMIT = 50
268
+
269
+ def clean_backtrace(error)
270
+ frames = error.backtrace
271
+ return nil if frames.nil? || frames.empty?
272
+
273
+ if defined?(::Rails) && ::Rails.respond_to?(:backtrace_cleaner)
274
+ cleaned = ::Rails.backtrace_cleaner.clean(frames)
275
+ frames = cleaned unless cleaned.nil? || cleaned.empty?
276
+ end
277
+
278
+ frames.first(STACK_TRACE_LIMIT)
279
+ end
256
280
  end
257
281
  end
@@ -5,8 +5,8 @@ require 'json'
5
5
  module IuguLogger
6
6
  # event.action registry validator.
7
7
  #
8
- # Loads a compiled event.action registry (`dist/registry.json`) and validates
9
- # each `event.action` emitted against it.
8
+ # Loads a registry produced by `iugu-private/iugu-logging-schema/tools/compile_registry.rb`
9
+ # (`dist/registry.json`) and validates each `event.action` emitted against it.
10
10
  #
11
11
  # Three modes:
12
12
  # :strict — raise IuguLogger::UnknownEventAction / SchemaViolation
@@ -1,5 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module IuguLogger
4
- VERSION = '0.10.0'
4
+ VERSION = '0.11.0'
5
+
6
+ # Canonical schema version this SDK is built against. MUST match the
7
+ # `version` of the vendored snapshot at
8
+ # spec/conformance/fixtures/canonical_schema.json — the schema_version_spec
9
+ # asserts this, and the schema-freshness CI compares it against the latest
10
+ # release of iugu-private/iugu-logging-schema.
11
+ #
12
+ # Bump this ONLY via `rake iugu_logger:sync_schema` (or the schema-sync
13
+ # workflow), never by hand. Schema changes upstream FIRST, the SDK syncs
14
+ # AFTER. See CONTRIBUTING / IUGU_LOGGING_STANDARD.md §4.
15
+ SUPPORTED_SCHEMA_VERSION = '2.0.0'
5
16
  end
data/lib/iugu_logger.rb CHANGED
@@ -18,9 +18,11 @@ require 'iugu_logger/railtie' if defined?(::Rails::Railtie)
18
18
  # iugu Logging Standard (ILS) — Ruby SDK
19
19
  #
20
20
  # Native iugu structured logging SDK. Standalone (no third-party logging
21
- # gem dependency). Implements the iugu Logging Standard (ILS) canonical schema.
21
+ # gem dependency). Implements the canonical schema from `iugu-logging-schema`.
22
22
  #
23
- # Compatibility: Ruby >= 2.4 (covers Rails 4.2 through modern services).
23
+ # Spec: https://github.com/iugu-private/devops/blob/main/docs/IUGU_LOGGING_STANDARD.md
24
+ #
25
+ # Compatibility: Ruby >= 2.4 (covers platform Rails 4.2 through modern services).
24
26
  #
25
27
  # @example basic setup
26
28
  # IuguLogger.configure do |c|
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: iugu_logger
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.0
4
+ version: 0.11.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eng Plataforma iugu
@@ -100,7 +100,8 @@ executables: []
100
100
  extensions: []
101
101
  extra_rdoc_files: []
102
102
  files:
103
- - LICENSE.md
103
+ - CHANGELOG.md
104
+ - CODEOWNERS
104
105
  - README.md
105
106
  - lib/generators/iugu_logger/install/install_generator.rb
106
107
  - lib/generators/iugu_logger/install/templates/iugu_logger.rb.tt
@@ -119,12 +120,13 @@ files:
119
120
  - lib/iugu_logger/tenant_context.rb
120
121
  - lib/iugu_logger/trace_context.rb
121
122
  - lib/iugu_logger/version.rb
122
- homepage: https://rubygems.org/gems/iugu_logger
123
+ homepage: https://github.com/iugu-private/iugu-logger-ruby
123
124
  licenses:
124
- - Apache-2.0
125
+ - Nonstandard
125
126
  metadata:
126
- allowed_push_host: https://rubygems.org
127
- rubygems_mfa_required: 'true'
127
+ source_code_uri: https://github.com/iugu-private/iugu-logger-ruby
128
+ changelog_uri: https://github.com/iugu-private/iugu-logger-ruby/blob/main/CHANGELOG.md
129
+ iugu_logging_standard: https://github.com/iugu-private/devops/blob/main/docs/IUGU_LOGGING_STANDARD.md
128
130
  rdoc_options: []
129
131
  require_paths:
130
132
  - lib
@@ -139,7 +141,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
139
141
  - !ruby/object:Gem::Version
140
142
  version: '0'
141
143
  requirements: []
142
- rubygems_version: 3.6.9
144
+ rubygems_version: 3.6.8
143
145
  specification_version: 4
144
146
  summary: Native iugu structured logging SDK — schema canonical, PII-aware, trace-context
145
147
  aware.
data/LICENSE.md DELETED
@@ -1,202 +0,0 @@
1
-
2
- Apache License
3
- Version 2.0, January 2004
4
- http://www.apache.org/licenses/
5
-
6
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7
-
8
- 1. Definitions.
9
-
10
- "License" shall mean the terms and conditions for use, reproduction,
11
- and distribution as defined by Sections 1 through 9 of this document.
12
-
13
- "Licensor" shall mean the copyright owner or entity authorized by
14
- the copyright owner that is granting the License.
15
-
16
- "Legal Entity" shall mean the union of the acting entity and all
17
- other entities that control, are controlled by, or are under common
18
- control with that entity. For the purposes of this definition,
19
- "control" means (i) the power, direct or indirect, to cause the
20
- direction or management of such entity, whether by contract or
21
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
22
- outstanding shares, or (iii) beneficial ownership of such entity.
23
-
24
- "You" (or "Your") shall mean an individual or Legal Entity
25
- exercising permissions granted by this License.
26
-
27
- "Source" form shall mean the preferred form for making modifications,
28
- including but not limited to software source code, documentation
29
- source, and configuration files.
30
-
31
- "Object" form shall mean any form resulting from mechanical
32
- transformation or translation of a Source form, including but
33
- not limited to compiled object code, generated documentation,
34
- and conversions to other media types.
35
-
36
- "Work" shall mean the work of authorship, whether in Source or
37
- Object form, made available under the License, as indicated by a
38
- copyright notice that is included in or attached to the work
39
- (an example is provided in the Appendix below).
40
-
41
- "Derivative Works" shall mean any work, whether in Source or Object
42
- form, that is based on (or derived from) the Work and for which the
43
- editorial revisions, annotations, elaborations, or other modifications
44
- represent, as a whole, an original work of authorship. For the purposes
45
- of this License, Derivative Works shall not include works that remain
46
- separable from, or merely link (or bind by name) to the interfaces of,
47
- the Work and Derivative Works thereof.
48
-
49
- "Contribution" shall mean any work of authorship, including
50
- the original version of the Work and any modifications or additions
51
- to that Work or Derivative Works thereof, that is intentionally
52
- submitted to Licensor for inclusion in the Work by the copyright owner
53
- or by an individual or Legal Entity authorized to submit on behalf of
54
- the copyright owner. For the purposes of this definition, "submitted"
55
- means any form of electronic, verbal, or written communication sent
56
- to the Licensor or its representatives, including but not limited to
57
- communication on electronic mailing lists, source code control systems,
58
- and issue tracking systems that are managed by, or on behalf of, the
59
- Licensor for the purpose of discussing and improving the Work, but
60
- excluding communication that is conspicuously marked or otherwise
61
- designated in writing by the copyright owner as "Not a Contribution."
62
-
63
- "Contributor" shall mean Licensor and any individual or Legal Entity
64
- on behalf of whom a Contribution has been received by Licensor and
65
- subsequently incorporated within the Work.
66
-
67
- 2. Grant of Copyright License. Subject to the terms and conditions of
68
- this License, each Contributor hereby grants to You a perpetual,
69
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70
- copyright license to reproduce, prepare Derivative Works of,
71
- publicly display, publicly perform, sublicense, and distribute the
72
- Work and such Derivative Works in Source or Object form.
73
-
74
- 3. Grant of Patent License. Subject to the terms and conditions of
75
- this License, each Contributor hereby grants to You a perpetual,
76
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77
- (except as stated in this section) patent license to make, have made,
78
- use, offer to sell, sell, import, and otherwise transfer the Work,
79
- where such license applies only to those patent claims licensable
80
- by such Contributor that are necessarily infringed by their
81
- Contribution(s) alone or by combination of their Contribution(s)
82
- with the Work to which such Contribution(s) was submitted. If You
83
- institute patent litigation against any entity (including a
84
- cross-claim or counterclaim in a lawsuit) alleging that the Work
85
- or a Contribution incorporated within the Work constitutes direct
86
- or contributory patent infringement, then any patent licenses
87
- granted to You under this License for that Work shall terminate
88
- as of the date such litigation is filed.
89
-
90
- 4. Redistribution. You may reproduce and distribute copies of the
91
- Work or Derivative Works thereof in any medium, with or without
92
- modifications, and in Source or Object form, provided that You
93
- meet the following conditions:
94
-
95
- (a) You must give any other recipients of the Work or
96
- Derivative Works a copy of this License; and
97
-
98
- (b) You must cause any modified files to carry prominent notices
99
- stating that You changed the files; and
100
-
101
- (c) You must retain, in the Source form of any Derivative Works
102
- that You distribute, all copyright, patent, trademark, and
103
- attribution notices from the Source form of the Work,
104
- excluding those notices that do not pertain to any part of
105
- the Derivative Works; and
106
-
107
- (d) If the Work includes a "NOTICE" text file as part of its
108
- distribution, then any Derivative Works that You distribute must
109
- include a readable copy of the attribution notices contained
110
- within such NOTICE file, excluding those notices that do not
111
- pertain to any part of the Derivative Works, in at least one
112
- of the following places: within a NOTICE text file distributed
113
- as part of the Derivative Works; within the Source form or
114
- documentation, if provided along with the Derivative Works; or,
115
- within a display generated by the Derivative Works, if and
116
- wherever such third-party notices normally appear. The contents
117
- of the NOTICE file are for informational purposes only and
118
- do not modify the License. You may add Your own attribution
119
- notices within Derivative Works that You distribute, alongside
120
- or as an addendum to the NOTICE text from the Work, provided
121
- that such additional attribution notices cannot be construed
122
- as modifying the License.
123
-
124
- You may add Your own copyright statement to Your modifications and
125
- may provide additional or different license terms and conditions
126
- for use, reproduction, or distribution of Your modifications, or
127
- for any such Derivative Works as a whole, provided Your use,
128
- reproduction, and distribution of the Work otherwise complies with
129
- the conditions stated in this License.
130
-
131
- 5. Submission of Contributions. Unless You explicitly state otherwise,
132
- any Contribution intentionally submitted for inclusion in the Work
133
- by You to the Licensor shall be under the terms and conditions of
134
- this License, without any additional terms or conditions.
135
- Notwithstanding the above, nothing herein shall supersede or modify
136
- the terms of any separate license agreement you may have executed
137
- with Licensor regarding such Contributions.
138
-
139
- 6. Trademarks. This License does not grant permission to use the trade
140
- names, trademarks, service marks, or product names of the Licensor,
141
- except as required for reasonable and customary use in describing the
142
- origin of the Work and reproducing the content of the NOTICE file.
143
-
144
- 7. Disclaimer of Warranty. Unless required by applicable law or
145
- agreed to in writing, Licensor provides the Work (and each
146
- Contributor provides its Contributions) on an "AS IS" BASIS,
147
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148
- implied, including, without limitation, any warranties or conditions
149
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150
- PARTICULAR PURPOSE. You are solely responsible for determining the
151
- appropriateness of using or redistributing the Work and assume any
152
- risks associated with Your exercise of permissions under this License.
153
-
154
- 8. Limitation of Liability. In no event and under no legal theory,
155
- whether in tort (including negligence), contract, or otherwise,
156
- unless required by applicable law (such as deliberate and grossly
157
- negligent acts) or agreed to in writing, shall any Contributor be
158
- liable to You for damages, including any direct, indirect, special,
159
- incidental, or consequential damages of any character arising as a
160
- result of this License or out of the use or inability to use the
161
- Work (including but not limited to damages for loss of goodwill,
162
- work stoppage, computer failure or malfunction, or any and all
163
- other commercial damages or losses), even if such Contributor
164
- has been advised of the possibility of such damages.
165
-
166
- 9. Accepting Warranty or Additional Liability. While redistributing
167
- the Work or Derivative Works thereof, You may choose to offer,
168
- and charge a fee for, acceptance of support, warranty, indemnity,
169
- or other liability obligations and/or rights consistent with this
170
- License. However, in accepting such obligations, You may act only
171
- on Your own behalf and on Your sole responsibility, not on behalf
172
- of any other Contributor, and only if You agree to indemnify,
173
- defend, and hold each Contributor harmless for any liability
174
- incurred by, or claims asserted against, such Contributor by reason
175
- of your accepting any such warranty or additional liability.
176
-
177
- END OF TERMS AND CONDITIONS
178
-
179
- APPENDIX: How to apply the Apache License to your work.
180
-
181
- To apply the Apache License to your work, attach the following
182
- boilerplate notice, with the fields enclosed by brackets "[]"
183
- replaced with your own identifying information. (Don't include
184
- the brackets!) The text should be enclosed in the appropriate
185
- comment syntax for the file format. We also recommend that a
186
- file or class name and description of purpose be included on the
187
- same "printed page" as the copyright notice for easier
188
- identification within third-party archives.
189
-
190
- Copyright 2026 iugu
191
-
192
- Licensed under the Apache License, Version 2.0 (the "License");
193
- you may not use this file except in compliance with the License.
194
- You may obtain a copy of the License at
195
-
196
- http://www.apache.org/licenses/LICENSE-2.0
197
-
198
- Unless required by applicable law or agreed to in writing, software
199
- distributed under the License is distributed on an "AS IS" BASIS,
200
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201
- See the License for the specific language governing permissions and
202
- limitations under the License.