plutonium 0.50.0 → 0.51.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 (132) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/skills/plutonium/SKILL.md +85 -102
  3. data/.claude/skills/plutonium-app/SKILL.md +572 -0
  4. data/.claude/skills/plutonium-auth/SKILL.md +163 -300
  5. data/.claude/skills/plutonium-behavior/SKILL.md +838 -0
  6. data/.claude/skills/plutonium-resource/SKILL.md +1176 -0
  7. data/.claude/skills/plutonium-tenancy/SKILL.md +655 -0
  8. data/.claude/skills/plutonium-testing/SKILL.md +6 -5
  9. data/.claude/skills/plutonium-ui/SKILL.md +900 -0
  10. data/CHANGELOG.md +27 -2
  11. data/Rakefile +2 -1
  12. data/app/assets/plutonium.css +1 -11
  13. data/app/assets/plutonium.js +1009 -1214
  14. data/app/assets/plutonium.js.map +3 -3
  15. data/app/assets/plutonium.min.js +52 -51
  16. data/app/assets/plutonium.min.js.map +3 -3
  17. data/docs/.vitepress/config.ts +37 -27
  18. data/docs/getting-started/index.md +22 -29
  19. data/docs/getting-started/installation.md +37 -80
  20. data/docs/getting-started/tutorial/index.md +4 -5
  21. data/docs/guides/adding-resources.md +66 -377
  22. data/docs/guides/authentication.md +94 -463
  23. data/docs/guides/authorization.md +124 -370
  24. data/docs/guides/creating-packages.md +94 -296
  25. data/docs/guides/custom-actions.md +121 -441
  26. data/docs/guides/index.md +22 -42
  27. data/docs/guides/multi-tenancy.md +116 -187
  28. data/docs/guides/nested-resources.md +103 -431
  29. data/docs/guides/search-filtering.md +123 -240
  30. data/docs/guides/testing.md +5 -4
  31. data/docs/guides/theming.md +157 -407
  32. data/docs/guides/troubleshooting.md +5 -3
  33. data/docs/guides/user-invites.md +106 -425
  34. data/docs/guides/user-profile.md +76 -243
  35. data/docs/index.md +1 -1
  36. data/docs/reference/app/generators.md +517 -0
  37. data/docs/reference/app/index.md +158 -0
  38. data/docs/reference/app/packages.md +146 -0
  39. data/docs/reference/app/portals.md +377 -0
  40. data/docs/reference/auth/accounts.md +230 -0
  41. data/docs/reference/auth/index.md +88 -0
  42. data/docs/reference/auth/profile.md +185 -0
  43. data/docs/reference/behavior/controllers.md +395 -0
  44. data/docs/reference/behavior/index.md +22 -0
  45. data/docs/reference/behavior/interactions.md +341 -0
  46. data/docs/reference/behavior/policies.md +417 -0
  47. data/docs/reference/index.md +56 -49
  48. data/docs/reference/resource/actions.md +423 -0
  49. data/docs/reference/resource/definition.md +508 -0
  50. data/docs/reference/resource/index.md +50 -0
  51. data/docs/reference/resource/model.md +348 -0
  52. data/docs/reference/resource/query.md +305 -0
  53. data/docs/reference/tenancy/entity-scoping.md +361 -0
  54. data/docs/reference/tenancy/index.md +36 -0
  55. data/docs/reference/tenancy/invites.md +393 -0
  56. data/docs/reference/tenancy/nested-resources.md +267 -0
  57. data/docs/reference/testing/index.md +287 -0
  58. data/docs/reference/ui/assets.md +400 -0
  59. data/docs/reference/ui/components.md +165 -0
  60. data/docs/reference/ui/displays.md +104 -0
  61. data/docs/reference/ui/forms.md +284 -0
  62. data/docs/reference/ui/index.md +30 -0
  63. data/docs/reference/ui/layouts.md +106 -0
  64. data/docs/reference/ui/pages.md +189 -0
  65. data/docs/reference/ui/tables.md +117 -0
  66. data/docs/superpowers/specs/2026-05-09-typeahead-endpoint-design.md +203 -0
  67. data/docs/superpowers/specs/2026-05-12-skill-compaction-design.md +99 -0
  68. data/docs/superpowers/specs/2026-05-13-docs-restructure-design.md +186 -0
  69. data/gemfiles/rails_7.gemfile.lock +1 -1
  70. data/gemfiles/rails_8.0.gemfile.lock +1 -1
  71. data/gemfiles/rails_8.1.gemfile.lock +1 -1
  72. data/lib/generators/pu/core/update/update_generator.rb +0 -20
  73. data/lib/generators/pu/invites/install_generator.rb +1 -0
  74. data/lib/plutonium/definition/base.rb +1 -1
  75. data/lib/plutonium/definition/{views.rb → index_views.rb} +21 -20
  76. data/lib/plutonium/helpers/turbo_helper.rb +11 -0
  77. data/lib/plutonium/helpers/turbo_stream_actions_helper.rb +14 -0
  78. data/lib/plutonium/resource/controller.rb +1 -0
  79. data/lib/plutonium/resource/controllers/crud_actions.rb +19 -1
  80. data/lib/plutonium/resource/controllers/typeahead.rb +180 -0
  81. data/lib/plutonium/resource/policy.rb +7 -0
  82. data/lib/plutonium/routing/mapper_extensions.rb +15 -0
  83. data/lib/plutonium/ui/component/methods.rb +4 -0
  84. data/lib/plutonium/ui/form/base.rb +6 -2
  85. data/lib/plutonium/ui/form/components/json.rb +58 -0
  86. data/lib/plutonium/ui/form/components/resource_select.rb +62 -8
  87. data/lib/plutonium/ui/form/components/secure_association.rb +98 -22
  88. data/lib/plutonium/ui/form/concerns/typeahead_attributes.rb +83 -0
  89. data/lib/plutonium/ui/form/resource.rb +0 -4
  90. data/lib/plutonium/ui/grid/resource.rb +1 -1
  91. data/lib/plutonium/ui/layout/base.rb +1 -0
  92. data/lib/plutonium/ui/page/base.rb +0 -7
  93. data/lib/plutonium/ui/page/index.rb +4 -4
  94. data/lib/plutonium/ui/table/resource.rb +1 -1
  95. data/lib/plutonium/version.rb +1 -1
  96. data/lib/plutonium.rb +8 -0
  97. data/lib/tasks/release.rake +15 -1
  98. data/package.json +10 -10
  99. data/src/css/slim_select.css +4 -0
  100. data/src/js/controllers/slim_select_controller.js +61 -0
  101. data/src/js/turbo/turbo_actions.js +33 -0
  102. data/yarn.lock +553 -543
  103. metadata +44 -33
  104. data/.claude/skills/plutonium-assets/SKILL.md +0 -512
  105. data/.claude/skills/plutonium-controller/SKILL.md +0 -396
  106. data/.claude/skills/plutonium-create-resource/SKILL.md +0 -303
  107. data/.claude/skills/plutonium-definition/SKILL.md +0 -1223
  108. data/.claude/skills/plutonium-entity-scoping/SKILL.md +0 -317
  109. data/.claude/skills/plutonium-forms/SKILL.md +0 -465
  110. data/.claude/skills/plutonium-installation/SKILL.md +0 -331
  111. data/.claude/skills/plutonium-interaction/SKILL.md +0 -413
  112. data/.claude/skills/plutonium-invites/SKILL.md +0 -408
  113. data/.claude/skills/plutonium-model/SKILL.md +0 -440
  114. data/.claude/skills/plutonium-nested-resources/SKILL.md +0 -360
  115. data/.claude/skills/plutonium-package/SKILL.md +0 -198
  116. data/.claude/skills/plutonium-policy/SKILL.md +0 -456
  117. data/.claude/skills/plutonium-portal/SKILL.md +0 -410
  118. data/.claude/skills/plutonium-views/SKILL.md +0 -651
  119. data/docs/reference/assets/index.md +0 -496
  120. data/docs/reference/controller/index.md +0 -412
  121. data/docs/reference/definition/actions.md +0 -462
  122. data/docs/reference/definition/fields.md +0 -383
  123. data/docs/reference/definition/index.md +0 -326
  124. data/docs/reference/definition/query.md +0 -351
  125. data/docs/reference/generators/index.md +0 -648
  126. data/docs/reference/interaction/index.md +0 -449
  127. data/docs/reference/model/features.md +0 -248
  128. data/docs/reference/model/index.md +0 -218
  129. data/docs/reference/policy/index.md +0 -456
  130. data/docs/reference/portal/index.md +0 -379
  131. data/docs/reference/views/forms.md +0 -411
  132. data/docs/reference/views/index.md +0 -544
@@ -1,379 +0,0 @@
1
- # Portal Reference
2
-
3
- Complete reference for portal configuration.
4
-
5
- ## Overview
6
-
7
- Portals are web interfaces that expose resources to users. Each portal can have:
8
- - Its own authentication
9
- - Custom authorization rules
10
- - UI customizations
11
- - Entity scoping (multi-tenancy)
12
-
13
- ## Creating a Portal
14
-
15
- ```bash
16
- rails generate pu:pkg:portal admin
17
- ```
18
-
19
- ### Generator Options
20
-
21
- | Option | Description |
22
- |--------|-------------|
23
- | `--auth NAME` | Rodauth account to authenticate with (e.g., `--auth=user`) |
24
- | `--public` | Grant public access (no authentication) |
25
- | `--byo` | Bring your own authentication |
26
- | `--scope CLASS` | Entity class to scope to for multi-tenancy (e.g., `--scope=Organization`) |
27
-
28
- ```bash
29
- # Non-interactive examples
30
- rails generate pu:pkg:portal admin --auth=admin
31
- rails generate pu:pkg:portal api --public
32
- rails generate pu:pkg:portal custom --byo
33
-
34
- # With entity scoping (multi-tenancy)
35
- rails generate pu:pkg:portal admin --auth=admin --scope=Organization
36
- ```
37
-
38
- Without flags, the generator prompts interactively for authentication choice.
39
-
40
- ## Base Configuration
41
-
42
- ```ruby
43
- # packages/admin_portal/lib/admin_portal/engine.rb
44
- module AdminPortal
45
- class Engine < Rails::Engine
46
- include Plutonium::Portal::Engine
47
-
48
- # Configuration here
49
- end
50
- end
51
- ```
52
-
53
- ## Authentication
54
-
55
- Authentication is configured in the portal's controller concern.
56
-
57
- ### Basic Authentication
58
-
59
- ```ruby
60
- # packages/admin_portal/app/controllers/admin_portal/concerns/controller.rb
61
- module AdminPortal
62
- module Concerns
63
- module Controller
64
- extend ActiveSupport::Concern
65
- include Plutonium::Portal::Controller
66
- include Plutonium::Auth::Rodauth(:admin)
67
- end
68
- end
69
- end
70
- ```
71
-
72
- ### Public Portal (No Authentication)
73
-
74
- ```ruby
75
- # packages/public_portal/app/controllers/public_portal/concerns/controller.rb
76
- module PublicPortal
77
- module Concerns
78
- module Controller
79
- extend ActiveSupport::Concern
80
- include Plutonium::Portal::Controller
81
- include Plutonium::Auth::Public
82
- end
83
- end
84
- end
85
- ```
86
-
87
- ### Multiple Account Types
88
-
89
- ```ruby
90
- # packages/admin_portal/app/controllers/admin_portal/concerns/controller.rb
91
- include Plutonium::Auth::Rodauth(:admin)
92
-
93
- # packages/customer_portal/app/controllers/customer_portal/concerns/controller.rb
94
- include Plutonium::Auth::Rodauth(:customer)
95
- ```
96
-
97
- ### Accessing Current User
98
-
99
- ```ruby
100
- # In controllers
101
- current_user
102
-
103
- # In views
104
- current_user
105
-
106
- # In policies
107
- user # The authenticated user
108
- ```
109
-
110
- ## Entity Scoping (Multi-tenancy)
111
-
112
- ### Basic Scoping
113
-
114
- ```ruby
115
- module CustomerPortal
116
- class Engine < Rails::Engine
117
- include Plutonium::Portal::Engine
118
-
119
- config.after_initialize do
120
- scope_to_entity Organization
121
- end
122
- end
123
- end
124
- ```
125
-
126
- ### With Strategy Options
127
-
128
- ```ruby
129
- config.after_initialize do
130
- # Path-based (default): /organizations/:organization_id/posts
131
- scope_to_entity Organization, strategy: :path
132
-
133
- # Custom param key
134
- scope_to_entity Organization, strategy: :path, param_key: :org_id
135
- end
136
- ```
137
-
138
- See the [Multi-tenancy Guide](/guides/multi-tenancy) for complete documentation.
139
-
140
- ## Routing
141
-
142
- ### Mounting the Portal
143
-
144
- ```ruby
145
- # config/routes.rb
146
- Rails.application.routes.draw do
147
- mount AdminPortal::Engine, at: "/admin"
148
- end
149
- ```
150
-
151
- ### Portal Routes
152
-
153
- ```ruby
154
- # packages/admin_portal/config/routes.rb
155
- AdminPortal::Engine.routes.draw do
156
- resources :posts
157
- resources :users
158
-
159
- # Nested routes
160
- resources :posts do
161
- resources :comments
162
- end
163
-
164
- # Custom routes
165
- get "dashboard", to: "dashboard#index"
166
- end
167
- ```
168
-
169
- ### Root Route
170
-
171
- ```ruby
172
- AdminPortal::Engine.routes.draw do
173
- root to: "dashboard#index"
174
-
175
- resources :posts
176
- end
177
- ```
178
-
179
- ## Controllers
180
-
181
- ### Base Controller
182
-
183
- ```ruby
184
- # packages/admin_portal/app/controllers/admin_portal/resource_controller.rb
185
- module AdminPortal
186
- class ResourceController < ::ResourceController
187
- include AdminPortal::Concerns::Controller
188
- end
189
- end
190
- ```
191
-
192
- ### Resource Controllers
193
-
194
- ```ruby
195
- # packages/admin_portal/app/controllers/admin_portal/posts_controller.rb
196
- module AdminPortal
197
- class PostsController < ResourceController
198
- private
199
-
200
- def build_resource
201
- super.tap do |post|
202
- post.user = current_user
203
- end
204
- end
205
- end
206
- end
207
- ```
208
-
209
- ## Portal-Specific Overrides
210
-
211
- ### Definitions
212
-
213
- ```ruby
214
- # packages/admin_portal/app/definitions/admin_portal/post_definition.rb
215
- module AdminPortal
216
- class PostDefinition < ::PostDefinition
217
- # Add admin-only fields
218
- field :internal_notes
219
- field :moderation_status
220
-
221
- # Admin-only action
222
- action :feature, interaction: FeaturePost
223
- end
224
- end
225
- ```
226
-
227
- ### Policies
228
-
229
- ```ruby
230
- # packages/admin_portal/app/policies/admin_portal/post_policy.rb
231
- module AdminPortal
232
- class PostPolicy < ::PostPolicy
233
- # Admins can do everything
234
- def update?
235
- true
236
- end
237
-
238
- def destroy?
239
- true
240
- end
241
-
242
- def relation_scope(relation)
243
- relation # No restrictions
244
- end
245
- end
246
- end
247
- ```
248
-
249
- ### Views
250
-
251
- ```ruby
252
- # packages/admin_portal/app/views/admin_portal/posts/index_page.rb
253
- module AdminPortal
254
- module Posts
255
- class IndexPage < Plutonium::UI::Page::Index
256
- def page_title
257
- "Manage Posts"
258
- end
259
- end
260
- end
261
- end
262
- ```
263
-
264
- ## Layouts
265
-
266
- ### Custom Layout
267
-
268
- ```ruby
269
- # packages/admin_portal/app/views/layouts/admin_portal/application.rb
270
- module AdminPortal
271
- class ApplicationLayout < Plutonium::UI::Layout::Application
272
- def render_logo
273
- img(src: asset_path("admin-logo.svg"), class: "h-8")
274
- end
275
-
276
- def nav_items
277
- [
278
- { label: "Dashboard", path: admin_root_path, icon: Phlex::TablerIcons::Home },
279
- { label: "Posts", path: admin_posts_path, icon: Phlex::TablerIcons::FileText },
280
- { label: "Users", path: admin_users_path, icon: Phlex::TablerIcons::Users }
281
- ]
282
- end
283
-
284
- def render_user_menu
285
- div(class: "flex items-center gap-4") do
286
- span(class: "text-sm") { current_user.email }
287
- link_to "Logout", logout_path, class: "text-gray-500 hover:text-gray-700"
288
- end
289
- end
290
- end
291
- end
292
- ```
293
-
294
- ## Public Routes
295
-
296
- To allow unauthenticated access to specific actions:
297
-
298
- ```ruby
299
- class AdminPortal::PagesController < AdminPortal::PlutoniumController
300
- skip_before_action :authenticate, only: [:health]
301
-
302
- def health
303
- render json: { status: "ok" }
304
- end
305
- end
306
- ```
307
-
308
- ## Dashboard
309
-
310
- ### Dashboard Controller
311
-
312
- ```ruby
313
- # packages/admin_portal/app/controllers/admin_portal/dashboard_controller.rb
314
- module AdminPortal
315
- class DashboardController < PlutoniumController
316
- def index
317
- @stats = {
318
- posts: Post.count,
319
- users: User.count,
320
- comments: Comment.count
321
- }
322
- end
323
- end
324
- end
325
- ```
326
-
327
- ### Dashboard View
328
-
329
- ```ruby
330
- # packages/admin_portal/app/views/admin_portal/dashboard/index_page.rb
331
- module AdminPortal
332
- module Dashboard
333
- class IndexPage < Plutonium::UI::Page::Base
334
- def initialize(stats:)
335
- @stats = stats
336
- end
337
-
338
- def view_template
339
- h1(class: "text-2xl font-bold mb-6") { "Dashboard" }
340
-
341
- div(class: "grid grid-cols-3 gap-6") do
342
- @stats.each do |label, value|
343
- stat_card(label.to_s.titleize, value)
344
- end
345
- end
346
- end
347
-
348
- private
349
-
350
- def stat_card(label, value)
351
- div(class: "bg-white rounded-lg shadow p-6") do
352
- p(class: "text-gray-500 text-sm") { label }
353
- p(class: "text-3xl font-bold") { value.to_s }
354
- end
355
- end
356
- end
357
- end
358
- end
359
- ```
360
-
361
- ## Configuration Options
362
-
363
- ### Engine Options
364
-
365
- | Option | Description |
366
- |--------|-------------|
367
- | `scope_to_entity` | Entity class for multi-tenancy scoping |
368
-
369
- ### Controller Concern Options
370
-
371
- | Include | Description |
372
- |---------|-------------|
373
- | `Plutonium::Auth::Rodauth(:name)` | Authenticate with Rodauth account type |
374
- | `Plutonium::Auth::Public` | No authentication required |
375
-
376
- ## Related
377
-
378
- - [Authentication Guide](/guides/authentication)
379
- - [Multi-tenancy Guide](/guides/multi-tenancy)