plutonium 0.33.1 → 0.34.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 (143) hide show
  1. checksums.yaml +4 -4
  2. data/# Plutonium: The pre-alpha demo.md +4 -2
  3. data/.claude/skills/assets/SKILL.md +416 -0
  4. data/.claude/skills/connect-resource/SKILL.md +112 -0
  5. data/.claude/skills/controller/SKILL.md +302 -0
  6. data/.claude/skills/create-resource/SKILL.md +240 -0
  7. data/.claude/skills/definition/SKILL.md +218 -0
  8. data/.claude/skills/definition-actions/SKILL.md +386 -0
  9. data/.claude/skills/definition-fields/SKILL.md +474 -0
  10. data/.claude/skills/definition-query/SKILL.md +334 -0
  11. data/.claude/skills/forms/SKILL.md +439 -0
  12. data/.claude/skills/installation/SKILL.md +300 -0
  13. data/.claude/skills/interaction/SKILL.md +382 -0
  14. data/.claude/skills/model/SKILL.md +267 -0
  15. data/.claude/skills/model-features/SKILL.md +286 -0
  16. data/.claude/skills/nested-resources/SKILL.md +274 -0
  17. data/.claude/skills/package/SKILL.md +191 -0
  18. data/.claude/skills/policy/SKILL.md +352 -0
  19. data/.claude/skills/portal/SKILL.md +400 -0
  20. data/.claude/skills/resource/SKILL.md +281 -0
  21. data/.claude/skills/rodauth/SKILL.md +452 -0
  22. data/.claude/skills/views/SKILL.md +563 -0
  23. data/Appraisals +46 -4
  24. data/CHANGELOG.md +32 -1
  25. data/app/assets/plutonium.css +2 -2
  26. data/config/brakeman.ignore +239 -0
  27. data/config/initializers/action_policy.rb +1 -1
  28. data/docs/.vitepress/config.ts +132 -47
  29. data/docs/concepts/architecture.md +226 -0
  30. data/docs/concepts/auto-detection.md +254 -0
  31. data/docs/concepts/index.md +61 -0
  32. data/docs/concepts/packages-portals.md +304 -0
  33. data/docs/concepts/resources.md +224 -0
  34. data/docs/cookbook/blog.md +412 -0
  35. data/docs/cookbook/index.md +289 -0
  36. data/docs/cookbook/saas.md +481 -0
  37. data/docs/getting-started/index.md +56 -0
  38. data/docs/getting-started/installation.md +146 -0
  39. data/docs/getting-started/tutorial/01-setup.md +118 -0
  40. data/docs/getting-started/tutorial/02-first-resource.md +180 -0
  41. data/docs/getting-started/tutorial/03-authentication.md +246 -0
  42. data/docs/getting-started/tutorial/04-authorization.md +170 -0
  43. data/docs/getting-started/tutorial/05-custom-actions.md +202 -0
  44. data/docs/getting-started/tutorial/06-nested-resources.md +147 -0
  45. data/docs/getting-started/tutorial/07-customizing-ui.md +254 -0
  46. data/docs/getting-started/tutorial/index.md +64 -0
  47. data/docs/guides/adding-resources.md +420 -0
  48. data/docs/guides/authentication.md +551 -0
  49. data/docs/guides/authorization.md +468 -0
  50. data/docs/guides/creating-packages.md +380 -0
  51. data/docs/guides/custom-actions.md +523 -0
  52. data/docs/guides/index.md +45 -0
  53. data/docs/guides/multi-tenancy.md +302 -0
  54. data/docs/guides/nested-resources.md +411 -0
  55. data/docs/guides/search-filtering.md +266 -0
  56. data/docs/guides/theming.md +321 -0
  57. data/docs/index.md +67 -26
  58. data/docs/public/CLAUDE.md +64 -21
  59. data/docs/reference/assets/index.md +496 -0
  60. data/docs/reference/controller/index.md +363 -0
  61. data/docs/reference/definition/actions.md +400 -0
  62. data/docs/reference/definition/fields.md +350 -0
  63. data/docs/reference/definition/index.md +252 -0
  64. data/docs/reference/definition/query.md +342 -0
  65. data/docs/reference/generators/index.md +469 -0
  66. data/docs/reference/index.md +49 -0
  67. data/docs/reference/interaction/index.md +445 -0
  68. data/docs/reference/model/features.md +248 -0
  69. data/docs/reference/model/index.md +219 -0
  70. data/docs/reference/policy/index.md +385 -0
  71. data/docs/reference/portal/index.md +382 -0
  72. data/docs/reference/views/forms.md +396 -0
  73. data/docs/reference/views/index.md +479 -0
  74. data/gemfiles/rails_7.gemfile +9 -2
  75. data/gemfiles/rails_7.gemfile.lock +146 -111
  76. data/gemfiles/rails_8.0.gemfile +20 -0
  77. data/gemfiles/rails_8.0.gemfile.lock +417 -0
  78. data/gemfiles/rails_8.1.gemfile +20 -0
  79. data/gemfiles/rails_8.1.gemfile.lock +419 -0
  80. data/lib/generators/pu/gem/dotenv/templates/.env +2 -0
  81. data/lib/generators/pu/gem/dotenv/templates/config/initializers/001_ensure_required_env.rb +3 -1
  82. data/lib/generators/pu/lib/plutonium_generators/model_generator_base.rb +13 -16
  83. data/lib/generators/pu/pkg/portal/USAGE +65 -0
  84. data/lib/generators/pu/pkg/portal/portal_generator.rb +22 -9
  85. data/lib/generators/pu/res/conn/USAGE +71 -0
  86. data/lib/generators/pu/res/model/USAGE +106 -110
  87. data/lib/generators/pu/res/model/templates/model.rb.tt +6 -2
  88. data/lib/generators/pu/res/scaffold/USAGE +85 -0
  89. data/lib/generators/pu/rodauth/install_generator.rb +2 -6
  90. data/lib/generators/pu/rodauth/templates/config/initializers/url_options.rb +17 -0
  91. data/lib/generators/pu/skills/sync/USAGE +14 -0
  92. data/lib/generators/pu/skills/sync/sync_generator.rb +66 -0
  93. data/lib/plutonium/action_policy/sti_policy_lookup.rb +1 -1
  94. data/lib/plutonium/core/controller.rb +2 -2
  95. data/lib/plutonium/interaction/base.rb +1 -0
  96. data/lib/plutonium/package/engine.rb +2 -2
  97. data/lib/plutonium/query/adhoc_block.rb +6 -2
  98. data/lib/plutonium/query/model_scope.rb +1 -1
  99. data/lib/plutonium/railtie.rb +4 -0
  100. data/lib/plutonium/resource/controllers/crud_actions/index_action.rb +1 -1
  101. data/lib/plutonium/resource/query_object.rb +38 -8
  102. data/lib/plutonium/ui/table/components/scopes_bar.rb +39 -34
  103. data/lib/plutonium/version.rb +1 -1
  104. data/lib/tasks/release.rake +19 -4
  105. data/package.json +1 -1
  106. metadata +76 -39
  107. data/brakeman.ignore +0 -28
  108. data/docs/api-examples.md +0 -49
  109. data/docs/guide/claude-code-guide.md +0 -74
  110. data/docs/guide/deep-dive/authorization.md +0 -189
  111. data/docs/guide/deep-dive/multitenancy.md +0 -256
  112. data/docs/guide/deep-dive/resources.md +0 -390
  113. data/docs/guide/getting-started/01-installation.md +0 -165
  114. data/docs/guide/index.md +0 -28
  115. data/docs/guide/introduction/01-what-is-plutonium.md +0 -211
  116. data/docs/guide/introduction/02-core-concepts.md +0 -440
  117. data/docs/guide/tutorial/01-project-setup.md +0 -75
  118. data/docs/guide/tutorial/02-creating-a-feature-package.md +0 -45
  119. data/docs/guide/tutorial/03-defining-resources.md +0 -90
  120. data/docs/guide/tutorial/04-creating-a-portal.md +0 -101
  121. data/docs/guide/tutorial/05-customizing-the-ui.md +0 -128
  122. data/docs/guide/tutorial/06-adding-custom-actions.md +0 -101
  123. data/docs/guide/tutorial/07-implementing-authorization.md +0 -90
  124. data/docs/markdown-examples.md +0 -85
  125. data/docs/modules/action.md +0 -244
  126. data/docs/modules/authentication.md +0 -236
  127. data/docs/modules/configuration.md +0 -599
  128. data/docs/modules/controller.md +0 -443
  129. data/docs/modules/core.md +0 -316
  130. data/docs/modules/definition.md +0 -1308
  131. data/docs/modules/display.md +0 -759
  132. data/docs/modules/form.md +0 -495
  133. data/docs/modules/generator.md +0 -400
  134. data/docs/modules/index.md +0 -167
  135. data/docs/modules/interaction.md +0 -642
  136. data/docs/modules/package.md +0 -151
  137. data/docs/modules/policy.md +0 -176
  138. data/docs/modules/portal.md +0 -710
  139. data/docs/modules/query.md +0 -297
  140. data/docs/modules/resource_record.md +0 -618
  141. data/docs/modules/routing.md +0 -690
  142. data/docs/modules/table.md +0 -301
  143. data/docs/modules/ui.md +0 -631
@@ -0,0 +1,382 @@
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
+
27
+ ```bash
28
+ # Non-interactive examples
29
+ rails generate pu:pkg:portal admin --auth=admin
30
+ rails generate pu:pkg:portal api --public
31
+ rails generate pu:pkg:portal custom --byo
32
+ ```
33
+
34
+ Without flags, the generator prompts interactively for authentication choice.
35
+
36
+ ## Base Configuration
37
+
38
+ ```ruby
39
+ # packages/admin_portal/lib/admin_portal/engine.rb
40
+ module AdminPortal
41
+ class Engine < Rails::Engine
42
+ include Plutonium::Portal::Engine
43
+
44
+ # Configuration here
45
+ end
46
+ end
47
+ ```
48
+
49
+ ## Authentication
50
+
51
+ Authentication is configured in the portal's controller concern.
52
+
53
+ ### Basic Authentication
54
+
55
+ ```ruby
56
+ # packages/admin_portal/app/controllers/admin_portal/concerns/controller.rb
57
+ module AdminPortal
58
+ module Concerns
59
+ module Controller
60
+ extend ActiveSupport::Concern
61
+ include Plutonium::Portal::Controller
62
+ include Plutonium::Auth::Rodauth(:admin)
63
+ end
64
+ end
65
+ end
66
+ ```
67
+
68
+ ### Public Portal (No Authentication)
69
+
70
+ ```ruby
71
+ # packages/public_portal/app/controllers/public_portal/concerns/controller.rb
72
+ module PublicPortal
73
+ module Concerns
74
+ module Controller
75
+ extend ActiveSupport::Concern
76
+ include Plutonium::Portal::Controller
77
+ include Plutonium::Auth::Public
78
+ end
79
+ end
80
+ end
81
+ ```
82
+
83
+ ### Multiple Account Types
84
+
85
+ ```ruby
86
+ # packages/admin_portal/app/controllers/admin_portal/concerns/controller.rb
87
+ include Plutonium::Auth::Rodauth(:admin)
88
+
89
+ # packages/customer_portal/app/controllers/customer_portal/concerns/controller.rb
90
+ include Plutonium::Auth::Rodauth(:customer)
91
+ ```
92
+
93
+ ### Accessing Current User
94
+
95
+ ```ruby
96
+ # In controllers
97
+ current_user
98
+
99
+ # In views
100
+ current_user
101
+
102
+ # In policies
103
+ user # The authenticated user
104
+ ```
105
+
106
+ ## Entity Scoping (Multi-tenancy)
107
+
108
+ ### Basic Scoping
109
+
110
+ ```ruby
111
+ module CustomerPortal
112
+ class Engine < Rails::Engine
113
+ include Plutonium::Portal::Engine
114
+
115
+ config.after_initialize do
116
+ scope_to_entity Organization
117
+ end
118
+ end
119
+ end
120
+ ```
121
+
122
+ ### With Strategy Options
123
+
124
+ ```ruby
125
+ config.after_initialize do
126
+ # Path-based (default): /organizations/:organization_id/posts
127
+ scope_to_entity Organization, strategy: :path
128
+
129
+ # Custom param key
130
+ scope_to_entity Organization, strategy: :path, param_key: :org_id
131
+ end
132
+ ```
133
+
134
+ See the [Multi-tenancy Guide](/guides/multi-tenancy) for complete documentation.
135
+
136
+ ## Routing
137
+
138
+ ### Mounting the Portal
139
+
140
+ ```ruby
141
+ # config/routes.rb
142
+ Rails.application.routes.draw do
143
+ mount AdminPortal::Engine, at: "/admin"
144
+ end
145
+ ```
146
+
147
+ ### Portal Routes
148
+
149
+ ```ruby
150
+ # packages/admin_portal/config/routes.rb
151
+ AdminPortal::Engine.routes.draw do
152
+ resources :posts
153
+ resources :users
154
+
155
+ # Nested routes
156
+ resources :posts do
157
+ resources :comments
158
+ end
159
+
160
+ # Custom routes
161
+ get "dashboard", to: "dashboard#index"
162
+ end
163
+ ```
164
+
165
+ ### Root Route
166
+
167
+ ```ruby
168
+ AdminPortal::Engine.routes.draw do
169
+ root to: "dashboard#index"
170
+
171
+ resources :posts
172
+ end
173
+ ```
174
+
175
+ ## Controllers
176
+
177
+ ### Base Controller
178
+
179
+ ```ruby
180
+ # packages/admin_portal/app/controllers/admin_portal/resource_controller.rb
181
+ module AdminPortal
182
+ class ResourceController < Plutonium::Portal::ResourceController
183
+ layout "admin_portal/application"
184
+
185
+ private
186
+
187
+ def after_sign_in_path
188
+ admin_root_path
189
+ end
190
+ end
191
+ end
192
+ ```
193
+
194
+ ### Resource Controllers
195
+
196
+ ```ruby
197
+ # packages/admin_portal/app/controllers/admin_portal/posts_controller.rb
198
+ module AdminPortal
199
+ class PostsController < ResourceController
200
+ private
201
+
202
+ def build_resource
203
+ super.tap do |post|
204
+ post.user = current_user
205
+ end
206
+ end
207
+ end
208
+ end
209
+ ```
210
+
211
+ ## Portal-Specific Overrides
212
+
213
+ ### Definitions
214
+
215
+ ```ruby
216
+ # packages/admin_portal/app/definitions/admin_portal/post_definition.rb
217
+ module AdminPortal
218
+ class PostDefinition < ::PostDefinition
219
+ # Add admin-only fields
220
+ field :internal_notes
221
+ field :moderation_status
222
+
223
+ # Admin-only action
224
+ action :feature, interaction: FeaturePost
225
+ end
226
+ end
227
+ ```
228
+
229
+ ### Policies
230
+
231
+ ```ruby
232
+ # packages/admin_portal/app/policies/admin_portal/post_policy.rb
233
+ module AdminPortal
234
+ class PostPolicy < ::PostPolicy
235
+ # Admins can do everything
236
+ def update?
237
+ true
238
+ end
239
+
240
+ def destroy?
241
+ true
242
+ end
243
+
244
+ def relation_scope(relation)
245
+ relation # No restrictions
246
+ end
247
+ end
248
+ end
249
+ ```
250
+
251
+ ### Views
252
+
253
+ ```ruby
254
+ # packages/admin_portal/app/views/admin_portal/posts/index_page.rb
255
+ module AdminPortal
256
+ module Posts
257
+ class IndexPage < Plutonium::UI::Page::Index
258
+ def page_title
259
+ "Manage Posts"
260
+ end
261
+ end
262
+ end
263
+ end
264
+ ```
265
+
266
+ ## Layouts
267
+
268
+ ### Custom Layout
269
+
270
+ ```ruby
271
+ # packages/admin_portal/app/views/layouts/admin_portal/application.rb
272
+ module AdminPortal
273
+ class ApplicationLayout < Plutonium::UI::Layout::Application
274
+ def render_logo
275
+ img(src: asset_path("admin-logo.svg"), class: "h-8")
276
+ end
277
+
278
+ def nav_items
279
+ [
280
+ { label: "Dashboard", path: admin_root_path, icon: Phlex::TablerIcons::Home },
281
+ { label: "Posts", path: admin_posts_path, icon: Phlex::TablerIcons::FileText },
282
+ { label: "Users", path: admin_users_path, icon: Phlex::TablerIcons::Users }
283
+ ]
284
+ end
285
+
286
+ def render_user_menu
287
+ div(class: "flex items-center gap-4") do
288
+ span(class: "text-sm") { current_user.email }
289
+ link_to "Logout", logout_path, class: "text-gray-500 hover:text-gray-700"
290
+ end
291
+ end
292
+ end
293
+ end
294
+ ```
295
+
296
+ ## Public Routes
297
+
298
+ To allow unauthenticated access to specific actions:
299
+
300
+ ```ruby
301
+ class AdminPortal::PagesController < AdminPortal::ResourceController
302
+ skip_before_action :authenticate, only: [:health]
303
+
304
+ def health
305
+ render json: { status: "ok" }
306
+ end
307
+ end
308
+ ```
309
+
310
+ ## Dashboard
311
+
312
+ ### Dashboard Controller
313
+
314
+ ```ruby
315
+ # packages/admin_portal/app/controllers/admin_portal/dashboard_controller.rb
316
+ module AdminPortal
317
+ class DashboardController < ResourceController
318
+ def index
319
+ @stats = {
320
+ posts: Post.count,
321
+ users: User.count,
322
+ comments: Comment.count
323
+ }
324
+ end
325
+ end
326
+ end
327
+ ```
328
+
329
+ ### Dashboard View
330
+
331
+ ```ruby
332
+ # packages/admin_portal/app/views/admin_portal/dashboard/index_page.rb
333
+ module AdminPortal
334
+ module Dashboard
335
+ class IndexPage < Plutonium::UI::Page::Base
336
+ def initialize(stats:)
337
+ @stats = stats
338
+ end
339
+
340
+ def view_template
341
+ h1(class: "text-2xl font-bold mb-6") { "Dashboard" }
342
+
343
+ div(class: "grid grid-cols-3 gap-6") do
344
+ @stats.each do |label, value|
345
+ stat_card(label.to_s.titleize, value)
346
+ end
347
+ end
348
+ end
349
+
350
+ private
351
+
352
+ def stat_card(label, value)
353
+ div(class: "bg-white rounded-lg shadow p-6") do
354
+ p(class: "text-gray-500 text-sm") { label }
355
+ p(class: "text-3xl font-bold") { value.to_s }
356
+ end
357
+ end
358
+ end
359
+ end
360
+ end
361
+ ```
362
+
363
+ ## Configuration Options
364
+
365
+ ### Engine Options
366
+
367
+ | Option | Description |
368
+ |--------|-------------|
369
+ | `scope_to_entity` | Entity class for multi-tenancy scoping |
370
+
371
+ ### Controller Concern Options
372
+
373
+ | Include | Description |
374
+ |---------|-------------|
375
+ | `Plutonium::Auth::Rodauth(:name)` | Authenticate with Rodauth account type |
376
+ | `Plutonium::Auth::Public` | No authentication required |
377
+
378
+ ## Related
379
+
380
+ - [Packages and Portals Concept](/concepts/packages-portals)
381
+ - [Authentication Guide](/guides/authentication)
382
+ - [Multi-tenancy Guide](/guides/multi-tenancy)