@riligar/agents-kit 1.6.0 → 1.8.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/.agent/skills/riligar-design-system/assets/theme.js +33 -30
- package/.agent/skills/riligar-dev-auth-elysia/SKILL.md +79 -0
- package/.agent/skills/riligar-dev-auth-elysia/assets/server-snippets.ts +45 -0
- package/.agent/skills/riligar-dev-auth-elysia/references/context-and-user.md +26 -0
- package/.agent/skills/riligar-dev-auth-elysia/references/manual-verification.md +36 -0
- package/.agent/skills/riligar-dev-auth-elysia/references/route-protection.md +52 -0
- package/.agent/skills/riligar-dev-auth-react/SKILL.md +85 -0
- package/.agent/skills/riligar-dev-auth-react/assets/setup-snippets.js +52 -0
- package/.agent/skills/riligar-dev-auth-react/references/concepts.md +24 -0
- package/.agent/skills/riligar-dev-auth-react/references/hooks-and-components.md +39 -0
- package/.agent/skills/riligar-dev-auth-react/references/route-protection.md +63 -0
- package/.agent/skills/riligar-dev-backend/SKILL.md +14 -6
- package/package.json +1 -1
|
@@ -1,42 +1,28 @@
|
|
|
1
|
-
|
|
2
|
-
* RiLiGar Design System - Mantine 8 Theme
|
|
3
|
-
* Estética minimalista e adaptável (Light/Dark Mode).
|
|
4
|
-
*
|
|
5
|
-
* CENTRALIZAÇÃO TOTAL:
|
|
6
|
-
* Toda a configuração visual (sizes, borders, radius) DEVE estar aqui.
|
|
7
|
-
* O código do componente deve ser limpo.
|
|
8
|
-
*/
|
|
9
|
-
|
|
10
|
-
import { createTheme } from '@mantine/core'
|
|
1
|
+
import { createTheme, rem } from '@mantine/core'
|
|
11
2
|
|
|
12
3
|
export const theme = createTheme({
|
|
13
4
|
fontFamily: 'Montserrat, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif',
|
|
14
5
|
|
|
15
6
|
colors: {
|
|
16
|
-
// Escala
|
|
17
|
-
// Preto: #34322D
|
|
18
|
-
// Cinza: #F8F8F8
|
|
19
|
-
// Branco: #FFFFFF
|
|
7
|
+
// Escala Neutra Universal (Substitui o gray padrão)
|
|
20
8
|
gray: [
|
|
21
|
-
'#
|
|
22
|
-
'#
|
|
23
|
-
'#
|
|
24
|
-
'#
|
|
25
|
-
'#
|
|
26
|
-
'#
|
|
27
|
-
'#
|
|
28
|
-
'#
|
|
29
|
-
'#
|
|
30
|
-
'#
|
|
9
|
+
'#F9FAFB', // 0: App Background
|
|
10
|
+
'#F3F4F6', // 1: Hover/Subtle
|
|
11
|
+
'#E5E7EB', // 2: Borders
|
|
12
|
+
'#D1D5DB', // 3: Disabled
|
|
13
|
+
'#9CA3AF', // 4: Placeholder
|
|
14
|
+
'#6B7280', // 5: Text Secondary
|
|
15
|
+
'#4B5563', // 6: Text Primary Soft
|
|
16
|
+
'#374151', // 7: Text Primary
|
|
17
|
+
'#1F2937', // 8: Headers
|
|
18
|
+
'#11181C', // 9: Absolute Black
|
|
31
19
|
],
|
|
32
20
|
// Semânticos neutralizados para manter monochromaticidade total
|
|
33
21
|
error: ['#F9FAFB', '#F3F4F6', '#E5E7EB', '#D1D5DB', '#9CA3AF', '#6B7280', '#4B5563', '#374151', '#1F2937', '#11181C'],
|
|
34
22
|
success: ['#F9FAFB', '#F3F4F6', '#E5E7EB', '#D1D5DB', '#9CA3AF', '#6B7280', '#4B5563', '#374151', '#1F2937', '#11181C'],
|
|
35
23
|
},
|
|
36
24
|
|
|
37
|
-
primaryColor: '
|
|
38
|
-
black: '#34322D',
|
|
39
|
-
white: '#FFFFFF',
|
|
25
|
+
primaryColor: 'dark', // Escala dark mapeada para cinzas
|
|
40
26
|
autoContrast: true,
|
|
41
27
|
|
|
42
28
|
defaultRadius: 'md', // 6px
|
|
@@ -84,7 +70,6 @@ export const theme = createTheme({
|
|
|
84
70
|
fw: 500,
|
|
85
71
|
radius: 'md',
|
|
86
72
|
},
|
|
87
|
-
// Variações semânticas via theme vars se necessário
|
|
88
73
|
},
|
|
89
74
|
TextInput: {
|
|
90
75
|
defaultProps: {
|
|
@@ -93,9 +78,9 @@ export const theme = createTheme({
|
|
|
93
78
|
},
|
|
94
79
|
styles: theme => ({
|
|
95
80
|
input: {
|
|
96
|
-
border: `1px solid ${theme.colors.gray[2]}`,
|
|
81
|
+
border: `1px solid ${theme.colors.gray[2]}`,
|
|
97
82
|
'&:focus': {
|
|
98
|
-
borderColor: theme.colors.
|
|
83
|
+
borderColor: theme.colors.dark[8],
|
|
99
84
|
},
|
|
100
85
|
},
|
|
101
86
|
}),
|
|
@@ -114,5 +99,23 @@ export const theme = createTheme({
|
|
|
114
99
|
radius: 'md',
|
|
115
100
|
},
|
|
116
101
|
},
|
|
102
|
+
ThemeIcon: {
|
|
103
|
+
defaultProps: {
|
|
104
|
+
size: 'lg',
|
|
105
|
+
radius: 'md',
|
|
106
|
+
variant: 'light',
|
|
107
|
+
color: 'gray',
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
Title: {
|
|
111
|
+
defaultProps: {
|
|
112
|
+
lh: 1.2,
|
|
113
|
+
},
|
|
114
|
+
},
|
|
115
|
+
Text: {
|
|
116
|
+
defaultProps: {
|
|
117
|
+
lh: 1.6,
|
|
118
|
+
},
|
|
119
|
+
},
|
|
117
120
|
},
|
|
118
121
|
})
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: riligar-dev-auth-elysia
|
|
3
|
+
description: 'Comprehensive guide for integrating the Riligar Auth Elysia SDK into backend servers. Use when a user needs to: (1) Set up a backend auth plugin, (2) Configure Elysia with Riligar Secret Key, (3) Protect API routes or groups, (4) Access authenticated user data in handlers, (5) Perform manual JWT verification.'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Riligar Auth Elysia Skill
|
|
7
|
+
|
|
8
|
+
This skill provides a backend workflow for integrating authentication and permissions using the `@riligar/auth-elysia` SDK.
|
|
9
|
+
|
|
10
|
+
## Core Integration Workflow
|
|
11
|
+
|
|
12
|
+
### 1. Installation
|
|
13
|
+
|
|
14
|
+
Install the backend SDK:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
npm install @riligar/auth-elysia
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### 2. Environment Variables
|
|
21
|
+
|
|
22
|
+
Set up your Secret Key and URLs in your `.env` file.
|
|
23
|
+
|
|
24
|
+
> [!CAUTION]
|
|
25
|
+
> Backend integration requires the **Secret Key** (`sk_...`). Never share this key or include it in client-side code.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# .env
|
|
29
|
+
AUTH_API_URL=https://manager.myauth.click
|
|
30
|
+
AUTH_API_SECRET=sk_live_your_secret_key
|
|
31
|
+
AUTH_JWKS_URL=https://manager.myauth.click/.well-known/jwks.json
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### 3. Plugin Registration
|
|
35
|
+
|
|
36
|
+
Add the `authPlugin` to your Elysia instance.
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
import { Elysia } from 'elysia'
|
|
40
|
+
import { authPlugin } from '@riligar/auth-elysia'
|
|
41
|
+
|
|
42
|
+
const app = new Elysia()
|
|
43
|
+
.use(
|
|
44
|
+
authPlugin({
|
|
45
|
+
apiUrl: process.env.AUTH_API_URL,
|
|
46
|
+
apiKey: process.env.AUTH_API_SECRET,
|
|
47
|
+
jwksUrl: process.env.AUTH_JWKS_URL,
|
|
48
|
+
})
|
|
49
|
+
)
|
|
50
|
+
.listen(3000)
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
For more patterns, see [server-snippets.ts](assets/server-snippets.ts).
|
|
54
|
+
|
|
55
|
+
## Specialized Guides
|
|
56
|
+
|
|
57
|
+
- **Context & User Data**: Documentation for `ctx.auth` and `ctx.user`. See [context-and-user.md](references/context-and-user.md).
|
|
58
|
+
- **Route Protection**: How to implement `requireAuth` middleware and guard route groups. See [route-protection.md](references/route-protection.md).
|
|
59
|
+
- **Manual Verification**: Using `verifyToken` for custom JWT handling. See [manual-verification.md](references/manual-verification.md).
|
|
60
|
+
|
|
61
|
+
## Common Tasks
|
|
62
|
+
|
|
63
|
+
### Protecting a Route Group
|
|
64
|
+
|
|
65
|
+
Use `onBeforeHandle` to secure multiple endpoints efficiently.
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
app.group('/api/v1', app => app.onBeforeHandle(requireAuth).get('/data', () => ({ ok: true })))
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
### Accessing User Profile
|
|
72
|
+
|
|
73
|
+
Access the decoded user data directly from the context.
|
|
74
|
+
|
|
75
|
+
```typescript
|
|
76
|
+
app.get('/profile', ({ user }) => {
|
|
77
|
+
return { id: user.id, email: user.email }
|
|
78
|
+
})
|
|
79
|
+
```
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Server Snippets for Elysia
|
|
2
|
+
|
|
3
|
+
// 1. Core Server with Auth Plugin
|
|
4
|
+
export const fullServerSetup = `
|
|
5
|
+
import { Elysia } from 'elysia'
|
|
6
|
+
import { authPlugin } from '@riligar/auth-elysia'
|
|
7
|
+
|
|
8
|
+
const app = new Elysia()
|
|
9
|
+
.use(authPlugin({
|
|
10
|
+
apiUrl: process.env.AUTH_API_URL, // https://manager.myauth.click
|
|
11
|
+
apiKey: process.env.AUTH_API_SECRET, // sk_live_...
|
|
12
|
+
jwksUrl: process.env.AUTH_JWKS_URL, // .well-known/jwks.json
|
|
13
|
+
}))
|
|
14
|
+
.get('/public', () => 'Hello World')
|
|
15
|
+
.get('/private', ({ auth, user }) => {
|
|
16
|
+
if (!auth.isAuthenticated) return 'Unauthorized'
|
|
17
|
+
return \`Hello \${user.name}\`
|
|
18
|
+
})
|
|
19
|
+
.listen(3000)
|
|
20
|
+
`
|
|
21
|
+
|
|
22
|
+
// 2. Auth Middleware
|
|
23
|
+
export const middlewareSnippet = `
|
|
24
|
+
export const requireAuth = ({ auth, set }) => {
|
|
25
|
+
if (!auth.isAuthenticated) {
|
|
26
|
+
set.status = 401
|
|
27
|
+
return { error: 'Unauthorized' }
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
// Usage: app.get('/protected', requireAuth, () => 'Secret Area')
|
|
32
|
+
`
|
|
33
|
+
|
|
34
|
+
// 3. User Data access
|
|
35
|
+
export const userAccessSnippet = `
|
|
36
|
+
app.get('/me', ({ auth, user }) => {
|
|
37
|
+
if (!auth.isAuthenticated) return { error: 'Not logged in' }
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
id: user.id,
|
|
41
|
+
email: user.email,
|
|
42
|
+
verified: user.emailVerified
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
`
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Auth Context and User Object
|
|
2
|
+
|
|
3
|
+
The `@riligar/auth-elysia` plugin decorates the Elysia context with `auth` and `user` objects.
|
|
4
|
+
|
|
5
|
+
## Auth Object (`ctx.auth`)
|
|
6
|
+
|
|
7
|
+
Provides metadata about the current request's authentication state.
|
|
8
|
+
|
|
9
|
+
| Property | Type | Description |
|
|
10
|
+
| :--------------------- | :----------------- | :----------------------------------------------- |
|
|
11
|
+
| `auth.isAuthenticated` | `boolean` | `true` if a valid JWT was found and verified. |
|
|
12
|
+
| `auth.token` | `string \| null` | The raw JWT token from the Authorization header. |
|
|
13
|
+
| `auth.error` | `string \| null` | Error message if verification failed. |
|
|
14
|
+
| `auth.verify()` | `Promise<boolean>` | Manually triggers token verification. |
|
|
15
|
+
|
|
16
|
+
## User Object (`ctx.user`)
|
|
17
|
+
|
|
18
|
+
Contains the decoded payload from the JWT. Only populated if `isAuthenticated` is `true`.
|
|
19
|
+
|
|
20
|
+
| Property | Type | Description |
|
|
21
|
+
| :------------------- | :-------- | :------------------------------------------------ |
|
|
22
|
+
| `user.id` | `string` | Unique identifier of the user (from `sub` claim). |
|
|
23
|
+
| `user.email` | `string` | User's email address. |
|
|
24
|
+
| `user.name` | `string` | User's display name. |
|
|
25
|
+
| `user.emailVerified` | `boolean` | Whether the user's email has been verified. |
|
|
26
|
+
| `user.metadata` | `object` | Custom metadata associated with the user account. |
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# Manual Token Verification
|
|
2
|
+
|
|
3
|
+
In some cases, you may need to verify a JWT manually outside of the standard `authPlugin` context (e.g., in a background job, cron, or a custom WebSocket handler).
|
|
4
|
+
|
|
5
|
+
## Using `verifyToken`
|
|
6
|
+
|
|
7
|
+
The SDK exports a `verifyToken` function that handles the full JWKS verification flow.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
import { verifyToken } from '@riligar/auth-elysia'
|
|
11
|
+
|
|
12
|
+
async function customHandler(token: string) {
|
|
13
|
+
try {
|
|
14
|
+
const payload = await verifyToken(token, {
|
|
15
|
+
jwksUrl: process.env.AUTH_JWKS_URL,
|
|
16
|
+
// optional: issuer, audience verification
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
console.log('Valid user:', payload.sub)
|
|
20
|
+
return payload
|
|
21
|
+
} catch (error) {
|
|
22
|
+
console.error('Verification failed:', error.message)
|
|
23
|
+
throw new Error('Unauthorized')
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## JWKS Caching
|
|
29
|
+
|
|
30
|
+
The `verifyToken` function automatically caches the JWKS keys to avoid unnecessary network requests. If you need to force a refresh (e.g., after a key rotation), use `refreshJwks`:
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
import { refreshJwks } from '@riligar/auth-elysia'
|
|
34
|
+
|
|
35
|
+
await refreshJwks(process.env.AUTH_JWKS_URL)
|
|
36
|
+
```
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Route Protection and Middleware
|
|
2
|
+
|
|
3
|
+
Effective patterns for securing your Elysia API routes.
|
|
4
|
+
|
|
5
|
+
## Recommended Middleware Pattern
|
|
6
|
+
|
|
7
|
+
Create a reusable `requireAuth` helper to enforce authentication on specific endpoints.
|
|
8
|
+
|
|
9
|
+
```typescript
|
|
10
|
+
const requireAuth = ({ auth, set }) => {
|
|
11
|
+
if (!auth.isAuthenticated) {
|
|
12
|
+
set.status = 401
|
|
13
|
+
return { error: 'Unauthorized: Missing or invalid token' }
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Applying Protection
|
|
19
|
+
|
|
20
|
+
### To a single route
|
|
21
|
+
|
|
22
|
+
```typescript
|
|
23
|
+
app.get('/me', requireAuth, ({ user }) => {
|
|
24
|
+
return { name: user.name }
|
|
25
|
+
})
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### To a group of routes
|
|
29
|
+
|
|
30
|
+
Use `onBeforeHandle` to protect an entire API section.
|
|
31
|
+
|
|
32
|
+
```typescript
|
|
33
|
+
app.group('/api/admin', app =>
|
|
34
|
+
app
|
|
35
|
+
.onBeforeHandle(requireAuth)
|
|
36
|
+
.get('/dashboard', () => ({ stats: '...' }))
|
|
37
|
+
.post('/settings', () => ({ saved: true }))
|
|
38
|
+
)
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Permission-Based access (RBAC)
|
|
42
|
+
|
|
43
|
+
You can extend the middleware to check for specific roles or permissions.
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
const requireAdmin = ({ auth, user, set }) => {
|
|
47
|
+
if (!auth.isAuthenticated || user.role !== 'admin') {
|
|
48
|
+
set.status = 403
|
|
49
|
+
return { error: 'Forbidden' }
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
```
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: riligar-dev-auth-react
|
|
3
|
+
description: 'Comprehensive guide for integrating the Riligar Auth React SDK into web applications. Use when a user needs to: (1) Set up authentication from scratch, (2) Configure AuthProvider, (3) Implement route protection, (4) Use auth hooks or pre-built UI components, (5) Handle login/signup/profile/magic links in React.'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Riligar Auth React Skill
|
|
7
|
+
|
|
8
|
+
This skill provides a complete workflow for integrating authentication and permissions using the `@riligar/auth-react` SDK.
|
|
9
|
+
|
|
10
|
+
## Core Integration Workflow
|
|
11
|
+
|
|
12
|
+
### 1. Installation
|
|
13
|
+
|
|
14
|
+
Install the SDK using bun (preferred) or npm:
|
|
15
|
+
|
|
16
|
+
```bash
|
|
17
|
+
bun add @riligar/auth-react
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### 2. Environment Variables
|
|
21
|
+
|
|
22
|
+
Set up your Public Key in your `.env.local` file.
|
|
23
|
+
|
|
24
|
+
> [!IMPORTANT]
|
|
25
|
+
> Always use the **Public Key** (`pk_...`) in the frontend. Never expose your Secret Key.
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
# .env.local
|
|
29
|
+
VITE_AUTH_API_KEY=pk_live_your_public_key
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### 3. AuthProvider Setup
|
|
33
|
+
|
|
34
|
+
Wrap your application (usually in `main.jsx` or `App.jsx`) with the `AuthProvider`.
|
|
35
|
+
|
|
36
|
+
```jsx
|
|
37
|
+
import { AuthProvider } from '@riligar/auth-react'
|
|
38
|
+
|
|
39
|
+
ReactDOM.createRoot(document.getElementById('root')).render(
|
|
40
|
+
<AuthProvider apiKey={import.meta.env.VITE_AUTH_API_KEY}>
|
|
41
|
+
<App />
|
|
42
|
+
</AuthProvider>
|
|
43
|
+
)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
For more setup patterns, see [setup-snippets.js](assets/setup-snippets.js).
|
|
47
|
+
|
|
48
|
+
## Specialized Guides
|
|
49
|
+
|
|
50
|
+
- **Hooks & UI Components**: Comprehensive list of `useAuth`, `useSignIn`, and pre-built Mantine components. See [hooks-and-components.md](references/hooks-and-components.md).
|
|
51
|
+
- **Route Protection**: How to use `<Protect />`, `<SignedIn>`, and active route guards. See [route-protection.md](references/route-protection.md).
|
|
52
|
+
- **Core Concepts**: Understanding B2C/B2B models and API key security. See [concepts.md](references/concepts.md).
|
|
53
|
+
|
|
54
|
+
## Common Tasks
|
|
55
|
+
|
|
56
|
+
### Checking Auth State
|
|
57
|
+
|
|
58
|
+
Use `useAuth()` to access user data and authentication status.
|
|
59
|
+
|
|
60
|
+
```jsx
|
|
61
|
+
const { user, isAuthenticated, loading } = useAuth()
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
### Adding a Login Form
|
|
65
|
+
|
|
66
|
+
Simply drop the `<SignIn />` component. Use `variant="modal"` if you want it in a popup.
|
|
67
|
+
|
|
68
|
+
```jsx
|
|
69
|
+
<SignIn />
|
|
70
|
+
// or
|
|
71
|
+
<SignIn variant="modal" opened={isOpen} onClose={() => setIsOpen(false)} />
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Protecting a Dashboard
|
|
75
|
+
|
|
76
|
+
Wrap your sub-routes with `<Protect />`.
|
|
77
|
+
|
|
78
|
+
```jsx
|
|
79
|
+
<Route element={<Protect redirectTo="/login" />}>
|
|
80
|
+
<Route
|
|
81
|
+
path="/dashboard"
|
|
82
|
+
element={<Dashboard />}
|
|
83
|
+
/>
|
|
84
|
+
</Route>
|
|
85
|
+
```
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Setup Snippets
|
|
2
|
+
|
|
3
|
+
// 1. main.jsx / index.jsx setup
|
|
4
|
+
export const authProviderSetup = `
|
|
5
|
+
import { AuthProvider } from '@riligar/auth-react';
|
|
6
|
+
|
|
7
|
+
ReactDOM.createRoot(document.getElementById('root')).render(
|
|
8
|
+
<React.StrictMode>
|
|
9
|
+
<AuthProvider apiKey={import.meta.env.VITE_AUTH_API_KEY}>
|
|
10
|
+
<App />
|
|
11
|
+
</AuthProvider>
|
|
12
|
+
</React.StrictMode>
|
|
13
|
+
);
|
|
14
|
+
`
|
|
15
|
+
|
|
16
|
+
// 2. Protected Routes setup
|
|
17
|
+
export const protectedRoutesSnippet = `
|
|
18
|
+
import { Protect, SignIn } from '@riligar/auth-react';
|
|
19
|
+
import { BrowserRouter, Routes, Route } from 'react-router-dom';
|
|
20
|
+
|
|
21
|
+
function AppRoutes() {
|
|
22
|
+
return (
|
|
23
|
+
<BrowserRouter>
|
|
24
|
+
<Routes>
|
|
25
|
+
<Route path="/signin" element={<SignIn />} />
|
|
26
|
+
|
|
27
|
+
<Route element={<Protect redirectTo="/signin" />}>
|
|
28
|
+
<Route path="/" element={<Dashboard />} />
|
|
29
|
+
<Route path="/profile" element={<Profile />} />
|
|
30
|
+
</Route>
|
|
31
|
+
</Routes>
|
|
32
|
+
</BrowserRouter>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
`
|
|
36
|
+
|
|
37
|
+
// 3. User State hook
|
|
38
|
+
export const useAuthExample = `
|
|
39
|
+
import { useAuth } from '@riligar/auth-react';
|
|
40
|
+
|
|
41
|
+
function UserButton() {
|
|
42
|
+
const { user, isAuthenticated, signOut } = useAuth();
|
|
43
|
+
|
|
44
|
+
if (!isAuthenticated) return null;
|
|
45
|
+
|
|
46
|
+
return (
|
|
47
|
+
<button onClick={signOut}>
|
|
48
|
+
Log out {user.name}
|
|
49
|
+
</button>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
`
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Concepts and Security
|
|
2
|
+
|
|
3
|
+
## Access Models
|
|
4
|
+
|
|
5
|
+
Riligar Auth supports two primary access models:
|
|
6
|
+
|
|
7
|
+
- **B2C (Business-to-Consumer)**: Individual users access the application directly. Ideal for public-facing apps, e-commerce, and courses.
|
|
8
|
+
- **B2B (Business-to-Business)**: Users belong to organizations or teams. Multi-tenancy is handled at the core level. Ideal for SaaS and team tools.
|
|
9
|
+
|
|
10
|
+
## API Keys
|
|
11
|
+
|
|
12
|
+
Security is based on key pairs:
|
|
13
|
+
|
|
14
|
+
| Key Type | Prefix | Environment | Note |
|
|
15
|
+
| :------------- | :------- | :---------- | :--------------------------------------------------- |
|
|
16
|
+
| **Public Key** | `pk_...` | Frontend | Safe to expose in the browser. |
|
|
17
|
+
| **Secret Key** | `sk_...` | Backend | **NEVER** expose in the browser or client-side code. |
|
|
18
|
+
|
|
19
|
+
## Security Features
|
|
20
|
+
|
|
21
|
+
- **JWT Tokens**: Signed and verifiable locally via JWKS.
|
|
22
|
+
- **Zero-Trust**: No credentials stored on your application server.
|
|
23
|
+
- **Protection**: Native rate-limiting and brute-force protection.
|
|
24
|
+
- **Offline Verification**: Public JWKS endpoint allows backend verification without calling the Auth API on every request.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Hooks and Components
|
|
2
|
+
|
|
3
|
+
## Hooks
|
|
4
|
+
|
|
5
|
+
All hooks provide access to authentication state and actions.
|
|
6
|
+
|
|
7
|
+
| Hook | Description |
|
|
8
|
+
| :------------------- | :------------------------------------------------------------------------------------------------- |
|
|
9
|
+
| `useAuth()` | Main state: `user`, `isAuthenticated`, `loading`, `error` |
|
|
10
|
+
| `useSignIn()` | Function: `signIn(email, password)` |
|
|
11
|
+
| `useSignUp()` | Function: `signUp(email, password, name)` |
|
|
12
|
+
| `useSignOut()` | Function: `signOut()` |
|
|
13
|
+
| `useMagicLink()` | Functions: `sendMagicLink(email)`, `verifyMagicLink(token)` |
|
|
14
|
+
| `usePasswordReset()` | Functions: `forgotPassword(email)`, `resetPassword(token, newPass)` |
|
|
15
|
+
| `useUser()` | Access to `user` object and update methods: `updateProfile()`, `changePassword()`, `changeEmail()` |
|
|
16
|
+
|
|
17
|
+
## UI Components
|
|
18
|
+
|
|
19
|
+
Pre-built components using the Riligar Design System (Mantine-based).
|
|
20
|
+
|
|
21
|
+
| Component | Description | Variants |
|
|
22
|
+
| :---------------------- | :-------------------------------------- | :-------------- |
|
|
23
|
+
| `<SignIn />` | Full login form | `card`, `modal` |
|
|
24
|
+
| `<SignUp />` | Registration form | `card`, `modal` |
|
|
25
|
+
| `<MagicLink />` | Magic link request form | `card`, `modal` |
|
|
26
|
+
| `<MagicLinkCallback />` | Verification handler (no UI) | - |
|
|
27
|
+
| `<ForgotPassword />` | Password reset request | `card`, `modal` |
|
|
28
|
+
| `<ResetPassword />` | New password setter | - |
|
|
29
|
+
| `<VerifyEmail />` | Email verification handler | - |
|
|
30
|
+
| `<UserProfile />` | Profile, password, and email management | `card`, `modal` |
|
|
31
|
+
|
|
32
|
+
### Variant Props (for Card/Modal)
|
|
33
|
+
|
|
34
|
+
| Prop | Type | Default | Description |
|
|
35
|
+
| :----------- | :------------------ | :------- | :-------------------------------------- |
|
|
36
|
+
| `variant` | `'card' \| 'modal'` | `'card'` | Rendering mode. |
|
|
37
|
+
| `opened` | `boolean` | - | Visibility for `modal` variant. |
|
|
38
|
+
| `onClose` | `function` | - | Callback when closing the modal. |
|
|
39
|
+
| `modalProps` | `object` | `{}` | Extra props for the underlying `Modal`. |
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# Route Protection
|
|
2
|
+
|
|
3
|
+
## Components
|
|
4
|
+
|
|
5
|
+
Use these components to control access to specific parts of your application.
|
|
6
|
+
|
|
7
|
+
| Component | Description |
|
|
8
|
+
| :-------------- | :--------------------------------------------------- |
|
|
9
|
+
| `<Protect />` | Route guard wrapper for React Router. |
|
|
10
|
+
| `<SignedIn>` | Renders children only if user is authenticated. |
|
|
11
|
+
| `<SignedOut>` | Renders children only if user is NOT authenticated. |
|
|
12
|
+
| `<AuthLoading>` | Renders children only while checking authentication. |
|
|
13
|
+
|
|
14
|
+
## Usage Patterns
|
|
15
|
+
|
|
16
|
+
### Protecting Routes (React Router)
|
|
17
|
+
|
|
18
|
+
```jsx
|
|
19
|
+
import { Protect, SignIn } from '@riligar/auth-react'
|
|
20
|
+
import { Routes, Route } from 'react-router-dom'
|
|
21
|
+
|
|
22
|
+
;<Routes>
|
|
23
|
+
<Route
|
|
24
|
+
path="/login"
|
|
25
|
+
element={<SignIn />}
|
|
26
|
+
/>
|
|
27
|
+
|
|
28
|
+
<Route element={<Protect redirectTo="/login" />}>
|
|
29
|
+
<Route
|
|
30
|
+
path="/dashboard"
|
|
31
|
+
element={<Dashboard />}
|
|
32
|
+
/>
|
|
33
|
+
<Route
|
|
34
|
+
path="/settings"
|
|
35
|
+
element={<Settings />}
|
|
36
|
+
/>
|
|
37
|
+
</Route>
|
|
38
|
+
</Routes>
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Conditional UI Elements
|
|
42
|
+
|
|
43
|
+
```jsx
|
|
44
|
+
import { SignedIn, SignedOut, AuthLoading } from '@riligar/auth-react'
|
|
45
|
+
|
|
46
|
+
function Header() {
|
|
47
|
+
return (
|
|
48
|
+
<header>
|
|
49
|
+
<AuthLoading>
|
|
50
|
+
<Spinner />
|
|
51
|
+
</AuthLoading>
|
|
52
|
+
|
|
53
|
+
<SignedIn>
|
|
54
|
+
<UserMenu />
|
|
55
|
+
</SignedIn>
|
|
56
|
+
|
|
57
|
+
<SignedOut>
|
|
58
|
+
<LoginButton />
|
|
59
|
+
</SignedOut>
|
|
60
|
+
</header>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
```
|
|
@@ -43,12 +43,20 @@ allowed-tools: Read, Write, Edit, Glob, Grep
|
|
|
43
43
|
|
|
44
44
|
---
|
|
45
45
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
|
49
|
-
|
|
|
50
|
-
|
|
|
51
|
-
|
|
|
46
|
+
## 🔗 Related Skills
|
|
47
|
+
|
|
48
|
+
| Need | Skill |
|
|
49
|
+
| ------------------- | ------------------------------------------------- |
|
|
50
|
+
| **Core Standards** | @[.agent/skills/riligar-dev-clean-code] |
|
|
51
|
+
| **Architecture** | @[.agent/skills/riligar-dev-architecture] |
|
|
52
|
+
| **Database** | @[.agent/skills/riligar-dev-database] |
|
|
53
|
+
| **Infrastructure** | @[.agent/skills/riligar-infrastructure] |
|
|
54
|
+
| **Tech Stack** | @[.agent/skills/riligar-tech-stack] |
|
|
55
|
+
| **Business Case** | @[.agent/skills/riligar-business-startup-analyst] |
|
|
56
|
+
| **Market Analysis** | @[.agent/skills/riligar-business-startup-market] |
|
|
57
|
+
| **Code Review** | @[.agent/skills/riligar-dev-code-review] |
|
|
58
|
+
| **Task Planning** | @[.agent/skills/riligar-plan-writing] |
|
|
59
|
+
| **SEO Tech** | @[.agent/skills/riligar-dev-seo] |
|
|
52
60
|
|
|
53
61
|
---
|
|
54
62
|
|