otto 1.6.0 → 2.0.0.pre1

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 (136) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +1 -1
  3. data/.github/workflows/claude-code-review.yml +53 -0
  4. data/.github/workflows/claude.yml +49 -0
  5. data/.gitignore +3 -0
  6. data/.rubocop.yml +24 -345
  7. data/CHANGELOG.rst +83 -0
  8. data/CLAUDE.md +56 -0
  9. data/Gemfile +10 -3
  10. data/Gemfile.lock +23 -28
  11. data/README.md +2 -0
  12. data/bin/rspec +4 -4
  13. data/changelog.d/20250911_235619_delano_next.rst +28 -0
  14. data/changelog.d/20250912_123055_delano_remove_ostruct.rst +21 -0
  15. data/changelog.d/20250912_175625_claude_delano_remove_ostruct.rst +21 -0
  16. data/changelog.d/README.md +120 -0
  17. data/changelog.d/scriv.ini +5 -0
  18. data/docs/.gitignore +1 -0
  19. data/docs/migrating/v2.0.0-pre1.md +276 -0
  20. data/examples/.gitignore +1 -0
  21. data/examples/advanced_routes/README.md +33 -0
  22. data/examples/advanced_routes/app/controllers/handlers/async.rb +9 -0
  23. data/examples/advanced_routes/app/controllers/handlers/dynamic.rb +9 -0
  24. data/examples/advanced_routes/app/controllers/handlers/static.rb +9 -0
  25. data/examples/advanced_routes/app/controllers/modules/auth.rb +9 -0
  26. data/examples/advanced_routes/app/controllers/modules/transformer.rb +9 -0
  27. data/examples/advanced_routes/app/controllers/modules/validator.rb +9 -0
  28. data/examples/advanced_routes/app/controllers/routes_app.rb +232 -0
  29. data/examples/advanced_routes/app/controllers/v2/admin.rb +9 -0
  30. data/examples/advanced_routes/app/controllers/v2/config.rb +9 -0
  31. data/examples/advanced_routes/app/controllers/v2/settings.rb +9 -0
  32. data/examples/advanced_routes/app/logic/admin/logic/manager.rb +27 -0
  33. data/examples/advanced_routes/app/logic/admin/panel.rb +27 -0
  34. data/examples/advanced_routes/app/logic/analytics_processor.rb +25 -0
  35. data/examples/advanced_routes/app/logic/complex/business/handler.rb +27 -0
  36. data/examples/advanced_routes/app/logic/data_logic.rb +23 -0
  37. data/examples/advanced_routes/app/logic/data_processor.rb +25 -0
  38. data/examples/advanced_routes/app/logic/input_validator.rb +24 -0
  39. data/examples/advanced_routes/app/logic/nested/feature/logic.rb +27 -0
  40. data/examples/advanced_routes/app/logic/reports_generator.rb +27 -0
  41. data/examples/advanced_routes/app/logic/simple_logic.rb +25 -0
  42. data/examples/advanced_routes/app/logic/system/config/manager.rb +27 -0
  43. data/examples/advanced_routes/app/logic/test_logic.rb +23 -0
  44. data/examples/advanced_routes/app/logic/transform_logic.rb +23 -0
  45. data/examples/advanced_routes/app/logic/upload_logic.rb +23 -0
  46. data/examples/advanced_routes/app/logic/v2/logic/dashboard.rb +27 -0
  47. data/examples/advanced_routes/app/logic/v2/logic/processor.rb +27 -0
  48. data/examples/advanced_routes/app.rb +33 -0
  49. data/examples/advanced_routes/config.rb +23 -0
  50. data/examples/advanced_routes/config.ru +7 -0
  51. data/examples/advanced_routes/puma.rb +20 -0
  52. data/examples/advanced_routes/routes +167 -0
  53. data/examples/advanced_routes/run.rb +39 -0
  54. data/examples/advanced_routes/test.rb +58 -0
  55. data/examples/authentication_strategies/README.md +32 -0
  56. data/examples/authentication_strategies/app/auth.rb +68 -0
  57. data/examples/authentication_strategies/app/controllers/auth_controller.rb +29 -0
  58. data/examples/authentication_strategies/app/controllers/main_controller.rb +28 -0
  59. data/examples/authentication_strategies/config.ru +24 -0
  60. data/examples/authentication_strategies/routes +37 -0
  61. data/examples/basic/README.md +29 -0
  62. data/examples/basic/app.rb +7 -35
  63. data/examples/basic/routes +0 -9
  64. data/examples/mcp_demo/README.md +87 -0
  65. data/examples/mcp_demo/app.rb +29 -34
  66. data/examples/mcp_demo/config.ru +9 -60
  67. data/examples/security_features/README.md +46 -0
  68. data/examples/security_features/app.rb +23 -24
  69. data/examples/security_features/config.ru +8 -10
  70. data/lib/otto/core/configuration.rb +167 -0
  71. data/lib/otto/core/error_handler.rb +86 -0
  72. data/lib/otto/core/file_safety.rb +61 -0
  73. data/lib/otto/core/middleware_stack.rb +157 -0
  74. data/lib/otto/core/router.rb +183 -0
  75. data/lib/otto/core/uri_generator.rb +44 -0
  76. data/lib/otto/design_system.rb +7 -5
  77. data/lib/otto/helpers/base.rb +3 -0
  78. data/lib/otto/helpers/request.rb +10 -8
  79. data/lib/otto/helpers/response.rb +5 -4
  80. data/lib/otto/helpers/validation.rb +9 -7
  81. data/lib/otto/mcp/auth/token.rb +10 -9
  82. data/lib/otto/mcp/protocol.rb +24 -27
  83. data/lib/otto/mcp/rate_limiting.rb +8 -3
  84. data/lib/otto/mcp/registry.rb +7 -2
  85. data/lib/otto/mcp/route_parser.rb +10 -15
  86. data/lib/otto/mcp/server.rb +21 -11
  87. data/lib/otto/mcp/validation.rb +14 -10
  88. data/lib/otto/response_handlers/auto.rb +39 -0
  89. data/lib/otto/response_handlers/base.rb +16 -0
  90. data/lib/otto/response_handlers/default.rb +16 -0
  91. data/lib/otto/response_handlers/factory.rb +39 -0
  92. data/lib/otto/response_handlers/json.rb +28 -0
  93. data/lib/otto/response_handlers/redirect.rb +25 -0
  94. data/lib/otto/response_handlers/view.rb +24 -0
  95. data/lib/otto/response_handlers.rb +9 -135
  96. data/lib/otto/route.rb +9 -9
  97. data/lib/otto/route_definition.rb +15 -18
  98. data/lib/otto/route_handlers/base.rb +121 -0
  99. data/lib/otto/route_handlers/class_method.rb +89 -0
  100. data/lib/otto/route_handlers/factory.rb +29 -0
  101. data/lib/otto/route_handlers/instance_method.rb +69 -0
  102. data/lib/otto/route_handlers/lambda.rb +59 -0
  103. data/lib/otto/route_handlers/logic_class.rb +93 -0
  104. data/lib/otto/route_handlers.rb +10 -405
  105. data/lib/otto/security/authentication/auth_strategy.rb +44 -0
  106. data/lib/otto/security/authentication/authentication_middleware.rb +123 -0
  107. data/lib/otto/security/authentication/failure_result.rb +36 -0
  108. data/lib/otto/security/authentication/strategies/api_key_strategy.rb +40 -0
  109. data/lib/otto/security/authentication/strategies/permission_strategy.rb +47 -0
  110. data/lib/otto/security/authentication/strategies/public_strategy.rb +19 -0
  111. data/lib/otto/security/authentication/strategies/role_strategy.rb +57 -0
  112. data/lib/otto/security/authentication/strategies/session_strategy.rb +41 -0
  113. data/lib/otto/security/authentication/strategy_result.rb +223 -0
  114. data/lib/otto/security/authentication.rb +28 -282
  115. data/lib/otto/security/config.rb +14 -12
  116. data/lib/otto/security/configurator.rb +219 -0
  117. data/lib/otto/security/csrf.rb +8 -143
  118. data/lib/otto/security/middleware/csrf_middleware.rb +151 -0
  119. data/lib/otto/security/middleware/rate_limit_middleware.rb +38 -0
  120. data/lib/otto/security/middleware/validation_middleware.rb +252 -0
  121. data/lib/otto/security/rate_limiter.rb +86 -0
  122. data/lib/otto/security/rate_limiting.rb +10 -105
  123. data/lib/otto/security/validator.rb +8 -253
  124. data/lib/otto/static.rb +3 -0
  125. data/lib/otto/utils.rb +14 -0
  126. data/lib/otto/version.rb +3 -1
  127. data/lib/otto.rb +142 -498
  128. data/otto.gemspec +2 -2
  129. metadata +89 -28
  130. data/examples/dynamic_pages/app.rb +0 -115
  131. data/examples/dynamic_pages/config.ru +0 -30
  132. data/examples/dynamic_pages/routes +0 -21
  133. data/examples/helpers_demo/app.rb +0 -244
  134. data/examples/helpers_demo/config.ru +0 -26
  135. data/examples/helpers_demo/routes +0 -7
  136. data/lib/concurrent_cache_store.rb +0 -68
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0acf8247a8132f9e836ba841732a45bf265efbc0cae190c744e323a97229d913
4
- data.tar.gz: 05fe0d3c74d9385e470ea45856e0c8cb2b081ff6eea63a83951039bd426219b3
3
+ metadata.gz: a3de0a572bb6389f8e3f6b64d3295630c1d2f9872734d5840c5c2e5dc89f1fd4
4
+ data.tar.gz: 41caaa99c08d5646d576b5c15d4392757e541ae00218dd7a3831d4532ee7a30c
5
5
  SHA512:
6
- metadata.gz: 1f86dd56ef78a8f892d4e75046f2ac4560e951999773b668dba6a15a270d4f811aa0df56f618c0a8b1ce75af7b76799ca083b0b30788cc5733cc570107233f64
7
- data.tar.gz: 6fd7fcc1008ed682dbcc7a4e400a220c55a8f1cd9d3081e7d089e761c14f883d11028ad1b0e279d7ea96c33e2ff4fc6afb0aabf69356d0c42ba8527eb2e4627d
6
+ metadata.gz: bbef30e2f11091b5b74c7c20aeead0b118b22bd5a52b77cc23c8901f8dcc58f9465748b1d3c46ae1c2cf0a75b7736d07248d9150a6b9fe28ddc02ef23543ca83
7
+ data.tar.gz: 765a1cc021e278ca5ff484dd55e49695176c8aac998a3374677026857c27643c237088347fd3b04bbae69f4d6eae2ffec089bffbb7019f339c43c85f6e035668
@@ -38,7 +38,7 @@ jobs:
38
38
  experimental: true
39
39
 
40
40
  steps:
41
- - uses: actions/checkout@v4
41
+ - uses: actions/checkout@v5
42
42
  - name: Set up Ruby
43
43
  uses: ruby/setup-ruby@v1
44
44
  with:
@@ -0,0 +1,53 @@
1
+ name: Claude Code Review
2
+
3
+ on:
4
+ pull_request:
5
+ types: [opened, synchronize]
6
+ # Optional: Only run on specific file changes
7
+ # paths:
8
+ # - "src/**/*.ts"
9
+ # - "src/**/*.tsx"
10
+ # - "src/**/*.js"
11
+ # - "src/**/*.jsx"
12
+
13
+ jobs:
14
+ claude-review:
15
+ # Optional: Filter by PR author
16
+ # if: |
17
+ # github.event.pull_request.user.login == 'external-contributor' ||
18
+ # github.event.pull_request.user.login == 'new-developer' ||
19
+ # github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
20
+
21
+ runs-on: ubuntu-latest
22
+ permissions:
23
+ contents: read
24
+ pull-requests: read
25
+ issues: read
26
+ id-token: write
27
+
28
+ steps:
29
+ - name: Checkout repository
30
+ uses: actions/checkout@v4
31
+ with:
32
+ fetch-depth: 1
33
+
34
+ - name: Run Claude Code Review
35
+ id: claude-review
36
+ uses: anthropics/claude-code-action@v1
37
+ with:
38
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
39
+ prompt: |
40
+ Please review this pull request and provide feedback on:
41
+ - Code quality and best practices
42
+ - Potential bugs or issues
43
+ - Performance considerations
44
+ - Security concerns
45
+ - Test coverage
46
+
47
+ Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback.
48
+
49
+ Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR.
50
+
51
+ # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
52
+ # or https://docs.anthropic.com/en/docs/claude-code/sdk#command-line for available options
53
+ claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"'
@@ -0,0 +1,49 @@
1
+ name: Claude Code
2
+
3
+ on:
4
+ issue_comment:
5
+ types: [created]
6
+ pull_request_review_comment:
7
+ types: [created]
8
+ issues:
9
+ types: [opened, assigned]
10
+ pull_request_review:
11
+ types: [submitted]
12
+
13
+ jobs:
14
+ claude:
15
+ if: |
16
+ (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
17
+ (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
18
+ (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
19
+ (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
20
+ runs-on: ubuntu-latest
21
+ permissions:
22
+ contents: read
23
+ pull-requests: read
24
+ issues: read
25
+ id-token: write
26
+ actions: read # Required for Claude to read CI results on PRs
27
+ steps:
28
+ - name: Checkout repository
29
+ uses: actions/checkout@v4
30
+ with:
31
+ fetch-depth: 1
32
+
33
+ - name: Run Claude Code
34
+ id: claude
35
+ uses: anthropics/claude-code-action@v1
36
+ with:
37
+ claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
38
+
39
+ # This is an optional setting that allows Claude to read CI results on PRs
40
+ additional_permissions: |
41
+ actions: read
42
+
43
+ # Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
44
+ # prompt: 'Update the pull request description to include a summary of changes.'
45
+
46
+ # Optional: Add claude_args to customize behavior and configuration
47
+ # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
48
+ # or https://docs.anthropic.com/en/docs/claude-code/sdk#command-line for available options
49
+ # claude_args: '--model claude-opus-4-1-20250805 --allowed-tools Bash(gh pr:*)'
data/.gitignore CHANGED
@@ -8,6 +8,7 @@
8
8
  *.log
9
9
  *.md
10
10
  *.txt
11
+ .*.json
11
12
  !LICENSE.txt
12
13
  !spec/fixtures/*.txt
13
14
  .ruby-version
@@ -20,3 +21,5 @@ vendor
20
21
  .ruby-lsp
21
22
  .rspec_status
22
23
  .mcp.json
24
+ .claude
25
+ .serena
data/.rubocop.yml CHANGED
@@ -8,410 +8,89 @@
8
8
  # refer to the RuboCop documentation:
9
9
  # https://docs.rubocop.org/rubocop/cops.html
10
10
  #
11
-
12
11
  plugins:
12
+ - rubocop-rspec
13
13
  - rubocop-performance
14
14
  - rubocop-thread_safety
15
- - rubocop-rspec
16
15
 
17
16
  AllCops:
18
17
  NewCops: enable
19
- DisabledByDefault: false # flip to true for a good autocorrect time
20
18
  UseCache: true
21
19
  MaxFilesInCache: 100
22
20
  TargetRubyVersion: 3.2
23
21
  Exclude:
24
- - "spec/**/*.rb"
22
+ - "spec/**/*"
25
23
  - "vendor/**/*"
26
24
 
27
- Layout/CaseIndentation:
28
- Enabled: true
29
- EnforcedStyle: end # case, end
30
- IndentOneStep: false
31
- IndentationWidth: 2
32
-
33
- Layout/CommentIndentation:
34
- Enabled: true
35
-
36
- Layout/MultilineMethodCallBraceLayout:
37
- Enabled: true
38
- EnforcedStyle: new_line # symmetrical, new_line, same_line
39
-
40
- Layout/TrailingWhitespace:
41
- Enabled: true
42
-
43
- Layout/SpaceAroundEqualsInParameterDefault:
44
- Enabled: true
45
-
46
- Layout/SpaceAroundOperators:
47
- Enabled: false
48
-
49
- # Use parentheses around a logical expression if it makes easier to read.
50
- Style/RedundantParentheses:
51
- Enabled: false
52
-
53
- Lint/UnusedMethodArgument:
54
- Enabled: true
55
-
56
- Lint/UselessAssignment:
57
- Enabled: true
58
-
59
- Lint/DuplicateBranch:
60
- Enabled: true
61
- IgnoreLiteralBranches: false
62
- IgnoreConstantBranches: false
63
- IgnoreDuplicateElseBranch: false
64
-
65
- # Offense count: 3
66
- # Configuration parameters: AllowedMethods, AllowedPatterns.
67
- Metrics/PerceivedComplexity:
68
- Max: 20
69
-
70
- # Offense count: 186
71
- # Configuration parameters: AllowedConstants.
72
- Style/Documentation:
73
- Enabled: false
74
-
75
- Style/RescueStandardError:
76
- Enabled: true
77
- EnforcedStyle: explicit
78
-
79
- # When true: Use match? instead of =~ when MatchData is not used. True is preferred but not for autocorrection. Regexs are too picky. Need to manually check every time.
80
- Performance/RegexpMatch:
81
- Enabled: false
82
-
25
+ #
26
+ # Trailing commas
83
27
  Style/TrailingCommaInHashLiteral:
84
- Enabled: true
85
28
  EnforcedStyleForMultiline: comma
86
-
87
- Style/StringLiterals:
88
- Enabled: true
89
- EnforcedStyle: single_quotes
90
-
91
- # The Style/DoubleNegation cop is disabled because double negation provides
92
- # a concise, idiomatic way to convert values to boolean in Ruby. Alternative
93
- # approaches like ternary expressions or comparison with nil create unnecessary
94
- # verbosity without adding clarity. In cases where boolean coercion is the
95
- # explicit intent, !! clearly communicates this purpose to other Ruby developers.
96
- Style/DoubleNegation:
97
- Enabled: false
98
-
99
- # Offense count: non-0
100
- Style/FormatString:
101
- EnforcedStyle: format
102
29
  Enabled: true
103
30
 
104
- Style/FormatStringToken:
105
- EnforcedStyle: unannotated
106
- Enabled: true
107
-
108
- Style/RedundantReturn:
109
- Enabled: true
110
- AllowMultipleReturnValues: false
111
-
112
- Style/IfUnlessModifier:
113
- Enabled: false
114
-
115
- # We prefer `extend self` and `class << self`.
116
- Style/ModuleFunction:
117
- Enabled: true
118
- AutoCorrect: false
119
- EnforcedStyle: extend_self
120
-
121
- # Prefer 3 line if/else over one-liner
122
- Style/GuardClause:
31
+ Style/TrailingCommaInArrayLiteral:
32
+ EnforcedStyleForMultiline: comma
123
33
  Enabled: true
124
- MinBodyLength: 3
125
- AllowConsecutiveConditionals: false
126
34
 
127
- Style/SymbolArray:
128
- EnforcedStyle: brackets
35
+ Style/TrailingCommaInArguments:
129
36
  Enabled: true
130
37
 
131
- Style/StringLiteralsInInterpolation:
38
+ Style/TrailingCommaInBlockArgs:
132
39
  Enabled: true
133
40
 
134
- Style/BlockDelimiters:
41
+ Lint/TrailingCommaInAttributeDeclaration:
135
42
  Enabled: true
136
43
 
137
- Naming/PredicateMethod:
138
- Enabled: false
139
- Mode: "conservative"
140
- AllowedMethods:
141
- - validate!
142
- - migrate
143
-
144
- # We use class instance variables quite a bit, mostly for readonly values set
145
- # at boot time. Except for our models with have redis-rb Redis instances
146
- # connected on their associated db via ModelClass.dbclient. We're well aware
147
- # so keeping this disabled reduces warning noise.
148
- ThreadSafety/ClassInstanceVariable:
149
- Enabled: false
150
-
151
- Naming/RescuedExceptionsVariableName:
152
- Enabled: true
153
- PreferredName: ex # Default is 'e'
154
-
155
- Naming/PredicatePrefix:
156
- Enabled: true
157
- ForbiddenPrefixes: [is_, has_, have_]
158
- AllowedMethods: [
159
- has_passphrase?, # correlates with the REST API field `has_passphrase`
160
- ]
161
-
162
- Layout/MultilineMethodCallIndentation:
163
- EnforcedStyle: indented
164
- IndentationWidth: 2
165
-
166
44
  Gemspec/DeprecatedAttributeAssignment:
167
45
  Enabled: true
168
46
 
169
47
  Gemspec/DevelopmentDependencies:
170
48
  Enabled: true
171
49
 
172
- Layout/ElseAlignment:
173
- Enabled: false
174
-
175
- Layout/EndAlignment:
176
- Enabled: false
177
- # Severity: low
178
- # SupportedStylesAlignWith: 2
179
- # Leave commented out. When we set align with, endless "error occurred"
180
- # EnforcedStyle: keyword # keyword, variable, start_of_line
181
-
182
- Layout/ExtraSpacing:
183
- Enabled: true
184
- AllowForAlignment: true
185
- AllowBeforeTrailingComments: true
186
- ForceEqualSignAlignment: true
187
-
188
- Layout/IndentationConsistency:
189
- EnforcedStyle: indented_internal_methods
190
- Enabled: true
191
-
192
- Layout/IndentationWidth:
193
- # We don't want to enforce indentation width because it's doing weird things
194
- # with if/else statements that capture values. The `if` expression is aligned
195
- # with the right side of the `test` but the `else` expression is aligned with
196
- # the start of the line.
197
- Width: 2
198
- Enabled: false
199
-
200
50
  Layout/HashAlignment:
201
- Enabled: true
202
-
203
- Layout/FirstHashElementIndentation:
204
- Enabled: true
51
+ Enabled: false
205
52
 
206
53
  Lint/Void:
207
- Enabled: true
208
-
209
- Lint/CopDirectiveSyntax:
210
- Enabled: true
54
+ Enabled: false
211
55
 
212
- # Offense count: 122
213
- # Assignment Branch Condition size
214
56
  Metrics/AbcSize:
215
57
  Enabled: false
216
58
  Max: 20
217
59
 
218
- # Offense count: 217
219
- Layout/LineLength:
220
- Enabled: false
221
- AllowHeredoc: true
222
- AllowURI: true
223
- URISchemes:
224
- - https
225
- IgnoreCopDirectives: true
226
- AllowedPatterns: []
227
- SplitStrings: false
228
- Max: 100
229
-
230
- # Align the arguments of a method call if they span more than one line.
231
- Layout/ArgumentAlignment:
232
- Enabled: true
233
- EnforcedStyle: with_fixed_indentation # with_first_argument, with_fixed_indentation
234
- IndentationWidth: 2
235
-
236
- Layout/EmptyLineAfterGuardClause:
237
- Enabled: true
238
-
239
- Layout/EmptyLineBetweenDefs:
240
- Enabled: true
241
-
242
- Layout/EmptyLines:
243
- Enabled: true
244
-
245
- Layout/EmptyLinesAroundAccessModifier:
246
- Enabled: true
247
-
248
- Layout/EmptyLinesAroundAttributeAccessor:
249
- Enabled: true
250
-
251
- Layout/EmptyLinesAroundBlockBody:
252
- Enabled: true
253
-
254
- Layout/EmptyLinesAroundClassBody:
255
- Enabled: true
256
-
257
- Layout/EmptyLinesAroundExceptionHandlingKeywords:
258
- Enabled: true
259
-
260
- Layout/EmptyLinesAroundMethodBody:
261
- Enabled: true
262
-
263
- Layout/EmptyLinesAroundModuleBody:
264
- Enabled: true
265
-
266
60
  Metrics/ClassLength:
267
61
  Enabled: true
268
- Max: 350
62
+ Max: 200
63
+
64
+ Metrics/CyclomaticComplexity:
65
+ Enabled: false
269
66
 
270
- # Offense count: non-0
271
67
  Metrics/MethodLength:
272
68
  Enabled: true
273
- Max: 50
69
+ Max: 40
274
70
  CountAsOne: ["method_call"]
275
71
 
276
72
  Metrics/ModuleLength:
277
73
  Enabled: true
278
- Max: 350
74
+ Max: 250
279
75
  CountAsOne: ["method_call"]
280
76
 
281
77
  Performance/Size:
282
78
  Enabled: true
283
- Exclude: []
284
-
285
- Naming/AsciiIdentifiers:
286
- Enabled: true
287
-
288
- Metrics/CyclomaticComplexity:
289
- Enabled: false
79
+ Exclude:
80
+ # - lib/example.rb
290
81
 
291
82
  Style/NegatedIfElseCondition:
292
83
  Enabled: true
293
84
 
294
- Style/TrailingCommaInArguments:
295
- Enabled: true
296
- EnforcedStyleForMultiline: comma
297
-
298
- Style/TrailingCommaInArrayLiteral:
299
- Enabled: true
300
- EnforcedStyleForMultiline: comma
301
-
302
- # Use #empty? when testing for objects of length 0.
303
- Style/ZeroLengthPredicate:
304
- Enabled: true
305
- Safe: true
306
-
307
- Style/MethodDefParentheses:
308
- Enabled: true
309
-
310
- Style/FrozenStringLiteralComment:
311
- Enabled: true
312
- EnforcedStyle: never
313
-
314
- Style/SuperArguments:
315
- Enabled: true
316
-
317
- # Offense count: non-0
318
- ThreadSafety/ClassAndModuleAttributes:
319
- Description: Avoid mutating class and module attributes.
320
- Enabled: true
321
- ActiveSupportClassAttributeAllowed: false
322
-
323
- ThreadSafety/DirChdir:
324
- Description: Avoid using `Dir.chdir` due to its process-wide effect.
325
- Enabled: true
326
- AllowCallWithBlock: false
327
-
328
- # Do not assign mutable objects to class instance variables.
329
- ThreadSafety/MutableClassInstanceVariable:
330
- Description:
331
- Enabled: true
332
- EnforcedStyle: literals # one of literals, strict
333
- SafeAutoCorrect: false
334
-
335
- # Avoid starting new threads. Let a framework like Sidekiq handle the threads.
336
- ThreadSafety/NewThread:
337
- Enabled: true
338
-
339
- # Avoid instance variables in Rack middleware.
340
- ThreadSafety/RackMiddlewareInstanceVariable:
341
- Description:
342
- Enabled: true
343
- Include:
344
- - lib/middleware/*.rb
345
- - lib/middleware/onetime/*.rb
346
-
347
- # Unsafe autocorrect:
348
- Performance/MapCompact:
349
- Enabled: false
350
- Performance/StringInclude:
351
- Enabled: false
352
- Style/ClassAndModuleChildren:
353
- Enabled: false
354
- Style/GlobalStdStream:
355
- Enabled: false
356
- Style/HashConversion:
357
- Enabled: false
358
- Style/HashEachMethods:
359
- Enabled: false
360
- Style/IdenticalConditionalBranches:
361
- Enabled: false
362
- Style/MinMaxComparison:
363
- Enabled: false
364
- Style/MutableConstant:
365
- Enabled: false
366
- Style/NumericPredicate:
367
- Enabled: false
368
- Style/RaiseArgs:
369
- Enabled: false
370
- Style/RedundantInterpolation:
371
- Enabled: false
372
- Style/SafeNavigation:
373
- Enabled: false
374
- Style/SpecialGlobalVars:
375
- Enabled: false
376
- Style/StringConcatenation:
377
- Enabled: false
378
- Style/SymbolProc:
85
+ Naming/AsciiIdentifiers:
379
86
  Enabled: false
380
87
 
381
- # warnings
382
- Lint/RedundantCopDisableDirective:
383
- Enabled: false
384
- Lint/AssignmentInCondition:
88
+ Style/FrozenStringLiteralComment:
385
89
  Enabled: false
386
90
 
387
- # Manual corrections
388
- Metrics/BlockLength:
389
- Enabled: false
390
- Metrics/BlockNesting:
391
- Enabled: false
392
- Metrics/ParameterLists:
393
- Enabled: false
394
- Naming/AccessorMethodName:
395
- Enabled: false
396
- Naming/MethodParameterName:
397
- Enabled: false
398
- Performance/CollectionLiteralInLoop:
399
- Enabled: false
400
- Style/OptionalBooleanParameter:
91
+ Naming/MemoizedInstanceVariableName:
401
92
  Enabled: false
402
93
 
403
- # warnings
404
- Lint/DuplicateMethods:
405
- Enabled: false
406
- Lint/UselessOr:
407
- Enabled: false
408
- Lint/UnreachableLoop:
409
- Enabled: false
410
- Lint/MissingCopEnableDirective:
411
- Enabled: false
412
- Lint/MissingSuper:
413
- Enabled: false
414
- Lint/EmptyFile:
415
- Enabled: false
416
- Lint/RescueException:
94
+ # We use class instance vars sparingly at load time
95
+ ThreadSafety/ClassInstanceVariable:
417
96
  Enabled: false
data/CHANGELOG.rst ADDED
@@ -0,0 +1,83 @@
1
+ CHANGELOG.rst
2
+ =============
3
+
4
+ All notable changes to Otto are documented here.
5
+
6
+ The format is based on `Keep a
7
+ Changelog <https://keepachangelog.com/en/1.1.0/>`__, and this project
8
+ adheres to `Semantic
9
+ Versioning <https://semver.org/spec/v2.0.0.html>`__.
10
+
11
+ .. raw:: html
12
+
13
+ <!--scriv-insert-here-->
14
+
15
+ .. _changelog-2.0.0-pre1:
16
+
17
+ 2.0.0-pre1 — 2025-09-10
18
+ =======================
19
+
20
+ Added
21
+ -----
22
+
23
+ - Comprehensive test coverage for error handling methods (handle_error, secure_error_response,
24
+ json_error_response)
25
+ - Test coverage for private configuration methods (configure_locale, configure_security,
26
+ configure_authentication, configure_mcp)
27
+ - Expanded MCP functionality test coverage including route parsing and server initialization
28
+ - Security header validation in all error responses
29
+ - Content negotiation testing for JSON vs plain text error responses
30
+ - Development vs production mode error handling verification
31
+
32
+ - ``Otto::Security::Configurator`` class for consolidated security configuration
33
+ - ``Otto::Core::MiddlewareStack`` class for enhanced middleware management
34
+ - Unified ``security.configure()`` method for streamlined security setup
35
+ - Middleware introspection capabilities via ``middleware_list`` and ``middleware_details`` methods
36
+
37
+ Changed
38
+ -------
39
+
40
+ - **BREAKING**: Direct middleware_stack manipulation no longer supported. Use ``otto.use()`` instead
41
+ of ``otto.middleware_stack <<``. See `migration guide <docs/migrating/v2.0.0-pre1.md>`__ for upgrade
42
+ path.
43
+
44
+ - Refactored main Otto class from 767 lines to 348 lines using composition pattern (#29)
45
+ - Modernized initialization method with helper functions while maintaining backward compatibility
46
+ - Applied Ruby 3.2+ features including pattern matching and anonymous block forwarding
47
+ - Improved method organization and separation of concerns
48
+
49
+ - Refactored security configuration methods to use new ``Otto::Security::Configurator`` facade
50
+ - Enhanced middleware stack management with better registration and execution interfaces
51
+ - Improved separation of concerns between security configuration and middleware handling
52
+
53
+ - Unified middleware stack implementation for improved performance and consistency
54
+ - Optimized middleware lookup and registration with O(1) Set-based tracking
55
+ - Memoized middleware list to reduce array creation overhead
56
+ - Improved middleware registration to handle varied argument scenarios
57
+
58
+ Documentation
59
+ -------------
60
+
61
+ - Added changelog management system with Scriv configuration
62
+ - Created comprehensive changelog process documentation
63
+
64
+ AI Assistance
65
+ -------------
66
+
67
+ - Comprehensive test suite development covering 76 new test cases across 3 test files
68
+ - Error handling analysis and edge case identification
69
+ - Configuration method testing strategy development
70
+ - MCP functionality testing with proper mocking and stubbing techniques
71
+ - Test quality assurance ensuring all 460 examples pass with 0 failures
72
+
73
+ - Extracted core Otto class functionality into 5 focused modules (Router, FileSafety, Configuration,
74
+ ErrorHandler, UriGenerator) using composition pattern for improved maintainability while preserving
75
+ complete API backward compatibility (#28)
76
+
77
+ - Comprehensive refactoring implementation developed with AI assistance
78
+ - Systematic approach to maintaining backward compatibility during modernization
79
+ - Full test suite validation ensuring zero breaking changes across 460 test cases
80
+
81
+ - Comprehensive refactoring of middleware stack management
82
+ - Performance optimization and code quality improvements
83
+ - Developed detailed migration guide for smooth transition