aris 1.4.0 → 1.5.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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +251 -0
  3. data/README.md +18 -0
  4. data/docs/ADAPTERS.md +478 -0
  5. data/docs/ARCHITECTURE.md +222 -0
  6. data/docs/CONTENT.md +967 -0
  7. data/docs/PERFORMANCE.md +492 -0
  8. data/docs/PLUGIN_DEVELOPMENT.md +688 -0
  9. data/docs/USAGE.md +4998 -0
  10. data/docs/plugins/API_KEY_AUTH.md +232 -0
  11. data/docs/plugins/BASIC_AUTH.md +582 -0
  12. data/docs/plugins/BEARER_AUTH.md +394 -0
  13. data/docs/plugins/CACHE.md +369 -0
  14. data/docs/plugins/COMPRESSION.md +216 -0
  15. data/docs/plugins/COOKIES.md +30 -0
  16. data/docs/plugins/CORS.md +283 -0
  17. data/docs/plugins/CSRF.md +751 -0
  18. data/docs/plugins/ETAG.md +308 -0
  19. data/docs/plugins/FORM_PARSER.md +193 -0
  20. data/docs/plugins/HEALTH_CHECK.md +469 -0
  21. data/docs/plugins/JSON.md +291 -0
  22. data/docs/plugins/MULTIPART.md +427 -0
  23. data/docs/plugins/RATE_LIMITER.md +368 -0
  24. data/docs/plugins/REQUEST_ID.md +369 -0
  25. data/docs/plugins/REQUEST_LOGGER.md +151 -0
  26. data/docs/plugins/SECURITY.md +193 -0
  27. data/docs/plugins/SESSION.md +98 -0
  28. data/lib/aris/adapters/rack/adapter.rb +17 -2
  29. data/lib/aris/adapters/rack/request.rb +29 -11
  30. data/lib/aris/plugins/basic_auth.rb +3 -1
  31. data/lib/aris/plugins/cookies.rb +4 -32
  32. data/lib/aris/plugins/cors.rb +8 -1
  33. data/lib/aris/plugins/csrf.rb +63 -22
  34. data/lib/aris/plugins/flash.rb +3 -1
  35. data/lib/aris/plugins/form_parser.rb +53 -29
  36. data/lib/aris/plugins/multipart.rb +22 -2
  37. data/lib/aris/plugins/request_logger.rb +8 -1
  38. data/lib/aris/plugins/security_headers.rb +8 -1
  39. data/lib/aris/plugins/session.rb +150 -99
  40. data/lib/aris/response_helpers.rb +41 -0
  41. data/lib/aris/version.rb +2 -2
  42. metadata +31 -3
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bf323ca0ed960b60c26e09f0b575212544c8c5b15b95be5e299b6296f03d97df
4
- data.tar.gz: a68dfcec5a685a815f069f960f9bdcf6462115d6f5758e4adbedaf3ddbe3b3fa
3
+ metadata.gz: 547d34f5d148e75eec825310ab4da2bd6e80b02710386b7655210f4d5291804b
4
+ data.tar.gz: 41c84020f283351be32ff5b23444a4cc667e1034aec4f631efa586684c5f6833
5
5
  SHA512:
6
- metadata.gz: d42298b4ba003ec4d10494b9545e23fc381e037087720293e176e46a49446d9897c665a8dc3d4e684551193df7b2c07850f8743542b75718b7242b0bda816246
7
- data.tar.gz: b04ef54738e7f457ee594d83407f27a58b94b05c8d8c00c03106f9cfdaf950d3c58d0e153fdfe613d2e98f41a9216d10c93b84d9b9b5768e49474e9e40d283c2
6
+ metadata.gz: e34a068d4a4cd75e4694686896c1a8596da07b55abb4c7dff4cae3ead8e1d62d7871c76dbdbdeed21be8a7a44b7f39f883dae9dadd129c76b9b1f5ad743ac753
7
+ data.tar.gz: 591b1a14fb433f46da7907ade3167dee46dcee2fca40e6187a1bc748c7be3dd02ca9e93a9a6bc30393e5a35e37584eb8ba6519ebc7cc01cd7313c3237990767d
data/CHANGELOG.md ADDED
@@ -0,0 +1,251 @@
1
+ # Changelog
2
+
3
+ ## [1.5.0] - 2026-09-12
4
+
5
+ Sessions you can build a login on, and Rack 3 correct responses. Suite: 424 tests / 1289 assertions, green.
6
+
7
+ ### 🔒 Security
8
+
9
+ * **Sessions are encrypted and authenticated.** The session cookie is now an AES-256-GCM payload keyed from `Aris::Config.secret_key_base`. Before, it was Base64-encoded JSON: readable, and forgeable by anyone who could type `{"user_id":1}`. A tampered, forged, expired, or wrong-key cookie loads as an empty session. `expire_after` is enforced server-side. A missing or short secret raises a clear `ArgumentError`. **Any 1.4 session cookie is ignored.** See `docs/plugins/SESSION.md`.
10
+ * **CSRF tokens are session-backed.** The old plugin kept the token in `Thread.current` and compared it across requests, which is meaningless under a threaded server. Tokens now live in the session, are exposed as `request.csrf_token`, and are accepted from the `_csrf` form field or the `X-CSRF-Token` header, compared in constant time. Requires `use: [:session, :form_parser, :csrf]` in that order. See `docs/plugins/CSRF.md`.
11
+
12
+ ### 🐛 Fixed
13
+
14
+ * **Cookies were never read under the Rack adapter.** `Aris::Adapters::Rack::Request#cookies` looked at `env['rack.request.cookie_hash']`, which nothing populated, so sessions and flash could not persist in production. It now parses the `Cookie` header.
15
+ * **Several `Set-Cookie` values were comma-joined into one header**, which browsers cannot parse — setting a session and a flash in one response lost one of them. Cookies are emitted as a Rack 3 Array under `set-cookie`.
16
+ * **`FormParser.build` returned an instance that could not be called** (every request 500'd — 16 red tests since 1.4.2). Instances and the bare class both work now, on both adapters.
17
+ * **`Session.build` had the same problem**; instances work.
18
+ * `request.body` on the Rack adapter can be read more than once (memoized, input rewound).
19
+ * `:flash`, `:security_headers`, `:cors`, `:request_logger` are self-registered like every other plugin, so `use: [:flash]` works without a manual `register_plugin`. The three configurable ones run with defaults when used by symbol. (`BasicAuth` still needs `.build(username:, password:)`.)
20
+ * Tests that asserted a capitalized `Location` header against Rack-3 lowercase output fixed.
21
+
22
+ ### ✨ Added
23
+
24
+ * `response.set_cookie` / `response.delete_cookie` on every response (Mock and Rack), with `path`, `domain`, `max_age`, `expires`, `httponly`, `secure`, `same_site`. The `:cookies` plugin is now a no-op kept for compatibility. See `docs/plugins/COOKIES.md`.
25
+ * `request.form_params` and `request.params` (query + form) after `:form_parser`; `request.multipart_params`, `request.multipart_files`, `request.multipart_data` after `:multipart`, with fields merged into `request.params`.
26
+ * The Rack adapter normalizes every response header name to lowercase and merges duplicates, as Rack 3 requires. Plugins may keep setting `'Cache-Control'` etc.; the wire output is `cache-control`.
27
+
28
+ ### 🔧 Changed
29
+
30
+ * `request.cookies` is available on Rack requests without any plugin.
31
+ * Session data keys are always symbols.
32
+
33
+
34
+ ## [1.4.2] - 2026-01-22
35
+
36
+ ### 🐛 Fixed
37
+
38
+ * Fixed a bug where form_parser plugin failed to pass parameters to handlers
39
+
40
+ Parameters are reached as follows:
41
+
42
+ ```ruby
43
+ def self.send(req, res, params)
44
+ email = req.form_params['email']
45
+ ```
46
+
47
+ ## [1.4.0] - 2025-12-30
48
+ This release adds native static file serving with production-grade MIME type handling.
49
+
50
+ ### ✨ Added
51
+ * **Static File Serving:** Introduced `Aris::Config.serve_static` to serve static assets directly from the `public/` directory in development. Works seamlessly with nginx in production (nginx handles static files, Aris handles dynamic routes).
52
+ * **Configurable MIME Types:** Added `Aris::Config.mime_types` with sensible defaults for common file types (images, fonts, CSS, JS). Fully extensible for custom file formats.
53
+ * **Cache Headers:** Static files are served with `Cache-Control: public, max-age=31536000` for optimal browser caching.
54
+
55
+ ### 🔧 Changed
56
+ * Both `RackApp` and `MockAdapter` now check for static files before routing, improving performance for asset-heavy applications.
57
+
58
+ ### 📝 Usage
59
+ ```ruby
60
+ # Enable in development (disabled by default)
61
+ Aris.configure do |c|
62
+ c.serve_static = ENV['RACK_ENV'] != 'production'
63
+
64
+ # Optional: Add custom MIME types
65
+ c.mime_types = {
66
+ '.webm' => 'video/webm',
67
+ '.flac' => 'audio/flac'
68
+ }
69
+ end
70
+ ```
71
+
72
+ ## [1.3.0] - 2025-12-30
73
+
74
+ This release focuses on state management and fine-tuning URL strictness.
75
+
76
+ ### ✨ Added
77
+
78
+ * **Session & Flash Support:** Introduced `Aris::Plugins::Session` and `Aris::Plugins::Flash`. Supports persistence across redirects and "flash.now" for the current request cycle.
79
+ * **Trailing Slash Configuration:** Added `Aris::Config.trailing_slash`. You can now choose between `:strict` (default), `:ignore`, or `:redirect` (301/302) to normalize incoming paths.
80
+ * **Cookie Management:** Added `Aris::Plugins::Cookies` with a fluent helper API for reading, writing, and deleting cookies with secure defaults.
81
+
82
+ ### 🐛 Fixed
83
+
84
+ * Fixed a bug where the `MockAdapter` would not correctly pass the response object into handler blocks, causing issues with state-dependent plugins.
85
+
86
+ ---
87
+
88
+ ## [1.2.0] - 2025-12-15
89
+
90
+ Deep integration for internationalization and complex domain patterns.
91
+
92
+ ### ✨ Added
93
+
94
+ * **First-Class Locales:** Added `Aris::LocaleInjector`. Routes can now be expanded per-locale (e.g., `/en/about` and `/es/acerca` pointing to the same handler).
95
+ * **Locale-Aware Path Generation:** `Aris.path` now accepts a `locale:` argument to generate localized URLs automatically.
96
+ * **Root Locale Redirect:** Added `root_locale_redirect: true` to domain configurations to automatically bounce users from `/` to their default locale.
97
+ * **Subdomain Wildcards:** Enhanced the Trie to support `*.example.com` routing. The `request.subdomain` helper now correctly extracts multi-level subdomains (e.g., "app.staging").
98
+
99
+ ### 💥 Changed
100
+
101
+ * **Response Helpers:** Refactored `Aris::Response` into a modular helper system. Handlers now have access to `res.json`, `res.html`, `res.text`, and `res.xml`.
102
+
103
+ ---
104
+
105
+ ## [1.1.0] - 2025-11-20
106
+
107
+ Introduction of the "Utils" layer for SEO and automated metadata.
108
+
109
+ ### ✨ Added
110
+
111
+ * **Sitemap Generator:** Added `Aris::Utils::Sitemap`. Automatically generates `sitemap.xml` based on discovered routes and provided metadata (priority, changefreq).
112
+ * **Redirects Manager:** Added `Aris::Utils::Redirects`. Allows registering legacy URL mappings directly within route handlers using the `redirects_from` helper.
113
+ * **Content Negotiation:** Added `res.negotiate`. Handlers can now respond to different formats (JSON, XML, HTML) using a single block.
114
+
115
+ ### 💥 Changed
116
+
117
+ * **Header Normalization:** Aris now internally downcases all header keys to ensure compatibility between different Rack servers and the Mock adapter.
118
+
119
+ ---
120
+
121
+ ## [1.0.0] - 2025-10-30
122
+
123
+ The "Autodiscovery" Milestone. This version marks the transition to a file-based convention for large-scale applications.
124
+
125
+ ### ✨ Added
126
+
127
+ * **Route Autodiscovery:** Introduced `Aris.discover_and_define(routes_dir)`. Aris now scans your directory structure (e.g., `domain/path/_id/get.rb`) to build the routing tree automatically.
128
+ * **Convention-over-Configuration:** Parameterized routes are now identified by the `_` prefix in the filesystem (e.g., `_slug` becomes `:slug`).
129
+ * **OpenAPI/Swagger Metadata:** Added `api_doc` helper to handlers to facilitate automatic documentation generation.
130
+
131
+ ### 💥 Changed
132
+
133
+ * **Handler Resolution:** The `PipelineRunner` now lazily loads `Handler` constants from Ruby files only when the route is matched, significantly reducing boot time for thousands of routes.
134
+
135
+ ---
136
+
137
+ ## [0.9.0] - 2025-10-05
138
+
139
+ Performance optimization and production hardening.
140
+
141
+ ### ✨ Added
142
+
143
+ * **Request ID Tracking:** Added `Aris::Plugins::RequestId`. Automatically preserves or generates `X-Request-ID` headers for distributed tracing.
144
+ * **Response Compression:** Added `Aris::Plugins::Compression`. Transparent Gzip compression for text-based responses over a configurable size threshold.
145
+ * **Security Headers:** Added `Aris::Plugins::SecurityHeaders`. Configurable defaults for HSTS, CSP, X-Frame-Options, and Referrer-Policy.
146
+
147
+ ### ⚡ Performance
148
+
149
+ * Optimized Trie traversal by caching path segments, resulting in a 15% speed increase for deeply nested routes.
150
+
151
+ ---
152
+
153
+ ## [0.8.0] - 2025-09-10
154
+
155
+ Advanced matching features.
156
+
157
+ ### ✨ Added
158
+
159
+ * **Path Constraints:** Added `constraints: { id: /\d+/ }` support. Routes now only match if parameters satisfy the provided regex.
160
+ * **Wildcard Globbing:** Added support for `*path` segments to capture remaining path parts into a single parameter.
161
+ * **Health Checks:** Added `Aris::Plugins::HealthCheck`. A highly configurable plugin for liveness/readiness probes with dependency monitoring.
162
+
163
+ ---
164
+
165
+ ## [0.7.0] - 2025-08-15
166
+
167
+ Middleware and the Plugin Pipeline.
168
+
169
+ ### ✨ Added
170
+
171
+ * **The Plugin System:** Introduced the `use:` key at domain, scope, and route levels. Plugins follow a `call(request, response)` contract.
172
+ * **JSON Body Parser:** Added `Aris::Plugins::Json` to automatically parse incoming payloads into `request.json_body`.
173
+ * **Form Parser:** Added support for `application/x-www-form-urlencoded` payloads via `Aris::Plugins::FormParser`.
174
+
175
+ ---
176
+
177
+ ## [0.6.0] - 2025-07-20
178
+
179
+ Hardened Authentication.
180
+
181
+ ### ✨ Added
182
+
183
+ * **Bearer Auth Plugin:** Standardized token-based authentication.
184
+ * **Basic Auth Plugin:** Easy username/password protection for admin scopes.
185
+ * **API Key Auth Plugin:** Header-based key validation with custom validator support.
186
+ * **CORS Plugin:** Full support for origins, methods, credentials, and preflight `OPTIONS` handling.
187
+
188
+ ---
189
+
190
+ ## [0.5.0] - 2025-06-28
191
+
192
+ Integrated CSRF and Mocking.
193
+
194
+ ### ✨ Added
195
+
196
+ * **CSRF Protection:** A two-phase plugin (`CsrfTokenGenerator` and `CsrfProtection`) to secure state-changing requests.
197
+ * **Mock Adapter:** Built `Aris::Adapters::Mock` to allow full integration testing of routes and plugins without a live Rack server.
198
+
199
+ ---
200
+
201
+ ## [0.4.0] - 2025-06-01
202
+
203
+ The "Rack" release.
204
+
205
+ ### ✨ Added
206
+
207
+ * **Rack Adapter:** Official production adapter `Aris::Adapters::RackApp`.
208
+ * **Agnostic Request/Response:** Wrapped Rack environment in `Aris::Request` and `Aris::Response` to ensure handlers remain server-agnostic.
209
+
210
+ ---
211
+
212
+ ## [0.3.0] - 2025-05-15
213
+
214
+ Named routes and URL generation.
215
+
216
+ ### ✨ Added
217
+
218
+ * **Named Routes:** Added the `as:` option to route definitions.
219
+ * **Path/URL Helpers:** Introduced `Aris.path` and `Aris.url`. Support for query parameter appending and automatic URI encoding.
220
+ * **Domain Context:** Added `Aris.with_domain` for scoped URL generation.
221
+
222
+ ---
223
+
224
+ ## [0.2.0] - 2025-04-25
225
+
226
+ Multi-domain support.
227
+
228
+ ### ✨ Added
229
+
230
+ * **Multi-Domain Routing:** The routing hash now accepts domain strings as top-level keys.
231
+ * **Wildcard Domain Fallback:** Support for the `"*"` domain key to handle health checks or generic responses across all hosts.
232
+
233
+ ---
234
+
235
+ ## [0.1.0] - 2025-04-10
236
+
237
+ ### ✨ Added
238
+
239
+ * **Initial Release!**
240
+ * Core Trie-based routing engine.
241
+ * Support for standard HTTP verbs (GET, POST, PUT, PATCH, DELETE).
242
+ * Parameter extraction (e.g., `/users/:id`).
243
+ * Global `Aris.routes` configuration.
244
+
245
+ ---
246
+
247
+ **Would you like me to ...**
248
+
249
+ * Generate the `VERSION` file for this project?
250
+ * Create a `ROADMAP.md` for 2026?
251
+ * Implement a CLI command to auto-generate this changelog from git tags?
data/README.md CHANGED
@@ -118,6 +118,24 @@ Aris.routes({
118
118
  })
119
119
  ```
120
120
 
121
+ ### Sessions, cookies, CSRF, forms
122
+
123
+ ```ruby
124
+ Aris.configure { |c| c.secret_key_base = ENV.fetch('SECRET_KEY_BASE') }
125
+
126
+ Aris.routes({
127
+ "example.com": {
128
+ use: [:session, :form_parser, :csrf],
129
+ "/login": { post: { to: ->(req, res, prm) {
130
+ req.session[:user_id] = 1 # encrypted + authenticated cookie
131
+ res.redirect('/')
132
+ } } }
133
+ }
134
+ })
135
+ ```
136
+
137
+ `request.session`, `request.cookies`, `request.form_params`, `request.csrf_token`, `response.set_cookie` — see `docs/plugins/`.
138
+
121
139
  ### Composable Plugins
122
140
 
123
141
  Plugins execute between routing and handler dispatch. They're just callables that can inspect, modify, or halt the request.