safire 0.1.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.
Files changed (72) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +1 -0
  3. data/.rubocop.yml +62 -0
  4. data/.tool-versions +1 -0
  5. data/CHANGELOG.md +35 -0
  6. data/CODE_OF_CONDUCT.md +17 -0
  7. data/CONTRIBUTION.md +283 -0
  8. data/Gemfile +26 -0
  9. data/Gemfile.lock +186 -0
  10. data/LICENSE +201 -0
  11. data/README.md +159 -0
  12. data/ROADMAP.md +54 -0
  13. data/Rakefile +26 -0
  14. data/docs/.gitignore +5 -0
  15. data/docs/404.html +25 -0
  16. data/docs/Gemfile +37 -0
  17. data/docs/Gemfile.lock +195 -0
  18. data/docs/_config.yml +103 -0
  19. data/docs/_includes/footer_custom.html +6 -0
  20. data/docs/_includes/head_custom.html +14 -0
  21. data/docs/_sass/custom/custom.scss +108 -0
  22. data/docs/adr/ADR-001-activesupport-dependency.md +50 -0
  23. data/docs/adr/ADR-002-facade-and-forwardable.md +79 -0
  24. data/docs/adr/ADR-003-protocol-vs-client-type.md +67 -0
  25. data/docs/adr/ADR-004-clientconfig-immutability-and-entity-masking.md +59 -0
  26. data/docs/adr/ADR-005-per-client-http-ownership.md +58 -0
  27. data/docs/adr/ADR-006-lazy-discovery.md +83 -0
  28. data/docs/adr/ADR-007-https-only-redirects-and-localhost-exception.md +59 -0
  29. data/docs/adr/ADR-008-warn-return-false-for-compliance-validation.md +74 -0
  30. data/docs/adr/index.md +22 -0
  31. data/docs/advanced.md +284 -0
  32. data/docs/configuration/client-setup.md +158 -0
  33. data/docs/configuration/index.md +60 -0
  34. data/docs/configuration/logging.md +86 -0
  35. data/docs/index.md +64 -0
  36. data/docs/installation.md +96 -0
  37. data/docs/security.md +256 -0
  38. data/docs/smart-on-fhir/confidential-asymmetric/authorization.md +72 -0
  39. data/docs/smart-on-fhir/confidential-asymmetric/index.md +162 -0
  40. data/docs/smart-on-fhir/confidential-asymmetric/token-exchange.md +250 -0
  41. data/docs/smart-on-fhir/confidential-symmetric/authorization.md +75 -0
  42. data/docs/smart-on-fhir/confidential-symmetric/index.md +69 -0
  43. data/docs/smart-on-fhir/confidential-symmetric/token-exchange.md +215 -0
  44. data/docs/smart-on-fhir/discovery/capability-checks.md +142 -0
  45. data/docs/smart-on-fhir/discovery/index.md +96 -0
  46. data/docs/smart-on-fhir/discovery/metadata.md +147 -0
  47. data/docs/smart-on-fhir/index.md +72 -0
  48. data/docs/smart-on-fhir/post-based-authorization.md +190 -0
  49. data/docs/smart-on-fhir/public-client/authorization.md +112 -0
  50. data/docs/smart-on-fhir/public-client/index.md +80 -0
  51. data/docs/smart-on-fhir/public-client/token-exchange.md +249 -0
  52. data/docs/troubleshooting/auth-errors.md +124 -0
  53. data/docs/troubleshooting/client-errors.md +130 -0
  54. data/docs/troubleshooting/index.md +99 -0
  55. data/docs/troubleshooting/token-errors.md +99 -0
  56. data/docs/udap.md +78 -0
  57. data/lib/safire/client.rb +195 -0
  58. data/lib/safire/client_config.rb +169 -0
  59. data/lib/safire/client_config_builder.rb +72 -0
  60. data/lib/safire/entity.rb +26 -0
  61. data/lib/safire/errors.rb +247 -0
  62. data/lib/safire/http_client.rb +87 -0
  63. data/lib/safire/jwt_assertion.rb +237 -0
  64. data/lib/safire/middleware/https_only_redirects.rb +39 -0
  65. data/lib/safire/pkce.rb +39 -0
  66. data/lib/safire/protocols/behaviours.rb +54 -0
  67. data/lib/safire/protocols/smart.rb +378 -0
  68. data/lib/safire/protocols/smart_metadata.rb +231 -0
  69. data/lib/safire/version.rb +4 -0
  70. data/lib/safire.rb +54 -0
  71. data/safire.gemspec +36 -0
  72. metadata +184 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: f9d11ee8ab8db74c9b225f12835caaf092616a0044372252617783b6187e3043
4
+ data.tar.gz: 8d73cdb90ed9d4ca7ec1e028bfe3e68464c7284f73e2d101a084be346e9b0085
5
+ SHA512:
6
+ metadata.gz: bf3cd169be16cb9598f2de3f572d0efeeb6c0ed98826b0690588c684e15c2a95afc6cf340d35a53c0f6d9eebc11c59dafdcdd02e71b0ddb8fbf629071644d90b
7
+ data.tar.gz: 6beaec7923441fb46d8fc4cc193ffff16354bb60fb62f141a3a36131e22f275df3d4ddfa31dd5548eebb6ad3a8872cd952c4cc4ab9dc31968b9eb644b0d097be
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,62 @@
1
+ plugins:
2
+ - rubocop-rspec
3
+
4
+ AllCops:
5
+ TargetRubyVersion: 4.0
6
+ NewCops: enable
7
+ Exclude:
8
+ - 'vendor/**/*'
9
+ - 'tmp/**/*'
10
+ - 'bin/**/*'
11
+
12
+ Style/Documentation:
13
+ Enabled: false
14
+
15
+ Style/FrozenStringLiteralComment:
16
+ Enabled: false
17
+
18
+ Layout/LineLength:
19
+ Max: 120
20
+
21
+ Metrics/ClassLength:
22
+ Enabled: false
23
+
24
+ Metrics/MethodLength:
25
+ Max: 20
26
+ Exclude:
27
+ - 'spec/**/*'
28
+ - '*.gemspec'
29
+
30
+ Metrics/BlockLength:
31
+ Exclude:
32
+ - 'spec/**/*'
33
+ - '*.gemspec'
34
+
35
+ Metrics/ParameterLists:
36
+ CountKeywordArgs: false
37
+
38
+ RSpec/ExampleLength:
39
+ Max: 20
40
+ Exclude:
41
+ - 'spec/integration/**/*'
42
+
43
+ RSpec/MultipleExpectations:
44
+ Max: 10
45
+ Exclude:
46
+ - 'spec/integration/**/*'
47
+
48
+ RSpec/MultipleMemoizedHelpers:
49
+ Enabled: false
50
+
51
+ RSpec/NestedGroups:
52
+ Enabled: false
53
+
54
+ # Integration tests describe workflows, not classes
55
+ RSpec/DescribeClass:
56
+ Exclude:
57
+ - 'spec/integration/**/*'
58
+
59
+ # Live integration tests need before(:all)/after(:all) for WebMock management
60
+ RSpec/BeforeAfterAll:
61
+ Exclude:
62
+ - 'spec/integration/**/*'
data/.tool-versions ADDED
@@ -0,0 +1 @@
1
+ ruby 4.0.2
data/CHANGELOG.md ADDED
@@ -0,0 +1,35 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
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
+ ## [Unreleased]
9
+
10
+ ## [0.1.0] - 2026-03-25
11
+
12
+ ### Added
13
+
14
+ - `Safire::Client` facade with `protocol:` (`:smart`) and `client_type:`
15
+ (`:public`, `:confidential_symmetric`, `:confidential_asymmetric`) keywords
16
+ - SMART on FHIR App Launch 2.2.0 support via `Safire::Protocols::Smart`:
17
+ - Server metadata discovery from `/.well-known/smart-configuration`
18
+ - Authorization URL builder for GET and POST-based authorization
19
+ (`authorize-post` capability)
20
+ - Authorization code → access token exchange
21
+ - Token refresh
22
+ - PKCE (S256) support with per-request code verifier generation
23
+ - Private key JWT assertion (`private_key_jwt`) for confidential asymmetric
24
+ clients; RS384 and ES384 auto-detected from the key type
25
+ - Token response validation (`token_response_valid?`) per SMART App Launch
26
+ 2.2.0 §Token Response
27
+ - `Protocols::Behaviours` contract module defining the required protocol
28
+ interface
29
+ - Sensitive data filtering in HTTP request/response logs
30
+ - SSL verification warning when `ssl_options: { verify: false }` is configured
31
+ - HTTPS-only redirect enforcement with an exception for localhost
32
+ - Configurable logger, HTTP logging toggle, and `User-Agent` header via
33
+ `Safire::Configuration`
34
+ - `Safire::ClientConfigBuilder` for constructing `ClientConfig` with a fluent
35
+ interface
@@ -0,0 +1,17 @@
1
+ # Contributor Covenant Code of Conduct
2
+
3
+ This project has adopted the [Contributor Covenant](https://www.contributor-covenant.org/) version 2.1 as its Code of Conduct.
4
+
5
+ For the full text, please see: https://www.contributor-covenant.org/version/2/1/code_of_conduct/
6
+
7
+ ## Our Pledge
8
+
9
+ We as members, contributors, and leaders pledge to make participation in our community a welcoming experience for everyone.
10
+
11
+ ## Reporting
12
+
13
+ Instances of unacceptable behavior may be reported to the project maintainers. All complaints will be reviewed and investigated promptly and fairly.
14
+
15
+ ## Attribution
16
+
17
+ This Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org), version 2.1.
data/CONTRIBUTION.md ADDED
@@ -0,0 +1,283 @@
1
+ # Contributing to Safire
2
+
3
+ Thank you for your interest in contributing to Safire! This document provides guidelines and instructions for contributing.
4
+
5
+ ## Table of Contents
6
+
7
+ - [Code of Conduct](#code-of-conduct)
8
+ - [Getting Started](#getting-started)
9
+ - [Development Setup](#development-setup)
10
+ - [Making Changes](#making-changes)
11
+ - [Coding Standards](#coding-standards)
12
+ - [Testing](#testing)
13
+ - [Submitting Changes](#submitting-changes)
14
+ - [Reporting Issues](#reporting-issues)
15
+
16
+ ## Code of Conduct
17
+
18
+ This project adheres to a [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to the project maintainers.
19
+
20
+ ## Getting Started
21
+
22
+ 1. Fork the repository on GitHub
23
+ 2. Clone your fork locally:
24
+ ```bash
25
+ git clone https://github.com/YOUR_USERNAME/safire.git
26
+ cd safire
27
+ ```
28
+ 3. Add the upstream repository:
29
+ ```bash
30
+ git remote add upstream https://github.com/vanessuniq/safire.git
31
+ ```
32
+
33
+ ## Development Setup
34
+
35
+ ### Requirements
36
+
37
+ - Ruby 4.0.2 or later
38
+ - Bundler
39
+
40
+ ### Setup
41
+
42
+ ```bash
43
+ # Install dependencies
44
+ bin/setup
45
+
46
+ # Run the test suite to verify setup
47
+ bundle exec rspec
48
+
49
+ # Start an interactive console
50
+ bin/console
51
+ ```
52
+
53
+ ### Running the Demo Application
54
+
55
+ ```bash
56
+ bin/demo
57
+ ```
58
+
59
+ Visit http://localhost:4567 to explore Safire's features interactively.
60
+
61
+ ## Making Changes
62
+
63
+ ### Branch Naming
64
+
65
+ Create a descriptive branch name:
66
+
67
+ - `feature/add-udap-discovery` - New features
68
+ - `fix/token-refresh-error` - Bug fixes
69
+ - `docs/update-readme` - Documentation updates
70
+ - `refactor/simplify-client-config` - Code refactoring
71
+
72
+ ### Commit Messages
73
+
74
+ Write clear, concise commit messages:
75
+
76
+ - Use the imperative mood ("Add feature" not "Added feature")
77
+ - Keep the subject line as the entire commit message (no body)
78
+ - Message should be 50 characters or less
79
+ - Reference issues when applicable (`Fixes #123`)
80
+
81
+ Example:
82
+ ```
83
+ Add UDAP discovery endpoint support
84
+ ```
85
+
86
+ ### Small, Focused Commits
87
+
88
+ - Each commit should represent a single logical change
89
+ - Keep commits small and reviewable
90
+ - Separate refactoring from new features
91
+
92
+ ## Coding Standards
93
+
94
+ ### Style Guide
95
+
96
+ This project uses [RuboCop](https://rubocop.org/) for code style enforcement:
97
+
98
+ ```bash
99
+ # Check for style violations
100
+ bundle exec rubocop
101
+
102
+ # Auto-fix correctable violations
103
+ bundle exec rubocop -a
104
+ ```
105
+
106
+ ### Key Conventions
107
+
108
+ - **Naming**: Use descriptive names; prefer clarity over brevity
109
+ - **Methods**: Keep methods short and focused (under 15 lines when possible)
110
+ - **Classes**: Follow single responsibility principle
111
+ - **Documentation**: Add YARD documentation for public methods
112
+
113
+ ### Example
114
+
115
+ ```ruby
116
+ # Good: Clear, documented, follows conventions
117
+ module Safire
118
+ module Protocols
119
+ # Handles SMART on FHIR metadata discovery
120
+ class SmartMetadata
121
+ # Checks if the server supports EHR-initiated launches
122
+ #
123
+ # @return [Boolean] true if EHR launch is supported with required endpoints
124
+ def supports_ehr_launch?
125
+ ehr_launch_capability? && authorization_endpoint.present?
126
+ end
127
+
128
+ private
129
+
130
+ def ehr_launch_capability?
131
+ capability?('launch-ehr')
132
+ end
133
+ end
134
+ end
135
+ end
136
+ ```
137
+
138
+ ## Testing
139
+
140
+ ### Running Tests
141
+
142
+ ```bash
143
+ # Run all tests
144
+ bundle exec rspec
145
+
146
+ # Run specific test file
147
+ bundle exec rspec spec/safire/client_spec.rb
148
+
149
+ # Run with documentation format
150
+ bundle exec rspec --format documentation
151
+
152
+ # Run integration tests
153
+ bundle exec rspec --tag live
154
+ ```
155
+
156
+ ### Writing Tests
157
+
158
+ - Place tests in `spec/` mirroring the `lib/` structure
159
+ - Use descriptive `describe` and `it` blocks
160
+ - Test edge cases and error conditions
161
+ - Use WebMock for HTTP stubbing (no real network calls in unit tests)
162
+
163
+ Example:
164
+ ```ruby
165
+ RSpec.describe Safire::Client do
166
+ describe '#server_metadata' do
167
+ context 'when server returns valid configuration' do
168
+ it 'returns a SmartMetadata object' do
169
+ stub_smart_configuration(valid_config)
170
+
171
+ metadata = client.server_metadata
172
+
173
+ expect(metadata).to be_a(Safire::Protocols::SmartMetadata)
174
+ expect(metadata.token_endpoint).to eq('https://example.com/token')
175
+ end
176
+ end
177
+
178
+ context 'when server returns 404' do
179
+ it 'raises DiscoveryError' do
180
+ stub_smart_configuration_not_found
181
+
182
+ expect { client.server_metadata }.to raise_error(Safire::Errors::DiscoveryError)
183
+ end
184
+ end
185
+ end
186
+ end
187
+ ```
188
+
189
+ ### Test Coverage
190
+
191
+ - Aim for high test coverage on new code
192
+ - All public methods should have tests
193
+ - Include both happy path and error cases
194
+
195
+ ## Submitting Changes
196
+
197
+ ### Before Submitting
198
+
199
+ 1. Ensure all tests pass:
200
+ ```bash
201
+ bundle exec rspec
202
+ ```
203
+
204
+ 2. Ensure code style is correct:
205
+ ```bash
206
+ bundle exec rubocop
207
+ ```
208
+
209
+ 3. Update documentation if needed:
210
+ ```bash
211
+ bundle exec yard doc
212
+ ```
213
+
214
+ 4. Verify Jekyll docs build (if you modified docs/):
215
+ ```bash
216
+ cd docs && bundle install && bundle exec jekyll build
217
+ ```
218
+
219
+ 5. Rebase on latest main:
220
+ ```bash
221
+ git fetch upstream
222
+ git rebase upstream/main
223
+ ```
224
+
225
+ ### Pull Request Process
226
+
227
+ 1. Push your branch to your fork:
228
+ ```bash
229
+ git push origin feature/your-feature
230
+ ```
231
+
232
+ 2. Open a Pull Request against `main`
233
+
234
+ 3. Fill out the PR template with:
235
+ - Summary of changes
236
+ - Related issues
237
+ - Test plan
238
+ - Screenshots (if UI changes)
239
+
240
+ 4. Wait for CI checks to pass
241
+
242
+ 5. Address review feedback promptly
243
+
244
+ ### PR Guidelines
245
+
246
+ - Keep PRs focused on a single concern
247
+ - Include tests for new functionality
248
+ - Update documentation as needed
249
+ - Respond to review comments constructively
250
+
251
+ ## Reporting Issues
252
+
253
+ ### Bug Reports
254
+
255
+ Include:
256
+ - Safire version (`Safire::VERSION`)
257
+ - Ruby version
258
+ - Steps to reproduce
259
+ - Expected vs actual behavior
260
+ - Error messages and stack traces
261
+ - Minimal reproduction code if possible
262
+
263
+ ### Feature Requests
264
+
265
+ Include:
266
+ - Use case description
267
+ - Proposed solution (if any)
268
+ - Alternatives considered
269
+ - Relevant SMART/UDAP spec references
270
+
271
+ ### Security Issues
272
+
273
+ For security vulnerabilities, please email the maintainers directly rather than opening a public issue.
274
+
275
+ ## Questions?
276
+
277
+ - Open a [GitHub Discussion](https://github.com/vanessuniq/safire/discussions) for questions
278
+ - Check existing issues and documentation first
279
+ - Be respectful and patient
280
+
281
+ ---
282
+
283
+ Thank you for contributing to Safire!
data/Gemfile ADDED
@@ -0,0 +1,26 @@
1
+ source 'https://rubygems.org'
2
+
3
+ ruby '4.0.2'
4
+
5
+ gemspec
6
+
7
+ group :development, :test do
8
+ gem 'bundler-audit', '~> 0.9'
9
+ gem 'debug'
10
+ gem 'pry'
11
+ gem 'pry-byebug'
12
+ gem 'rspec', '~> 3.12'
13
+ gem 'rubocop', '~> 1.57'
14
+ gem 'rubocop-rspec', '~> 3.0', require: false
15
+ gem 'timecop', '~> 0.9'
16
+ end
17
+
18
+ group :development do
19
+ gem 'yard', '~> 0.9'
20
+ end
21
+
22
+ group :test do
23
+ gem 'simplecov', require: false
24
+ gem 'simplecov-cobertura', require: false
25
+ gem 'webmock', '~> 3.18'
26
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,186 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ safire (0.1.0)
5
+ activesupport (~> 8.0.0)
6
+ addressable (~> 2.8)
7
+ faraday (~> 2.14)
8
+ faraday-follow_redirects (~> 0.4)
9
+ jwt (~> 2.8)
10
+
11
+ GEM
12
+ remote: https://rubygems.org/
13
+ specs:
14
+ activesupport (8.0.2.1)
15
+ base64
16
+ benchmark (>= 0.3)
17
+ bigdecimal
18
+ concurrent-ruby (~> 1.0, >= 1.3.1)
19
+ connection_pool (>= 2.2.5)
20
+ drb
21
+ i18n (>= 1.6, < 2)
22
+ logger (>= 1.4.2)
23
+ minitest (>= 5.1)
24
+ securerandom (>= 0.3)
25
+ tzinfo (~> 2.0, >= 2.0.5)
26
+ uri (>= 0.13.1)
27
+ addressable (2.8.9)
28
+ public_suffix (>= 2.0.2, < 8.0)
29
+ ast (2.4.3)
30
+ base64 (0.3.0)
31
+ benchmark (0.4.1)
32
+ bigdecimal (3.3.1)
33
+ bundler-audit (0.9.3)
34
+ bundler (>= 1.2.0)
35
+ thor (~> 1.0)
36
+ byebug (13.0.0)
37
+ reline (>= 0.6.0)
38
+ coderay (1.1.3)
39
+ concurrent-ruby (1.3.5)
40
+ connection_pool (2.5.4)
41
+ crack (1.0.1)
42
+ bigdecimal
43
+ rexml
44
+ date (3.4.1)
45
+ debug (1.11.1)
46
+ irb (~> 1.10)
47
+ reline (>= 0.3.8)
48
+ diff-lcs (1.6.2)
49
+ docile (1.4.1)
50
+ drb (2.2.3)
51
+ erb (5.0.3)
52
+ faraday (2.14.1)
53
+ faraday-net_http (>= 2.0, < 3.5)
54
+ json
55
+ logger
56
+ faraday-follow_redirects (0.5.0)
57
+ faraday (>= 1, < 3)
58
+ faraday-net_http (3.4.2)
59
+ net-http (~> 0.5)
60
+ hashdiff (1.2.1)
61
+ i18n (1.14.7)
62
+ concurrent-ruby (~> 1.0)
63
+ io-console (0.8.2)
64
+ irb (1.15.3)
65
+ pp (>= 0.6.0)
66
+ rdoc (>= 4.0.0)
67
+ reline (>= 0.4.2)
68
+ json (2.19.2)
69
+ jwt (2.10.2)
70
+ base64
71
+ language_server-protocol (3.17.0.5)
72
+ lint_roller (1.1.0)
73
+ logger (1.7.0)
74
+ method_source (1.1.0)
75
+ minitest (6.0.1)
76
+ prism (~> 1.5)
77
+ net-http (0.9.1)
78
+ uri (>= 0.11.1)
79
+ parallel (1.27.0)
80
+ parser (3.3.10.2)
81
+ ast (~> 2.4.1)
82
+ racc
83
+ pp (0.6.3)
84
+ prettyprint
85
+ prettyprint (0.2.0)
86
+ prism (1.9.0)
87
+ pry (0.16.0)
88
+ coderay (~> 1.1)
89
+ method_source (~> 1.0)
90
+ reline (>= 0.6.0)
91
+ pry-byebug (3.12.0)
92
+ byebug (~> 13.0)
93
+ pry (>= 0.13, < 0.17)
94
+ psych (5.2.6)
95
+ date
96
+ stringio
97
+ public_suffix (6.0.2)
98
+ racc (1.8.1)
99
+ rainbow (3.1.1)
100
+ rdoc (6.14.2)
101
+ erb
102
+ psych (>= 4.0.0)
103
+ regexp_parser (2.11.3)
104
+ reline (0.6.3)
105
+ io-console (~> 0.5)
106
+ rexml (3.4.4)
107
+ rspec (3.13.2)
108
+ rspec-core (~> 3.13.0)
109
+ rspec-expectations (~> 3.13.0)
110
+ rspec-mocks (~> 3.13.0)
111
+ rspec-core (3.13.6)
112
+ rspec-support (~> 3.13.0)
113
+ rspec-expectations (3.13.5)
114
+ diff-lcs (>= 1.2.0, < 2.0)
115
+ rspec-support (~> 3.13.0)
116
+ rspec-mocks (3.13.6)
117
+ diff-lcs (>= 1.2.0, < 2.0)
118
+ rspec-support (~> 3.13.0)
119
+ rspec-support (3.13.6)
120
+ rubocop (1.86.0)
121
+ json (~> 2.3)
122
+ language_server-protocol (~> 3.17.0.2)
123
+ lint_roller (~> 1.1.0)
124
+ parallel (~> 1.10)
125
+ parser (>= 3.3.0.2)
126
+ rainbow (>= 2.2.2, < 4.0)
127
+ regexp_parser (>= 2.9.3, < 3.0)
128
+ rubocop-ast (>= 1.49.0, < 2.0)
129
+ ruby-progressbar (~> 1.7)
130
+ unicode-display_width (>= 2.4.0, < 4.0)
131
+ rubocop-ast (1.49.1)
132
+ parser (>= 3.3.7.2)
133
+ prism (~> 1.7)
134
+ rubocop-rspec (3.9.0)
135
+ lint_roller (~> 1.1)
136
+ rubocop (~> 1.81)
137
+ ruby-progressbar (1.13.0)
138
+ securerandom (0.4.1)
139
+ simplecov (0.22.0)
140
+ docile (~> 1.1)
141
+ simplecov-html (~> 0.11)
142
+ simplecov_json_formatter (~> 0.1)
143
+ simplecov-cobertura (3.1.0)
144
+ rexml
145
+ simplecov (~> 0.19)
146
+ simplecov-html (0.13.2)
147
+ simplecov_json_formatter (0.1.4)
148
+ stringio (3.1.9)
149
+ thor (1.4.0)
150
+ timecop (0.9.10)
151
+ tzinfo (2.0.6)
152
+ concurrent-ruby (~> 1.0)
153
+ unicode-display_width (3.2.0)
154
+ unicode-emoji (~> 4.1)
155
+ unicode-emoji (4.2.0)
156
+ uri (1.1.1)
157
+ webmock (3.26.2)
158
+ addressable (>= 2.8.0)
159
+ crack (>= 0.3.2)
160
+ hashdiff (>= 0.4.0, < 2.0.0)
161
+ yard (0.9.38)
162
+
163
+ PLATFORMS
164
+ ruby
165
+ x86_64-linux
166
+
167
+ DEPENDENCIES
168
+ bundler-audit (~> 0.9)
169
+ debug
170
+ pry
171
+ pry-byebug
172
+ rspec (~> 3.12)
173
+ rubocop (~> 1.57)
174
+ rubocop-rspec (~> 3.0)
175
+ safire!
176
+ simplecov
177
+ simplecov-cobertura
178
+ timecop (~> 0.9)
179
+ webmock (~> 3.18)
180
+ yard (~> 0.9)
181
+
182
+ RUBY VERSION
183
+ ruby 4.0.2p0
184
+
185
+ BUNDLED WITH
186
+ 2.7.1