plutonium 0.65.0 → 0.66.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 (104) hide show
  1. checksums.yaml +4 -4
  2. data/.claude/skills/plutonium/SKILL.md +43 -43
  3. data/.claude/skills/plutonium-app/SKILL.md +101 -59
  4. data/.claude/skills/plutonium-async-interactions/SKILL.md +19 -19
  5. data/.claude/skills/plutonium-auth/SKILL.md +119 -53
  6. data/.claude/skills/plutonium-behavior/SKILL.md +110 -78
  7. data/.claude/skills/plutonium-dashboard/SKILL.md +11 -4
  8. data/.claude/skills/plutonium-kanban/SKILL.md +81 -49
  9. data/.claude/skills/plutonium-resource/SKILL.md +144 -133
  10. data/.claude/skills/plutonium-tenancy/SKILL.md +104 -55
  11. data/.claude/skills/plutonium-testing/SKILL.md +130 -33
  12. data/.claude/skills/plutonium-ui/SKILL.md +151 -96
  13. data/.claude/skills/plutonium-wizard/SKILL.md +93 -82
  14. data/CHANGELOG.md +21 -0
  15. data/README.md +9 -9
  16. data/SECURITY.md +1 -1
  17. data/app/assets/plutonium.css +1 -1
  18. data/docs/.vitepress/sync-skills.mjs +6 -3
  19. data/docs/blog/introducing-plutonium-dashboards.md +4 -5
  20. data/docs/blog/introducing-plutonium-i18n.md +4 -5
  21. data/docs/getting-started/installation.md +5 -5
  22. data/docs/getting-started/tutorial/02-first-resource.md +3 -3
  23. data/docs/getting-started/tutorial/03-authentication.md +7 -7
  24. data/docs/getting-started/tutorial/04-authorization.md +21 -4
  25. data/docs/getting-started/tutorial/05-custom-actions.md +2 -2
  26. data/docs/getting-started/tutorial/06-nested-resources.md +5 -2
  27. data/docs/getting-started/tutorial/07-author-portal.md +2 -2
  28. data/docs/getting-started/tutorial/08-customizing-ui.md +45 -30
  29. data/docs/getting-started/tutorial/index.md +1 -1
  30. data/docs/guides/adding-resources.md +10 -7
  31. data/docs/guides/authentication.md +25 -25
  32. data/docs/guides/authorization.md +24 -24
  33. data/docs/guides/creating-packages.md +17 -17
  34. data/docs/guides/custom-actions.md +32 -32
  35. data/docs/guides/customizing-ui.md +29 -26
  36. data/docs/guides/dashboards.md +1 -1
  37. data/docs/guides/index.md +3 -3
  38. data/docs/guides/kanban.md +55 -55
  39. data/docs/guides/multi-tenancy.md +35 -22
  40. data/docs/guides/nested-resources.md +21 -21
  41. data/docs/guides/performance.md +3 -3
  42. data/docs/guides/search-filtering.md +13 -13
  43. data/docs/guides/testing.md +16 -12
  44. data/docs/guides/theming.md +32 -17
  45. data/docs/guides/troubleshooting.md +2 -2
  46. data/docs/guides/user-invites.md +17 -17
  47. data/docs/guides/user-profile.md +51 -24
  48. data/docs/guides/wizards.md +55 -55
  49. data/docs/reference/app/generators.md +22 -22
  50. data/docs/reference/app/index.md +15 -18
  51. data/docs/reference/app/packages.md +8 -8
  52. data/docs/reference/app/portals.md +75 -29
  53. data/docs/reference/auth/accounts.md +15 -15
  54. data/docs/reference/auth/index.md +12 -12
  55. data/docs/reference/auth/profile.md +67 -29
  56. data/docs/reference/behavior/async-interactions.md +24 -24
  57. data/docs/reference/behavior/controllers.md +28 -28
  58. data/docs/reference/behavior/index.md +5 -5
  59. data/docs/reference/behavior/interactions.md +44 -44
  60. data/docs/reference/behavior/policies.md +48 -28
  61. data/docs/reference/configuration.md +6 -6
  62. data/docs/reference/dashboard/dsl.md +2 -2
  63. data/docs/reference/dashboard/index.md +1 -1
  64. data/docs/reference/generators/lite.md +7 -7
  65. data/docs/reference/i18n.md +23 -0
  66. data/docs/reference/index.md +1 -1
  67. data/docs/reference/kanban/authorization.md +9 -9
  68. data/docs/reference/kanban/dsl.md +32 -32
  69. data/docs/reference/kanban/index.md +1 -1
  70. data/docs/reference/kanban/positioning.md +17 -15
  71. data/docs/reference/resource/actions.md +51 -51
  72. data/docs/reference/resource/definition.md +73 -73
  73. data/docs/reference/resource/export.md +6 -6
  74. data/docs/reference/resource/index.md +16 -16
  75. data/docs/reference/resource/model.md +24 -24
  76. data/docs/reference/resource/positioning.md +78 -76
  77. data/docs/reference/resource/query.md +13 -13
  78. data/docs/reference/tenancy/entity-scoping.md +65 -35
  79. data/docs/reference/tenancy/index.md +11 -11
  80. data/docs/reference/tenancy/invites.md +20 -20
  81. data/docs/reference/tenancy/nested-resources.md +13 -13
  82. data/docs/reference/testing/index.md +116 -22
  83. data/docs/reference/ui/assets.md +57 -25
  84. data/docs/reference/ui/components.md +20 -20
  85. data/docs/reference/ui/displays.md +14 -14
  86. data/docs/reference/ui/forms.md +35 -35
  87. data/docs/reference/ui/index.md +17 -15
  88. data/docs/reference/ui/layouts.md +21 -21
  89. data/docs/reference/ui/pages.md +22 -22
  90. data/docs/reference/ui/tables.md +7 -7
  91. data/docs/reference/wizard/anchoring-resume.md +33 -32
  92. data/docs/reference/wizard/dsl.md +44 -44
  93. data/docs/reference/wizard/index.md +6 -6
  94. data/docs/reference/wizard/one-time.md +18 -18
  95. data/docs/reference/wizard/registration-launch.md +32 -32
  96. data/docs/reference/wizard/storage-config.md +23 -23
  97. data/gemfiles/rails_8.1.gemfile.lock +1 -1
  98. data/lib/generators/pu/profile/conn_generator.rb +6 -0
  99. data/lib/plutonium/resource/record/associated_with.rb +23 -2
  100. data/lib/plutonium/ui/form/concerns/typeahead_attributes.rb +7 -1
  101. data/lib/plutonium/version.rb +1 -1
  102. data/package.json +1 -1
  103. data/src/css/components.css +10 -10
  104. metadata +2 -2
@@ -11,25 +11,25 @@ All resource models inherit from `ResourceRecord` (created by `pu:core:install`)
11
11
  class Post < ResourceRecord
12
12
  end
13
13
 
14
- # Inside a feature package — uses the package's ResourceRecord
14
+ # Inside a feature package: uses the package's ResourceRecord
15
15
  module Blogging
16
16
  class Post < Blogging::ResourceRecord
17
17
  end
18
18
  end
19
19
  ```
20
20
 
21
- `ResourceRecord` is abstract and inherits from `ApplicationRecord`. Standard ActiveRecord features (associations, validations, scopes, callbacks, attribute macros) all work — Plutonium adds capabilities on top.
21
+ `ResourceRecord` is abstract and inherits from `ApplicationRecord`. Standard ActiveRecord features (associations, validations, scopes, callbacks, attribute macros) all work; Plutonium adds capabilities on top.
22
22
 
23
23
  ## What `Plutonium::Resource::Record` adds
24
24
 
25
25
  | Module | Purpose | Section |
26
26
  |---|---|---|
27
- | `HasCents` | Money handling — cents column ↔ decimal accessor | [has_cents](#has-cents) |
27
+ | `HasCents` | Money handling: cents column ↔ decimal accessor | [has_cents](#has-cents) |
28
28
  | `Routes` | URL parameter customization (slugs, dynamic params) | [URL routing](#url-routing) |
29
29
  | `Labeling` | `to_label` for human-readable record names | [Labeling](#labeling) |
30
30
  | `FieldNames` | Field introspection by category | [Field introspection](#field-introspection) |
31
31
  | `Associations` | Auto-generated SGID accessors on every association | [SGID accessors](#sgid-accessors) |
32
- | `AssociatedWith` | Multi-tenant scoping — `Model.associated_with(entity)` | [Tenancy](/reference/tenancy/entity-scoping) |
32
+ | `AssociatedWith` | Multi-tenant scoping: `Model.associated_with(entity)` | [Tenancy](/reference/tenancy/entity-scoping) |
33
33
 
34
34
  ## Section layout
35
35
 
@@ -89,7 +89,7 @@ end
89
89
 
90
90
  ## `has_cents`
91
91
 
92
- Stores monetary values as integer cents and exposes a decimal virtual accessor. Use this for money — never store decimals directly.
92
+ Stores monetary values as integer cents and exposes a decimal virtual accessor. Use this for money; never store decimals directly.
93
93
 
94
94
  ```ruby
95
95
  class Product < ResourceRecord
@@ -112,16 +112,16 @@ product.price = 10.999
112
112
  product.price_cents # => 1099
113
113
  ```
114
114
 
115
- **Currency symbol (`unit:`)** — a `String` is used verbatim (`unit: "£"`); a `Symbol`
115
+ **Currency symbol (`unit:`).** A `String` is used verbatim (`unit: "£"`); a `Symbol`
116
116
  names a method read off the record for per-row currencies (`unit: :currency_symbol`
117
117
  → `record.currency_symbol`); `false` explicitly renders no symbol. This unit is picked
118
- up automatically anywhere the value renders as currency — show pages, tables, and
119
- grid/kanban cards — so you configure it once on the model. A per-display
118
+ up automatically anywhere the value renders as currency (show pages, tables, and
119
+ grid/kanban cards), so you configure it once on the model. A per-display
120
120
  `display :price, as: :currency, unit: …` overrides it for that display.
121
121
 
122
122
  A `has_cents` field also **infers the currency input** on forms: a bare `input :price`
123
123
  renders the [currency input](../ui/forms#currency-fields) (number field + unit prefix),
124
- no `as: :currency` needed — matching the display side.
124
+ no `as: :currency` needed, matching the display side.
125
125
 
126
126
  Resolution is `display unit → has_cents unit → config default`, where `nil` means
127
127
  "not set, keep looking" and `false` means "stop, no symbol". When nothing is set, it
@@ -148,7 +148,7 @@ end
148
148
  field :price, as: :decimal # ✅ virtual name
149
149
  ```
150
150
 
151
- Generators sometimes emit the `_cents` name in the policy — fix by hand (and verify `has_cents` is declared on the model).
151
+ Generators sometimes emit the `_cents` name in the policy; fix by hand (and verify `has_cents` is declared on the model).
152
152
  :::
153
153
 
154
154
  ### Options
@@ -176,7 +176,7 @@ product.errors[:price_cents] # => ["must be greater than 0"]
176
176
  product.errors[:price] # => ["is invalid"]
177
177
  ```
178
178
 
179
- The framework adds an `after_validation` hook that copies `:invalid` from `price_cents` → `price` automatically — no manual wiring needed.
179
+ The framework adds an `after_validation` hook that copies `:invalid` from `price_cents` → `price` automatically, no manual wiring needed.
180
180
 
181
181
  ### Introspection
182
182
 
@@ -196,7 +196,7 @@ post.to_param # => "1" (numeric id)
196
196
  # URL: /posts/1
197
197
  ```
198
198
 
199
- ### `path_parameter` — use a stable column
199
+ ### `path_parameter`: use a stable column
200
200
 
201
201
  Use a column that's unique and human-readable instead of the numeric id:
202
202
 
@@ -212,9 +212,9 @@ user.to_param # => "john_doe"
212
212
  User.from_path_param("john_doe") # finds by username
213
213
  ```
214
214
 
215
- `path_parameter` is a class-level macro (private class method). The column you pass MUST be unique — Plutonium uses it for lookup.
215
+ `path_parameter` is a class-level macro (private class method). The column you pass MUST be unique; Plutonium uses it for lookup.
216
216
 
217
- ### `dynamic_path_parameter` — SEO-friendly id + slug
217
+ ### `dynamic_path_parameter`: SEO-friendly id + slug
218
218
 
219
219
  Combines the id (for stable lookup) with a slug from another column (for SEO):
220
220
 
@@ -230,7 +230,7 @@ article.to_param # => "42-hello-world"
230
230
  Article.from_path_param("42-hello-world") # extracts "42", finds by id
231
231
  ```
232
232
 
233
- The slug is informational — only the id portion is used for lookup, so changing the title doesn't break old URLs.
233
+ The slug is informational: only the id portion is used for lookup, so changing the title doesn't break old URLs.
234
234
 
235
235
  ## Labeling
236
236
 
@@ -262,7 +262,7 @@ end
262
262
 
263
263
  ## SGID accessors
264
264
 
265
- Every association on a resource model gets Signed Global ID accessors automatically — for secure form submission, API payloads, and hidden fields without exposing database ids.
265
+ Every association on a resource model gets Signed Global ID accessors automatically, for secure form submission, API payloads, and hidden fields without exposing database ids.
266
266
 
267
267
  ### Singular associations (`belongs_to`, `has_one`)
268
268
 
@@ -292,7 +292,7 @@ user.add_post_sgid(sgid) # append
292
292
  user.remove_post_sgid(sgid) # remove
293
293
  ```
294
294
 
295
- These are what `secure_association_tag` uses in forms — see [UI › Forms](/reference/ui/forms).
295
+ These are what `secure_association_tag` uses in forms; see [UI › Forms](/reference/ui/forms).
296
296
 
297
297
  ## Field introspection
298
298
 
@@ -335,11 +335,11 @@ Resolution order, association path requirements, three model shapes, and custom
335
335
 
336
336
  ## Standard ActiveRecord features
337
337
 
338
- Everything you'd expect works — associations, validations, scopes, callbacks, delegations, `has_rich_text`, `has_secure_token`, `has_one_attached`, etc. Where Plutonium adds twists:
338
+ Everything you'd expect works: associations, validations, scopes, callbacks, delegations, `has_rich_text`, `has_secure_token`, `has_one_attached`, etc. Where Plutonium adds twists:
339
339
 
340
- - **Section ordering** is by convention, not enforcement — pick the right slot in the [layout above](#section-layout) so the file stays scannable.
341
- - **Compound uniqueness for tenant-scoped resources:** `validates :code, uniqueness: {scope: :organization_id}` — without the scope, uniqueness leaks across tenants.
342
- - **Keep models thin** — business logic that touches multiple records or has multi-step state changes belongs in [interactions](/reference/behavior/interactions), not model methods.
340
+ - **Section ordering** is by convention, not enforcement: pick the right slot in the [layout above](#section-layout) so the file stays scannable.
341
+ - **Compound uniqueness for tenant-scoped resources:** `validates :code, uniqueness: {scope: :organization_id}`, without the scope, uniqueness leaks across tenants.
342
+ - **Keep models thin**: business logic that touches multiple records or has multi-step state changes belongs in [interactions](/reference/behavior/interactions), not model methods.
343
343
 
344
344
  ## Nested resources
345
345
 
@@ -369,6 +369,6 @@ Override with `self.table_name = "posts"` if you need a shared table.
369
369
 
370
370
  ## Related
371
371
 
372
- - [Definition](./definition) — controls how the model's fields render
373
- - [Tenancy › Entity scoping](/reference/tenancy/entity-scoping) — `associated_with`, three model shapes
374
- - [App › Generators](/reference/app/generators) — `pu:res:scaffold` field syntax
372
+ - [Definition](./definition): controls how the model's fields render
373
+ - [Tenancy › Entity scoping](/reference/tenancy/entity-scoping): `associated_with`, three model shapes
374
+ - [App › Generators](/reference/app/generators): `pu:res:scaffold` field syntax