plutonium 0.50.0 → 0.52.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 (201) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/skills/plutonium/SKILL.md +85 -102
  3. data/.claude/skills/plutonium-app/SKILL.md +574 -0
  4. data/.claude/skills/plutonium-auth/SKILL.md +167 -302
  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 +674 -0
  8. data/.claude/skills/plutonium-testing/SKILL.md +9 -6
  9. data/.claude/skills/plutonium-ui/SKILL.md +900 -0
  10. data/CHANGELOG.md +44 -2
  11. data/Rakefile +2 -1
  12. data/app/assets/plutonium.css +1 -11
  13. data/app/assets/plutonium.js +1010 -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 +38 -29
  18. data/docs/.vitepress/theme/components/HomeAudienceSplit.vue +53 -0
  19. data/docs/.vitepress/theme/components/HomeCta.vue +108 -0
  20. data/docs/.vitepress/theme/components/HomeHero.vue +70 -0
  21. data/docs/.vitepress/theme/components/HomeInTheBox.vue +74 -0
  22. data/docs/.vitepress/theme/components/HomePillars.vue +42 -0
  23. data/docs/.vitepress/theme/components/HomeStopWriting.vue +49 -0
  24. data/docs/.vitepress/theme/components/HomeWalkthrough.vue +111 -0
  25. data/docs/.vitepress/theme/components/SectionLanding.vue +115 -0
  26. data/docs/.vitepress/theme/custom.css +144 -0
  27. data/docs/.vitepress/theme/index.ts +58 -1
  28. data/docs/getting-started/index.md +33 -57
  29. data/docs/getting-started/installation.md +37 -80
  30. data/docs/getting-started/tutorial/02-first-resource.md +17 -8
  31. data/docs/getting-started/tutorial/03-authentication.md +31 -23
  32. data/docs/getting-started/tutorial/05-custom-actions.md +9 -4
  33. data/docs/getting-started/tutorial/06-nested-resources.md +7 -1
  34. data/docs/getting-started/tutorial/07-author-portal.md +8 -0
  35. data/docs/getting-started/tutorial/08-customizing-ui.md +4 -0
  36. data/docs/getting-started/tutorial/index.md +4 -5
  37. data/docs/guides/adding-resources.md +66 -377
  38. data/docs/guides/authentication.md +98 -462
  39. data/docs/guides/authorization.md +124 -370
  40. data/docs/guides/creating-packages.md +93 -298
  41. data/docs/guides/custom-actions.md +126 -441
  42. data/docs/guides/customizing-ui.md +258 -0
  43. data/docs/guides/index.md +49 -52
  44. data/docs/guides/multi-tenancy.md +123 -186
  45. data/docs/guides/nested-resources.md +137 -396
  46. data/docs/guides/search-filtering.md +127 -238
  47. data/docs/guides/testing.md +10 -5
  48. data/docs/guides/theming.md +168 -405
  49. data/docs/guides/troubleshooting.md +5 -3
  50. data/docs/guides/user-invites.md +112 -425
  51. data/docs/guides/user-profile.md +82 -241
  52. data/docs/index.md +10 -219
  53. data/docs/public/asciinema/home-scaffold.cast +305 -0
  54. data/docs/public/images/guides/custom-actions-bulk.png +0 -0
  55. data/docs/public/images/guides/multi-tenancy-dashboard.png +0 -0
  56. data/docs/public/images/guides/multi-tenancy-welcome.png +0 -0
  57. data/docs/public/images/guides/nested-inputs.png +0 -0
  58. data/docs/public/images/guides/nested-resources-tab.png +0 -0
  59. data/docs/public/images/guides/search-filtering-index.png +0 -0
  60. data/docs/public/images/guides/search-filtering-panel.png +0 -0
  61. data/docs/public/images/guides/theming-after.png +0 -0
  62. data/docs/public/images/guides/theming-before.png +0 -0
  63. data/docs/public/images/guides/user-invites-landing.png +0 -0
  64. data/docs/public/images/guides/user-profile-edit.png +0 -0
  65. data/docs/public/images/guides/user-profile-show.png +0 -0
  66. data/docs/public/images/home-index.png +0 -0
  67. data/docs/public/images/home-new.png +0 -0
  68. data/docs/public/images/home-show.png +0 -0
  69. data/docs/public/images/tutorial/02-empty-index.png +0 -0
  70. data/docs/public/images/tutorial/02-index-with-posts.png +0 -0
  71. data/docs/public/images/tutorial/02-new-form-modal.png +0 -0
  72. data/docs/public/images/tutorial/02-new-form.png +0 -0
  73. data/docs/public/images/tutorial/03-create-account.png +0 -0
  74. data/docs/public/images/tutorial/03-login.png +0 -0
  75. data/docs/public/images/tutorial/04-admin-index.png +0 -0
  76. data/docs/public/images/tutorial/05-actions-menu.png +0 -0
  77. data/docs/public/images/tutorial/05-row-actions.png +0 -0
  78. data/docs/public/images/tutorial/06-comments-tab.png +0 -0
  79. data/docs/public/images/tutorial/06-post-with-comments.png +0 -0
  80. data/docs/public/images/tutorial/07-author-dashboard.png +0 -0
  81. data/docs/public/images/tutorial/07-author-portal.png +0 -0
  82. data/docs/public/images/tutorial/08-customized-index.png +0 -0
  83. data/docs/reference/app/generators.md +517 -0
  84. data/docs/reference/app/index.md +158 -0
  85. data/docs/reference/app/packages.md +146 -0
  86. data/docs/reference/app/portals.md +377 -0
  87. data/docs/reference/auth/accounts.md +229 -0
  88. data/docs/reference/auth/index.md +88 -0
  89. data/docs/reference/auth/profile.md +185 -0
  90. data/docs/reference/behavior/controllers.md +395 -0
  91. data/docs/reference/behavior/index.md +22 -0
  92. data/docs/reference/behavior/interactions.md +341 -0
  93. data/docs/reference/behavior/policies.md +417 -0
  94. data/docs/reference/index.md +67 -48
  95. data/docs/reference/resource/actions.md +423 -0
  96. data/docs/reference/resource/definition.md +508 -0
  97. data/docs/reference/resource/index.md +50 -0
  98. data/docs/reference/resource/model.md +348 -0
  99. data/docs/reference/resource/query.md +305 -0
  100. data/docs/reference/tenancy/entity-scoping.md +368 -0
  101. data/docs/reference/tenancy/index.md +36 -0
  102. data/docs/reference/tenancy/invites.md +400 -0
  103. data/docs/reference/tenancy/nested-resources.md +267 -0
  104. data/docs/reference/testing/index.md +287 -0
  105. data/docs/reference/ui/assets.md +400 -0
  106. data/docs/reference/ui/components.md +165 -0
  107. data/docs/reference/ui/displays.md +104 -0
  108. data/docs/reference/ui/forms.md +284 -0
  109. data/docs/reference/ui/index.md +30 -0
  110. data/docs/reference/ui/layouts.md +106 -0
  111. data/docs/reference/ui/pages.md +189 -0
  112. data/docs/reference/ui/tables.md +121 -0
  113. data/docs/superpowers/plans/2026-05-15-public-pages-overhaul.md +1648 -0
  114. data/docs/superpowers/plans/2026-05-15-public-pages-overhaul.md.tasks.json +109 -0
  115. data/docs/superpowers/specs/2026-05-09-typeahead-endpoint-design.md +203 -0
  116. data/docs/superpowers/specs/2026-05-12-skill-compaction-design.md +99 -0
  117. data/docs/superpowers/specs/2026-05-13-docs-restructure-design.md +186 -0
  118. data/docs/superpowers/specs/2026-05-15-public-pages-overhaul-design.md +263 -0
  119. data/gemfiles/rails_7.gemfile.lock +1 -1
  120. data/gemfiles/rails_8.0.gemfile.lock +1 -1
  121. data/gemfiles/rails_8.1.gemfile.lock +1 -1
  122. data/lib/generators/pu/core/assets/assets_generator.rb +10 -0
  123. data/lib/generators/pu/core/update/update_generator.rb +0 -20
  124. data/lib/generators/pu/invites/install_generator.rb +45 -0
  125. data/lib/generators/pu/invites/templates/packages/invites/app/controllers/invites/user_invitations_controller.rb.tt +1 -0
  126. data/lib/generators/pu/profile/conn_generator.rb +2 -2
  127. data/lib/generators/pu/res/conn/conn_generator.rb +33 -6
  128. data/lib/generators/pu/res/model/templates/model.rb.tt +4 -0
  129. data/lib/generators/pu/rodauth/account_generator.rb +2 -1
  130. data/lib/generators/pu/rodauth/admin_generator.rb +0 -2
  131. data/lib/generators/pu/rodauth/migration_generator.rb +0 -2
  132. data/lib/generators/pu/rodauth/views_generator.rb +0 -2
  133. data/lib/generators/pu/saas/membership/USAGE +4 -1
  134. data/lib/generators/pu/saas/setup_generator.rb +16 -4
  135. data/lib/generators/pu/saas/welcome/templates/app/controllers/welcome_controller.rb.tt +1 -1
  136. data/lib/plutonium/definition/base.rb +1 -1
  137. data/lib/plutonium/definition/{views.rb → index_views.rb} +21 -20
  138. data/lib/plutonium/helpers/turbo_helper.rb +30 -0
  139. data/lib/plutonium/helpers/turbo_stream_actions_helper.rb +14 -0
  140. data/lib/plutonium/resource/controller.rb +1 -0
  141. data/lib/plutonium/resource/controllers/crud_actions.rb +23 -5
  142. data/lib/plutonium/resource/controllers/interactive_actions.rb +3 -3
  143. data/lib/plutonium/resource/controllers/typeahead.rb +180 -0
  144. data/lib/plutonium/resource/policy.rb +7 -0
  145. data/lib/plutonium/routing/mapper_extensions.rb +15 -0
  146. data/lib/plutonium/ui/component/methods.rb +5 -0
  147. data/lib/plutonium/ui/form/base.rb +23 -3
  148. data/lib/plutonium/ui/form/components/json.rb +58 -0
  149. data/lib/plutonium/ui/form/components/resource_select.rb +62 -8
  150. data/lib/plutonium/ui/form/components/secure_association.rb +103 -22
  151. data/lib/plutonium/ui/form/concerns/typeahead_attributes.rb +83 -0
  152. data/lib/plutonium/ui/form/interaction.rb +1 -1
  153. data/lib/plutonium/ui/form/resource.rb +0 -4
  154. data/lib/plutonium/ui/form/theme.rb +1 -1
  155. data/lib/plutonium/ui/grid/resource.rb +1 -1
  156. data/lib/plutonium/ui/layout/base.rb +1 -0
  157. data/lib/plutonium/ui/page/base.rb +0 -7
  158. data/lib/plutonium/ui/page/edit.rb +1 -1
  159. data/lib/plutonium/ui/page/index.rb +4 -4
  160. data/lib/plutonium/ui/page/new.rb +1 -1
  161. data/lib/plutonium/ui/table/components/filter_form.rb +12 -4
  162. data/lib/plutonium/ui/table/resource.rb +1 -1
  163. data/lib/plutonium/version.rb +1 -1
  164. data/lib/plutonium.rb +8 -0
  165. data/lib/tasks/release.rake +15 -1
  166. data/package.json +13 -10
  167. data/src/css/slim_select.css +4 -0
  168. data/src/js/controllers/form_controller.js +5 -4
  169. data/src/js/controllers/slim_select_controller.js +61 -0
  170. data/src/js/turbo/turbo_actions.js +33 -0
  171. data/yarn.lock +661 -544
  172. metadata +86 -33
  173. data/.claude/skills/plutonium-assets/SKILL.md +0 -512
  174. data/.claude/skills/plutonium-controller/SKILL.md +0 -396
  175. data/.claude/skills/plutonium-create-resource/SKILL.md +0 -303
  176. data/.claude/skills/plutonium-definition/SKILL.md +0 -1223
  177. data/.claude/skills/plutonium-entity-scoping/SKILL.md +0 -317
  178. data/.claude/skills/plutonium-forms/SKILL.md +0 -465
  179. data/.claude/skills/plutonium-installation/SKILL.md +0 -331
  180. data/.claude/skills/plutonium-interaction/SKILL.md +0 -413
  181. data/.claude/skills/plutonium-invites/SKILL.md +0 -408
  182. data/.claude/skills/plutonium-model/SKILL.md +0 -440
  183. data/.claude/skills/plutonium-nested-resources/SKILL.md +0 -360
  184. data/.claude/skills/plutonium-package/SKILL.md +0 -198
  185. data/.claude/skills/plutonium-policy/SKILL.md +0 -456
  186. data/.claude/skills/plutonium-portal/SKILL.md +0 -410
  187. data/.claude/skills/plutonium-views/SKILL.md +0 -651
  188. data/docs/reference/assets/index.md +0 -496
  189. data/docs/reference/controller/index.md +0 -412
  190. data/docs/reference/definition/actions.md +0 -462
  191. data/docs/reference/definition/fields.md +0 -383
  192. data/docs/reference/definition/index.md +0 -326
  193. data/docs/reference/definition/query.md +0 -351
  194. data/docs/reference/generators/index.md +0 -648
  195. data/docs/reference/interaction/index.md +0 -449
  196. data/docs/reference/model/features.md +0 -248
  197. data/docs/reference/model/index.md +0 -218
  198. data/docs/reference/policy/index.md +0 -456
  199. data/docs/reference/portal/index.md +0 -379
  200. data/docs/reference/views/forms.md +0 -411
  201. data/docs/reference/views/index.md +0 -544
@@ -12,23 +12,27 @@ Rodauth is a Ruby authentication framework that Plutonium uses for:
12
12
 
13
13
  Plutonium integrates Rodauth seamlessly with its portal system.
14
14
 
15
- ## Setting Up Authentication
15
+ ## Installing Rodauth
16
16
 
17
- If you used the Plutonium template, Rodauth is already installed. If not:
17
+ Run the Plutonium Rodauth installer once per app — it creates the Rodauth app, plugin, and initializer:
18
18
 
19
19
  ```bash
20
20
  rails generate pu:rodauth:install
21
- rails db:migrate
22
21
  ```
23
22
 
23
+ (No migration is needed yet; the account-type generator below creates its own tables.)
24
+
24
25
  ## Creating an Account Type
25
26
 
26
- Plutonium supports multiple account types. For admin accounts that cannot self-register, use the `admin` generator:
27
+ Plutonium supports multiple account types. For admins, use the dedicated `pu:rodauth:admin` generator — it's a preset on top of `pu:rodauth:account` that enables 2FA, lockout, audit logging, and disables public signup:
27
28
 
28
29
  ```bash
29
30
  rails generate pu:rodauth:admin admin
31
+ rails db:migrate
30
32
  ```
31
33
 
34
+ For self-service user accounts, the corresponding command is `rails generate pu:rodauth:account user`.
35
+
32
36
  This creates:
33
37
 
34
38
  ### Account Model (`app/models/admin.rb`)
@@ -57,30 +61,28 @@ end
57
61
 
58
62
  The generator also creates migrations for the account table and authentication features.
59
63
 
60
- ## Configuring the Portal
64
+ ## Gating the Portal with Authentication
61
65
 
62
- Authentication is configured in the portal's controller concern. Update it to use Rodauth:
66
+ In [Chapter 2](./02-first-resource) you generated the admin portal with `--public`. Now that you have an `admin` Rodauth account, swap the portal over to require login. The fastest way is to re-run the portal generator with `--auth=admin --force`:
63
67
 
64
- ```ruby
65
- # packages/admin_portal/app/controllers/admin_portal/concerns/controller.rb
66
- module AdminPortal
67
- module Concerns
68
- module Controller
69
- extend ActiveSupport::Concern
70
- include Plutonium::Portal::Controller
71
- include Plutonium::Auth::Rodauth(:admin)
72
- end
73
- end
74
- end
68
+ ```bash
69
+ rails generate pu:pkg:portal admin --auth=admin --force
75
70
  ```
76
71
 
77
- This provides `current_user` and authentication helpers throughout the portal.
72
+ This updates two files:
78
73
 
79
- ## Running Migrations
74
+ - `packages/admin_portal/app/controllers/admin_portal/concerns/controller.rb` — swaps `include Plutonium::Auth::Public` for `include Plutonium::Auth::Rodauth(:admin)`, giving you `current_user`, `logout_url`, and `profile_url` helpers throughout the portal.
75
+ - `packages/admin_portal/config/routes.rb` — wraps the engine mount in a routes-level constraint:
80
76
 
81
- ```bash
82
- rails db:migrate
83
- ```
77
+ ```ruby
78
+ constraints Rodauth::Rails.authenticate(:admin) do
79
+ mount AdminPortal::Engine, at: "/admin"
80
+ end
81
+ ```
82
+
83
+ The routes constraint is what actually gates access — unauthenticated requests to `/admin/*` are redirected to `/admins/login` before they hit any controller or policy.
84
+
85
+ (If you prefer not to regenerate, you can apply both edits by hand — they're shown above.)
84
86
 
85
87
  ## Testing Authentication
86
88
 
@@ -90,7 +92,13 @@ Restart your server:
90
92
  bin/dev
91
93
  ```
92
94
 
93
- Visit `http://localhost:3000/admin/blogging/posts`. You'll be redirected to the login page.
95
+ Visit `http://localhost:3000/admin/blogging/posts`. You'll be redirected to the login page:
96
+
97
+ ![Admin login page](/images/tutorial/03-login.png)
98
+
99
+ The "Create a New Account" link goes to the same Rodauth-rendered account creation form:
100
+
101
+ ![Create account page](/images/tutorial/03-create-account.png)
94
102
 
95
103
  ### Creating an Admin Account
96
104
 
@@ -79,10 +79,15 @@ end
79
79
 
80
80
  ## Testing the Action
81
81
 
82
- 1. Create an unpublished post
83
- 2. View the post details
84
- 3. Click the "Publish" action button
85
- 4. The post is now published
82
+ Open any unpublished post and click **Actions** in the top-right — the "Publish Post" item appears with its Tabler icon:
83
+
84
+ ![Publish action in the show page menu](/images/tutorial/05-actions-menu.png)
85
+
86
+ It also shows on each table row's `⋮` menu — same action, available wherever the record is rendered:
87
+
88
+ ![Publish action in the row menu](/images/tutorial/05-row-actions.png)
89
+
90
+ Click "Publish Post" and the post is updated; the flash banner confirms success.
86
91
 
87
92
  ## Actions with User Input
88
93
 
@@ -69,7 +69,13 @@ class Blogging::PostPolicy < Blogging::ResourcePolicy
69
69
  end
70
70
  ```
71
71
 
72
- The panel links to the nested comments route and shows "Add Comment" if the user has permission.
72
+ The post show page now has tabs **Details** and **Comments** driven by the associations you permit:
73
+
74
+ ![Post show page with Details and Comments tabs](/images/tutorial/06-post-with-comments.png)
75
+
76
+ Clicking **Comments** opens the nested index for that post — a complete sub-resource view with its own paginated table, "New" button, and row actions:
77
+
78
+ ![Nested comments index](/images/tutorial/06-comments-tab.png)
73
79
 
74
80
  ## Comment Policy
75
81
 
@@ -168,6 +168,14 @@ Now you have two portals:
168
168
  | Admin | `/admin` | Admin | All posts |
169
169
  | Author | `/author` | User | Own posts only |
170
170
 
171
+ Log in at `/users/login` with the user account and you land on the Author Portal dashboard — the same chrome as the Admin Portal but mounted at `/author`, gated by `Rodauth::Rails.authenticate(:user)`:
172
+
173
+ ![Author Portal dashboard](/images/tutorial/07-author-dashboard.png)
174
+
175
+ The posts list lives at `/author/blogging/posts` — same `Blogging::Post` resource, different portal context (and once you add the scoping policy below, scoped to the logged-in author):
176
+
177
+ ![Author Portal posts index](/images/tutorial/07-author-portal.png)
178
+
171
179
  ### Test the difference:
172
180
 
173
181
  1. **Create an Admin account** at `/admin/register`
@@ -117,6 +117,10 @@ class Blogging::PostDefinition < Blogging::ResourceDefinition
117
117
  end
118
118
  ```
119
119
 
120
+ The default "Posts" heading becomes your branded title and description:
121
+
122
+ ![Customized index page title](/images/tutorial/08-customized-index.png)
123
+
120
124
  For more advanced customization, you can create custom page classes that inherit from Plutonium's page components:
121
125
 
122
126
  ```ruby
@@ -55,13 +55,12 @@ Create a second portal with different access levels for content authors.
55
55
  ### [8. Customizing the UI](./08-customizing-ui)
56
56
  Customize forms, tables, and views to match your requirements.
57
57
 
58
- ## Getting Help
58
+ ## Getting help
59
59
 
60
60
  If you get stuck:
61
- - Check the [Guides](/guides/) for detailed explanations
62
- - Browse the [Reference Documentation](/reference/) for API details
63
- - Visit our [GitHub Issues](https://github.com/radioactive-labs/plutonium-core/issues)
64
61
 
65
- Let's get started!
62
+ - Check the [Guides](/guides/) for task-oriented walkthroughs.
63
+ - Browse the [Reference](/reference/) for full API surface — [App](/reference/app/), [Resource](/reference/resource/), [Behavior](/reference/behavior/), [UI](/reference/ui/), [Auth](/reference/auth/), [Tenancy](/reference/tenancy/), [Testing](/reference/testing/).
64
+ - Visit [GitHub Issues](https://github.com/radioactive-labs/plutonium-core/issues).
66
65
 
67
66
  [Begin Chapter 1: Project Setup →](./01-setup)