@bluealba/platform-cli 1.0.1 → 1.1.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.
- package/dist/index.js +278 -15
- package/docs/404.mdx +5 -0
- package/docs/architecture/api-explorer.mdx +478 -0
- package/docs/architecture/architecture-diagrams.mdx +12 -0
- package/docs/architecture/authentication-system.mdx +903 -0
- package/docs/architecture/authorization-system.mdx +886 -0
- package/docs/architecture/bootstrap.mdx +1442 -0
- package/docs/architecture/gateway-architecture.mdx +845 -0
- package/docs/architecture/multi-tenancy.mdx +1150 -0
- package/docs/architecture/overview.mdx +776 -0
- package/docs/architecture/scheduler.mdx +818 -0
- package/docs/architecture/shell.mdx +885 -0
- package/docs/architecture/ui-extension-points.mdx +781 -0
- package/docs/architecture/user-states.mdx +794 -0
- package/docs/development/overview.mdx +21 -0
- package/docs/development/workflow.mdx +914 -0
- package/docs/getting-started/core-concepts.mdx +892 -0
- package/docs/getting-started/installation.mdx +780 -0
- package/docs/getting-started/overview.mdx +83 -0
- package/docs/getting-started/quick-start.mdx +940 -0
- package/docs/guides/adding-documentation-sites.mdx +1367 -0
- package/docs/guides/creating-services.mdx +1736 -0
- package/docs/guides/creating-ui-modules.mdx +1860 -0
- package/docs/guides/identity-providers.mdx +1007 -0
- package/docs/guides/mermaid-diagrams.mdx +212 -0
- package/docs/guides/using-feature-flags.mdx +1059 -0
- package/docs/guides/working-with-rooms.mdx +566 -0
- package/docs/index.mdx +57 -0
- package/docs/platform-cli/commands.mdx +604 -0
- package/docs/platform-cli/overview.mdx +195 -0
- package/package.json +5 -2
- package/skills/ba-platform/platform-cli.skill.md +26 -0
- package/skills/ba-platform/platform.skill.md +35 -0
- package/templates/application-monorepo-template/gitignore +95 -0
- package/templates/bootstrap-service-template/Dockerfile.development +1 -1
- package/templates/bootstrap-service-template/gitignore +57 -0
- package/templates/bootstrap-service-template/package.json +1 -1
- package/templates/bootstrap-service-template/src/main.ts +6 -16
- package/templates/customization-ui-module-template/Dockerfile.development +1 -1
- package/templates/customization-ui-module-template/gitignore +73 -0
- package/templates/nestjs-service-module-template/Dockerfile.development +1 -1
- package/templates/nestjs-service-module-template/gitignore +56 -0
- package/templates/platform-init-template/{{platformName}}-core/gitignore +97 -0
- package/templates/platform-init-template/{{platformName}}-core/local/.env.example +1 -1
- package/templates/platform-init-template/{{platformName}}-core/local/platform-docker-compose.yml +1 -1
- package/templates/platform-init-template/{{platformName}}-core/local/{{platformName}}-core-docker-compose.yml +0 -1
- package/templates/react-ui-module-template/Dockerfile +1 -1
- package/templates/react-ui-module-template/Dockerfile.development +1 -3
- package/templates/react-ui-module-template/caddy/Caddyfile +1 -1
- package/templates/react-ui-module-template/gitignore +72 -0
- package/templates/react-ui-module-template/Dockerfile_nginx +0 -11
- package/templates/react-ui-module-template/nginx/default.conf +0 -23
|
@@ -0,0 +1,892 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Core Concepts
|
|
3
|
+
description: Essential concepts of the Blue Alba Platform - Applications, Modules, Operations, Roles, Rules, Tenants, and Catalog
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
import { Card, CardGrid, Aside, Tabs, TabItem } from '@astrojs/starlight/components';
|
|
7
|
+
|
|
8
|
+
Understanding these core concepts is essential for working effectively with the Blue Alba Platform. These building blocks form the foundation of the platform's architecture and authorization system.
|
|
9
|
+
|
|
10
|
+
## Platform Building Blocks
|
|
11
|
+
|
|
12
|
+
<CardGrid stagger>
|
|
13
|
+
<Card title="Applications" icon="seti:folder">
|
|
14
|
+
Logical groupings of related functionality that users interact with. Examples: "Customer Portal", "Admin Console", "Analytics Dashboard".
|
|
15
|
+
</Card>
|
|
16
|
+
|
|
17
|
+
<Card title="Modules" icon="puzzle">
|
|
18
|
+
Deployable units of code - either a backend service or frontend UI. Modules belong to Applications and can be shared across them.
|
|
19
|
+
</Card>
|
|
20
|
+
|
|
21
|
+
<Card title="Operations" icon="approve-check">
|
|
22
|
+
The most granular level of permissions. Every action a user can perform (read, write, delete, approve) is an Operation.
|
|
23
|
+
</Card>
|
|
24
|
+
|
|
25
|
+
<Card title="Roles" icon="seti:config">
|
|
26
|
+
Collections of Operations that define what a user can do. Examples: "Admin", "Viewer", "Editor".
|
|
27
|
+
</Card>
|
|
28
|
+
|
|
29
|
+
<Card title="Rules" icon="seti:license">
|
|
30
|
+
Authorization logic that allows or denies Operations based on conditions. Rules implement business authorization logic.
|
|
31
|
+
</Card>
|
|
32
|
+
|
|
33
|
+
<Card title="Tenants" icon="codeberg">
|
|
34
|
+
Isolated instances of the platform for different customers or organizations. Each tenant has separate data, users, and configurations.
|
|
35
|
+
</Card>
|
|
36
|
+
|
|
37
|
+
<Card title="Catalog" icon="open-book">
|
|
38
|
+
Dynamic registry of Applications and Modules that enables runtime discovery and routing of services.
|
|
39
|
+
</Card>
|
|
40
|
+
|
|
41
|
+
<Card title="Platform Context" icon="seti:json">
|
|
42
|
+
Request-scoped information about the current tenant, user, and application being accessed.
|
|
43
|
+
</Card>
|
|
44
|
+
</CardGrid>
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Applications
|
|
49
|
+
|
|
50
|
+
**Applications** are the highest-level organizational concept in the platform. They represent logical groupings of functionality that make sense to end users.
|
|
51
|
+
|
|
52
|
+
### What is an Application?
|
|
53
|
+
|
|
54
|
+
An Application is:
|
|
55
|
+
- A **named collection** of related features (e.g., "Customer Portal", "Administration")
|
|
56
|
+
- A **logical grouping** of one or more Modules (UIs and services)
|
|
57
|
+
- A **unit of access control** - users are granted access to Applications
|
|
58
|
+
- An **entry point** in the navigation menu
|
|
59
|
+
|
|
60
|
+
### Application Structure
|
|
61
|
+
|
|
62
|
+
```typescript
|
|
63
|
+
interface Application {
|
|
64
|
+
id: string;
|
|
65
|
+
name: string; // Unique identifier (e.g., "admin-portal")
|
|
66
|
+
displayName: string;
|
|
67
|
+
description: string;
|
|
68
|
+
modules: Module[]; // Associated modules
|
|
69
|
+
allowedByDefault: boolean; // Application visible to all users without manual assignment
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### Example Applications
|
|
74
|
+
|
|
75
|
+
<Tabs>
|
|
76
|
+
<TabItem label="Administration">
|
|
77
|
+
**Application**: Platform Administration
|
|
78
|
+
|
|
79
|
+
**Purpose**: Manage users, roles, applications, and platform configuration
|
|
80
|
+
|
|
81
|
+
**Modules**:
|
|
82
|
+
- Admin UI (frontend)
|
|
83
|
+
- User Management Service (backend)
|
|
84
|
+
- Application Catalog Service (backend)
|
|
85
|
+
</TabItem>
|
|
86
|
+
|
|
87
|
+
<TabItem label="Customer Portal">
|
|
88
|
+
**Application**: Customer Self-Service Portal
|
|
89
|
+
|
|
90
|
+
**Purpose**: Allow customers to view orders, submit tickets, manage profile
|
|
91
|
+
|
|
92
|
+
**Modules**:
|
|
93
|
+
- Customer Portal UI (frontend)
|
|
94
|
+
- Orders Service (backend)
|
|
95
|
+
- Ticketing Service (backend)
|
|
96
|
+
</TabItem>
|
|
97
|
+
|
|
98
|
+
<TabItem label="Analytics">
|
|
99
|
+
**Application**: Analytics Dashboard
|
|
100
|
+
|
|
101
|
+
**Purpose**: View business metrics and reports
|
|
102
|
+
|
|
103
|
+
**Modules**:
|
|
104
|
+
- Analytics UI (frontend)
|
|
105
|
+
- Reporting Service (backend)
|
|
106
|
+
</TabItem>
|
|
107
|
+
</Tabs>
|
|
108
|
+
|
|
109
|
+
<Aside type="tip">
|
|
110
|
+
Think of Applications as the items you see in the main navigation menu. Each Application groups related features that users access together.
|
|
111
|
+
</Aside>
|
|
112
|
+
|
|
113
|
+
---
|
|
114
|
+
|
|
115
|
+
## Modules
|
|
116
|
+
|
|
117
|
+
**Modules** are the deployable units of code - the actual services and UIs that make up your platform.
|
|
118
|
+
|
|
119
|
+
### What is a Module?
|
|
120
|
+
|
|
121
|
+
A Module is:
|
|
122
|
+
- A **deployable artifact** (a service or UI application)
|
|
123
|
+
- Either a **backend service** (microservice) or **frontend UI** (micro-frontend)
|
|
124
|
+
- A **registered entity** in the application catalog
|
|
125
|
+
- A **route target** that the gateway can proxy to
|
|
126
|
+
|
|
127
|
+
### Module Types
|
|
128
|
+
|
|
129
|
+
There are six types of modules:
|
|
130
|
+
|
|
131
|
+
**UI Modules** (Frontend) [app]
|
|
132
|
+
- React-based micro-frontends
|
|
133
|
+
- Loaded dynamically by the Shell UI
|
|
134
|
+
- Built with `pae-ui-react-sdk`
|
|
135
|
+
- Examples: Customer Portal UI, CRM UI
|
|
136
|
+
|
|
137
|
+
**Tool Modules** (Frontend) [tool]
|
|
138
|
+
- React-based micro-frontends that provide platform utilities and administration features
|
|
139
|
+
- Appear in the navbar tools section rather than the application selector
|
|
140
|
+
- Built with `pae-ui-react-sdk`
|
|
141
|
+
- Examples: Admin UI, Documentation UI
|
|
142
|
+
|
|
143
|
+
**Service Modules** (Backend) [service]
|
|
144
|
+
- NestJS or Express-based microservices
|
|
145
|
+
- Registered with the gateway
|
|
146
|
+
- Handle business logic and data persistence
|
|
147
|
+
- Examples: Habits Service, Scheduler Service
|
|
148
|
+
|
|
149
|
+
**Utility** (Frontend) [utility]
|
|
150
|
+
- React-based micro-frontends
|
|
151
|
+
- It is loaded by the browser but is not mounted on a DOM element.
|
|
152
|
+
- Provides reusable elements such as components, styles, and utility functions.
|
|
153
|
+
- Examples: pae-ui-react-core
|
|
154
|
+
|
|
155
|
+
**Cloud Function** (Backend) [cloud-function]
|
|
156
|
+
- Support for running serverless functions
|
|
157
|
+
|
|
158
|
+
**Documentation Modules** (Documentation) [documentation]
|
|
159
|
+
- Documentation sites created using the [Blue Alba Platform Documentation Template](/_/docs/guides/adding-documentation-sites/).
|
|
160
|
+
|
|
161
|
+
### Module Structure
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
interface Module {
|
|
165
|
+
name: string; // Unique identifier
|
|
166
|
+
displayName: string;
|
|
167
|
+
description: string;
|
|
168
|
+
type: 'app' | 'tool' | 'service' | 'utility' | 'cloud-function' | 'documentation'; // Module type
|
|
169
|
+
|
|
170
|
+
applicationId: string; // Parent application
|
|
171
|
+
baseUrl: string;
|
|
172
|
+
host: string;
|
|
173
|
+
port: number;
|
|
174
|
+
|
|
175
|
+
dependsOn: string[];
|
|
176
|
+
|
|
177
|
+
// Only for 'app' and 'tool' types
|
|
178
|
+
ui: {
|
|
179
|
+
"route": string;
|
|
180
|
+
"mountAtSelector": "#pae-shell-ui-content",
|
|
181
|
+
"bundleFile": string; // file path
|
|
182
|
+
"customProps": {}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
authorization: {
|
|
186
|
+
"operations": string[];
|
|
187
|
+
"routes": {}
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
### Module Registration
|
|
194
|
+
|
|
195
|
+
Modules register themselves with the gateway's catalog on startup:
|
|
196
|
+
|
|
197
|
+
<Tabs>
|
|
198
|
+
<TabItem label="Service Module">
|
|
199
|
+
```typescript
|
|
200
|
+
// In a backend service
|
|
201
|
+
const module = {
|
|
202
|
+
code: 'habits-service',
|
|
203
|
+
name: 'Habits Tracking Service',
|
|
204
|
+
type: 'SERVICE',
|
|
205
|
+
applicationId: 'habits-app',
|
|
206
|
+
serviceUrl: 'http://pae-habits-service:4002',
|
|
207
|
+
routes: [
|
|
208
|
+
{ path: '/habits', method: 'GET' },
|
|
209
|
+
{ path: '/habits/:id', method: 'GET' },
|
|
210
|
+
{ path: '/habits', method: 'POST' }
|
|
211
|
+
]
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
// Register with catalog
|
|
215
|
+
await catalogClient.registerModule(module);
|
|
216
|
+
```
|
|
217
|
+
</TabItem>
|
|
218
|
+
|
|
219
|
+
<TabItem label="UI Module">
|
|
220
|
+
```typescript
|
|
221
|
+
// In a frontend UI
|
|
222
|
+
const module = {
|
|
223
|
+
code: 'habits-ui',
|
|
224
|
+
name: 'Habits UI',
|
|
225
|
+
type: 'UI',
|
|
226
|
+
applicationId: 'habits-app',
|
|
227
|
+
entryPoint: 'http://localhost:8081/main.js',
|
|
228
|
+
containerElement: '#habits-app-container'
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
// Register with catalog
|
|
232
|
+
await catalogClient.registerModule(module);
|
|
233
|
+
```
|
|
234
|
+
</TabItem>
|
|
235
|
+
|
|
236
|
+
<TabItem label="Documentation Module">
|
|
237
|
+
```typescript
|
|
238
|
+
// In a documentation service
|
|
239
|
+
const module = {
|
|
240
|
+
code: 'app-documentation',
|
|
241
|
+
name: 'App Documentation',
|
|
242
|
+
type: 'DOCUMENTATION',
|
|
243
|
+
applicationId: 'app-documentation',
|
|
244
|
+
baseUrl: '/app/docs',
|
|
245
|
+
routes: [
|
|
246
|
+
{ path: '/habits', method: 'GET' },
|
|
247
|
+
{ path: '/habits/:id', method: 'GET' },
|
|
248
|
+
{ path: '/habits', method: 'POST' }
|
|
249
|
+
],
|
|
250
|
+
service: {
|
|
251
|
+
host: "pae-sandbox-documentation",
|
|
252
|
+
port: 80
|
|
253
|
+
},
|
|
254
|
+
dependsOn: [
|
|
255
|
+
"@bluealba/pae-shell-ui"
|
|
256
|
+
]
|
|
257
|
+
};
|
|
258
|
+
|
|
259
|
+
// Register with catalog
|
|
260
|
+
await catalogClient.registerModule(module);
|
|
261
|
+
```
|
|
262
|
+
</TabItem>
|
|
263
|
+
</Tabs>
|
|
264
|
+
|
|
265
|
+
---
|
|
266
|
+
|
|
267
|
+
## Operations
|
|
268
|
+
|
|
269
|
+
**Operations** represent the most granular level of permissions in the platform. Every action that requires authorization is an Operation.
|
|
270
|
+
|
|
271
|
+
### What is an Operation?
|
|
272
|
+
|
|
273
|
+
An Operation is:
|
|
274
|
+
- A **specific permission** (e.g., "users.read", "orders.create", "reports.delete")
|
|
275
|
+
- The **smallest unit** of authorization
|
|
276
|
+
- A **building block** for Roles
|
|
277
|
+
- Typically **verb-based** (read, write, update, delete, approve, etc.)
|
|
278
|
+
|
|
279
|
+
### Operation Naming Convention
|
|
280
|
+
|
|
281
|
+
Operations follow a hierarchical naming pattern using double colons (::):
|
|
282
|
+
|
|
283
|
+
```
|
|
284
|
+
{domain}::{resource}::{action}[.{modifier}]
|
|
285
|
+
|
|
286
|
+
#### Structure
|
|
287
|
+
|
|
288
|
+
- **domain**: Functional area of the system (e.g., authorization, authentication, documentation)
|
|
289
|
+
- **resource**: Specific entity within the domain (e.g., role, auth-methods, impersonation)
|
|
290
|
+
- **action**: Operation to perform (e.g., delete, manage, read, config)
|
|
291
|
+
- **modifier (optional)**: Additional qualifier to specify scope or context
|
|
292
|
+
|
|
293
|
+
Examples:
|
|
294
|
+
- `authorization::role::delete` - Delete roles from the authorization system
|
|
295
|
+
- `authorization::role::manage-operations` - Manage operations assigned to specific roles
|
|
296
|
+
- `documentation::access` - Access system documentation
|
|
297
|
+
|
|
298
|
+
### Operation Structure
|
|
299
|
+
|
|
300
|
+
```typescript
|
|
301
|
+
interface Operation {
|
|
302
|
+
id: string;
|
|
303
|
+
name: string; // e.g., "users::read"
|
|
304
|
+
description: string;
|
|
305
|
+
applicationId: string; // Which app this belongs to
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Using Operations in Code
|
|
310
|
+
|
|
311
|
+
Operations are checked throughout the platform:
|
|
312
|
+
|
|
313
|
+
<Tabs>
|
|
314
|
+
<TabItem label="Frontend (React)">
|
|
315
|
+
```typescript
|
|
316
|
+
import { useAuth } from '@bluealba/pae-ui-react-core';
|
|
317
|
+
|
|
318
|
+
function UserManagement() {
|
|
319
|
+
const { hasAccess } = useAuth();
|
|
320
|
+
|
|
321
|
+
const canRead = hasAccess('users.read');
|
|
322
|
+
const canWrite = hasAccess('users.write');
|
|
323
|
+
const canDelete = hasAccess('users.delete');
|
|
324
|
+
|
|
325
|
+
return (
|
|
326
|
+
<div>
|
|
327
|
+
{canRead && <UserList />}
|
|
328
|
+
{canWrite && <CreateUserButton />}
|
|
329
|
+
{canDelete && <DeleteUserButton />}
|
|
330
|
+
</div>
|
|
331
|
+
);
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
</TabItem>
|
|
335
|
+
</Tabs>
|
|
336
|
+
|
|
337
|
+
<Aside>
|
|
338
|
+
**Best Practice**: Define Operations at a granular level. It's easier to combine fine-grained Operations into Roles than to split coarse-grained ones later.
|
|
339
|
+
</Aside>
|
|
340
|
+
|
|
341
|
+
---
|
|
342
|
+
|
|
343
|
+
## Roles
|
|
344
|
+
|
|
345
|
+
**Roles** are collections of Operations that define what a user can do in the system.
|
|
346
|
+
|
|
347
|
+
### What is a Role?
|
|
348
|
+
|
|
349
|
+
A Role is:
|
|
350
|
+
- A **named collection** of Operations
|
|
351
|
+
- A **permission set** assigned to users
|
|
352
|
+
- A **template** for common access patterns
|
|
353
|
+
- **Reusable** across different users and groups
|
|
354
|
+
|
|
355
|
+
### Role Structure
|
|
356
|
+
|
|
357
|
+
```typescript
|
|
358
|
+
interface Role {
|
|
359
|
+
id: string;
|
|
360
|
+
name: string; // e.g., "admin", "viewer"
|
|
361
|
+
description: string;
|
|
362
|
+
applicationId: string; // Which app this role applies to
|
|
363
|
+
operations: Operation[]; // Granted operations
|
|
364
|
+
}
|
|
365
|
+
```
|
|
366
|
+
|
|
367
|
+
### Common Role Patterns
|
|
368
|
+
|
|
369
|
+
<CardGrid>
|
|
370
|
+
<Card title="Admin Role" icon="star">
|
|
371
|
+
**Operations**: All operations for an application
|
|
372
|
+
|
|
373
|
+
**Use Case**: System administrators who need full access
|
|
374
|
+
|
|
375
|
+
**Example**:
|
|
376
|
+
- `users::*` (all user operations)
|
|
377
|
+
- `orders::*` (all order operations)
|
|
378
|
+
- `settings::*` (all settings operations)
|
|
379
|
+
</Card>
|
|
380
|
+
|
|
381
|
+
<Card title="Viewer Role" icon="open-book">
|
|
382
|
+
**Operations**: Only read operations
|
|
383
|
+
|
|
384
|
+
**Use Case**: Users who need to view data but not modify it
|
|
385
|
+
|
|
386
|
+
**Example**:
|
|
387
|
+
- `users::read`
|
|
388
|
+
- `orders::read`
|
|
389
|
+
- `reports::read`
|
|
390
|
+
</Card>
|
|
391
|
+
|
|
392
|
+
<Card title="Editor Role" icon="pencil">
|
|
393
|
+
**Operations**: Read and write operations (but not delete)
|
|
394
|
+
|
|
395
|
+
**Use Case**: Users who can create and update data
|
|
396
|
+
|
|
397
|
+
**Example**:
|
|
398
|
+
- `users::read`
|
|
399
|
+
- `users::write`
|
|
400
|
+
- `orders::read`
|
|
401
|
+
- `orders::write`
|
|
402
|
+
</Card>
|
|
403
|
+
|
|
404
|
+
<Card title="Custom Role" icon="setting">
|
|
405
|
+
**Operations**: Specific subset for business needs
|
|
406
|
+
|
|
407
|
+
**Use Case**: Specialized roles for unique workflows
|
|
408
|
+
|
|
409
|
+
**Example** (Approver):
|
|
410
|
+
- `orders::read`
|
|
411
|
+
- `orders::approve`
|
|
412
|
+
- `orders::reject`
|
|
413
|
+
</Card>
|
|
414
|
+
</CardGrid>
|
|
415
|
+
|
|
416
|
+
### Role Assignment
|
|
417
|
+
|
|
418
|
+
Users receive Roles in two ways:
|
|
419
|
+
|
|
420
|
+
1. **Direct Assignment**: Role assigned directly to a user
|
|
421
|
+
2. **Group Membership**: User belongs to a Group that has the Role
|
|
422
|
+
|
|
423
|
+
```typescript
|
|
424
|
+
// Direct role assignment
|
|
425
|
+
await userService.assignRole(userId, roleId);
|
|
426
|
+
|
|
427
|
+
// Group-based assignment
|
|
428
|
+
await groupService.addMember(groupId, userId);
|
|
429
|
+
// User automatically gets all roles assigned to the group
|
|
430
|
+
```
|
|
431
|
+
|
|
432
|
+
<Aside type="tip">
|
|
433
|
+
**Best Practice**: Use Groups for role assignment rather than direct assignment. This makes managing permissions for many users much easier.
|
|
434
|
+
</Aside>
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## Rules
|
|
439
|
+
|
|
440
|
+
**Rules** are the mechanism that connects authorization concepts together by associating **Resources** with **Subjects**.
|
|
441
|
+
|
|
442
|
+
### What is a Rule?
|
|
443
|
+
|
|
444
|
+
A Rule is:
|
|
445
|
+
- The **association** between a Resource and a Subject
|
|
446
|
+
- A **grant or deny** decision for access
|
|
447
|
+
- The **building block** of the authorization system
|
|
448
|
+
- How the platform determines **who can access what**
|
|
449
|
+
|
|
450
|
+
### Key Concepts
|
|
451
|
+
|
|
452
|
+
#### Resources
|
|
453
|
+
|
|
454
|
+
A **Resource** is anything that can be protected by authorization. In the platform, there are three types of Resources:
|
|
455
|
+
|
|
456
|
+
<CardGrid>
|
|
457
|
+
<Card title="Operations" icon="approve-check">
|
|
458
|
+
The most granular resource - a specific permission or action (e.g., `users::read`, `orders::delete`)
|
|
459
|
+
</Card>
|
|
460
|
+
|
|
461
|
+
<Card title="Roles" icon="seti:config">
|
|
462
|
+
A collection of Operations grouped together (e.g., "admin", "viewer")
|
|
463
|
+
</Card>
|
|
464
|
+
|
|
465
|
+
<Card title="Applications" icon="seti:folder">
|
|
466
|
+
A logical grouping of functionality (e.g., "platform", "customer-portal")
|
|
467
|
+
</Card>
|
|
468
|
+
</CardGrid>
|
|
469
|
+
|
|
470
|
+
<Aside type="note">
|
|
471
|
+
You can grant or deny access to any of these three resource types: **Operations**, **Roles**, or **Applications**.
|
|
472
|
+
</Aside>
|
|
473
|
+
|
|
474
|
+
#### Subjects
|
|
475
|
+
|
|
476
|
+
A **Subject** is the target to which access is granted or denied. There are two types of Subjects:
|
|
477
|
+
|
|
478
|
+
<Tabs>
|
|
479
|
+
<TabItem label="User">
|
|
480
|
+
**User**: A specific individual identified by the Identity Provider
|
|
481
|
+
|
|
482
|
+
```json
|
|
483
|
+
{
|
|
484
|
+
"subjectType": "user",
|
|
485
|
+
"subject": "john.doe@company.com",
|
|
486
|
+
"resourceType": "operation",
|
|
487
|
+
"resource": "orders::read",
|
|
488
|
+
"denied": false
|
|
489
|
+
}
|
|
490
|
+
```
|
|
491
|
+
|
|
492
|
+
The `subject` field contains the user's identifier (typically their email from the Identity Provider).
|
|
493
|
+
|
|
494
|
+
**Use Case**: Give John Doe access to read orders
|
|
495
|
+
</TabItem>
|
|
496
|
+
|
|
497
|
+
<TabItem label="Group">
|
|
498
|
+
**Group**: Users belonging to a group from the Identity Provider
|
|
499
|
+
|
|
500
|
+
```json
|
|
501
|
+
{
|
|
502
|
+
"subjectType": "group",
|
|
503
|
+
"subject": "sales-team",
|
|
504
|
+
"resourceType": "application",
|
|
505
|
+
"resource": "reports-app",
|
|
506
|
+
"denied": false
|
|
507
|
+
}
|
|
508
|
+
```
|
|
509
|
+
|
|
510
|
+
The `subject` field contains the group identifier from the Identity Provider.
|
|
511
|
+
|
|
512
|
+
**Use Case**: Give all members of the Sales Team group access to the Reports application
|
|
513
|
+
</TabItem>
|
|
514
|
+
</Tabs>
|
|
515
|
+
|
|
516
|
+
### Rule Structure
|
|
517
|
+
|
|
518
|
+
A Rule has the following structure:
|
|
519
|
+
|
|
520
|
+
```typescript
|
|
521
|
+
interface Rule {
|
|
522
|
+
// Subject: Who is this rule for?
|
|
523
|
+
subjectType: 'user' | 'group';
|
|
524
|
+
subject: string; // User email or group identifier
|
|
525
|
+
|
|
526
|
+
// Resource: What are they getting access to?
|
|
527
|
+
resourceType: 'operation' | 'role' | 'application';
|
|
528
|
+
resource: string; // Resource identifier
|
|
529
|
+
|
|
530
|
+
// Effect: Grant or deny?
|
|
531
|
+
denied: boolean; // false = ALLOW, true = DENY
|
|
532
|
+
|
|
533
|
+
// Tenant scope
|
|
534
|
+
tenantId?: number; // null = global (applies to all tenants)
|
|
535
|
+
}
|
|
536
|
+
```
|
|
537
|
+
|
|
538
|
+
**Field Descriptions:**
|
|
539
|
+
|
|
540
|
+
| Field | Type | Description | Example |
|
|
541
|
+
|-------|------|-------------|---------|
|
|
542
|
+
| `subjectType` | `"user"` \| `"group"` | Type of subject | `"user"` |
|
|
543
|
+
| `subject` | `string` | User email or group name | `"juan.bruno@bluealba.com"` |
|
|
544
|
+
| `resourceType` | `"operation"` \| `"role"` \| `"application"` | Type of resource | `"application"` |
|
|
545
|
+
| `resource` | `string` | Resource identifier | `"platform"` |
|
|
546
|
+
| `denied` | `boolean` | `false` = ALLOW, `true` = DENY | `false` |
|
|
547
|
+
| `tenantId` | `number` \| `null` | Tenant scope. `null` = global (all tenants) | `1` |
|
|
548
|
+
|
|
549
|
+
### Tenant-Scoped vs Global Rules
|
|
550
|
+
|
|
551
|
+
Rules can be either **tenant-scoped** or **global**:
|
|
552
|
+
|
|
553
|
+
- **Tenant-scoped** (`tenantId` is set): The rule only applies within that specific tenant. Rules created from the Admin UI are always scoped to the current tenant.
|
|
554
|
+
- **Global** (`tenantId` is `null`): The rule applies across all tenants. In the Admin UI, these are displayed with a "Global" badge.
|
|
555
|
+
|
|
556
|
+
<Aside type="note">
|
|
557
|
+
When deleting a global rule from the Admin UI, a confirmation dialog warns that the deletion will affect all tenants.
|
|
558
|
+
</Aside>
|
|
559
|
+
|
|
560
|
+
### How Rules Work
|
|
561
|
+
|
|
562
|
+
Rules create associations between Subjects and Resources:
|
|
563
|
+
|
|
564
|
+
```
|
|
565
|
+
Subject + Resource + Effect = Rule
|
|
566
|
+
|
|
567
|
+
Examples:
|
|
568
|
+
- User "john@company.com" + Operation "orders::read" + ALLOW
|
|
569
|
+
→ John can read orders
|
|
570
|
+
|
|
571
|
+
- Group "admins" + Application "admin-portal" + ALLOW
|
|
572
|
+
→ All admin group members can access Admin Portal
|
|
573
|
+
|
|
574
|
+
- User "temp@company.com" + Role "admin" + DENY
|
|
575
|
+
→ Temp user explicitly cannot have admin role (even if assigned)
|
|
576
|
+
```
|
|
577
|
+
|
|
578
|
+
### Rule Examples
|
|
579
|
+
|
|
580
|
+
<Tabs>
|
|
581
|
+
<TabItem label="User → Operation">
|
|
582
|
+
**Grant a user access to a specific operation**
|
|
583
|
+
|
|
584
|
+
```json
|
|
585
|
+
{
|
|
586
|
+
"subjectType": "user",
|
|
587
|
+
"subject": "developer@company.com",
|
|
588
|
+
"resourceType": "operation",
|
|
589
|
+
"resource": "users::delete",
|
|
590
|
+
"denied": false
|
|
591
|
+
}
|
|
592
|
+
```
|
|
593
|
+
|
|
594
|
+
**Result**: User `developer@company.com` can delete users
|
|
595
|
+
</TabItem>
|
|
596
|
+
|
|
597
|
+
<TabItem label="Group → Application">
|
|
598
|
+
**Grant a group access to an application**
|
|
599
|
+
|
|
600
|
+
```json
|
|
601
|
+
{
|
|
602
|
+
"subjectType": "group",
|
|
603
|
+
"subject": "engineering",
|
|
604
|
+
"resourceType": "application",
|
|
605
|
+
"resource": "developer-portal",
|
|
606
|
+
"denied": false
|
|
607
|
+
}
|
|
608
|
+
```
|
|
609
|
+
|
|
610
|
+
**Result**: All users in the `engineering` group can access the Developer Portal
|
|
611
|
+
</TabItem>
|
|
612
|
+
|
|
613
|
+
<TabItem label="User → Role">
|
|
614
|
+
**Assign a role to a user**
|
|
615
|
+
|
|
616
|
+
```json
|
|
617
|
+
{
|
|
618
|
+
"subjectType": "user",
|
|
619
|
+
"subject": "admin@company.com",
|
|
620
|
+
"resourceType": "role",
|
|
621
|
+
"resource": "platform-admin",
|
|
622
|
+
"denied": false
|
|
623
|
+
}
|
|
624
|
+
```
|
|
625
|
+
|
|
626
|
+
**Result**: User `admin@company.com` gets the `platform-admin` role and all its operations
|
|
627
|
+
</TabItem>
|
|
628
|
+
|
|
629
|
+
<TabItem label="Deny Rule">
|
|
630
|
+
**Explicitly deny access**
|
|
631
|
+
|
|
632
|
+
```json
|
|
633
|
+
{
|
|
634
|
+
"subjectType": "user",
|
|
635
|
+
"subject": "contractor@company.com",
|
|
636
|
+
"resourceType": "operation",
|
|
637
|
+
"resource": "sensitive::access",
|
|
638
|
+
"denied": true
|
|
639
|
+
}
|
|
640
|
+
```
|
|
641
|
+
|
|
642
|
+
**Result**: User `contractor@company.com` cannot access sensitive data (even if their role grants it)
|
|
643
|
+
</TabItem>
|
|
644
|
+
|
|
645
|
+
<TabItem label="Group → Role">
|
|
646
|
+
**Assign a role to all members of a group**
|
|
647
|
+
|
|
648
|
+
```json
|
|
649
|
+
{
|
|
650
|
+
"subjectType": "group",
|
|
651
|
+
"subject": "support-team",
|
|
652
|
+
"resourceType": "role",
|
|
653
|
+
"resource": "customer-support",
|
|
654
|
+
"denied": false
|
|
655
|
+
}
|
|
656
|
+
```
|
|
657
|
+
|
|
658
|
+
**Result**: All users in the `support-team` group get the `customer-support` role
|
|
659
|
+
</TabItem>
|
|
660
|
+
</Tabs>
|
|
661
|
+
|
|
662
|
+
|
|
663
|
+
---
|
|
664
|
+
|
|
665
|
+
## Tenants
|
|
666
|
+
|
|
667
|
+
**Tenants** enable multi-tenancy - running a single instance of the platform for multiple customers or organizations with complete data isolation.
|
|
668
|
+
|
|
669
|
+
### What is a Tenant?
|
|
670
|
+
|
|
671
|
+
A Tenant is:
|
|
672
|
+
- An **isolated instance** of the platform
|
|
673
|
+
- A **customer or organization** using the platform
|
|
674
|
+
- The **top-level data boundary** for all resources
|
|
675
|
+
- A **context** that flows through every request
|
|
676
|
+
|
|
677
|
+
### Tenant Structure
|
|
678
|
+
|
|
679
|
+
```typescript
|
|
680
|
+
interface Tenant {
|
|
681
|
+
id: string;
|
|
682
|
+
code: string; // Unique identifier (e.g., "acme-corp")
|
|
683
|
+
name: string; // Display name
|
|
684
|
+
status: 'ACTIVE' | 'SUSPENDED' | 'DELETED';
|
|
685
|
+
|
|
686
|
+
// Configuration
|
|
687
|
+
settings?: Record<string, any>;
|
|
688
|
+
branding?: {
|
|
689
|
+
logo?: string;
|
|
690
|
+
primaryColor?: string;
|
|
691
|
+
secondaryColor?: string;
|
|
692
|
+
};
|
|
693
|
+
|
|
694
|
+
// Subscription info
|
|
695
|
+
plan?: string;
|
|
696
|
+
subscriptionStartDate?: Date;
|
|
697
|
+
subscriptionEndDate?: Date;
|
|
698
|
+
}
|
|
699
|
+
```
|
|
700
|
+
|
|
701
|
+
### Tenant Isolation
|
|
702
|
+
|
|
703
|
+
Every resource in the platform belongs to a tenant:
|
|
704
|
+
|
|
705
|
+
```typescript
|
|
706
|
+
// Users belong to tenants
|
|
707
|
+
interface User {
|
|
708
|
+
id: string;
|
|
709
|
+
tenantId: string; // Isolates users by tenant
|
|
710
|
+
email: string;
|
|
711
|
+
// ...
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
// Data belongs to tenants
|
|
715
|
+
interface Order {
|
|
716
|
+
id: string;
|
|
717
|
+
tenantId: string; // Isolates orders by tenant
|
|
718
|
+
customerId: string;
|
|
719
|
+
// ...
|
|
720
|
+
}
|
|
721
|
+
```
|
|
722
|
+
|
|
723
|
+
### Platform Context
|
|
724
|
+
|
|
725
|
+
The **Platform Context** carries tenant information through every request:
|
|
726
|
+
|
|
727
|
+
```typescript
|
|
728
|
+
interface PlatformContext {
|
|
729
|
+
tenantId: string; // Current tenant
|
|
730
|
+
userId: string; // Current user
|
|
731
|
+
applicationId?: string; // Current application
|
|
732
|
+
requestId: string; // Trace ID
|
|
733
|
+
}
|
|
734
|
+
```
|
|
735
|
+
|
|
736
|
+
The gateway extracts the tenant from:
|
|
737
|
+
1. **JWT token** (for authenticated users)
|
|
738
|
+
2. **API key** (for service-to-service calls)
|
|
739
|
+
3. **Subdomain** (e.g., `acme.platform.com`)
|
|
740
|
+
4. **Custom header** (for development)
|
|
741
|
+
|
|
742
|
+
### Tenant Isolation in Practice
|
|
743
|
+
|
|
744
|
+
<Tabs>
|
|
745
|
+
<TabItem label="Automatic (Recommended)">
|
|
746
|
+
Use the platform's built-in tenant context:
|
|
747
|
+
|
|
748
|
+
```typescript
|
|
749
|
+
// Backend service
|
|
750
|
+
@Injectable()
|
|
751
|
+
export class OrdersService {
|
|
752
|
+
async findAll(@PlatformContext() ctx: PlatformContext) {
|
|
753
|
+
// Automatically filters by ctx.tenantId
|
|
754
|
+
return this.ordersRepository.find({
|
|
755
|
+
where: { tenantId: ctx.tenantId }
|
|
756
|
+
});
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
```
|
|
760
|
+
</TabItem>
|
|
761
|
+
|
|
762
|
+
<TabItem label="Manual (Advanced)">
|
|
763
|
+
Explicitly handle tenant filtering:
|
|
764
|
+
|
|
765
|
+
```typescript
|
|
766
|
+
@Injectable()
|
|
767
|
+
export class OrdersService {
|
|
768
|
+
async findAll(tenantId: string) {
|
|
769
|
+
// Manual tenant filtering
|
|
770
|
+
return this.ordersRepository.find({
|
|
771
|
+
where: { tenantId }
|
|
772
|
+
});
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
```
|
|
776
|
+
</TabItem>
|
|
777
|
+
</Tabs>
|
|
778
|
+
|
|
779
|
+
<Aside type="caution" title="Critical">
|
|
780
|
+
**Always** filter data by `tenantId`. Failing to do so can expose data across tenant boundaries - a serious security issue.
|
|
781
|
+
</Aside>
|
|
782
|
+
|
|
783
|
+
---
|
|
784
|
+
|
|
785
|
+
## Catalog
|
|
786
|
+
|
|
787
|
+
The **Catalog** is the platform's dynamic registry of Applications and Modules.
|
|
788
|
+
|
|
789
|
+
### What is the Catalog?
|
|
790
|
+
|
|
791
|
+
The Catalog is:
|
|
792
|
+
- A **service registry** that tracks all services and UIs
|
|
793
|
+
- A **dynamic routing table** for the gateway
|
|
794
|
+
- A **discovery mechanism** for micro-frontends
|
|
795
|
+
- The **source of truth** for available applications
|
|
796
|
+
|
|
797
|
+
### How the Catalog Works
|
|
798
|
+
|
|
799
|
+
```mermaid
|
|
800
|
+
graph LR
|
|
801
|
+
A[Service Starts] --> B[Register with Catalog]
|
|
802
|
+
B --> C[Catalog Stores Metadata]
|
|
803
|
+
C --> D[Gateway Queries Catalog]
|
|
804
|
+
D --> E[Gateway Routes Requests]
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
1. **Registration**: Services and UIs register on startup
|
|
808
|
+
2. **Storage**: Catalog stores module metadata in database
|
|
809
|
+
3. **Discovery**: Gateway queries catalog for routing
|
|
810
|
+
4. **Routing**: Gateway proxies requests to appropriate service
|
|
811
|
+
|
|
812
|
+
### Catalog API
|
|
813
|
+
|
|
814
|
+
The catalog provides APIs for managing modules:
|
|
815
|
+
|
|
816
|
+
```typescript
|
|
817
|
+
// Register a module
|
|
818
|
+
POST /catalog/modules
|
|
819
|
+
{
|
|
820
|
+
"code": "habits-service",
|
|
821
|
+
"name": "Habits Service",
|
|
822
|
+
"type": "SERVICE",
|
|
823
|
+
"serviceUrl": "http://pae-habits-service:4002",
|
|
824
|
+
"routes": [...]
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
// Get all modules
|
|
828
|
+
GET /catalog/modules
|
|
829
|
+
|
|
830
|
+
// Get modules by application
|
|
831
|
+
GET /catalog/applications/{appId}/modules
|
|
832
|
+
|
|
833
|
+
// Unregister a module
|
|
834
|
+
DELETE /catalog/modules/{moduleId}
|
|
835
|
+
```
|
|
836
|
+
|
|
837
|
+
### Benefits of the Catalog
|
|
838
|
+
|
|
839
|
+
<CardGrid>
|
|
840
|
+
<Card title="Zero-Config Gateway" icon="setting">
|
|
841
|
+
Gateway doesn't need configuration files - it learns routes from the catalog
|
|
842
|
+
</Card>
|
|
843
|
+
|
|
844
|
+
<Card title="Flexible Deployment" icon="rocket">
|
|
845
|
+
Add, remove, or update services without redeploying the gateway
|
|
846
|
+
</Card>
|
|
847
|
+
|
|
848
|
+
<Card title="Health Tracking" icon="approve-check">
|
|
849
|
+
Catalog can track service health and availability
|
|
850
|
+
</Card>
|
|
851
|
+
</CardGrid>
|
|
852
|
+
|
|
853
|
+
---
|
|
854
|
+
|
|
855
|
+
## Putting It All Together
|
|
856
|
+
|
|
857
|
+
Here's how these concepts work together in a real scenario:
|
|
858
|
+
|
|
859
|
+
### Example: User Views Their Orders
|
|
860
|
+
|
|
861
|
+
1. **User** (belongs to **Tenant** "ACME Corp") logs in
|
|
862
|
+
2. **Gateway** authenticates and extracts **Platform Context** (tenant, user)
|
|
863
|
+
3. User navigates to the "Orders" **Application** in the Shell UI
|
|
864
|
+
4. **Catalog** provides the Orders **Module** location to the Shell
|
|
865
|
+
5. Shell loads the Orders UI **Module** (micro-frontend)
|
|
866
|
+
6. User clicks "View My Orders"
|
|
867
|
+
7. UI checks if user has `orders.read` **Operation** (they do via their **Role**)
|
|
868
|
+
8. UI calls the Orders Service via the **Gateway**
|
|
869
|
+
9. **Gateway** checks authorization:
|
|
870
|
+
- User has `orders.read` operation
|
|
871
|
+
- **Rules** evaluated: "allow read own orders" passes
|
|
872
|
+
10. Gateway routes request to Orders **Service Module**
|
|
873
|
+
11. Service queries database filtered by **Tenant** ID
|
|
874
|
+
12. Orders returned to UI
|
|
875
|
+
|
|
876
|
+
### Key Takeaways
|
|
877
|
+
|
|
878
|
+
- **Applications** group related functionality
|
|
879
|
+
- **Modules** are the deployable services and UIs
|
|
880
|
+
- **Operations** are granular permissions
|
|
881
|
+
- **Roles** collect Operations for assignment
|
|
882
|
+
- **Rules** add conditional logic
|
|
883
|
+
- **Tenants** provide multi-tenancy isolation
|
|
884
|
+
|
|
885
|
+
## Next Steps
|
|
886
|
+
|
|
887
|
+
Now that you understand the core concepts:
|
|
888
|
+
|
|
889
|
+
1. **[Installation Guide](/_/docs/getting-started/installation/)** - Set up your development environment
|
|
890
|
+
2. **[Development Workflow](/_/docs/getting-started/development-workflow/)** - Learn the day-to-day development process
|
|
891
|
+
3. **[Architecture Deep Dive](/_/docs/architecture/overview/)** - Explore the technical architecture
|
|
892
|
+
4. **[Authorization Guide](/_/docs/guides/authorization/)** - Master the authorization system
|