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
data/CLAUDE.md ADDED
@@ -0,0 +1,56 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Development Commands
6
+
7
+ ### Setup
8
+ ```bash
9
+ # Install development and test dependencies
10
+ bundle config set with 'development test'
11
+ bundle install
12
+
13
+ # Lint code
14
+ bundle exec rubocop
15
+
16
+ # Run tests
17
+ bundle exec rspec
18
+
19
+ # Run a specific test
20
+ bundle exec rspec spec/path/to/specific_spec.rb
21
+ # rspec settings in .rspec
22
+ ```
23
+
24
+ ## Project Overview
25
+
26
+ ### Core Components
27
+ - Ruby Rack-based web framework for defining web applications
28
+ - Focuses on security and simplicity
29
+ - Supports internationalization and optional security features
30
+
31
+ ### Key Features
32
+ - Plain-text routes configuration
33
+ - Automatic locale detection
34
+ - Optional security features:
35
+ - CSRF protection
36
+ - Input validation
37
+ - Security headers
38
+ - Trusted proxy configuration
39
+
40
+ ### Test Frameworks
41
+ - RSpec for unit and integration testing
42
+ - Tryouts for behavior-driven testing
43
+
44
+ ### Development Tools
45
+ - Rubocop for linting
46
+ - Debug gem for debugging
47
+ - Tryouts for alternative testing approach
48
+
49
+ ### Ruby Version Requirements
50
+ - Ruby 3.2+
51
+ - Rack 3.1+
52
+
53
+ ### Important Notes
54
+ - Always validate and sanitize user inputs
55
+ - Leverage built-in security features
56
+ - Use locale helpers for internationalization support
data/Gemfile CHANGED
@@ -1,12 +1,19 @@
1
1
  # Gemfile
2
2
 
3
+ # To install all development and test dependencies:
4
+ #
5
+ # $ bundle config set with 'development test'
6
+ # $ bundle install
7
+
3
8
  source 'https://rubygems.org'
4
9
 
5
10
  gemspec
6
11
 
12
+ gem 'rackup'
13
+
7
14
  group :test do
8
15
  gem 'rack-test'
9
- gem 'rspec', '~> 3.12'
16
+ gem 'rspec', '~> 3.13'
10
17
  end
11
18
 
12
19
  # bundle config set with 'optional'
@@ -17,7 +24,7 @@ group :development, :test, optional: true do
17
24
  end
18
25
 
19
26
  group :development do
20
- gem 'pry-byebug', require: false
27
+ gem 'debug'
21
28
  gem 'rubocop', require: false
22
29
  gem 'rubocop-performance', require: false
23
30
  gem 'rubocop-rspec', require: false
@@ -25,5 +32,5 @@ group :development do
25
32
  gem 'ruby-lsp', require: false
26
33
  gem 'stackprof', require: false
27
34
  gem 'syntax_tree', require: false
28
- gem 'tryouts', '~> 3.3.2', require: false
35
+ gem 'tryouts', '~> 3.6.0', require: false
29
36
  end
data/Gemfile.lock CHANGED
@@ -1,10 +1,9 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- otto (1.6.0)
4
+ otto (2.0.0.pre.pre1)
5
5
  facets (~> 3.1)
6
6
  loofah (~> 2.20)
7
- ostruct
8
7
  rack (~> 3.1, < 4.0)
9
8
  rack-parser (~> 0.7)
10
9
  rexml (>= 3.3.6)
@@ -13,12 +12,13 @@ GEM
13
12
  remote: https://rubygems.org/
14
13
  specs:
15
14
  ast (2.4.3)
16
- bigdecimal (3.2.2)
17
- byebug (12.0.0)
18
- coderay (1.1.3)
15
+ bigdecimal (3.2.3)
19
16
  concurrent-ruby (1.3.5)
20
17
  crass (1.0.6)
21
18
  date (3.4.1)
19
+ debug (1.11.0)
20
+ irb (~> 1.10)
21
+ reline (>= 0.3.8)
22
22
  diff-lcs (1.6.2)
23
23
  erb (5.0.2)
24
24
  facets (3.1.0)
@@ -40,7 +40,6 @@ GEM
40
40
  loofah (2.24.1)
41
41
  crass (~> 1.0.2)
42
42
  nokogiri (>= 1.12.0)
43
- method_source (1.1.0)
44
43
  minitest (5.25.5)
45
44
  nokogiri (1.18.9-aarch64-linux-gnu)
46
45
  racc (~> 1.4)
@@ -58,7 +57,6 @@ GEM
58
57
  racc (~> 1.4)
59
58
  nokogiri (1.18.9-x86_64-linux-musl)
60
59
  racc (~> 1.4)
61
- ostruct (0.6.3)
62
60
  parallel (1.27.0)
63
61
  parser (3.3.9.0)
64
62
  ast (~> 2.4.1)
@@ -70,25 +68,21 @@ GEM
70
68
  prettier_print (1.2.1)
71
69
  prettyprint (0.2.0)
72
70
  prism (1.4.0)
73
- pry (0.15.2)
74
- coderay (~> 1.1)
75
- method_source (~> 1.0)
76
- pry-byebug (3.11.0)
77
- byebug (~> 12.0)
78
- pry (>= 0.13, < 0.16)
79
71
  psych (5.2.6)
80
72
  date
81
73
  stringio
82
74
  racc (1.8.1)
83
- rack (3.2.0)
75
+ rack (3.2.1)
84
76
  rack-attack (6.7.0)
85
77
  rack (>= 1.0, < 4)
86
78
  rack-parser (0.7.0)
87
79
  rack
88
80
  rack-test (2.2.0)
89
81
  rack (>= 1.3)
82
+ rackup (2.2.1)
83
+ rack (>= 3)
90
84
  rainbow (3.1.1)
91
- rbs (3.9.4)
85
+ rbs (3.9.5)
92
86
  logger
93
87
  rdoc (6.14.2)
94
88
  erb
@@ -96,7 +90,7 @@ GEM
96
90
  regexp_parser (2.11.2)
97
91
  reline (0.6.2)
98
92
  io-console (~> 0.5)
99
- rexml (3.4.1)
93
+ rexml (3.4.3)
100
94
  rspec (3.13.1)
101
95
  rspec-core (~> 3.13.0)
102
96
  rspec-expectations (~> 3.13.0)
@@ -109,8 +103,8 @@ GEM
109
103
  rspec-mocks (3.13.5)
110
104
  diff-lcs (>= 1.2.0, < 2.0)
111
105
  rspec-support (~> 3.13.0)
112
- rspec-support (3.13.4)
113
- rubocop (1.79.2)
106
+ rspec-support (3.13.5)
107
+ rubocop (1.80.2)
114
108
  json (~> 2.3)
115
109
  language_server-protocol (~> 3.17.0.2)
116
110
  lint_roller (~> 1.1.0)
@@ -124,11 +118,11 @@ GEM
124
118
  rubocop-ast (1.46.0)
125
119
  parser (>= 3.3.7.2)
126
120
  prism (~> 1.4)
127
- rubocop-performance (1.25.0)
121
+ rubocop-performance (1.26.0)
128
122
  lint_roller (~> 1.1)
129
123
  rubocop (>= 1.75.0, < 2.0)
130
- rubocop-ast (>= 1.38.0, < 2.0)
131
- rubocop-rspec (3.6.0)
124
+ rubocop-ast (>= 1.44.0, < 2.0)
125
+ rubocop-rspec (3.7.0)
132
126
  lint_roller (~> 1.1)
133
127
  rubocop (~> 1.72, >= 1.72.1)
134
128
  rubocop-thread_safety (0.7.3)
@@ -145,7 +139,7 @@ GEM
145
139
  stringio (3.1.7)
146
140
  syntax_tree (6.3.0)
147
141
  prettier_print (>= 1.2.0)
148
- tryouts (3.3.2)
142
+ tryouts (3.6.0)
149
143
  concurrent-ruby (~> 1.0)
150
144
  irb
151
145
  minitest (~> 5.0)
@@ -157,9 +151,9 @@ GEM
157
151
  tty-color (0.6.0)
158
152
  tty-cursor (0.7.1)
159
153
  tty-screen (0.8.2)
160
- unicode-display_width (3.1.4)
161
- unicode-emoji (~> 4.0, >= 4.0.4)
162
- unicode-emoji (4.0.4)
154
+ unicode-display_width (3.2.0)
155
+ unicode-emoji (~> 4.1)
156
+ unicode-emoji (4.1.0)
163
157
 
164
158
  PLATFORMS
165
159
  aarch64-linux-gnu
@@ -172,12 +166,13 @@ PLATFORMS
172
166
  x86_64-linux-musl
173
167
 
174
168
  DEPENDENCIES
169
+ debug
175
170
  json_schemer
176
171
  otto!
177
- pry-byebug
178
172
  rack-attack
179
173
  rack-test
180
- rspec (~> 3.12)
174
+ rackup
175
+ rspec (~> 3.13)
181
176
  rubocop
182
177
  rubocop-performance
183
178
  rubocop-rspec
@@ -185,7 +180,7 @@ DEPENDENCIES
185
180
  ruby-lsp
186
181
  stackprof
187
182
  syntax_tree
188
- tryouts (~> 3.3.2)
183
+ tryouts (~> 3.6.0)
189
184
 
190
185
  BUNDLED WITH
191
186
  2.7.1
data/README.md CHANGED
@@ -2,6 +2,8 @@
2
2
 
3
3
  **Define your rack-apps in plain-text with built-in security.**
4
4
 
5
+ > **v2.0.0-pre1 Available**: This pre-release includes major improvements to middleware management and test coverage. See [changelog](CHANGELOG.rst) and [migration guide](docs/migrating/v2.0.0-pre1.md) for upgraders.
6
+
5
7
  ![Otto mascot](public/img/otto.jpg "Otto - All Rack, no Pinion")
6
8
 
7
9
  Otto apps have three files: a rackup file, a Ruby class, and a routes file. The routes file is just plain text that maps URLs to Ruby methods.
data/bin/rspec CHANGED
@@ -8,9 +8,9 @@
8
8
  # this file is here to facilitate running it.
9
9
  #
10
10
 
11
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__)
11
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
12
12
 
13
- require "rubygems"
14
- require "bundler/setup"
13
+ require 'rubygems'
14
+ require 'bundler/setup'
15
15
 
16
- load Gem.bin_path("rspec-core", "rspec")
16
+ load Gem.bin_path('rspec-core', 'rspec')
@@ -0,0 +1,28 @@
1
+ Added
2
+ -----
3
+
4
+ - ``Otto::RequestContext`` Data class providing immutable, structured authentication context for Logic classes
5
+ - Helper methods ``authenticated?``, ``has_role?``, ``has_permission?``, ``user_name``, ``session_id`` for cleaner Logic class implementation
6
+ - Factory methods for creating RequestContext from AuthResult or anonymous contexts
7
+
8
+ Changed
9
+ -------
10
+
11
+ - **BREAKING**: Logic class constructor signature changed from ``initialize(session, user, params, locale)`` to ``initialize(context, params, locale)``
12
+ - Logic classes now receive immutable RequestContext instead of separate session/user parameters
13
+ - LogicClassHandler simplified to single arity pattern, removing backward compatibility code
14
+ - Authentication middleware now creates RequestContext instances for all requests
15
+
16
+ Documentation
17
+ -------------
18
+
19
+ - Updated migration guide with comprehensive RequestContext examples and step-by-step conversion instructions
20
+ - Updated Logic class examples in advanced_routes and authentication_strategies to demonstrate new pattern
21
+ - Enhanced documentation with RequestContext API reference and helper method examples
22
+
23
+ AI Assistance
24
+ -------------
25
+
26
+ - RequestContext Data class design developed with AI architectural guidance for immutability and clean API
27
+ - Comprehensive migration of all example Logic classes with AI assistance for consistency and best practices
28
+ - Documentation improvements ensuring clarity of breaking changes and migration path
@@ -0,0 +1,21 @@
1
+ Changed
2
+ -------
3
+
4
+ - Replaced `RequestContext` with `StrategyResult` class for better authentication handling
5
+ - Simplified authentication strategy API to return `StrategyResult` or `nil` for success/failure
6
+ - Enhanced route handlers to support JSON request body parsing
7
+ - Updated authentication middleware to use `StrategyResult` throughout
8
+
9
+ Added
10
+ -----
11
+
12
+ - Added `StrategyResult` class with improved user model compatibility and cleaner API
13
+ - Added JSON request body parsing support in Logic class handlers
14
+
15
+ Removed
16
+ -------
17
+
18
+ - Removed `RequestContext` class (replaced by `StrategyResult`)
19
+ - Removed `AuthResult` class from authentication system
20
+ - Removed OpenStruct dependency across the framework
21
+ - Removed `ConcurrentCacheStore` example class for an ActiveSupport::Cache::MemoryStore-compatible interface with Rack::Attack
@@ -0,0 +1,21 @@
1
+ Changed
2
+ -------
3
+
4
+ - Reorganized Otto security module structure for better maintainability and separation of concerns
5
+ - Moved authentication strategies to ``Otto::Security::Authentication::Strategies`` namespace
6
+ - Moved security middleware to ``Otto::Security::Middleware`` namespace
7
+ - Moved ``StrategyResult`` and ``FailureResult`` to ``Otto::Security::Authentication`` namespace
8
+
9
+ Added
10
+ -----
11
+
12
+ - Added new modular directory structure under ``lib/otto/security/``
13
+ - Added backward compatibility aliases to maintain existing API compatibility
14
+ - Added proper namespacing for authentication components and middleware classes
15
+
16
+ AI Assistance
17
+ -------------
18
+
19
+ - Comprehensive security module reorganization with systematic namespace restructuring
20
+ - Automated test validation to ensure backward compatibility during refactoring
21
+ - Intelligent file organization following Ruby conventions and single responsibility principles
@@ -0,0 +1,120 @@
1
+ # Otto Changelog Process
2
+
3
+ This directory contains Otto's changelog management using [Scriv](https://scriv.readthedocs.io/).
4
+
5
+ ## Developer Workflow
6
+
7
+ ### Creating a Changelog Fragment
8
+
9
+ When making changes that affect users, create a changelog fragment:
10
+
11
+ ```bash
12
+ # Create a new fragment
13
+ scriv create
14
+
15
+ # Edit the generated file in changelog.d/
16
+ # Add entries under appropriate categories
17
+ ```
18
+
19
+ ### Categories
20
+
21
+ Use these categories in your fragments:
22
+
23
+ - **Added**: New features
24
+ - **Changed**: Changes in existing functionality
25
+ - **Deprecated**: Soon-to-be removed features
26
+ - **Removed**: Removed features
27
+ - **Fixed**: Bug fixes
28
+ - **Security**: Security fixes and improvements
29
+ - **Documentation**: Documentation changes
30
+ - **AI Assistance**: AI-assisted development, analysis, and improvements
31
+
32
+ ### Fragment Format
33
+
34
+ Each fragment uses reStructuredText format:
35
+
36
+ ```rst
37
+ Added
38
+ -----
39
+
40
+ - New feature description
41
+
42
+ Fixed
43
+ -----
44
+
45
+ - Bug fix description
46
+
47
+ AI Assistance
48
+ -------------
49
+
50
+ - Comprehensive test coverage development with AI assistance
51
+ ```
52
+
53
+ ### Committing Changes
54
+
55
+ Always commit the fragment alongside your code:
56
+
57
+ ```bash
58
+ # Stage both code and fragment
59
+ git add changelog.d/YYYYMMDD_HHmmss_username_branch.rst
60
+ git add [your code files]
61
+
62
+ # Commit together
63
+ git commit -m "Your commit message
64
+
65
+ Includes changelog fragment documenting changes."
66
+ ```
67
+
68
+ ## Release Process
69
+
70
+ During releases, maintainers aggregate all fragments:
71
+
72
+ ```bash
73
+ # Collect all fragments into CHANGELOG.rst
74
+ scriv collect
75
+
76
+ # Review the updated CHANGELOG.rst
77
+ git add CHANGELOG.rst
78
+ git commit -m "Release changelog for vX.Y.Z"
79
+ ```
80
+
81
+ ## Guidelines
82
+
83
+ ### When to Create Fragments
84
+
85
+ Create fragments for:
86
+ - ✅ New features users will notice
87
+ - ✅ Bug fixes that affect user experience
88
+ - ✅ Breaking changes or deprecations
89
+ - ✅ Security fixes
90
+ - ✅ API changes
91
+ - ✅ Significant internal improvements (use AI Assistance category)
92
+
93
+ Skip fragments for:
94
+ - ❌ Internal refactoring with no user impact
95
+ - ❌ Test-only changes (unless they represent significant coverage improvements)
96
+ - ❌ Documentation typo fixes
97
+ - ❌ CI/build changes
98
+
99
+ ### Fragment Quality
100
+
101
+ Good fragments:
102
+ - Are concise but descriptive
103
+ - Focus on user impact, not implementation details
104
+ - Link to issues/PRs when helpful: `(#123)`
105
+ - Use active voice: "Fixed authentication bug" not "Authentication bug was fixed"
106
+
107
+ ### AI Assistance Category
108
+
109
+ Use the "AI Assistance" category to document:
110
+ - Security analysis and hardened design discussions
111
+ - Implementation development with AI pair programming
112
+ - Comprehensive test coverage development
113
+ - Architecture improvements developed with AI
114
+ - Code review and debugging sessions with AI
115
+
116
+ This category ensures transparency about AI contributions to the project while highlighting areas where AI provided particular value.
117
+
118
+ ## Configuration
119
+
120
+ See `scriv.ini` for configuration details. The setup automatically detects Otto's version from `lib/otto/version.rb`.
@@ -0,0 +1,5 @@
1
+ [scriv]
2
+ format = rst
3
+ categories = Added, Changed, Deprecated, Removed, Fixed, Security, Documentation, AI Assistance
4
+ version = command: ruby -r ./lib/otto/version.rb -e "puts Otto::VERSION"
5
+ main_branches = main, next
data/docs/.gitignore CHANGED
@@ -1,2 +1,3 @@
1
1
  *
2
2
  !.gitignore
3
+ !migrating/