plutonium 0.23.4 → 0.23.5

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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/plutonium.css +2 -2
  3. data/config/initializers/sqlite_json_alias.rb +1 -1
  4. data/docs/.vitepress/config.ts +60 -19
  5. data/docs/guide/cursor-rules.md +75 -0
  6. data/docs/guide/deep-dive/authorization.md +189 -0
  7. data/docs/guide/{getting-started → deep-dive}/resources.md +137 -0
  8. data/docs/guide/getting-started/{installation.md → 01-installation.md} +0 -105
  9. data/docs/guide/index.md +28 -0
  10. data/docs/guide/introduction/02-core-concepts.md +440 -0
  11. data/docs/guide/tutorial/01-project-setup.md +75 -0
  12. data/docs/guide/tutorial/02-creating-a-feature-package.md +45 -0
  13. data/docs/guide/tutorial/03-defining-resources.md +90 -0
  14. data/docs/guide/tutorial/04-creating-a-portal.md +101 -0
  15. data/docs/guide/tutorial/05-customizing-the-ui.md +128 -0
  16. data/docs/guide/tutorial/06-adding-custom-actions.md +101 -0
  17. data/docs/guide/tutorial/07-implementing-authorization.md +90 -0
  18. data/docs/index.md +24 -31
  19. data/docs/modules/action.md +190 -0
  20. data/docs/modules/authentication.md +236 -0
  21. data/docs/modules/configuration.md +599 -0
  22. data/docs/modules/controller.md +398 -0
  23. data/docs/modules/core.md +316 -0
  24. data/docs/modules/definition.md +876 -0
  25. data/docs/modules/display.md +759 -0
  26. data/docs/modules/form.md +605 -0
  27. data/docs/modules/generator.md +288 -0
  28. data/docs/modules/index.md +167 -0
  29. data/docs/modules/interaction.md +470 -0
  30. data/docs/modules/package.md +151 -0
  31. data/docs/modules/policy.md +176 -0
  32. data/docs/modules/portal.md +710 -0
  33. data/docs/modules/query.md +287 -0
  34. data/docs/modules/resource_record.md +618 -0
  35. data/docs/modules/routing.md +641 -0
  36. data/docs/modules/table.md +293 -0
  37. data/docs/modules/ui.md +631 -0
  38. data/docs/public/plutonium.mdc +667 -0
  39. data/lib/generators/pu/core/assets/assets_generator.rb +0 -5
  40. data/lib/plutonium/ui/display/resource.rb +7 -2
  41. data/lib/plutonium/ui/table/resource.rb +8 -3
  42. data/lib/plutonium/version.rb +1 -1
  43. metadata +36 -9
  44. data/docs/guide/getting-started/authorization.md +0 -296
  45. data/docs/guide/getting-started/core-concepts.md +0 -432
  46. data/docs/guide/getting-started/index.md +0 -21
  47. data/docs/guide/tutorial.md +0 -401
  48. /data/docs/guide/{what-is-plutonium.md → introduction/01-what-is-plutonium.md} +0 -0
@@ -0,0 +1,641 @@
1
+ ---
2
+ title: Routing Module
3
+ ---
4
+
5
+ # Routing Module
6
+
7
+ Plutonium's routing system transforms the way you think about Rails routing. Instead of manually defining dozens of routes, you simply register your resources and Plutonium automatically generates comprehensive routing structures including CRUD operations, nested associations, interactive actions, and multi-tenant scoping.
8
+
9
+ ::: tip
10
+ The Routing module is located in `lib/plutonium/routing/` and seamlessly extends Rails' built-in routing system.
11
+ :::
12
+
13
+ ## The Routing Revolution
14
+
15
+ Traditional Rails routing requires you to manually define every route, leading to repetitive, error-prone route files. Plutonium's approach is radically different:
16
+
17
+ **Traditional Rails Approach:**
18
+ ```ruby
19
+ # Lots of manual route definition
20
+ resources :posts do
21
+ member do
22
+ post :publish
23
+ post :archive
24
+ end
25
+
26
+ resources :comments, except: [:new, :edit]
27
+ end
28
+
29
+ resources :users do
30
+ resources :posts, controller: 'users/posts'
31
+ resources :comments, controller: 'users/comments'
32
+ end
33
+ ```
34
+
35
+ **Plutonium Approach:**
36
+ ```ruby
37
+ # Simple, declarative registration
38
+ register_resource Post
39
+ register_resource Comment
40
+ register_resource User
41
+
42
+ # Plutonium automatically generates:
43
+ # - All CRUD routes
44
+ # - Nested association routes
45
+ # - Interactive action routes
46
+ # - Multi-tenant scoped routes
47
+ ```
48
+
49
+ ## Core Routing Principles
50
+
51
+ Plutonium's routing system is built on four fundamental concepts:
52
+
53
+ - **Declarative Registration**: Register resources instead of defining individual routes
54
+ - **Intelligent Generation**: Routes are created based on your model associations and definitions
55
+ - **Entity Scoping**: Automatic multi-tenant routing with parameter injection
56
+ - **Interactive Actions**: Dynamic routes for business operations and user interactions
57
+
58
+ ## Resource Registration: The Foundation
59
+
60
+ ### Basic Resource Registration
61
+
62
+ The heart of Plutonium routing is the `register_resource` method:
63
+
64
+ ```ruby
65
+ # packages/admin_portal/config/routes.rb
66
+ AdminPortal::Engine.routes.draw do
67
+ root to: "dashboard#index"
68
+
69
+ # Register your resources - that's it!
70
+ register_resource User
71
+ register_resource Post
72
+ register_resource Comment
73
+ end
74
+ ```
75
+
76
+ ### What Registration Creates
77
+
78
+ When you register a single resource, Plutonium automatically generates:
79
+
80
+ ```ruby
81
+ register_resource Post
82
+
83
+ # Standard CRUD routes:
84
+ # GET /posts # index - list all posts
85
+ # GET /posts/new # new - form for creating posts
86
+ # POST /posts # create - handle post creation
87
+ # GET /posts/:id # show - display specific post
88
+ # GET /posts/:id/edit # edit - form for editing posts
89
+ # PATCH /posts/:id # update - handle post updates
90
+ # PUT /posts/:id # update - alternative update method
91
+ # DELETE /posts/:id # destroy - delete posts
92
+
93
+ # Interactive action routes:
94
+ # GET /posts/resource_actions/:action # Resource-level operations
95
+ # POST /posts/resource_actions/:action # Execute resource operations
96
+ # GET /posts/:id/record_actions/:action # Individual record operations
97
+ # POST /posts/:id/record_actions/:action # Execute record operations
98
+ # GET /posts/bulk_actions/:action # Bulk operations on multiple records
99
+ # POST /posts/bulk_actions/:action # Execute bulk operations
100
+
101
+ # Nested association routes (if Post has_many :comments):
102
+ # GET /posts/:post_id/nested_comments # Comments belonging to a post
103
+ # GET /posts/:post_id/nested_comments/:id # Specific comment in context
104
+ ```
105
+
106
+ ### Advanced Registration Options
107
+
108
+ #### Singular Resources
109
+
110
+ For resources that don't need collection routes:
111
+
112
+ ```ruby
113
+ register_resource Profile, singular: true
114
+
115
+ # Generates singular routes:
116
+ # GET /profile # show
117
+ # GET /profile/new # new
118
+ # POST /profile # create
119
+ # GET /profile/edit # edit
120
+ # PATCH /profile # update
121
+ # DELETE /profile # destroy
122
+ ```
123
+
124
+ #### Custom Routes with Blocks
125
+
126
+ Add custom routes alongside the standard ones:
127
+
128
+ ```ruby
129
+ register_resource Post do
130
+ # Member routes (operate on specific posts)
131
+ member do
132
+ get :publish # GET /posts/1/publish
133
+ post :archive # POST /posts/1/archive
134
+ patch :featured # PATCH /posts/1/featured
135
+ end
136
+
137
+ # Collection routes (operate on post collection)
138
+ collection do
139
+ get :search # GET /posts/search
140
+ get :recent # GET /posts/recent
141
+ post :bulk_update # POST /posts/bulk_update
142
+ end
143
+
144
+ # Nested resources for complex relationships
145
+ resources :comments, only: [:index, :show]
146
+
147
+ # Alternative syntax for single routes
148
+ get :preview, on: :member # GET /posts/1/preview
149
+ end
150
+ ```
151
+
152
+ **Handling Custom Routes in Controllers:**
153
+ ```ruby
154
+ class PostsController < ApplicationController
155
+ include Plutonium::Resource::Controller
156
+
157
+ # Custom member actions
158
+ def publish
159
+ authorize_current!(resource_record!)
160
+ resource_record!.update!(published: true)
161
+ redirect_to resource_url_for(resource_record!), success: "Post published!"
162
+ end
163
+
164
+ def archive
165
+ authorize_current!(resource_record!)
166
+ resource_record!.update!(archived: true)
167
+ redirect_to resource_url_for(resource_class), success: "Post archived!"
168
+ end
169
+
170
+ # Custom collection actions
171
+ def search
172
+ authorize_current!(resource_class)
173
+ @query = params[:q]
174
+ @posts = resource_scope.where("title ILIKE ?", "%#{@query}%")
175
+ render :index
176
+ end
177
+ end
178
+ ```
179
+
180
+ ## Automatic Nested Resource Generation
181
+
182
+ One of Plutonium's most powerful features is automatic nested route generation based on your ActiveRecord associations.
183
+
184
+ ### How Association-Based Routing Works
185
+
186
+ ```ruby
187
+ # Define your model associations
188
+ class User < ApplicationRecord
189
+ include Plutonium::Resource::Record
190
+
191
+ has_many :posts
192
+ has_many :comments
193
+ has_many :projects
194
+ end
195
+
196
+ class Post < ApplicationRecord
197
+ include Plutonium::Resource::Record
198
+
199
+ belongs_to :user
200
+ has_many :comments
201
+ end
202
+
203
+ # Register resources normally
204
+ AdminPortal::Engine.routes.draw do
205
+ register_resource User
206
+ register_resource Post
207
+ register_resource Comment
208
+ end
209
+ ```
210
+
211
+ **Plutonium automatically generates nested routes:**
212
+ ```ruby
213
+ # User's nested resources:
214
+ # GET /users/:user_id/nested_posts # User's posts
215
+ # GET /users/:user_id/nested_posts/:id # Specific post by user
216
+ # GET /users/:user_id/nested_comments # User's comments
217
+ # GET /users/:user_id/nested_projects # User's projects
218
+
219
+ # Post's nested resources:
220
+ # GET /posts/:post_id/nested_comments # Post's comments
221
+ # GET /posts/:post_id/nested_comments/:id # Specific comment on post
222
+ ```
223
+
224
+ ### Nested Route Naming Convention
225
+
226
+ Nested routes use the `nested_#{resource_name}` pattern to avoid conflicts:
227
+
228
+ - **Standard route**: `/posts` → `PostsController#index`
229
+ - **Nested route**: `/users/:user_id/nested_posts` → `PostsController#index` (with `current_parent`)
230
+
231
+ ### Automatic Parent Resolution
232
+
233
+ Controllers automatically handle parent relationships in nested contexts:
234
+
235
+ ```ruby
236
+ class PostsController < ApplicationController
237
+ include Plutonium::Resource::Controller
238
+
239
+ def index
240
+ # When accessed via /users/123/nested_posts
241
+ current_parent # => User.find(123) - automatically resolved
242
+ parent_route_param # => :user_id
243
+ parent_input_param # => :user (the belongs_to association name)
244
+
245
+ # Parameters are automatically merged for creation
246
+ resource_params # => includes user: current_parent
247
+
248
+ # URLs automatically include parent context
249
+ resource_url_for(Post) # => "/users/123/nested_posts"
250
+ resource_url_for(@post) # => "/users/123/nested_posts/456"
251
+ end
252
+ end
253
+ ```
254
+
255
+ ## Entity Scoping: Multi-Tenant Routing
256
+
257
+ Entity scoping automatically transforms your routes to support multi-tenancy, where all data is scoped to a parent entity like Organization or Account.
258
+
259
+ ### Path-Based Scoping
260
+
261
+ The most common approach uses URL path parameters:
262
+
263
+ ```ruby
264
+ # Engine configuration
265
+ class AdminPortal::Engine < Rails::Engine
266
+ include Plutonium::Portal::Engine
267
+
268
+ scope_to_entity Organization, strategy: :path
269
+ end
270
+ ```
271
+
272
+ **Route Transformation:**
273
+ ```ruby
274
+ # Without scoping:
275
+ # GET /posts
276
+ # GET /posts/:id
277
+
278
+ # With path scoping:
279
+ # GET /:organization_id/posts
280
+ # GET /:organization_id/posts/:id
281
+ ```
282
+
283
+ ### Custom Scoping Strategies
284
+
285
+ For more sophisticated multi-tenancy patterns:
286
+
287
+ ```ruby
288
+ # Subdomain-based scoping
289
+ scope_to_entity Organization, strategy: :current_organization
290
+
291
+ # Custom parameter key
292
+ scope_to_entity Organization,
293
+ strategy: :path,
294
+ param_key: :org_slug
295
+
296
+ # Routes become: GET /:org_slug/posts
297
+ ```
298
+
299
+ **Required Controller Implementation:**
300
+ ```ruby
301
+ module AdminPortal::Concerns::Controller
302
+ private
303
+
304
+ # Method name MUST match the strategy name exactly
305
+ def current_organization
306
+ @current_organization ||= Organization.find_by!(subdomain: request.subdomain)
307
+ rescue ActiveRecord::RecordNotFound
308
+ redirect_to root_path, error: "Invalid organization"
309
+ end
310
+ end
311
+ ```
312
+
313
+ ### Entity Scoping with Nested Routes
314
+
315
+ Scoping applies to both standard and nested routes:
316
+
317
+ ```ruby
318
+ scope_to_entity Organization, strategy: :path
319
+
320
+ # Standard scoped routes:
321
+ # GET /:organization_id/users
322
+ # GET /:organization_id/posts
323
+
324
+ # Nested scoped routes:
325
+ # GET /:organization_id/users/:user_id/nested_posts
326
+ # GET /:organization_id/posts/:post_id/nested_comments
327
+ ```
328
+
329
+ ## Smart URL Generation
330
+
331
+ Plutonium provides intelligent URL generation that handles scoping, nesting, and context automatically.
332
+
333
+ ### The `resource_url_for` Method
334
+
335
+ This is your go-to method for generating resource URLs:
336
+
337
+ ```ruby
338
+ # Basic usage
339
+ resource_url_for(User) # => "/users"
340
+ resource_url_for(@user) # => "/users/123"
341
+ resource_url_for(@user, action: :edit) # => "/users/123/edit"
342
+
343
+ # With entity scoping
344
+ resource_url_for(@user) # => "/organizations/456/users/123"
345
+
346
+ # Nested resources
347
+ resource_url_for(Post, parent: @user) # => "/users/123/nested_posts"
348
+ resource_url_for(@post, parent: @user) # => "/users/123/nested_posts/789"
349
+
350
+ # Override parent context
351
+ resource_url_for(@post, parent: nil) # => "/posts/789"
352
+
353
+ # Different actions
354
+ resource_url_for(@post, action: :edit, parent: @user)
355
+ # => "/users/123/nested_posts/789/edit"
356
+ ```
357
+
358
+ ### Interactive Action URLs
359
+
360
+ Special URL generation for interactive actions:
361
+
362
+ ```ruby
363
+ # Record-level actions (operate on specific records)
364
+ record_action_url(@post, :publish)
365
+ # => "/posts/123/record_actions/publish"
366
+
367
+ # Resource-level actions (operate on the resource class)
368
+ resource_action_url(Post, :import)
369
+ # => "/posts/resource_actions/import"
370
+
371
+ # Bulk actions (operate on multiple records)
372
+ bulk_action_url(Post, :archive, ids: [1, 2, 3])
373
+ # => "/posts/bulk_actions/archive?ids[]=1&ids[]=2&ids[]=3"
374
+ ```
375
+
376
+ ### Context-Aware URL Generation
377
+
378
+ In nested controller contexts, URLs automatically include proper context:
379
+
380
+ ```ruby
381
+ class PostsController < ApplicationController
382
+ include Plutonium::Resource::Controller
383
+
384
+ def show
385
+ # When accessed via /users/123/nested_posts/456
386
+
387
+ # These automatically include the user context:
388
+ resource_url_for(Post) # => "/users/123/nested_posts"
389
+ resource_url_for(@post, action: :edit) # => "/users/123/nested_posts/456/edit"
390
+
391
+ # Parent is automatically detected:
392
+ current_parent # => User.find(123)
393
+ end
394
+ end
395
+ ```
396
+
397
+ ## Advanced Routing Patterns
398
+
399
+ ### Multiple Engine Mounting
400
+
401
+ Different engines can have different routing strategies:
402
+
403
+ ```ruby
404
+ # config/routes.rb
405
+ Rails.application.routes.draw do
406
+ # Admin portal with organization scoping
407
+ constraints Rodauth::Rails.authenticate(:admin) do
408
+ mount AdminPortal::Engine, at: "/admin"
409
+ end
410
+
411
+ # Customer portal with account scoping
412
+ constraints Rodauth::Rails.authenticate(:customer) do
413
+ mount CustomerPortal::Engine, at: "/app"
414
+ end
415
+
416
+ # Public portal with no scoping or authentication
417
+ mount PublicPortal::Engine, at: "/"
418
+ end
419
+ ```
420
+
421
+ ### Route Constraints and Conditions
422
+
423
+ ```ruby
424
+ Rails.application.routes.draw do
425
+ # Subdomain-based portal mounting
426
+ constraints subdomain: 'admin' do
427
+ mount AdminPortal::Engine, at: "/"
428
+ end
429
+
430
+ # Feature flag-based mounting
431
+ constraints ->(request) { FeatureFlag.enabled?(:beta_portal) } do
432
+ mount BetaPortal::Engine, at: "/beta"
433
+ end
434
+
435
+ # IP-based constraints for admin access
436
+ constraints ip: /192\.168\.1\.\d+/ do
437
+ mount AdminPortal::Engine, at: "/secure-admin"
438
+ end
439
+ end
440
+ ```
441
+
442
+ ### Route Generation Lifecycle
443
+
444
+ Understanding how Plutonium generates routes helps with debugging:
445
+
446
+ **1. Registration Phase:**
447
+ ```ruby
448
+ register_resource Post
449
+ # - Resource is registered with the engine
450
+ # - Route configuration is created and stored
451
+ # - Concern name is generated (posts_routes)
452
+ ```
453
+
454
+ **2. Route Definition Phase:**
455
+ ```ruby
456
+ concern :posts_routes do
457
+ resources :posts, controller: "posts", concerns: [:interactive_resource_actions] do
458
+ # Nested routes for has_many associations
459
+ resources "nested_comments", controller: "comments"
460
+ end
461
+ end
462
+ ```
463
+
464
+ **3. Route Materialization Phase:**
465
+ ```ruby
466
+ scope :organization_id, as: :organization_id do
467
+ concerns :posts_routes, :comments_routes, :users_routes
468
+ end
469
+ # - All registered concerns are materialized within appropriate scope
470
+ # - Entity scoping parameters are applied
471
+ # - Final route table is generated
472
+ ```
473
+
474
+ ## Debugging and Troubleshooting
475
+
476
+ ### Inspecting Generated Routes
477
+
478
+ ```ruby
479
+ # View all routes for an engine
480
+ AdminPortal::Engine.routes.routes.each do |route|
481
+ puts "#{route.verb.ljust(6)} #{route.path.spec}"
482
+ end
483
+
484
+ # View registered resources
485
+ AdminPortal::Engine.resource_register.resources
486
+ # => [User, Post, Comment]
487
+
488
+ # View route configurations
489
+ AdminPortal::Engine.routes.resource_route_config_lookup
490
+ # => { "posts" => {...}, "users" => {...} }
491
+
492
+ # Check available route helpers
493
+ AdminPortal::Engine.routes.url_helpers.methods.grep(/path|url/)
494
+ ```
495
+
496
+ ### Common Issues and Solutions
497
+
498
+ **Missing Nested Routes:**
499
+ ```ruby
500
+ # Ensure the association exists
501
+ User.reflect_on_association(:posts) # Should not be nil
502
+
503
+ # Check association route discovery
504
+ User.has_many_association_routes # Should include "posts"
505
+ ```
506
+
507
+ **Incorrect Entity Scoping:**
508
+ ```ruby
509
+ # Verify engine configuration
510
+ AdminPortal::Engine.scoped_to_entity? # => true
511
+ AdminPortal::Engine.scoped_entity_class # => Organization
512
+ AdminPortal::Engine.scoped_entity_strategy # => :path
513
+ ```
514
+
515
+ **Interactive Action Routes Missing:**
516
+ ```ruby
517
+ # Ensure action is defined in resource definition
518
+ PostDefinition.new.defined_actions.keys # Should include your action
519
+ ```
520
+
521
+ **Route Helper Not Found:**
522
+ ```ruby
523
+ # Include the engine's route helpers
524
+ include AdminPortal::Engine.routes.url_helpers
525
+
526
+ # Test URL generation
527
+ posts_path # => "/posts" or "/organizations/:organization_id/posts"
528
+ ```
529
+
530
+ ## Best Practices
531
+
532
+ ### Route Organization
533
+
534
+ **Register Resources Logically:**
535
+ ```ruby
536
+ # ✅ Good - logical grouping
537
+ AdminPortal::Engine.routes.draw do
538
+ # Core entities first
539
+ register_resource Organization
540
+ register_resource User
541
+
542
+ # Business domain resources
543
+ register_resource Project
544
+ register_resource Task
545
+
546
+ # Supporting resources
547
+ register_resource Comment
548
+ register_resource Attachment
549
+ end
550
+ ```
551
+
552
+ **Leverage Entity Scoping:**
553
+ ```ruby
554
+ # ✅ Good - consistent scoping strategy
555
+ class AdminPortal::Engine < Rails::Engine
556
+ scope_to_entity Organization, strategy: :path
557
+ end
558
+
559
+ # All resources automatically scoped to organization
560
+ # Consistent URL structure: /:organization_id/resources
561
+ ```
562
+
563
+ ### Security Considerations
564
+
565
+ ```ruby
566
+ # ✅ Good - proper scoping for multi-tenancy
567
+ scope_to_entity Organization, strategy: :path
568
+
569
+ # ✅ Good - route-level authentication
570
+ constraints Rodauth::Rails.authenticate(:admin) do
571
+ mount AdminPortal::Engine, at: "/admin"
572
+ end
573
+
574
+ # ✅ Good - controller-level authorization
575
+ class PostsController < ApplicationController
576
+ include Plutonium::Resource::Controller
577
+
578
+ private
579
+
580
+ def current_authorized_scope
581
+ super.where(organization: current_scoped_entity)
582
+ end
583
+ end
584
+ ```
585
+
586
+ ## Integration with Other Modules
587
+
588
+ ### With Resource Module
589
+
590
+ Routes automatically integrate with resource definitions:
591
+
592
+ ```ruby
593
+ class PostDefinition < Plutonium::Resource::Definition
594
+ # These create interactive action routes automatically
595
+ action :publish, interaction: PublishPostInteraction
596
+ action :archive, interaction: ArchivePostInteraction
597
+ end
598
+ ```
599
+
600
+ ### With Portal Module
601
+
602
+ Portals provide routing contexts and scoping:
603
+
604
+ ```ruby
605
+ module AdminPortal
606
+ class Engine < Rails::Engine
607
+ include Plutonium::Portal::Engine
608
+
609
+ # This affects all routes in this portal
610
+ scope_to_entity Organization, strategy: :path
611
+ end
612
+ end
613
+ ```
614
+
615
+ ### With Authentication Module
616
+
617
+ Routes can be protected by authentication constraints:
618
+
619
+ ```ruby
620
+ Rails.application.routes.draw do
621
+ # Only authenticated admins can access admin routes
622
+ constraints Rodauth::Rails.authenticate(:admin) do
623
+ mount AdminPortal::Engine, at: "/admin"
624
+ end
625
+
626
+ # Customer authentication for customer portal
627
+ constraints Rodauth::Rails.authenticate(:customer) do
628
+ mount CustomerPortal::Engine, at: "/app"
629
+ end
630
+ end
631
+ ```
632
+
633
+ ## Related Modules
634
+
635
+ The Routing module works seamlessly with other Plutonium components:
636
+
637
+ - **[Controller](./controller.md)**: HTTP request handling and URL generation methods
638
+ - **[Resource Record](./resource_record.md)**: Resource definitions that drive route generation
639
+ - **[Portal](./portal.md)**: Multi-tenant portal functionality and route scoping
640
+ - **[Action](./action.md)**: Interactive actions that create dynamic routes
641
+ - **[Authentication](./authentication.md)**: Route protection and authentication constraints