plutonium 0.56.0 → 0.56.2
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.
- checksums.yaml +4 -4
- data/.claude/skills/plutonium/SKILL.md +1 -1
- data/.claude/skills/plutonium-app/SKILL.md +1 -1
- data/.claude/skills/plutonium-auth/SKILL.md +1 -1
- data/.claude/skills/plutonium-resource/SKILL.md +35 -1
- data/CHANGELOG.md +19 -0
- data/CONTRIBUTING.md +1 -1
- data/README.md +38 -16
- data/app/assets/plutonium.css +1 -1
- data/docs/getting-started/installation.md +2 -2
- data/docs/getting-started/tutorial/02-first-resource.md +1 -1
- data/docs/getting-started/tutorial/03-authentication.md +3 -3
- data/docs/guides/adding-resources.md +1 -1
- data/docs/guides/authentication.md +1 -1
- data/docs/guides/creating-packages.md +1 -1
- data/docs/guides/multi-tenancy.md +1 -1
- data/docs/guides/nested-resources.md +1 -1
- data/docs/guides/user-invites.md +1 -1
- data/docs/guides/user-profile.md +1 -1
- data/docs/reference/app/generators.md +3 -3
- data/docs/reference/app/index.md +1 -1
- data/docs/reference/app/portals.md +1 -1
- data/docs/reference/auth/profile.md +1 -1
- data/docs/reference/resource/actions.md +55 -0
- data/docs/reference/resource/index.md +1 -1
- data/docs/reference/tenancy/invites.md +1 -1
- data/gemfiles/rails_7.gemfile.lock +1 -1
- data/gemfiles/rails_8.0.gemfile.lock +1 -1
- data/gemfiles/rails_8.1.gemfile.lock +1 -1
- data/lib/generators/pu/core/typespec/typespec_generator.rb +1 -1
- data/lib/generators/pu/core/update/update_generator.rb +10 -1
- data/lib/generators/pu/saas/welcome_generator.rb +1 -1
- data/lib/plutonium/action/base.rb +19 -2
- data/lib/plutonium/action/condition_context.rb +33 -0
- data/lib/plutonium/ui/grid/card.rb +3 -2
- data/lib/plutonium/ui/page/index.rb +1 -1
- data/lib/plutonium/ui/page/show.rb +1 -1
- data/lib/plutonium/ui/table/components/pagy_pagination.rb +3 -3
- data/lib/plutonium/ui/table/resource.rb +2 -2
- data/lib/plutonium/version.rb +1 -1
- data/package.json +1 -1
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 7932a8a7af49201798eaf8727c03857ab7b7b3490a7ce049acd89cf8efeeda38
|
|
4
|
+
data.tar.gz: 4a268a9cd14ae441ca664c249a3b602f2509aa63f38b9e76a4fd06b0d56fc3a3
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: eea920321f823c316c2ba4aa226e56e614fc0fc39790ee6ac9dd1893fc2a028d4165782823aab2bb8b4285bdbe868fbb43c68553df2eff74784ce04a6de98bff
|
|
7
|
+
data.tar.gz: 713961bf18c70042aa361e948a72caa918d67e0636f2b632715809f7e48c1d4aa41efe77e4517469d0e6ab8c13270965b9558a59d27e98264149646c5b757ea0
|
|
@@ -127,7 +127,7 @@ Meta-generators (`pu:saas:setup`) propagate flags to the generators they chain.
|
|
|
127
127
|
|
|
128
128
|
1. **Load the bootstrap bundle** (or the targeted skill from the router table).
|
|
129
129
|
2. **Generate** — `rails g pu:res:scaffold Model field:type ... --dest=main_app`.
|
|
130
|
-
3. **Migrate** — `rails db:
|
|
130
|
+
3. **Migrate** — `rails db:prepare`.
|
|
131
131
|
4. **Connect** — `rails g pu:res:conn Model --dest=portal_name`.
|
|
132
132
|
5. **Customize** — edit definition / policy as needed.
|
|
133
133
|
6. **Verify** — hit the route in the browser.
|
|
@@ -62,7 +62,7 @@ rails generate pu:pkg:portal admin --auth=user
|
|
|
62
62
|
|
|
63
63
|
# 4. First resource
|
|
64
64
|
rails generate pu:res:scaffold Post user:belongs_to title:string 'content:text?' --dest=main_app
|
|
65
|
-
rails db:
|
|
65
|
+
rails db:prepare
|
|
66
66
|
|
|
67
67
|
# 5. Connect resource to portal
|
|
68
68
|
rails generate pu:res:conn Post --dest=admin_portal
|
|
@@ -279,7 +279,7 @@ rails g pu:profile:setup date_of_birth:date bio:text \
|
|
|
279
279
|
rails generate pu:profile:install bio:text avatar:attachment 'timezone:string?' \
|
|
280
280
|
--dest=customer
|
|
281
281
|
|
|
282
|
-
rails db:
|
|
282
|
+
rails db:prepare
|
|
283
283
|
|
|
284
284
|
rails generate pu:profile:conn --dest=customer_portal
|
|
285
285
|
```
|
|
@@ -29,7 +29,7 @@ For tenancy / `associated_with` / `relation_scope`, load [[plutonium-tenancy]].
|
|
|
29
29
|
1. Pick destination: `--dest=main_app` or `--dest=package_name`.
|
|
30
30
|
2. Run `rails g pu:res:scaffold ResourceName field:type ... --dest=<dest>`.
|
|
31
31
|
3. Review the generated migration — add cascade deletes, composite indexes, defaults.
|
|
32
|
-
4. `rails db:
|
|
32
|
+
4. `rails db:prepare`.
|
|
33
33
|
5. `rails g pu:res:conn ResourceName --dest=<portal_name>`.
|
|
34
34
|
6. Customize the policy's `permitted_attributes_for_*` as needed.
|
|
35
35
|
7. Open the portal route in the browser.
|
|
@@ -1050,6 +1050,10 @@ action :name,
|
|
|
1050
1050
|
collection_record_action: true,
|
|
1051
1051
|
bulk_action: true,
|
|
1052
1052
|
|
|
1053
|
+
# Conditional visibility — display-only toggle, NOT authorization (see below).
|
|
1054
|
+
# `-> { false }` keeps the route live but hides the button (e.g. API-only).
|
|
1055
|
+
condition: -> { params[:beta] == "1" },
|
|
1056
|
+
|
|
1053
1057
|
# Grouping
|
|
1054
1058
|
category: :primary, # :primary, :secondary, :danger
|
|
1055
1059
|
position: 50,
|
|
@@ -1062,6 +1066,36 @@ action :name,
|
|
|
1062
1066
|
size: :lg # :sm / :md / :lg / :xl / :auto / :full — overrides definition's modal size
|
|
1063
1067
|
```
|
|
1064
1068
|
|
|
1069
|
+
### Conditional Actions (`condition:`)
|
|
1070
|
+
|
|
1071
|
+
Like `condition:` on inputs/displays/columns — define an action but render its **button** only when a runtime proc is truthy. The action and its route stay live either way; `condition:` only toggles the UI.
|
|
1072
|
+
|
|
1073
|
+
Headline use case: **expose an action's endpoint without a button** — one you call from the API, a webhook, or another service. Hide it with an always-falsy condition; the route still works:
|
|
1074
|
+
|
|
1075
|
+
```ruby
|
|
1076
|
+
# Defined and callable (API / programmatic), but no button anywhere:
|
|
1077
|
+
action :sync_inventory, interaction: SyncInventoryInteraction, condition: -> { false }
|
|
1078
|
+
|
|
1079
|
+
# Per-record display state — object is the row/shown record:
|
|
1080
|
+
action :reopen, interaction: ReopenInteraction, condition: -> { object.closed? }
|
|
1081
|
+
|
|
1082
|
+
# View/request-level toggle (feature flag, beta mode):
|
|
1083
|
+
action :preview, interaction: PreviewInteraction, condition: -> { params[:beta] == "1" }
|
|
1084
|
+
```
|
|
1085
|
+
|
|
1086
|
+
Inside the proc, `object`/`record` is the contextual record — the row/shown record for **record** and **collection-record** actions, **nil** for **resource** and **bulk** actions (guard with `object&.…` if shared). Every other call delegates to the **view context**: `current_user`, `current_parent`, `params`, `request`, `allowed_to?`, `resource_record!`, etc. `object` is evaluated per row in tables/grids, so per-record show/hide works there.
|
|
1087
|
+
|
|
1088
|
+
🚨 **`condition:` is NOT authorization — it only hides the button.** A hidden action still has a live route; anyone with the URL can trigger it. "Who may run this" belongs in the policy:
|
|
1089
|
+
|
|
1090
|
+
```ruby
|
|
1091
|
+
# 🚫 WRONG — does not stop non-admins; the route is live.
|
|
1092
|
+
action :wipe, interaction: WipeInteraction, condition: -> { current_user.admin? }
|
|
1093
|
+
# ✅ RIGHT — authorization in the policy, enforced regardless of condition:
|
|
1094
|
+
def wipe? = current_user.admin?
|
|
1095
|
+
```
|
|
1096
|
+
|
|
1097
|
+
The two compose: an action's button shows only when the policy permits **and** the condition is truthy; execution is gated by the policy alone. Use `object` in `condition:` for per-record *display*; use the policy for per-record *authorization*.
|
|
1098
|
+
|
|
1065
1099
|
`Action#with(...)` — actions are frozen value objects; clone with overrides:
|
|
1066
1100
|
|
|
1067
1101
|
```ruby
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
+
## [0.56.2] - 2026-06-05
|
|
2
|
+
|
|
3
|
+
### 🐛 Bug Fixes
|
|
4
|
+
|
|
5
|
+
- *(generators/update)* Run skills sync in unbundled env
|
|
6
|
+
- *(ui/pagination)* Prevent large page numbers from overflowing buttons
|
|
7
|
+
## [0.56.1] - 2026-06-05
|
|
8
|
+
|
|
9
|
+
### 🚀 Features
|
|
10
|
+
|
|
11
|
+
- *(actions)* Add display-only condition: to actions
|
|
12
|
+
|
|
13
|
+
### 🐛 Bug Fixes
|
|
14
|
+
|
|
15
|
+
- *(dummy)* Version-adapt kitchen_sinks migration
|
|
16
|
+
|
|
17
|
+
### 📚 Documentation
|
|
18
|
+
|
|
19
|
+
- Recommend db:prepare, firm up README, document conditional actions
|
|
1
20
|
## [0.56.0] - 2026-06-05
|
|
2
21
|
|
|
3
22
|
### 🚀 Features
|
data/CONTRIBUTING.md
CHANGED
data/README.md
CHANGED
|
@@ -2,8 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://badge.fury.io/rb/plutonium)
|
|
4
4
|
[](https://github.com/radioactive-labs/plutonium-core/actions/workflows/main.yml)
|
|
5
|
+
[](LICENSE.txt)
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
**The Rails framework for things you should never write again.**
|
|
8
|
+
|
|
9
|
+
Convention over configuration, extended to everything you keep rebuilding: **CRUD. Auth. Authorization. Multi-tenancy. Admin portals. Search, filters, bulk actions.** All generated. All customizable. All Rails.
|
|
7
10
|
|
|
8
11
|
## Quick Start
|
|
9
12
|
|
|
@@ -12,20 +15,36 @@ rails new myapp -a propshaft -j esbuild -c tailwind \
|
|
|
12
15
|
-m https://radioactive-labs.github.io/plutonium-core/templates/plutonium.rb
|
|
13
16
|
```
|
|
14
17
|
|
|
15
|
-
Then create
|
|
18
|
+
Then scaffold a resource, create a portal, and connect them:
|
|
16
19
|
|
|
17
20
|
```bash
|
|
18
21
|
cd myapp
|
|
19
|
-
|
|
20
|
-
|
|
22
|
+
|
|
23
|
+
# Scaffold a resource — model, migration, definition, policy
|
|
24
|
+
rails g pu:res:scaffold Post title:string body:text published_at:datetime --dest=main_app
|
|
25
|
+
rails db:prepare
|
|
26
|
+
|
|
27
|
+
# Create a portal (web interface) and connect the resource to it
|
|
28
|
+
rails g pu:pkg:portal app --public
|
|
29
|
+
rails g pu:res:conn Post --dest=app_portal
|
|
30
|
+
|
|
21
31
|
bin/dev
|
|
22
32
|
```
|
|
23
33
|
|
|
24
|
-
Visit `http://localhost:3000`
|
|
34
|
+
Visit `http://localhost:3000/app/posts` — you have a complete CRUD interface.
|
|
25
35
|
|
|
26
|
-
## What You
|
|
36
|
+
## What You Stop Writing
|
|
27
37
|
|
|
28
|
-
|
|
38
|
+
Same scaffold command you already know. A very different surface area.
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
rails g scaffold Post ... # Rails: just CRUD
|
|
42
|
+
rails g pu:res:scaffold Post ... # Plutonium: full CRUD + search + filters + bulk actions
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
And it doesn't stop at scaffolds:
|
|
46
|
+
|
|
47
|
+
**Resource-oriented architecture** — models, policies, definitions, and controllers that work together:
|
|
29
48
|
|
|
30
49
|
```ruby
|
|
31
50
|
# Policy controls WHO can do WHAT
|
|
@@ -47,7 +66,7 @@ class PostDefinition < ResourceDefinition
|
|
|
47
66
|
end
|
|
48
67
|
```
|
|
49
68
|
|
|
50
|
-
**Packages
|
|
69
|
+
**Packages and portals** — split your app into feature engines and themed web interfaces:
|
|
51
70
|
|
|
52
71
|
```bash
|
|
53
72
|
rails g pu:pkg:package blogging # Business logic
|
|
@@ -65,7 +84,7 @@ rails g pu:rodauth:account user
|
|
|
65
84
|
**Multi-tenancy** with entity scoping:
|
|
66
85
|
|
|
67
86
|
```ruby
|
|
68
|
-
# In portal engine
|
|
87
|
+
# In a portal engine
|
|
69
88
|
scope_to_entity Organization, strategy: :path
|
|
70
89
|
# Routes become /organizations/:organization_id/posts
|
|
71
90
|
```
|
|
@@ -86,6 +105,13 @@ class PublishInteraction < ResourceInteraction
|
|
|
86
105
|
end
|
|
87
106
|
```
|
|
88
107
|
|
|
108
|
+
## Why Plutonium
|
|
109
|
+
|
|
110
|
+
- **Convention over configuration** — extended to resources, policies, portals, and tenancy, not just routes and views.
|
|
111
|
+
- **It's just Rails** — generated code lives in your repo. Edit it, override it, delete it. The "magic" is regular Ruby mixins you can read.
|
|
112
|
+
- **Multi-tenant ready** — path or domain tenancy, scoped relations, invites and memberships out of the box.
|
|
113
|
+
- **AI-readable** — predictable file layout and naming, plus built-in [Claude Code skills](.claude/skills) that teach AI assistants the patterns.
|
|
114
|
+
|
|
89
115
|
## Documentation
|
|
90
116
|
|
|
91
117
|
Full documentation at **[radioactive-labs.github.io/plutonium-core](https://radioactive-labs.github.io/plutonium-core/)**
|
|
@@ -97,18 +123,14 @@ Full documentation at **[radioactive-labs.github.io/plutonium-core](https://radi
|
|
|
97
123
|
|
|
98
124
|
## Requirements
|
|
99
125
|
|
|
100
|
-
- Ruby 3.2+
|
|
101
|
-
- Rails 7.
|
|
126
|
+
- Ruby 3.2.2+
|
|
127
|
+
- Rails 7.2+ (Rails 8 recommended)
|
|
102
128
|
- Node.js 18+
|
|
103
129
|
|
|
104
130
|
## Contributing
|
|
105
131
|
|
|
106
132
|
See [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and guidelines.
|
|
107
133
|
|
|
108
|
-
## Status
|
|
109
|
-
|
|
110
|
-
Plutonium is used in production but still evolving. APIs may change between minor versions. Pin your version in Gemfile.
|
|
111
|
-
|
|
112
134
|
## License
|
|
113
135
|
|
|
114
|
-
MIT License
|
|
136
|
+
MIT License — see [LICENSE.txt](LICENSE.txt).
|