@rebasepro/agent-skills 0.7.0 → 0.9.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/LICENSE +21 -0
- package/package.json +9 -3
- package/skills/rebase-admin/SKILL.md +32 -32
- package/skills/rebase-api/SKILL.md +6 -6
- package/skills/rebase-auth/SKILL.md +52 -12
- package/skills/rebase-backend-postgres/SKILL.md +3 -3
- package/skills/rebase-basics/SKILL.md +11 -6
- package/skills/rebase-collections/SKILL.md +84 -46
- package/skills/rebase-cron-jobs/SKILL.md +5 -0
- package/skills/rebase-custom-functions/SKILL.md +21 -0
- package/skills/rebase-deployment/SKILL.md +12 -3
- package/skills/rebase-email/SKILL.md +1 -1
- package/skills/rebase-entity-history/SKILL.md +9 -9
- package/skills/rebase-realtime/SKILL.md +5 -5
- package/skills/rebase-sdk/SKILL.md +23 -0
- package/skills/rebase-security/SKILL.md +68 -28
- package/skills/rebase-storage/SKILL.md +180 -12
- package/skills/rebase-studio/SKILL.md +8 -8
- package/skills/rebase-ui-components/SKILL.md +91 -0
- package/skills/rebase-webhooks/SKILL.md +25 -30
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rebase
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/package.json
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebasepro/agent-skills",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.9.0",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "Bundled AI agent skills for Rebase",
|
|
6
6
|
"type": "module",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/rebasepro/rebase.git",
|
|
10
|
+
"directory": "rebase-agent-skills"
|
|
11
|
+
},
|
|
7
12
|
"files": [
|
|
8
13
|
"skills/"
|
|
9
14
|
],
|
|
@@ -11,5 +16,6 @@
|
|
|
11
16
|
".": "./package.json",
|
|
12
17
|
"./package.json": "./package.json",
|
|
13
18
|
"./skills": "./skills/"
|
|
14
|
-
}
|
|
15
|
-
}
|
|
19
|
+
},
|
|
20
|
+
"scripts": {}
|
|
21
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: rebase-admin
|
|
3
|
-
description: Guide for navigating the Rebase admin CMS, opening entities in side drawers, building URLs, embedding collection panels, using the collection registry, and programmatic navigation. Use this skill when an agent or user needs to navigate to a collection view, open
|
|
3
|
+
description: Guide for navigating the Rebase admin CMS, opening entities in side drawers, building URLs, embedding collection panels, using the collection registry, and programmatic navigation. Use this skill when an agent or user needs to navigate to a collection view, open a entity in the side panel/drawer, build admin URLs, embed a collection inside a custom page, use the entity selection dialog, or access CMS-specific controllers.
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Rebase Admin (`@rebasepro/admin`)
|
|
@@ -13,12 +13,12 @@ The `@rebasepro/admin` package provides the CMS layer for Rebase. It handles col
|
|
|
13
13
|
|
|
14
14
|
| Task | Hook / Component | Package |
|
|
15
15
|
|------|-----------------|---------|
|
|
16
|
-
| Open entity in side drawer | `
|
|
16
|
+
| Open entity in side drawer | `useSidePanel()` | `@rebasepro/admin` |
|
|
17
17
|
| Navigate to a collection view | `useUrlController()` | `@rebasepro/admin` |
|
|
18
18
|
| Look up a collection by slug | `useCollectionRegistryController()` | `@rebasepro/admin` |
|
|
19
19
|
| Embed a collection in a custom page | `<CollectionPanel>` | `@rebasepro/admin` |
|
|
20
20
|
| Add custom top-level views | `<RebaseCMS views={[...]}>` | `@rebasepro/admin` |
|
|
21
|
-
| Open
|
|
21
|
+
| Open a entity selection dialog | `useSelectionDialog()` | `@rebasepro/admin` |
|
|
22
22
|
| Open a custom side dialog | `useSideDialogsController()` | `@rebasepro/admin` |
|
|
23
23
|
| Set breadcrumbs | `useBreadcrumbsController()` | `@rebasepro/admin` |
|
|
24
24
|
| Access full CMS context | `useCMSContext()` | `@rebasepro/admin` |
|
|
@@ -28,16 +28,16 @@ The `@rebasepro/admin` package provides the CMS layer for Rebase. It handles col
|
|
|
28
28
|
|
|
29
29
|
## 1. Opening Entities in the Side Drawer
|
|
30
30
|
|
|
31
|
-
Use `
|
|
31
|
+
Use `useSidePanel()` to open, replace, or close entity side panels (the sliding drawer that shows entity forms).
|
|
32
32
|
|
|
33
33
|
```typescript
|
|
34
|
-
import {
|
|
34
|
+
import { useSidePanel } from "@rebasepro/admin";
|
|
35
35
|
```
|
|
36
36
|
|
|
37
|
-
###
|
|
37
|
+
### SidePanelController Interface
|
|
38
38
|
|
|
39
39
|
```typescript
|
|
40
|
-
interface
|
|
40
|
+
interface SidePanelController {
|
|
41
41
|
/** Close the last (topmost) panel */
|
|
42
42
|
close: () => void;
|
|
43
43
|
|
|
@@ -69,7 +69,7 @@ interface EntitySidePanelProps<M extends Record<string, unknown> = Record<string
|
|
|
69
69
|
width?: number | string;
|
|
70
70
|
|
|
71
71
|
/** Explicit collection config (auto-resolved from navigation if omitted) */
|
|
72
|
-
collection?:
|
|
72
|
+
collection?: CollectionConfig<M>;
|
|
73
73
|
|
|
74
74
|
/** Whether to update the browser URL when opening (default: true) */
|
|
75
75
|
updateUrl?: boolean;
|
|
@@ -98,7 +98,7 @@ interface EntitySidePanelProps<M extends Record<string, unknown> = Record<string
|
|
|
98
98
|
|
|
99
99
|
**Open an existing entity for editing:**
|
|
100
100
|
```tsx
|
|
101
|
-
const sideEntityController =
|
|
101
|
+
const sideEntityController = useSidePanel();
|
|
102
102
|
|
|
103
103
|
// Open the product with ID "abc123" in the side drawer
|
|
104
104
|
sideEntityController.open({
|
|
@@ -236,10 +236,10 @@ import { useCollectionRegistryController } from "@rebasepro/admin";
|
|
|
236
236
|
```typescript
|
|
237
237
|
type CollectionRegistryController<
|
|
238
238
|
DB = Record<string, unknown>,
|
|
239
|
-
EC extends
|
|
239
|
+
EC extends CollectionConfig = CollectionConfig
|
|
240
240
|
> = {
|
|
241
241
|
/** All registered collections */
|
|
242
|
-
collections?:
|
|
242
|
+
collections?: CollectionConfig[];
|
|
243
243
|
|
|
244
244
|
/** Whether the registry is ready */
|
|
245
245
|
initialised: boolean;
|
|
@@ -321,7 +321,7 @@ type CollectionPanelProps = {
|
|
|
321
321
|
className?: string;
|
|
322
322
|
|
|
323
323
|
/** Additional collection-level overrides */
|
|
324
|
-
collectionOverrides?: Partial<
|
|
324
|
+
collectionOverrides?: Partial<CollectionConfig>;
|
|
325
325
|
};
|
|
326
326
|
```
|
|
327
327
|
|
|
@@ -356,17 +356,17 @@ type CollectionPanelProps = {
|
|
|
356
356
|
|
|
357
357
|
## 5. Entity Selection Dialog
|
|
358
358
|
|
|
359
|
-
Use `
|
|
359
|
+
Use `useSelectionDialog()` to open a side dialog for selecting entities (same mechanism used by reference fields).
|
|
360
360
|
|
|
361
361
|
```typescript
|
|
362
|
-
import {
|
|
362
|
+
import { useSelectionDialog } from "@rebasepro/admin";
|
|
363
363
|
```
|
|
364
364
|
|
|
365
365
|
### Usage
|
|
366
366
|
|
|
367
367
|
```tsx
|
|
368
368
|
function MyComponent() {
|
|
369
|
-
const { open, close } =
|
|
369
|
+
const { open, close } = useSelectionDialog<Product>({
|
|
370
370
|
path: "products",
|
|
371
371
|
onSingleEntitySelected: (entity) => {
|
|
372
372
|
console.log("Selected:", entity.id);
|
|
@@ -378,7 +378,7 @@ function MyComponent() {
|
|
|
378
378
|
}
|
|
379
379
|
```
|
|
380
380
|
|
|
381
|
-
The hook accepts all `
|
|
381
|
+
The hook accepts all `SelectionProps` except `path` (which you pass separately), plus an `onClose` callback.
|
|
382
382
|
|
|
383
383
|
---
|
|
384
384
|
|
|
@@ -545,7 +545,7 @@ import { useCMSContext } from "@rebasepro/admin";
|
|
|
545
545
|
|
|
546
546
|
```typescript
|
|
547
547
|
type CMSContext = RebaseContext & {
|
|
548
|
-
sideEntityController:
|
|
548
|
+
sideEntityController: SidePanelController;
|
|
549
549
|
sideDialogsController: SideDialogsController;
|
|
550
550
|
urlController: UrlController;
|
|
551
551
|
navigationStateController: NavigationStateController;
|
|
@@ -572,14 +572,14 @@ context.data; // DataSource from RebaseContext
|
|
|
572
572
|
|
|
573
573
|
## 10. Common Patterns
|
|
574
574
|
|
|
575
|
-
### Navigate to a collection and open
|
|
575
|
+
### Navigate to a collection and open a entity
|
|
576
576
|
|
|
577
577
|
```tsx
|
|
578
|
-
import { useUrlController,
|
|
578
|
+
import { useUrlController, useSidePanel } from "@rebasepro/admin";
|
|
579
579
|
|
|
580
580
|
function navigateAndOpen() {
|
|
581
581
|
const urlController = useUrlController();
|
|
582
|
-
const sideEntityController =
|
|
582
|
+
const sideEntityController = useSidePanel();
|
|
583
583
|
|
|
584
584
|
// First navigate to the collection
|
|
585
585
|
urlController.navigate(urlController.buildUrlCollectionPath("products"));
|
|
@@ -595,10 +595,10 @@ function navigateAndOpen() {
|
|
|
595
595
|
### Open entity from a custom view without navigating
|
|
596
596
|
|
|
597
597
|
```tsx
|
|
598
|
-
import {
|
|
598
|
+
import { useSidePanel } from "@rebasepro/admin";
|
|
599
599
|
|
|
600
600
|
function MyCustomView() {
|
|
601
|
-
const sideEntityController =
|
|
601
|
+
const sideEntityController = useSidePanel();
|
|
602
602
|
|
|
603
603
|
return (
|
|
604
604
|
<button onClick={() => sideEntityController.open({
|
|
@@ -615,10 +615,10 @@ function MyCustomView() {
|
|
|
615
615
|
### Programmatic entity creation from a custom view
|
|
616
616
|
|
|
617
617
|
```tsx
|
|
618
|
-
import {
|
|
618
|
+
import { useSidePanel } from "@rebasepro/admin";
|
|
619
619
|
|
|
620
620
|
function CreateButton() {
|
|
621
|
-
const sideEntity =
|
|
621
|
+
const sideEntity = useSidePanel();
|
|
622
622
|
|
|
623
623
|
return (
|
|
624
624
|
<button onClick={() => sideEntity.open({
|
|
@@ -754,10 +754,10 @@ The admin package exports the following components (from `@rebasepro/admin`):
|
|
|
754
754
|
| `RebaseCMS` | Declarative CMS config (collections, views, editor) — renders nothing |
|
|
755
755
|
| `RebaseShell` | App shell (drawer, nav, routes, layout) — renders the actual UI |
|
|
756
756
|
| `CollectionPanel` | Embed a collection view inside custom pages |
|
|
757
|
-
| `
|
|
758
|
-
| `
|
|
757
|
+
| `DataCollectionView` | The collection view component |
|
|
758
|
+
| `EntityCustomView` | Entity detail/edit view |
|
|
759
759
|
| `EntityPreview` | Reference/relation preview chip |
|
|
760
|
-
| `EntityCard` | Card representation of
|
|
760
|
+
| `EntityCard` | Card representation of a entity |
|
|
761
761
|
| `SideDialogs` | Side dialog container |
|
|
762
762
|
| `SideEntityProvider` | Context provider for side entity controller |
|
|
763
763
|
| `EntitySelectionTable` | Table for selecting entities |
|
|
@@ -773,16 +773,16 @@ The admin package exports the following components (from `@rebasepro/admin`):
|
|
|
773
773
|
|
|
774
774
|
| Hook | Description |
|
|
775
775
|
|------|-------------|
|
|
776
|
-
| `
|
|
776
|
+
| `useSidePanel()` | Open/close entity side panels |
|
|
777
777
|
| `useSideDialogsController()` | Open/close generic side dialogs |
|
|
778
778
|
| `useUrlController()` | Build URLs and navigate |
|
|
779
779
|
| `useNavigationStateController()` | Access navigation state |
|
|
780
780
|
| `useCollectionRegistryController()` | Look up collections by slug |
|
|
781
781
|
| `useBreadcrumbsController()` | Read/set breadcrumbs |
|
|
782
782
|
| `useCMSContext()` | Full CMS context (core + CMS controllers) |
|
|
783
|
-
| `
|
|
783
|
+
| `useSelectionDialog()` | Open entity selection dialog |
|
|
784
784
|
| `useSelectionController()` | Multi-select controller |
|
|
785
|
-
| `
|
|
785
|
+
| `useHistory()` | Entity version history |
|
|
786
786
|
| `useApp()` | App-level utilities |
|
|
787
787
|
|
|
788
788
|
## Exported Utilities
|
|
@@ -796,8 +796,8 @@ The admin package exports the following components (from `@rebasepro/admin`):
|
|
|
796
796
|
| `getLastSegment(path)` | Get last path segment |
|
|
797
797
|
| `getCollectionBySlugWithin(collections, slug)` | Find collection in array |
|
|
798
798
|
| `mergeEntityActions(...)` | Merge entity action arrays |
|
|
799
|
-
| `resolveEntityAction(...)` | Resolve
|
|
800
|
-
| `resolveEntityView(...)` | Resolve
|
|
799
|
+
| `resolveEntityAction(...)` | Resolve a entity action |
|
|
800
|
+
| `resolveEntityView(...)` | Resolve a entity view |
|
|
801
801
|
| `isReferenceProperty(prop)` | Check if property is a reference |
|
|
802
802
|
| `isRelationProperty(prop)` | Check if property is a relation |
|
|
803
803
|
| `getIconForProperty(prop)` | Get icon for a property type |
|
|
@@ -43,8 +43,8 @@ All data routes are mounted under `/api/data/`. Other route categories:
|
|
|
43
43
|
| `GET` | `/api/data/{slug}/count` | Count matching entities (with optional filters) | `200` |
|
|
44
44
|
| `GET` | `/api/data/{slug}/:id` | Get a single entity by ID | `200` |
|
|
45
45
|
| `POST` | `/api/data/{slug}` | Create a new entity | `201` |
|
|
46
|
-
| `PUT` | `/api/data/{slug}/:id` | Update
|
|
47
|
-
| `DELETE` | `/api/data/{slug}/:id` | Delete
|
|
46
|
+
| `PUT` | `/api/data/{slug}/:id` | Update a entity | `200` |
|
|
47
|
+
| `DELETE` | `/api/data/{slug}/:id` | Delete a entity | `204` |
|
|
48
48
|
|
|
49
49
|
### Subcollection Routes
|
|
50
50
|
|
|
@@ -405,7 +405,7 @@ curl -H "Authorization: Bearer $TOKEN" \
|
|
|
405
405
|
"https://example.com/api/data/products?status=eq.active&price=gte.50&orderBy=created_at:desc&limit=10&offset=0&include=category"
|
|
406
406
|
```
|
|
407
407
|
|
|
408
|
-
### Create
|
|
408
|
+
### Create a entity
|
|
409
409
|
|
|
410
410
|
```bash
|
|
411
411
|
curl -X POST \
|
|
@@ -415,7 +415,7 @@ curl -X POST \
|
|
|
415
415
|
"https://example.com/api/data/products"
|
|
416
416
|
```
|
|
417
417
|
|
|
418
|
-
### Update
|
|
418
|
+
### Update a entity
|
|
419
419
|
|
|
420
420
|
```bash
|
|
421
421
|
curl -X PUT \
|
|
@@ -425,7 +425,7 @@ curl -X PUT \
|
|
|
425
425
|
"https://example.com/api/data/products/uuid-123"
|
|
426
426
|
```
|
|
427
427
|
|
|
428
|
-
### Delete
|
|
428
|
+
### Delete a entity
|
|
429
429
|
|
|
430
430
|
```bash
|
|
431
431
|
curl -X DELETE \
|
|
@@ -655,7 +655,7 @@ GET /api/collections
|
|
|
655
655
|
| `pagination.maxLimit` | `number` | `100` | Maximum allowed page size |
|
|
656
656
|
| `cors.origin` | `string \| string[] \| boolean` | — | CORS origin configuration |
|
|
657
657
|
| `cors.credentials` | `boolean` | `false` | Allow credentials in CORS |
|
|
658
|
-
| `collections` | `
|
|
658
|
+
| `collections` | `CollectionConfig[]` | `[]` | Collections to generate APIs for |
|
|
659
659
|
| `collectionsDir` | `string` | — | Directory to auto-discover collections |
|
|
660
660
|
|
|
661
661
|
## References
|
|
@@ -5,7 +5,7 @@ description: Guide for setting up and using Rebase Authentication, roles, Row-Le
|
|
|
5
5
|
|
|
6
6
|
# Rebase Authentication
|
|
7
7
|
|
|
8
|
-
Rebase ships a complete, built-in authentication system with JWT sessions, OAuth, MFA/TOTP, API keys, Row-Level Security, and lifecycle hooks — or you can plug in an external
|
|
8
|
+
Rebase ships a complete, built-in authentication system with JWT sessions, OAuth, MFA/TOTP, API keys, Row-Level Security, and lifecycle hooks — or you can plug in an external auth system (e.g., Clerk, Auth0, or custom identity providers) via the `AuthAdapter` interface.
|
|
9
9
|
|
|
10
10
|
> **IMPORTANT FOR AGENTS:** Always read the `rebase-basics` skill first. The auth system is configured inside `initializeRebaseBackend()` which is covered there.
|
|
11
11
|
|
|
@@ -33,21 +33,22 @@ Rebase ships a complete, built-in authentication system with JWT sessions, OAuth
|
|
|
33
33
|
|
|
34
34
|
Authentication is configured via the `auth` property of `initializeRebaseBackend()`. It accepts **either** a `RebaseAuthConfig` object (built-in auth) or an `AuthAdapter` (external auth).
|
|
35
35
|
|
|
36
|
-
> **Auth & multiple data sources.** The built-in auth system (users, sessions, API keys) is bootstrapped on the **default** data source — the auth collection must live there (the backend warns at boot otherwise). **RLS only protects Postgres**: server collections on engines without row-level security (e.g. MongoDB) still require authentication but enforce authorization at the app layer (the backend warns for these). **Direct data sources (e.g. Firestore) bypass Rebase auth entirely** — they're governed by the external backend's own rules/token; use an `AuthAdapter`
|
|
36
|
+
> **Auth & multiple data sources.** The built-in auth system (users, sessions, API keys) is bootstrapped on the **default** data source — the auth collection must live there (the backend warns at boot otherwise). **RLS only protects Postgres**: server collections on engines without row-level security (e.g. MongoDB) still require authentication but enforce authorization at the app layer (the backend warns for these). **Direct data sources (e.g. Firestore) bypass Rebase auth entirely** — they're governed by the external backend's own rules/token; use an `AuthAdapter` to unify identity. See the **rebase-collections** skill for the data-source model.
|
|
37
37
|
|
|
38
38
|
### RebaseAuthConfig
|
|
39
39
|
|
|
40
40
|
| Property | Type | Default | Description |
|
|
41
41
|
|---|---|---|---|
|
|
42
|
-
| `collection` | `
|
|
42
|
+
| `collection` | `CollectionConfig` | Built-in users collection | The collection used for auth user storage. Import `defaultUsersCollection` from `@rebasepro/common` or pass a custom collection with required auth fields. |
|
|
43
43
|
| `jwtSecret` | `string` | — | **Required.** Secret for signing JWT access tokens. |
|
|
44
44
|
| `accessExpiresIn` | `string` | `"1h"` | Access token lifetime (e.g. `"15m"`, `"2h"`). |
|
|
45
45
|
| `refreshExpiresIn` | `string` | `"30d"` | Refresh token lifetime. |
|
|
46
46
|
| `requireAuth` | `boolean` | `true` | When `true`, data routes return 401 for unauthenticated requests. Set to `false` to rely entirely on Postgres RLS. |
|
|
47
47
|
| `allowRegistration` | `boolean` | `false` | Enable self-service registration via `POST /auth/register`. |
|
|
48
|
+
| `allowUserLookup` | `boolean` | `false` | Expose `POST /auth/find-user` — an authenticated email→minimal-profile lookup (`uid`/`displayName`/`photoURL` only) for invite flows. Enables user enumeration by signed-in users, so it's off by default. See [Inviting by email](#inviting-teammates-by-email). |
|
|
48
49
|
| `serviceKey` | `string` | — | Static secret for server-to-server auth. Must be ≥ 32 characters. Requests with `Authorization: Bearer <serviceKey>` get admin access. |
|
|
49
50
|
| `defaultRole` | `string` | — | Role ID assigned to new users (except the first user, who always gets `"admin"`). **Must NOT be `"admin"`** — throws a security error at startup. |
|
|
50
|
-
| `providers` | `OAuthProvider<
|
|
51
|
+
| `providers` | `OAuthProvider<unknown>[]` | `[]` | **Canonical** OAuth provider array. Use `create*Provider` factories or pass custom providers. Named shorthand fields below are merged into this array at startup. |
|
|
51
52
|
| `hooks` | `AuthHooks` | — | [Lifecycle hooks](#auth-lifecycle-hooks) to customize passwords, credentials, and auth events. |
|
|
52
53
|
| `email` | `EmailConfig` | — | [Email configuration](#email-configuration) for password resets, verification, and welcome emails. |
|
|
53
54
|
| `google` | `{ clientId, clientSecret? }` | — | Google OAuth shorthand. |
|
|
@@ -107,9 +108,9 @@ await initializeRebaseBackend({
|
|
|
107
108
|
Instead of relying solely on the default database auth rules, you can mark any Postgres collection (such as `users.ts` or a custom `members.ts` collection) as the authentication collection. This is configured via the `auth` property on the collection itself:
|
|
108
109
|
|
|
109
110
|
```typescript
|
|
110
|
-
import {
|
|
111
|
+
import { PostgresCollectionConfig } from "@rebasepro/types";
|
|
111
112
|
|
|
112
|
-
const membersCollection:
|
|
113
|
+
const membersCollection: PostgresCollectionConfig = {
|
|
113
114
|
name: "Members",
|
|
114
115
|
slug: "members",
|
|
115
116
|
table: "members",
|
|
@@ -154,6 +155,27 @@ When custom hooks (`onCreateUser`, `onResetPassword`) are called, they receive a
|
|
|
154
155
|
|
|
155
156
|
> **IMPORTANT FOR AGENTS:** The very first user registered (via `POST /auth/register` or OAuth) is automatically promoted to `"admin"`. This prevents the chicken-and-egg problem. All subsequent users receive the `defaultRole`.
|
|
156
157
|
|
|
158
|
+
### Inviting teammates by email
|
|
159
|
+
|
|
160
|
+
Invite flows must turn an email into a user id, but the `users` collection is
|
|
161
|
+
RLS-protected from the client. **Do not** hand-roll an admin server function for
|
|
162
|
+
this — enable `allowUserLookup` and use the built-in primitive:
|
|
163
|
+
|
|
164
|
+
```typescript
|
|
165
|
+
// backend: initializeRebaseBackend({ auth: { allowUserLookup: true } })
|
|
166
|
+
|
|
167
|
+
// client:
|
|
168
|
+
const profile = await rebase.auth.findUserByEmail("teammate@example.com");
|
|
169
|
+
// → { uid, displayName, photoURL } | null (never email/roles/metadata)
|
|
170
|
+
if (profile) {
|
|
171
|
+
await rebase.data.team_members.create({ team_id, user_id: profile.uid });
|
|
172
|
+
}
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
The `find-user` endpoint is authenticated-only and returns just the minimal
|
|
176
|
+
public profile. It is off by default because it enables user enumeration by any
|
|
177
|
+
signed-in user.
|
|
178
|
+
|
|
157
179
|
---
|
|
158
180
|
|
|
159
181
|
## OAuth Providers
|
|
@@ -351,14 +373,14 @@ hooks: {
|
|
|
351
373
|
}
|
|
352
374
|
```
|
|
353
375
|
|
|
354
|
-
### Example:
|
|
376
|
+
### Example: External Token Bridge (e.g. custom auth system)
|
|
355
377
|
|
|
356
378
|
```typescript
|
|
357
379
|
import admin from "firebase-admin";
|
|
358
380
|
|
|
359
381
|
hooks: {
|
|
360
382
|
transformAuthResponse: async (response, context) => {
|
|
361
|
-
// Generate a
|
|
383
|
+
// Generate a custom provider token for the authenticated user
|
|
362
384
|
const firebaseToken = await admin.auth().createCustomToken(context.userId);
|
|
363
385
|
return {
|
|
364
386
|
...response,
|
|
@@ -371,7 +393,7 @@ hooks: {
|
|
|
371
393
|
}
|
|
372
394
|
```
|
|
373
395
|
|
|
374
|
-
The frontend can then call `signInWithCustomToken(
|
|
396
|
+
The frontend can then call `signInWithCustomToken(providerToken)` immediately after login.
|
|
375
397
|
|
|
376
398
|
---
|
|
377
399
|
|
|
@@ -664,7 +686,7 @@ All login/register/OAuth endpoints return:
|
|
|
664
686
|
}
|
|
665
687
|
```
|
|
666
688
|
|
|
667
|
-
> **TIP:** Use the `transformAuthResponse` hook to inject additional tokens (e.g.,
|
|
689
|
+
> **TIP:** Use the `transformAuthResponse` hook to inject additional tokens (e.g., external system tokens) or metadata into this response. See [Auth Lifecycle Hooks](#auth-lifecycle-hooks).
|
|
668
690
|
|
|
669
691
|
### Error Response Format
|
|
670
692
|
|
|
@@ -857,6 +879,21 @@ Requests with the `serviceKey` bypass RLS — they receive admin-level access wi
|
|
|
857
879
|
|
|
858
880
|
API keys use a service identity for RLS scoping: `uid: "api-key:{id}"`, `roles: ["service"]` (or `["admin", "service"]` when `admin: true`). They do not inherit the `created_by` user's identity.
|
|
859
881
|
|
|
882
|
+
### Reserved System Identities
|
|
883
|
+
|
|
884
|
+
The auth middleware assigns these reserved identities automatically. They are visible in `context.user` (Collection Callbacks / DataHooks) and `c.get("user")` (custom functions):
|
|
885
|
+
|
|
886
|
+
| Auth Method | `userId` | `roles` | When It Occurs |
|
|
887
|
+
|---|---|---|---|
|
|
888
|
+
| JWT (end-user) | Real user ID (e.g. `"abc123"`) | User's assigned roles (e.g. `["viewer"]`) | Normal authenticated requests |
|
|
889
|
+
| Service Key | `"service"` | `["admin"]` | Server-side `rebase.data` calls, cron jobs, or any request with `Authorization: Bearer <serviceKey>` |
|
|
890
|
+
| API Key (default) | `"api-key:{id}"` | `["service"]` | Machine-to-machine API key requests |
|
|
891
|
+
| API Key (admin) | `"api-key:{id}"` | `["admin", "service"]` | Admin API key requests |
|
|
892
|
+
| Anonymous | `"anon"` | `["anon"]` | Unauthenticated when `requireAuth: false` |
|
|
893
|
+
| No token + `requireAuth: true` | — | — | **Rejected (401)** |
|
|
894
|
+
|
|
895
|
+
> **IMPORTANT FOR AGENTS:** Server-side `rebase.data` (the singleton used in cron jobs, custom functions, and webhooks) is built with `createRebaseClient({ token: serviceKey })`. It round-trips through the REST API, so all middleware, DataHooks, and Collection Callbacks fire with `userId: "service"`, `roles: ["admin"]`. This lets developers distinguish server-internal reads from end-user reads in callbacks.
|
|
896
|
+
|
|
860
897
|
---
|
|
861
898
|
|
|
862
899
|
## Rate Limiting
|
|
@@ -917,7 +954,7 @@ const myLimiter = createRateLimiter({
|
|
|
917
954
|
|
|
918
955
|
## Custom Auth Adapters
|
|
919
956
|
|
|
920
|
-
For external auth systems (Clerk, Auth0,
|
|
957
|
+
For external auth systems (Clerk, Auth0, custom providers, or custom JWT), use the `AuthAdapter` interface or the `createCustomAuthAdapter()` helper.
|
|
921
958
|
|
|
922
959
|
### AuthAdapter Interface
|
|
923
960
|
|
|
@@ -1077,7 +1114,7 @@ Admin user and role management is handled via dedicated admin routes (mounted un
|
|
|
1077
1114
|
|
|
1078
1115
|
## Backend Hooks
|
|
1079
1116
|
|
|
1080
|
-
Backend hooks intercept data at the **API boundary** (after DB operations, before API responses). They are separate from auth hooks and collection-level `
|
|
1117
|
+
Backend hooks intercept data at the **API boundary** (after DB operations, before API responses). They are separate from auth hooks and collection-level `CollectionCallbacks`.
|
|
1081
1118
|
|
|
1082
1119
|
### BackendHooks Interface
|
|
1083
1120
|
|
|
@@ -1241,6 +1278,8 @@ When a request includes `Authorization: Bearer <serviceKey>`:
|
|
|
1241
1278
|
- Comparison is done with constant-time comparison to prevent timing attacks.
|
|
1242
1279
|
- Must be ≥ 32 characters (validated at startup).
|
|
1243
1280
|
|
|
1281
|
+
> **TIP:** In Collection Callbacks and DataHooks, server-side `rebase.data` calls appear as `userId: "service"`, `roles: ["admin"]`. Use this to skip masking, bypass rate limits, or grant elevated access in your callback logic.
|
|
1282
|
+
|
|
1244
1283
|
### Token Rotation
|
|
1245
1284
|
|
|
1246
1285
|
Refresh tokens are rotated on every use:
|
|
@@ -1281,3 +1320,4 @@ All auth endpoints validate input with Zod schemas:
|
|
|
1281
1320
|
- Source: `packages/types/src/types/auth_adapter.ts` — `AuthAdapter` interface
|
|
1282
1321
|
- Source: `packages/server-core/src/auth/rls-scope.ts` — RLS scoping
|
|
1283
1322
|
- Source: `packages/server-core/src/email/types.ts` — Email configuration
|
|
1323
|
+
- **Reserved Identities**: `"service"` / `"anon"` / `"api-key:{id}"` — see [Row-Level Security > Reserved System Identities](#reserved-system-identities)
|
|
@@ -69,7 +69,7 @@ rebase db migrate
|
|
|
69
69
|
|---------|---------|
|
|
70
70
|
| `@rebasepro/server-core` | Hono server coordinator, API generation, auth, storage, env validation |
|
|
71
71
|
| `@rebasepro/server-postgresql` | PostgreSQL bootstrapper, data driver, connection helpers, realtime (LISTEN/NOTIFY) |
|
|
72
|
-
| `@rebasepro/types` | Shared TypeScript type definitions (`
|
|
72
|
+
| `@rebasepro/types` | Shared TypeScript type definitions (`PostgresCollectionConfig`, etc.) |
|
|
73
73
|
|
|
74
74
|
## Connection Functions
|
|
75
75
|
|
|
@@ -339,7 +339,7 @@ The `initializeRebaseBackend()` coordinator calls bootstrapper methods in this o
|
|
|
339
339
|
|
|
340
340
|
| Property | Type | Default | Description |
|
|
341
341
|
|----------|------|---------|-------------|
|
|
342
|
-
| `collection` | `
|
|
342
|
+
| `collection` | `CollectionConfig` | Built-in `rebase.users` | Auth users collection |
|
|
343
343
|
| `jwtSecret` | `string` | Auto-generated in dev | JWT signing secret (≥32 chars) |
|
|
344
344
|
| `accessExpiresIn` | `string` | `"1h"` | Access token TTL |
|
|
345
345
|
| `refreshExpiresIn` | `string` | `"30d"` | Refresh token TTL |
|
|
@@ -514,7 +514,7 @@ const backend = await initializeRebaseBackend({
|
|
|
514
514
|
|
|
515
515
|
When enabled:
|
|
516
516
|
- The bootstrapper auto-creates a `rebase.entity_history` table
|
|
517
|
-
- Every `INSERT`, `UPDATE`, `DELETE` is recorded with before/after
|
|
517
|
+
- Every `INSERT`, `UPDATE`, `DELETE` is recorded with before/after entities
|
|
518
518
|
- History is queryable via the `/:slug/:entityId/history` REST endpoint
|
|
519
519
|
|
|
520
520
|
## Health Check
|
|
@@ -125,7 +125,7 @@ rebase/
|
|
|
125
125
|
| `@rebasepro/server-postgresql` | PostgreSQL bootstrapper and Drizzle ORM data driver | Backend setup when using PostgreSQL |
|
|
126
126
|
| `@rebasepro/server-mongodb` | MongoDB bootstrapper and data driver | Backend setup when using MongoDB |
|
|
127
127
|
| `@rebasepro/core` | Core framework, types, hooks, and React components | Frontend — React integration, hooks, providers |
|
|
128
|
-
| `@rebasepro/types` | Shared TypeScript type definitions (`
|
|
128
|
+
| `@rebasepro/types` | Shared TypeScript type definitions (`PostgresCollectionConfig`, `CollectionConfig`, `RebaseClient`, etc.) | Type imports across all packages |
|
|
129
129
|
| `@rebasepro/ui` | Standalone component library (Tailwind CSS v4 + Radix) | Building custom views in Studio or standalone UI |
|
|
130
130
|
| `@rebasepro/admin` | CMS frontend application | The Studio admin panel frontend |
|
|
131
131
|
| `@rebasepro/studio` | Admin panel, collection editor, visual schema editor | Studio-specific features and customization |
|
|
@@ -388,7 +388,7 @@ When `extend` is provided, the base `rebaseEnvSchema` is merged (`.merge()`) wit
|
|
|
388
388
|
| `DB_POOL_MAX` | `string` → `number` | `"20"` | No | Max database pool connections |
|
|
389
389
|
| `DB_POOL_IDLE_TIMEOUT` | `string` → `number` | `"30000"` | No | Pool idle timeout (ms) |
|
|
390
390
|
| `DB_POOL_CONNECT_TIMEOUT` | `string` → `number` | `"10000"` | No | Pool connect timeout (ms) |
|
|
391
|
-
| `STORAGE_TYPE` | `"local" \| "s3"` | `"local"` | No | File storage backend type |
|
|
391
|
+
| `STORAGE_TYPE` | `"local" \| "s3" \| "gcs"` | `"local"` | No | File storage backend type |
|
|
392
392
|
| `STORAGE_PATH` | `string` | — | No | Local storage directory path |
|
|
393
393
|
| `FORCE_LOCAL_STORAGE` | `"true" \| "false"` | — | No | Force local storage even in production |
|
|
394
394
|
| `S3_BUCKET` | `string` | — | When S3 | S3 bucket name |
|
|
@@ -397,6 +397,9 @@ When `extend` is provided, the base `rebaseEnvSchema` is merged (`.merge()`) wit
|
|
|
397
397
|
| `S3_SECRET_ACCESS_KEY` | `string` | — | When S3 | S3 secret key |
|
|
398
398
|
| `S3_ENDPOINT` | `string` (URL) | — | No | Custom S3 endpoint (MinIO, R2, etc.) |
|
|
399
399
|
| `S3_FORCE_PATH_STYLE` | `"true" \| "false"` | — | No | Use path-style S3 URLs |
|
|
400
|
+
| `GCS_BUCKET` | `string` | — | When GCS | GCS/Firebase Storage bucket name |
|
|
401
|
+
| `GCS_PROJECT_ID` | `string` | — | When GCS | GCP project ID |
|
|
402
|
+
| `GOOGLE_APPLICATION_CREDENTIALS` | `string` (path) | — | When GCS | Path to GCP service account JSON |
|
|
400
403
|
|
|
401
404
|
### Production Validations
|
|
402
405
|
|
|
@@ -431,14 +434,14 @@ import { initializeRebaseBackend, RebaseBackendConfig } from "@rebasepro/server-
|
|
|
431
434
|
|----------|------|---------|-------------|
|
|
432
435
|
| `server` | `Server` (Node `http.Server`) | — | **Required.** The HTTP server instance |
|
|
433
436
|
| `app` | `Hono<HonoEnv>` | — | **Required.** The Hono application instance |
|
|
434
|
-
| `collections` | `
|
|
437
|
+
| `collections` | `CollectionConfig[]` | `[]` | Inline collection definitions |
|
|
435
438
|
| `collectionsDir` | `string` | — | Directory to auto-discover collection files (used if `collections` is empty) |
|
|
436
439
|
| `basePath` | `string` | `"/api"` | Base path for all API routes |
|
|
437
440
|
| `database` | `DatabaseAdapter` | — | Database adapter (takes precedence over `bootstrappers`) |
|
|
438
441
|
| `bootstrappers` | `BackendBootstrapper[]` | `[]` | Database bootstrappers. Use one per engine for multiple engines in a single instance (e.g. Postgres + MongoDB); mark one `isDefault` |
|
|
439
442
|
| `dataSources` | `DataSourceDefinition[]` | `[]` | Declared data sources (`key`, `engine`, `transport`). Drives capabilities and the server-vs-direct distinction. Collections on a `direct`/`custom` transport are client-only — the backend skips data routes for them. Server engines need no entry |
|
|
440
443
|
| `auth` | `RebaseAuthConfig \| AuthAdapter` | — | Authentication config or pluggable adapter |
|
|
441
|
-
| `storage` | `BackendStorageConfig \| StorageController \| Record<string, ...>` | — | File storage configuration |
|
|
444
|
+
| `storage` | `BackendStorageConfig \| StorageController \| Record<string, ...>` | — | File storage configuration. Supports `"local"`, `"s3"`, and `"gcs"` (GCS/Firebase Storage) backends. Use `Record<string, StorageController>` for multi-backend setups with named sources |
|
|
442
445
|
| `history` | `unknown` | — | Entity history/audit-log configuration |
|
|
443
446
|
| `defaultSecurityRules` | `SecurityRule[]` | — | Default RLS rules for collections without their own |
|
|
444
447
|
| `enableSwagger` | `boolean` | `true` | Enable OpenAPI spec at `/api/docs` and Swagger UI at `/api/swagger` (dev only) |
|
|
@@ -456,7 +459,7 @@ import { initializeRebaseBackend, RebaseBackendConfig } from "@rebasepro/server-
|
|
|
456
459
|
|
|
457
460
|
| Property | Type | Default | Description |
|
|
458
461
|
|----------|------|---------|-------------|
|
|
459
|
-
| `collection` | `
|
|
462
|
+
| `collection` | `CollectionConfig` | `defaultUsersCollection` | The collection used for auth users |
|
|
460
463
|
| `jwtSecret` | `string` | — | JWT signing secret (≥32 chars) |
|
|
461
464
|
| `accessExpiresIn` | `string` | `"1h"` | Access token TTL |
|
|
462
465
|
| `refreshExpiresIn` | `string` | `"30d"` | Refresh token TTL |
|
|
@@ -546,6 +549,8 @@ await initializeRebaseBackend({
|
|
|
546
549
|
? { clientId: env.GOOGLE_CLIENT_ID }
|
|
547
550
|
: undefined,
|
|
548
551
|
},
|
|
552
|
+
// Single backend: { type: "local" | "s3" | "gcs" }
|
|
553
|
+
// Multi-backend: Record<string, StorageController> with named sources
|
|
549
554
|
storage: { type: env.STORAGE_TYPE },
|
|
550
555
|
defaultSecurityRules: [
|
|
551
556
|
{ operation: "select", access: "public" },
|
|
@@ -649,7 +654,7 @@ The Rebase MCP server provides these tools for AI agents. Use the MCP tool calli
|
|
|
649
654
|
| `rebase_schema_generate` | Generate Drizzle schema from collection definitions. Run after adding or modifying collection files | — |
|
|
650
655
|
| `rebase_schema_introspect` | Introspect the live database and generate Rebase collection definitions from existing tables | — |
|
|
651
656
|
| `rebase_db_push` | Apply the current Drizzle schema directly to the database (development shortcut, skips migration files) | — |
|
|
652
|
-
| `rebase_db_generate` | Generate SQL migration files from schema changes (compares current Drizzle schema against the last
|
|
657
|
+
| `rebase_db_generate` | Generate SQL migration files from schema changes (compares current Drizzle schema against the last entity) | — |
|
|
653
658
|
| `rebase_db_migrate` | Run all pending SQL migrations against the database | — |
|
|
654
659
|
|
|
655
660
|
### SDK
|