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.
- checksums.yaml +4 -4
- data/# Plutonium: The pre-alpha demo.md +4 -2
- data/.claude/skills/assets/SKILL.md +416 -0
- data/.claude/skills/connect-resource/SKILL.md +112 -0
- data/.claude/skills/controller/SKILL.md +302 -0
- data/.claude/skills/create-resource/SKILL.md +240 -0
- data/.claude/skills/definition/SKILL.md +218 -0
- data/.claude/skills/definition-actions/SKILL.md +386 -0
- data/.claude/skills/definition-fields/SKILL.md +474 -0
- data/.claude/skills/definition-query/SKILL.md +334 -0
- data/.claude/skills/forms/SKILL.md +439 -0
- data/.claude/skills/installation/SKILL.md +300 -0
- data/.claude/skills/interaction/SKILL.md +382 -0
- data/.claude/skills/model/SKILL.md +267 -0
- data/.claude/skills/model-features/SKILL.md +286 -0
- data/.claude/skills/nested-resources/SKILL.md +274 -0
- data/.claude/skills/package/SKILL.md +191 -0
- data/.claude/skills/policy/SKILL.md +352 -0
- data/.claude/skills/portal/SKILL.md +400 -0
- data/.claude/skills/resource/SKILL.md +281 -0
- data/.claude/skills/rodauth/SKILL.md +452 -0
- data/.claude/skills/views/SKILL.md +563 -0
- data/Appraisals +46 -4
- data/CHANGELOG.md +32 -1
- data/app/assets/plutonium.css +2 -2
- data/config/brakeman.ignore +239 -0
- data/config/initializers/action_policy.rb +1 -1
- data/docs/.vitepress/config.ts +132 -47
- data/docs/concepts/architecture.md +226 -0
- data/docs/concepts/auto-detection.md +254 -0
- data/docs/concepts/index.md +61 -0
- data/docs/concepts/packages-portals.md +304 -0
- data/docs/concepts/resources.md +224 -0
- data/docs/cookbook/blog.md +412 -0
- data/docs/cookbook/index.md +289 -0
- data/docs/cookbook/saas.md +481 -0
- data/docs/getting-started/index.md +56 -0
- data/docs/getting-started/installation.md +146 -0
- data/docs/getting-started/tutorial/01-setup.md +118 -0
- data/docs/getting-started/tutorial/02-first-resource.md +180 -0
- data/docs/getting-started/tutorial/03-authentication.md +246 -0
- data/docs/getting-started/tutorial/04-authorization.md +170 -0
- data/docs/getting-started/tutorial/05-custom-actions.md +202 -0
- data/docs/getting-started/tutorial/06-nested-resources.md +147 -0
- data/docs/getting-started/tutorial/07-customizing-ui.md +254 -0
- data/docs/getting-started/tutorial/index.md +64 -0
- data/docs/guides/adding-resources.md +420 -0
- data/docs/guides/authentication.md +551 -0
- data/docs/guides/authorization.md +468 -0
- data/docs/guides/creating-packages.md +380 -0
- data/docs/guides/custom-actions.md +523 -0
- data/docs/guides/index.md +45 -0
- data/docs/guides/multi-tenancy.md +302 -0
- data/docs/guides/nested-resources.md +411 -0
- data/docs/guides/search-filtering.md +266 -0
- data/docs/guides/theming.md +321 -0
- data/docs/index.md +67 -26
- data/docs/public/CLAUDE.md +64 -21
- data/docs/reference/assets/index.md +496 -0
- data/docs/reference/controller/index.md +363 -0
- data/docs/reference/definition/actions.md +400 -0
- data/docs/reference/definition/fields.md +350 -0
- data/docs/reference/definition/index.md +252 -0
- data/docs/reference/definition/query.md +342 -0
- data/docs/reference/generators/index.md +469 -0
- data/docs/reference/index.md +49 -0
- data/docs/reference/interaction/index.md +445 -0
- data/docs/reference/model/features.md +248 -0
- data/docs/reference/model/index.md +219 -0
- data/docs/reference/policy/index.md +385 -0
- data/docs/reference/portal/index.md +382 -0
- data/docs/reference/views/forms.md +396 -0
- data/docs/reference/views/index.md +479 -0
- data/gemfiles/rails_7.gemfile +9 -2
- data/gemfiles/rails_7.gemfile.lock +146 -111
- data/gemfiles/rails_8.0.gemfile +20 -0
- data/gemfiles/rails_8.0.gemfile.lock +417 -0
- data/gemfiles/rails_8.1.gemfile +20 -0
- data/gemfiles/rails_8.1.gemfile.lock +419 -0
- data/lib/generators/pu/gem/dotenv/templates/.env +2 -0
- data/lib/generators/pu/gem/dotenv/templates/config/initializers/001_ensure_required_env.rb +3 -1
- data/lib/generators/pu/lib/plutonium_generators/model_generator_base.rb +13 -16
- data/lib/generators/pu/pkg/portal/USAGE +65 -0
- data/lib/generators/pu/pkg/portal/portal_generator.rb +22 -9
- data/lib/generators/pu/res/conn/USAGE +71 -0
- data/lib/generators/pu/res/model/USAGE +106 -110
- data/lib/generators/pu/res/model/templates/model.rb.tt +6 -2
- data/lib/generators/pu/res/scaffold/USAGE +85 -0
- data/lib/generators/pu/rodauth/install_generator.rb +2 -6
- data/lib/generators/pu/rodauth/templates/config/initializers/url_options.rb +17 -0
- data/lib/generators/pu/skills/sync/USAGE +14 -0
- data/lib/generators/pu/skills/sync/sync_generator.rb +66 -0
- data/lib/plutonium/action_policy/sti_policy_lookup.rb +1 -1
- data/lib/plutonium/core/controller.rb +2 -2
- data/lib/plutonium/interaction/base.rb +1 -0
- data/lib/plutonium/package/engine.rb +2 -2
- data/lib/plutonium/query/adhoc_block.rb +6 -2
- data/lib/plutonium/query/model_scope.rb +1 -1
- data/lib/plutonium/railtie.rb +4 -0
- data/lib/plutonium/resource/controllers/crud_actions/index_action.rb +1 -1
- data/lib/plutonium/resource/query_object.rb +38 -8
- data/lib/plutonium/ui/table/components/scopes_bar.rb +39 -34
- data/lib/plutonium/version.rb +1 -1
- data/lib/tasks/release.rake +19 -4
- data/package.json +1 -1
- metadata +76 -39
- data/brakeman.ignore +0 -28
- data/docs/api-examples.md +0 -49
- data/docs/guide/claude-code-guide.md +0 -74
- data/docs/guide/deep-dive/authorization.md +0 -189
- data/docs/guide/deep-dive/multitenancy.md +0 -256
- data/docs/guide/deep-dive/resources.md +0 -390
- data/docs/guide/getting-started/01-installation.md +0 -165
- data/docs/guide/index.md +0 -28
- data/docs/guide/introduction/01-what-is-plutonium.md +0 -211
- data/docs/guide/introduction/02-core-concepts.md +0 -440
- data/docs/guide/tutorial/01-project-setup.md +0 -75
- data/docs/guide/tutorial/02-creating-a-feature-package.md +0 -45
- data/docs/guide/tutorial/03-defining-resources.md +0 -90
- data/docs/guide/tutorial/04-creating-a-portal.md +0 -101
- data/docs/guide/tutorial/05-customizing-the-ui.md +0 -128
- data/docs/guide/tutorial/06-adding-custom-actions.md +0 -101
- data/docs/guide/tutorial/07-implementing-authorization.md +0 -90
- data/docs/markdown-examples.md +0 -85
- data/docs/modules/action.md +0 -244
- data/docs/modules/authentication.md +0 -236
- data/docs/modules/configuration.md +0 -599
- data/docs/modules/controller.md +0 -443
- data/docs/modules/core.md +0 -316
- data/docs/modules/definition.md +0 -1308
- data/docs/modules/display.md +0 -759
- data/docs/modules/form.md +0 -495
- data/docs/modules/generator.md +0 -400
- data/docs/modules/index.md +0 -167
- data/docs/modules/interaction.md +0 -642
- data/docs/modules/package.md +0 -151
- data/docs/modules/policy.md +0 -176
- data/docs/modules/portal.md +0 -710
- data/docs/modules/query.md +0 -297
- data/docs/modules/resource_record.md +0 -618
- data/docs/modules/routing.md +0 -690
- data/docs/modules/table.md +0 -301
- 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)
|