otto 2.3.1 → 2.4.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 (41) hide show
  1. checksums.yaml +4 -4
  2. data/.github/dependabot.yml +1 -1
  3. data/.github/workflows/ci.yml +7 -1
  4. data/.github/workflows/claude-code-review.yml +32 -9
  5. data/.github/workflows/claude.yml +7 -5
  6. data/.github/workflows/code-smells.yml +2 -2
  7. data/.github/workflows/release-gem.yml +12 -2
  8. data/.github/workflows/ruby-lint.yml +66 -0
  9. data/.github/workflows/yardoc.yml +117 -0
  10. data/.yardopts +15 -0
  11. data/CHANGELOG.rst +59 -0
  12. data/Gemfile +4 -2
  13. data/Gemfile.lock +23 -17
  14. data/README.md +96 -0
  15. data/docs/.gitignore +1 -0
  16. data/docs/reverse-proxy-network-services.md +358 -0
  17. data/examples/caddy_tls_demo/README.md +100 -0
  18. data/examples/caddy_tls_demo/app.rb +41 -0
  19. data/examples/caddy_tls_demo/config.ru +31 -0
  20. data/examples/caddy_tls_demo/routes +9 -0
  21. data/examples/caddy_tls_demo/standalone.ru +38 -0
  22. data/lib/otto/caddy_tls/core.rb +74 -0
  23. data/lib/otto/caddy_tls/localhost_guard.rb +158 -0
  24. data/lib/otto/caddy_tls/server.rb +149 -0
  25. data/lib/otto/caddy_tls.rb +7 -0
  26. data/lib/otto/core/middleware_management.rb +7 -7
  27. data/lib/otto/core/middleware_stack.rb +39 -5
  28. data/lib/otto/core/router.rb +4 -8
  29. data/lib/otto/security/config.rb +227 -2
  30. data/lib/otto/security/configurator.rb +38 -0
  31. data/lib/otto/security/core.rb +62 -0
  32. data/lib/otto/security/csp/parser.rb +120 -0
  33. data/lib/otto/security/csp/report.rb +147 -0
  34. data/lib/otto/security/csp/report_middleware.rb +120 -0
  35. data/lib/otto/security/csp.rb +19 -0
  36. data/lib/otto/security/middleware/ip_privacy_middleware.rb +72 -7
  37. data/lib/otto/security.rb +1 -0
  38. data/lib/otto/utils.rb +36 -0
  39. data/lib/otto/version.rb +1 -1
  40. data/lib/otto.rb +26 -3
  41. metadata +23 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 72c7a8fdbc299b202666d5f94532e4eed6d3fc2b2ee6a58234519deba65bfb0c
4
- data.tar.gz: d82daec0441d3e9a8c196e6306aa8945292b8a322e3acbdf146294bc55345782
3
+ metadata.gz: e50cca678689db3e2447e76a8a1b12f3b709305d4f73908cb06dfe6883adc596
4
+ data.tar.gz: a6093388b74ffbd098c222a026c1f1cf439c8039c75a0d55b663a0874669c6ee
5
5
  SHA512:
6
- metadata.gz: 64e1787e35c416585076ba4befa922c4306f0f023cba463877a66b821ab9e1518e3afda4edd6e8a319a04750c3c29d5b79196fc4961f807438b1f27eed4d0687
7
- data.tar.gz: e6384fc6c848c602ea4c7f2c7eee7aaab7a715df054e404d6660e9c72fb85b52f4ff0a98108121a4995fe401a09bc67bcb459d0e37d00f4897a42df6b90d2d10
6
+ metadata.gz: ea5a8acda9a29c09d3a16a050050c2e9b9a1517c7f63e24bb7bc910801a7a07874fff1215550a740cef2c9c3698bc77378083b33f47794a7668b77feff9e6e67
7
+ data.tar.gz: 62cfbe824d5d0d9e159424a6d930217f05b8b01de7142108a6a80953207cca9037a3e63d6ae5c16585dda3ff7b8a9b2d070b593f748563c0a5a20ed852add37f
@@ -10,6 +10,6 @@ updates:
10
10
  schedule:
11
11
  interval: "weekly"
12
12
  - package-ecosystem: "bundler"
13
- directory: "/"
13
+ directory: "/" # Location of package manifests
14
14
  schedule:
15
15
  interval: "weekly"
@@ -37,6 +37,9 @@ jobs:
37
37
  # `require_relative 'file/write.rb'` against a file deleted in
38
38
  # the same release, the reason 2.0.2 exists.
39
39
  include:
40
+ - ruby: "3.2"
41
+ experimental: false
42
+ lockfile: "locked"
40
43
  - ruby: "3.3"
41
44
  experimental: false
42
45
  lockfile: "locked"
@@ -49,6 +52,9 @@ jobs:
49
52
  - ruby: "4.0"
50
53
  experimental: true
51
54
  lockfile: "locked"
55
+ - ruby: "3.2"
56
+ experimental: false
57
+ lockfile: "unlocked"
52
58
  - ruby: "3.3"
53
59
  experimental: false
54
60
  lockfile: "unlocked"
@@ -63,7 +69,7 @@ jobs:
63
69
  lockfile: "unlocked"
64
70
 
65
71
  steps:
66
- - uses: actions/checkout@v6.0.3
72
+ - uses: actions/checkout@v7.0.0
67
73
  - name: Set up Ruby
68
74
  uses: ruby/setup-ruby@v1
69
75
  continue-on-error: ${{ matrix.experimental }}
@@ -4,6 +4,16 @@ on:
4
4
  pull_request:
5
5
  types: [opened, synchronize, labeled]
6
6
  workflow_dispatch:
7
+ inputs:
8
+ model:
9
+ description: "Claude model for this run (overrides the CLAUDE_MODEL repo variable)"
10
+ type: choice
11
+ required: false
12
+ default: claude-opus-4-6
13
+ options:
14
+ - claude-opus-4-6
15
+ - claude-sonnet-4-6
16
+ - claude-haiku-4-5-20251001
7
17
 
8
18
  jobs:
9
19
  claude-review:
@@ -14,10 +24,21 @@ jobs:
14
24
  # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
15
25
 
16
26
  runs-on: ubuntu-latest
17
- if: |
18
- (github.event.action == 'opened') ||
19
- (github.event.action == 'labeled' && github.event.label.name == 'claude-review') ||
20
- (github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'claude-review'))
27
+ # Run only when ALL of the following hold:
28
+ # 1. Author is not a bot (renovate, dependabot, etc. surface as 'name[bot]').
29
+ # 2. PR head is not from a fork. Fork PRs run without repository secrets, so
30
+ # CLAUDE_CODE_OAUTH_TOKEN is empty and the action would fail.
31
+ # 3. The event is a freshly opened PR, a 'claude-review' label add, or a push
32
+ # to a PR that already carries the 'claude-review' label.
33
+ if: ${{
34
+ !endsWith(github.actor, '[bot]') &&
35
+ !github.event.pull_request.head.repo.fork &&
36
+ (
37
+ (github.event.action == 'opened') ||
38
+ (github.event.action == 'labeled' && github.event.label.name == 'claude-review') ||
39
+ (github.event.action == 'synchronize' && contains(github.event.pull_request.labels.*.name, 'claude-review'))
40
+ )
41
+ }}
21
42
 
22
43
  permissions:
23
44
  contents: read
@@ -27,7 +48,7 @@ jobs:
27
48
 
28
49
  steps:
29
50
  - name: Checkout repository
30
- uses: actions/checkout@v6.0.3
51
+ uses: actions/checkout@v7.0.0
31
52
  with:
32
53
  fetch-depth: 1
33
54
 
@@ -37,10 +58,12 @@ jobs:
37
58
  with:
38
59
  claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
39
60
 
40
- # Fall back to Sonnet when the primary model is unavailable/overloaded.
41
- # Without this, an unavailable primary surfaces as "Claude encountered
42
- # an error" and fails the claude-review check.
43
- fallback_model: "claude-sonnet-4-6"
61
+ # Primary model precedence: the workflow_dispatch "model" input (manual
62
+ # runs) -> the CLAUDE_MODEL repo variable -> this built-in default.
63
+ # Pinning a current id avoids the action's frozen default, which 404s
64
+ # ("model: claude-sonnet-4-20250514"). Fall back to Sonnet on overload.
65
+ model: "${{ inputs.model || vars.CLAUDE_MODEL || 'claude-opus-4-6' }}"
66
+ fallback_model: "${{ vars.CLAUDE_FALLBACK_MODEL || 'claude-sonnet-4-6' }}"
44
67
 
45
68
  # Direct prompt for automated review (no @claude mention needed)
46
69
  direct_prompt: |
@@ -26,7 +26,7 @@ jobs:
26
26
  actions: read # Required for Claude to read CI results on PRs
27
27
  steps:
28
28
  - name: Checkout repository
29
- uses: actions/checkout@v6.0.3
29
+ uses: actions/checkout@v7.0.0
30
30
  with:
31
31
  fetch-depth: 1
32
32
 
@@ -36,10 +36,12 @@ jobs:
36
36
  with:
37
37
  claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
38
38
 
39
- # Fall back to Sonnet when the primary model is unavailable/overloaded.
40
- # Without this, an unavailable primary surfaces as "Claude encountered
41
- # an error" and fails the claude-review check.
42
- fallback_model: "claude-sonnet-4-6"
39
+ # Primary model: set the CLAUDE_MODEL repo variable to override without
40
+ # editing this file. Pinning a current id avoids the action's frozen
41
+ # default, which 404s ("model: claude-sonnet-4-20250514"). Fall back to
42
+ # Sonnet if the primary is unavailable or overloaded.
43
+ model: "${{ vars.CLAUDE_MODEL || 'claude-opus-4-6' }}"
44
+ fallback_model: "${{ vars.CLAUDE_FALLBACK_MODEL || 'claude-sonnet-4-6' }}"
43
45
 
44
46
  # This is an optional setting that allows Claude to read CI results on PRs
45
47
  additional_permissions: |
@@ -21,7 +21,7 @@ jobs:
21
21
 
22
22
  steps:
23
23
  - name: Checkout code
24
- uses: actions/checkout@v6.0.3
24
+ uses: actions/checkout@v7.0.0
25
25
 
26
26
  - name: Set up Ruby
27
27
  uses: ruby/setup-ruby@v1
@@ -88,7 +88,7 @@ jobs:
88
88
 
89
89
  steps:
90
90
  - name: Checkout code
91
- uses: actions/checkout@v6.0.3
91
+ uses: actions/checkout@v7.0.0
92
92
 
93
93
  - name: Set up Ruby
94
94
  uses: ruby/setup-ruby@v1
@@ -114,6 +114,16 @@ jobs:
114
114
  runs-on: ubuntu-latest
115
115
  timeout-minutes: 10
116
116
 
117
+ # `rake` lives in the optional :development group (see Gemfile), so a plain
118
+ # `bundle install` skips it and rubygems/release-gem's `bundle exec rake
119
+ # release` dies with "rake is not currently included in the bundle". Opt the
120
+ # group in for the whole job: setup-ruby's cached `bundle install` reads
121
+ # BUNDLE_WITH so rake is installed, and the release step's `bundle exec`
122
+ # reads it too so rake stays in the resolved bundle. This mirrors the
123
+ # `bundle config set --local with` that ci.yml uses for the same groups.
124
+ env:
125
+ BUNDLE_WITH: development
126
+
117
127
  environment:
118
128
  name: rubygems.org
119
129
  url: https://rubygems.org/gems/otto
@@ -124,7 +134,7 @@ jobs:
124
134
 
125
135
  steps:
126
136
  - name: Checkout
127
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
137
+ uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
128
138
  with:
129
139
  persist-credentials: false
130
140
 
@@ -159,4 +169,4 @@ jobs:
159
169
  echo "Releasing otto ${gem_version} from tag ${RELEASE_TAG}"
160
170
 
161
171
  - name: Build and push gem to RubyGems
162
- uses: rubygems/release-gem@6317d8d1f7e28c24d28f6eff169ea854948bd9f7 # v1.2.0
172
+ uses: rubygems/release-gem@052cc82692552de3ef2b81fd670e41d13cba8092 # v1.4.0
@@ -0,0 +1,66 @@
1
+ # .github/workflows/ruby-lint.yml
2
+
3
+ name: Ruby Lint
4
+
5
+ # Runs RuboCop across the supported Ruby versions. Linting is informational:
6
+ # every dependency/lint step is continue-on-error, so style findings surface as
7
+ # annotations without blocking merges.
8
+
9
+ on:
10
+ push:
11
+ branches:
12
+ - fix/*
13
+ - rel/*
14
+ pull_request:
15
+ branches:
16
+ - main
17
+ - develop
18
+ - feature/*
19
+ workflow_dispatch:
20
+ inputs:
21
+ debug_enabled:
22
+ type: boolean
23
+ description: 'Run the build with tmate debugging enabled (https://github.com/marketplace/actions/debugging-with-tmate)'
24
+ required: false
25
+ default: false
26
+
27
+ permissions:
28
+ contents: read
29
+
30
+ jobs:
31
+ lint:
32
+ timeout-minutes: 10 # prevent hung jobs
33
+
34
+ runs-on: ubuntu-24.04
35
+
36
+ strategy:
37
+ fail-fast: true
38
+ matrix:
39
+ ruby: ['3.2', '3.3', '3.4', '3.5', '4.0']
40
+ continue-on-error: [true]
41
+
42
+ steps:
43
+ - name: Checkout code
44
+ uses: actions/checkout@v6.0.3
45
+
46
+ - uses: ruby/setup-ruby@v1
47
+ with:
48
+ ruby-version: ${{ matrix.ruby }}
49
+ bundler-cache: true
50
+
51
+ - name: Setup tmate session
52
+ uses: mxschmitt/action-tmate@35b54afac29c97fb54faba5b513f8fbd1882f113 # v3
53
+ if: ${{ github.event_name == 'workflow_dispatch' && inputs.debug_enabled }}
54
+ with:
55
+ detached: true
56
+
57
+ - name: Install dependencies
58
+ continue-on-error: ${{ matrix.continue-on-error }}
59
+ run: |
60
+ bundle config path vendor/bundle
61
+ bundle install --jobs 4 --retry 3
62
+
63
+ - name: Run Rubocop
64
+ continue-on-error: ${{ matrix.continue-on-error }}
65
+ run: |
66
+ bundle exec rubocop --config .rubocop.yml --format json --fail-level warning
@@ -0,0 +1,117 @@
1
+ name: Generate and Deploy YARD Documentation
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ paths:
8
+ - 'lib/**/*'
9
+ - 'docs/**/*'
10
+ - 'README.md'
11
+ - 'CHANGELOG.md'
12
+ - 'CHANGELOG.rst'
13
+ - 'LICENSE.txt'
14
+ - '.yardopts'
15
+ - '.github/workflows/yardoc.yml'
16
+ workflow_dispatch:
17
+
18
+ permissions:
19
+ contents: read
20
+ pages: write
21
+ id-token: write
22
+
23
+ # Allow only one concurrent deployment, skipping runs queued between the run
24
+ # in-progress and latest queued. Do NOT cancel in-progress runs so production
25
+ # deployments can complete.
26
+ concurrency:
27
+ group: "pages"
28
+ cancel-in-progress: false
29
+
30
+ jobs:
31
+ build-docs:
32
+ timeout-minutes: 10
33
+ runs-on: ubuntu-latest
34
+ name: Generate YARD Documentation
35
+ env:
36
+ # otto declares yard/kramdown in a `group :development` whose name also
37
+ # appears in an `optional: true` block, so Bundler treats `development`
38
+ # as optional and the default `bundle install` skips it (yard never
39
+ # installs -> `bundle exec yard` is "command not found"). Mirror otto's
40
+ # ci.yml convention so setup-ruby installs the dev/test gems.
41
+ BUNDLE_WITH: "development:test"
42
+
43
+ steps:
44
+ - name: Checkout repository
45
+ uses: actions/checkout@v6.0.3
46
+ with:
47
+ fetch-depth: 0
48
+
49
+ - name: Set up Ruby environment
50
+ uses: ruby/setup-ruby@v1
51
+ with:
52
+ ruby-version: '3.4'
53
+ bundler-cache: true
54
+
55
+ - name: Generate documentation
56
+ # Uses the repository's committed .yardopts as the single source of
57
+ # truth for the output dir, includes/excludes, markup, and tags.
58
+ run: |
59
+ echo "::group::YARD Documentation Generation"
60
+ bundle exec yard stats --list-undoc || true
61
+ bundle exec yard doc
62
+ echo "::endgroup::"
63
+
64
+ - name: Disable Jekyll processing
65
+ # YARD emits files and directories that begin with underscores; the
66
+ # .nojekyll marker stops GitHub Pages from stripping them.
67
+ run: touch doc/.nojekyll
68
+
69
+ - name: Validate documentation output
70
+ run: |
71
+ echo "::group::Documentation Validation"
72
+ if [ ! -d "doc" ]; then
73
+ echo "Error: documentation directory 'doc' was not generated." >&2
74
+ echo "Ensure .yardopts sets '--output-dir doc'." >&2
75
+ exit 1
76
+ fi
77
+ if [ ! -f "doc/index.html" ]; then
78
+ echo "Warning: doc/index.html not found"
79
+ fi
80
+ echo "Generated HTML files: $(find doc -name '*.html' | wc -l)"
81
+ echo "Total documentation size: $(du -sh doc/ | cut -f1)"
82
+ echo "::endgroup::"
83
+
84
+ - name: Setup GitHub Pages configuration
85
+ uses: actions/configure-pages@v6
86
+
87
+ - name: Upload documentation artifact
88
+ uses: actions/upload-pages-artifact@v5
89
+ with:
90
+ path: './doc'
91
+
92
+ deploy-pages:
93
+ timeout-minutes: 10
94
+ environment:
95
+ name: github-pages
96
+ url: ${{ steps.deployment.outputs.page_url }}
97
+ runs-on: ubuntu-latest
98
+ needs: build-docs
99
+ outputs:
100
+ page_url: ${{ steps.deployment.outputs.page_url }}
101
+
102
+ steps:
103
+ - name: Deploy to GitHub Pages
104
+ id: deployment
105
+ uses: actions/deploy-pages@v5
106
+
107
+ notify-completion:
108
+ timeout-minutes: 5
109
+ runs-on: ubuntu-latest
110
+ needs: [build-docs, deploy-pages]
111
+ if: success()
112
+
113
+ steps:
114
+ - name: Documentation deployment summary
115
+ run: |
116
+ echo "::notice title=Documentation Deployed::YARD documentation successfully deployed to GitHub Pages"
117
+ echo "::notice title=Access URL::Documentation available at: ${{ needs.deploy-pages.outputs.page_url }}"
data/.yardopts ADDED
@@ -0,0 +1,15 @@
1
+ --readme README.md
2
+ --title "Otto Ruby Library Documentation"
3
+ --protected
4
+ --no-private
5
+ --markup markdown
6
+ --markup-provider kramdown
7
+ --output-dir doc
8
+ --exclude lib/otto/version.rb
9
+ lib/**/*.rb
10
+ -
11
+ README.md
12
+ CHANGELOG.rst
13
+ LICENSE.txt
14
+ docs/**/*.md
15
+ examples/*.rb
data/CHANGELOG.rst CHANGED
@@ -7,6 +7,65 @@ The format is based on `Keep a Changelog <https://keepachangelog.com/en/1.1.0/>`
7
7
 
8
8
  <!--scriv-insert-here-->
9
9
 
10
+ .. _changelog-2.4.0:
11
+
12
+ 2.4.0 — 2026-07-01
13
+ ==================
14
+
15
+ Added
16
+ -----
17
+
18
+ - ``Otto#enable_csp_reporting!(report_uri, endpoint_url: nil, &block)`` —
19
+ turnkey CSP violation reporting. Emits a ``report-uri`` directive and, with
20
+ ``endpoint_url:``, a ``report-to`` directive plus ``Reporting-Endpoints``
21
+ header. Parses legacy ``application/csp-report`` and Reporting API
22
+ ``application/reports+json`` payloads into ``Otto::Security::CSP::Report``
23
+ and invokes the callback per violation. Opt-in. (delano/otto#174)
24
+
25
+ - ``MiddlewareStack`` ``:outermost`` position, for middleware that must run
26
+ ahead of all others regardless of registration order.
27
+
28
+ - ``Otto::CaddyTLS``: an opt-in Caddy on-demand TLS permission endpoint,
29
+ enabled with ``otto.enable_caddy_tls! { |domain| ... }``. (delano/otto#175)
30
+
31
+ Fixed
32
+ -----
33
+
34
+ - ``IPPrivacyMiddleware`` no longer writes ``nil`` into CGI-style Rack env
35
+ keys (e.g. ``HTTP_REFERER``, ``HTTP_USER_AGENT``, ``REMOTE_ADDR``) when
36
+ redacting request data, which violated the Rack SPEC and tripped
37
+ ``Rack::Lint``. Empty anonymized values now delete the key instead of
38
+ setting it to ``nil``, and a request with no resolvable client IP no
39
+ longer gets a ``nil`` ``REMOTE_ADDR``. (delano/otto#167)
40
+
41
+ - ``Otto::Security::CSP::ReportMiddleware`` no longer turns a downstream
42
+ error on a non-report request into an empty ``204``.
43
+
44
+ Security
45
+ --------
46
+
47
+ - The ``Otto::CaddyTLS`` permission endpoint is loopback-only by default and
48
+ fails closed. (delano/otto#175)
49
+
50
+ - Security middleware registered through the ``otto.security.*``
51
+ Configurator after ``Otto.new`` now actually runs on the request chain —
52
+ previously CSRF, request validation, rate limiting, and CSP reporting
53
+ silently went unenforced.
54
+
55
+ AI Assistance
56
+ -------------
57
+
58
+ - CSP violation reporting (``report-uri`` / ``report-to``), the
59
+ ``:outermost`` middleware position, and the Configurator
60
+ middleware-registration fix were designed and implemented with AI
61
+ assistance.
62
+
63
+ - ``Otto::CaddyTLS`` designed, implemented, and reviewed with AI assistance.
64
+
65
+ - The Rack SPEC ``nil``-into-CGI-key fix — including the sibling
66
+ ``REMOTE_ADDR`` masking bug and ``Rack::Lint`` test coverage — diagnosed
67
+ and fixed with AI assistance.
68
+
10
69
  .. _changelog-2.3.1:
11
70
 
12
71
  2.3.1 — 2026-06-22
data/Gemfile CHANGED
@@ -27,8 +27,8 @@ group :development do
27
27
  gem 'benchmark'
28
28
  gem 'debug'
29
29
  gem 'rackup' # Used to boot examples/ apps; not needed by specs
30
- gem 'rake', '~> 13.0', require: false # Provides `rake release` for release-gem.yml
31
- gem 'rubocop', '~> 1.86.2', require: false
30
+ gem 'rake', '~> 13.4', require: false # Provides `rake release` for release-gem.yml
31
+ gem 'rubocop', '~> 1.88.0', require: false
32
32
  gem 'rubocop-performance', require: false
33
33
  gem 'rubocop-rspec', require: false
34
34
  gem 'rubocop-thread_safety', require: false
@@ -36,4 +36,6 @@ group :development do
36
36
  gem 'stackprof', require: false
37
37
  gem 'syntax_tree', require: false
38
38
  gem 'tryouts', '~> 3.7.1', require: false
39
+ gem 'yard', '~> 0.9', require: false # API docs for yardoc.yml
40
+ gem 'kramdown', require: false # Markdown provider for YARD
39
41
  end
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- otto (2.3.1)
4
+ otto (2.4.0)
5
5
  concurrent-ruby (~> 1.3, < 2.0)
6
6
  logger (~> 1, < 2.0)
7
7
  loofah (~> 2.20)
@@ -15,7 +15,7 @@ GEM
15
15
  ast (2.4.3)
16
16
  benchmark (0.5.0)
17
17
  bigdecimal (4.1.1)
18
- concurrent-ruby (1.3.6)
18
+ concurrent-ruby (1.3.7)
19
19
  crass (1.0.6)
20
20
  date (3.5.1)
21
21
  debug (1.11.1)
@@ -59,12 +59,14 @@ GEM
59
59
  prism (>= 1.3.0)
60
60
  rdoc (>= 4.0.0)
61
61
  reline (>= 0.4.2)
62
- json (2.19.5)
62
+ json (2.19.9)
63
63
  json_schemer (2.5.0)
64
64
  bigdecimal
65
65
  hana (~> 1.3)
66
66
  regexp_parser (~> 2.0)
67
67
  simpleidn (~> 0.2)
68
+ kramdown (2.5.2)
69
+ rexml (>= 3.4.4)
68
70
  language_server-protocol (3.17.0.5)
69
71
  lint_roller (1.1.0)
70
72
  logger (1.7.0)
@@ -72,21 +74,21 @@ GEM
72
74
  crass (~> 1.0.2)
73
75
  nokogiri (>= 1.12.0)
74
76
  minitest (5.26.0)
75
- nokogiri (1.19.2-aarch64-linux-gnu)
77
+ nokogiri (1.19.4-aarch64-linux-gnu)
76
78
  racc (~> 1.4)
77
- nokogiri (1.19.2-aarch64-linux-musl)
79
+ nokogiri (1.19.4-aarch64-linux-musl)
78
80
  racc (~> 1.4)
79
- nokogiri (1.19.2-arm-linux-gnu)
81
+ nokogiri (1.19.4-arm-linux-gnu)
80
82
  racc (~> 1.4)
81
- nokogiri (1.19.2-arm-linux-musl)
83
+ nokogiri (1.19.4-arm-linux-musl)
82
84
  racc (~> 1.4)
83
- nokogiri (1.19.2-arm64-darwin)
85
+ nokogiri (1.19.4-arm64-darwin)
84
86
  racc (~> 1.4)
85
- nokogiri (1.19.2-x86_64-darwin)
87
+ nokogiri (1.19.4-x86_64-darwin)
86
88
  racc (~> 1.4)
87
- nokogiri (1.19.2-x86_64-linux-gnu)
89
+ nokogiri (1.19.4-x86_64-linux-gnu)
88
90
  racc (~> 1.4)
89
- nokogiri (1.19.2-x86_64-linux-musl)
91
+ nokogiri (1.19.4-x86_64-linux-musl)
90
92
  racc (~> 1.4)
91
93
  parallel (1.28.0)
92
94
  parser (3.3.11.1)
@@ -113,7 +115,7 @@ GEM
113
115
  rackup (2.3.1)
114
116
  rack (>= 3)
115
117
  rainbow (3.1.1)
116
- rake (13.1.0)
118
+ rake (13.4.2)
117
119
  rbs (4.0.2)
118
120
  logger
119
121
  prism (>= 1.6.0)
@@ -145,7 +147,7 @@ GEM
145
147
  diff-lcs (>= 1.2.0, < 2.0)
146
148
  rspec-support (~> 3.13.0)
147
149
  rspec-support (3.13.7)
148
- rubocop (1.86.2)
150
+ rubocop (1.88.0)
149
151
  json (~> 2.3)
150
152
  language_server-protocol (~> 3.17.0.2)
151
153
  lint_roller (~> 1.1.0)
@@ -163,9 +165,10 @@ GEM
163
165
  lint_roller (~> 1.1)
164
166
  rubocop (>= 1.75.0, < 2.0)
165
167
  rubocop-ast (>= 1.47.1, < 2.0)
166
- rubocop-rspec (3.9.0)
168
+ rubocop-rspec (3.10.2)
167
169
  lint_roller (~> 1.1)
168
- rubocop (~> 1.81)
170
+ regexp_parser (>= 2.0)
171
+ rubocop (~> 1.86, >= 1.86.2)
169
172
  rubocop-thread_safety (0.7.3)
170
173
  lint_roller (~> 1.1)
171
174
  rubocop (~> 1.72, >= 1.72.1)
@@ -197,6 +200,7 @@ GEM
197
200
  unicode-emoji (~> 4.1)
198
201
  unicode-emoji (4.2.0)
199
202
  user_agent_parser (2.21.0)
203
+ yard (0.9.44)
200
204
  zeitwerk (2.7.3)
201
205
 
202
206
  PLATFORMS
@@ -213,14 +217,15 @@ DEPENDENCIES
213
217
  benchmark
214
218
  debug
215
219
  json_schemer
220
+ kramdown
216
221
  otto!
217
222
  rack-attack
218
223
  rack-test
219
224
  rackup
220
- rake (~> 13.0)
225
+ rake (~> 13.4)
221
226
  reek (~> 6.5)
222
227
  rspec (~> 3.13)
223
- rubocop (~> 1.86.2)
228
+ rubocop (~> 1.88.0)
224
229
  rubocop-performance
225
230
  rubocop-rspec
226
231
  rubocop-thread_safety
@@ -229,6 +234,7 @@ DEPENDENCIES
229
234
  syntax_tree
230
235
  tryouts (~> 3.7.1)
231
236
  user_agent_parser (~> 2.18)
237
+ yard (~> 0.9)
232
238
 
233
239
  BUNDLED WITH
234
240
  2.7.1