@rebasepro/agent-skills 0.8.0 → 0.9.1-canary.09aaf62
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/package.json +1 -1
- package/skills/rebase-admin/SKILL.md +70 -40
- package/skills/rebase-api/SKILL.md +24 -18
- package/skills/rebase-auth/SKILL.md +44 -22
- package/skills/rebase-backend-postgres/SKILL.md +22 -21
- package/skills/rebase-basics/SKILL.md +101 -58
- package/skills/rebase-collections/SKILL.md +48 -51
- package/skills/rebase-cron-jobs/SKILL.md +2 -2
- package/skills/rebase-custom-functions/SKILL.md +28 -1
- package/skills/rebase-deployment/SKILL.md +38 -8
- package/skills/rebase-design-language/SKILL.md +2 -2
- package/skills/rebase-email/SKILL.md +11 -11
- package/skills/rebase-entity-history/SKILL.md +13 -13
- package/skills/rebase-local-env-setup/SKILL.md +4 -4
- package/skills/rebase-realtime/SKILL.md +42 -6
- package/skills/rebase-sdk/SKILL.md +1 -1
- package/skills/rebase-security/SKILL.md +274 -245
- package/skills/rebase-storage/SKILL.md +110 -11
- package/skills/rebase-studio/SKILL.md +39 -40
- package/skills/rebase-webhooks/SKILL.md +63 -75
package/package.json
CHANGED
|
@@ -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
|
-
| Add custom top-level views | `<
|
|
21
|
-
| Open
|
|
20
|
+
| Add custom top-level views | `<RebaseAdmin views={[...]}>` | `@rebasepro/admin` |
|
|
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;
|
|
@@ -566,20 +566,20 @@ context.authController; // from RebaseContext
|
|
|
566
566
|
context.data; // DataSource from RebaseContext
|
|
567
567
|
```
|
|
568
568
|
|
|
569
|
-
> **TIP:** Use `useCMSContext()` instead of `useRebaseContext()` when you need CMS controllers (side panels, navigation, URL). Use `useRebaseContext()` from `@rebasepro/
|
|
569
|
+
> **TIP:** Use `useCMSContext()` instead of `useRebaseContext()` when you need CMS controllers (side panels, navigation, URL). Use `useRebaseContext()` from `@rebasepro/app` when you only need core context (auth, data, storage).
|
|
570
570
|
|
|
571
571
|
---
|
|
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({
|
|
@@ -642,7 +642,7 @@ function CreateButton() {
|
|
|
642
642
|
|
|
643
643
|
## 10. Custom Top-Level Views
|
|
644
644
|
|
|
645
|
-
Add custom pages to the main CMS navigation using the `views` prop on `<
|
|
645
|
+
Add custom pages to the main CMS navigation using the `views` prop on `<RebaseAdmin>`. Views appear alongside collections in the sidebar and home page.
|
|
646
646
|
|
|
647
647
|
### AppView Interface
|
|
648
648
|
|
|
@@ -663,7 +663,7 @@ interface AppView {
|
|
|
663
663
|
### Static Views
|
|
664
664
|
|
|
665
665
|
```tsx
|
|
666
|
-
<
|
|
666
|
+
<RebaseAdmin
|
|
667
667
|
collections={collections}
|
|
668
668
|
views={[
|
|
669
669
|
{ slug: "dashboard", name: "Dashboard", icon: "LayoutDashboard", view: <Dashboard /> },
|
|
@@ -678,7 +678,7 @@ interface AppView {
|
|
|
678
678
|
Pass a function instead of an array to dynamically resolve views based on the current user:
|
|
679
679
|
|
|
680
680
|
```tsx
|
|
681
|
-
<
|
|
681
|
+
<RebaseAdmin
|
|
682
682
|
collections={collections}
|
|
683
683
|
views={({ user, authController, data }) => [
|
|
684
684
|
{ slug: "dashboard", name: "Dashboard", icon: "LayoutDashboard", view: <Dashboard /> },
|
|
@@ -703,7 +703,7 @@ const myPlugin: RebasePlugin = {
|
|
|
703
703
|
]
|
|
704
704
|
};
|
|
705
705
|
|
|
706
|
-
<
|
|
706
|
+
<RebaseAdmin plugins={[myPlugin]} />
|
|
707
707
|
```
|
|
708
708
|
|
|
709
709
|
All views (CMS, builder, plugin) are merged in order: **CMS views → Studio dev views → Plugin views**.
|
|
@@ -730,7 +730,7 @@ The `roles` field provides declarative access control. When set, the view is exc
|
|
|
730
730
|
Views participate in the same navigation group system as collections. Use the `group` property on the view, or control grouping centrally via `navigationGroupMappings`:
|
|
731
731
|
|
|
732
732
|
```tsx
|
|
733
|
-
<
|
|
733
|
+
<RebaseAdmin
|
|
734
734
|
collections={collections}
|
|
735
735
|
views={[
|
|
736
736
|
{ slug: "dashboard", name: "Dashboard", view: <Dashboard />, group: "Analytics" },
|
|
@@ -745,19 +745,49 @@ Views participate in the same navigation group system as collections. Use the `g
|
|
|
745
745
|
|
|
746
746
|
---
|
|
747
747
|
|
|
748
|
+
## 11. Where the Admin Lives — Mounting Under a URL Prefix
|
|
749
|
+
|
|
750
|
+
In the default scaffold the frontend **is** the admin panel: `App.tsx` renders `<RebaseAuth>` + `<RebaseAdmin>` + `<RebaseShell>` at the root, so the deployed URL shows the admin directly. There is no separate admin URL — in production one server serves both the API (`/api/*`) and this SPA.
|
|
751
|
+
|
|
752
|
+
When a project ships its **own product app** as the frontend, the admin is mounted under a prefix (commonly `/admin`) instead. Split the Vite entry by URL so each app is lazy-loaded and product visitors never download the admin bundle:
|
|
753
|
+
|
|
754
|
+
```tsx
|
|
755
|
+
// frontend/src/main.tsx
|
|
756
|
+
const isAdmin = window.location.pathname.startsWith("/admin");
|
|
757
|
+
const ProductApp = lazy(() => import("./App"));
|
|
758
|
+
const AdminApp = lazy(() => import("./AdminApp"));
|
|
759
|
+
|
|
760
|
+
if (isAdmin) {
|
|
761
|
+
// The admin uses useBlocker → needs a DATA router
|
|
762
|
+
const router = createBrowserRouter([{ path: "/admin/*", element: <AdminApp /> }]);
|
|
763
|
+
root.render(<RouterProvider router={router} />);
|
|
764
|
+
} else {
|
|
765
|
+
root.render(<BrowserRouter><ProductApp /></BrowserRouter>);
|
|
766
|
+
}
|
|
767
|
+
```
|
|
768
|
+
|
|
769
|
+
```tsx
|
|
770
|
+
// frontend/src/AdminApp.tsx — tell the CMS about the prefix
|
|
771
|
+
<RebaseAdmin collections={collections} basePath="/admin" />
|
|
772
|
+
```
|
|
773
|
+
|
|
774
|
+
> **IMPORTANT FOR AGENTS:** Choose **either** a router `basename="/admin"` **or** `<RebaseAdmin basePath="/admin">` — never both, or the prefix is applied twice. Without either, collection views hang on a spinner because URL⇄collection resolution never matches. `<RebaseAdmin>` requires a **data router** (`createBrowserRouter`) because it uses `useBlocker`.
|
|
775
|
+
|
|
776
|
+
---
|
|
777
|
+
|
|
748
778
|
## Exported Components
|
|
749
779
|
|
|
750
780
|
The admin package exports the following components (from `@rebasepro/admin`):
|
|
751
781
|
|
|
752
782
|
| Component | Description |
|
|
753
783
|
|-----------|-------------|
|
|
754
|
-
| `
|
|
784
|
+
| `RebaseAdmin` | Declarative CMS config (collections, views, editor) — renders nothing |
|
|
755
785
|
| `RebaseShell` | App shell (drawer, nav, routes, layout) — renders the actual UI |
|
|
756
786
|
| `CollectionPanel` | Embed a collection view inside custom pages |
|
|
757
|
-
| `
|
|
758
|
-
| `
|
|
787
|
+
| `DataCollectionView` | The collection view component |
|
|
788
|
+
| `EntityCustomView` | Entity detail/edit view |
|
|
759
789
|
| `EntityPreview` | Reference/relation preview chip |
|
|
760
|
-
| `EntityCard` | Card representation of
|
|
790
|
+
| `EntityCard` | Card representation of a entity |
|
|
761
791
|
| `SideDialogs` | Side dialog container |
|
|
762
792
|
| `SideEntityProvider` | Context provider for side entity controller |
|
|
763
793
|
| `EntitySelectionTable` | Table for selecting entities |
|
|
@@ -773,16 +803,16 @@ The admin package exports the following components (from `@rebasepro/admin`):
|
|
|
773
803
|
|
|
774
804
|
| Hook | Description |
|
|
775
805
|
|------|-------------|
|
|
776
|
-
| `
|
|
806
|
+
| `useSidePanel()` | Open/close entity side panels |
|
|
777
807
|
| `useSideDialogsController()` | Open/close generic side dialogs |
|
|
778
808
|
| `useUrlController()` | Build URLs and navigate |
|
|
779
809
|
| `useNavigationStateController()` | Access navigation state |
|
|
780
810
|
| `useCollectionRegistryController()` | Look up collections by slug |
|
|
781
811
|
| `useBreadcrumbsController()` | Read/set breadcrumbs |
|
|
782
812
|
| `useCMSContext()` | Full CMS context (core + CMS controllers) |
|
|
783
|
-
| `
|
|
813
|
+
| `useSelectionDialog()` | Open entity selection dialog |
|
|
784
814
|
| `useSelectionController()` | Multi-select controller |
|
|
785
|
-
| `
|
|
815
|
+
| `useHistory()` | Entity version history |
|
|
786
816
|
| `useApp()` | App-level utilities |
|
|
787
817
|
|
|
788
818
|
## Exported Utilities
|
|
@@ -796,8 +826,8 @@ The admin package exports the following components (from `@rebasepro/admin`):
|
|
|
796
826
|
| `getLastSegment(path)` | Get last path segment |
|
|
797
827
|
| `getCollectionBySlugWithin(collections, slug)` | Find collection in array |
|
|
798
828
|
| `mergeEntityActions(...)` | Merge entity action arrays |
|
|
799
|
-
| `resolveEntityAction(...)` | Resolve
|
|
800
|
-
| `resolveEntityView(...)` | Resolve
|
|
829
|
+
| `resolveEntityAction(...)` | Resolve a entity action |
|
|
830
|
+
| `resolveEntityView(...)` | Resolve a entity view |
|
|
801
831
|
| `isReferenceProperty(prop)` | Check if property is a reference |
|
|
802
832
|
| `isRelationProperty(prop)` | Check if property is a relation |
|
|
803
833
|
| `getIconForProperty(prop)` | Get icon for a property type |
|
|
@@ -5,7 +5,7 @@ description: Guide for working with Rebase auto-generated REST and GraphQL APIs.
|
|
|
5
5
|
|
|
6
6
|
# Rebase Auto-Generated APIs
|
|
7
7
|
|
|
8
|
-
> **WARNING FOR AGENTS**: If you are writing a script or data task, **default to using the Rebase SDK** (`@rebasepro/client` or `@rebasepro/server
|
|
8
|
+
> **WARNING FOR AGENTS**: If you are writing a script or data task, **default to using the Rebase SDK** (`@rebasepro/client` or `@rebasepro/server`) instead of making raw REST or GraphQL API calls (`fetch` / `curl`). For custom backend functions, use `client.functions.invoke('function-name', payload)` — **NEVER** manually construct `/api/functions/` URLs or extract tokens from localStorage. Only use raw API calls if specifically instructed to do so or if you are demonstrating HTTP usage to the user.
|
|
9
9
|
|
|
10
10
|
Every collection defined in Rebase automatically gets full REST CRUD and GraphQL endpoints. No manual route creation needed.
|
|
11
11
|
|
|
@@ -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
|
|
|
@@ -337,11 +337,17 @@ Authorization: Bearer rk_live_abc123...
|
|
|
337
337
|
|
|
338
338
|
If an API key lacks the required permission for an operation, a `403 API_KEY_FORBIDDEN` error is returned.
|
|
339
339
|
|
|
340
|
-
|
|
340
|
+
Beyond collections, the permission list also covers custom functions
|
|
341
|
+
(`"functions"` for all, `"functions/<name>"` for one) and file storage
|
|
342
|
+
(`"storage"`); the global `"*"` wildcard grants all three. API keys do NOT
|
|
343
|
+
bypass RLS: admin keys pass via the built-in admin policies, while non-admin
|
|
344
|
+
keys only see rows a security rule grants to the `service` role or the public.
|
|
345
|
+
|
|
346
|
+
**Admin API keys** — set `"admin": true` when creating a key to grant it the `admin` role. This gives access to all `/api/admin/*` routes (schema, users, other API keys, etc.) plus cron, backups, and logs. Use this for agents, MCP servers, and CI pipelines:
|
|
341
347
|
|
|
342
348
|
```bash
|
|
343
|
-
# CLI
|
|
344
|
-
rebase api-keys create --name "My Agent" --admin
|
|
349
|
+
# CLI (an explicit scope is required: --permissions '<json>' or --full-access)
|
|
350
|
+
rebase api-keys create --name "My Agent" --admin --full-access
|
|
345
351
|
|
|
346
352
|
# REST
|
|
347
353
|
POST /api/admin/api-keys
|
|
@@ -405,7 +411,7 @@ curl -H "Authorization: Bearer $TOKEN" \
|
|
|
405
411
|
"https://example.com/api/data/products?status=eq.active&price=gte.50&orderBy=created_at:desc&limit=10&offset=0&include=category"
|
|
406
412
|
```
|
|
407
413
|
|
|
408
|
-
### Create
|
|
414
|
+
### Create a entity
|
|
409
415
|
|
|
410
416
|
```bash
|
|
411
417
|
curl -X POST \
|
|
@@ -415,7 +421,7 @@ curl -X POST \
|
|
|
415
421
|
"https://example.com/api/data/products"
|
|
416
422
|
```
|
|
417
423
|
|
|
418
|
-
### Update
|
|
424
|
+
### Update a entity
|
|
419
425
|
|
|
420
426
|
```bash
|
|
421
427
|
curl -X PUT \
|
|
@@ -425,7 +431,7 @@ curl -X PUT \
|
|
|
425
431
|
"https://example.com/api/data/products/uuid-123"
|
|
426
432
|
```
|
|
427
433
|
|
|
428
|
-
### Delete
|
|
434
|
+
### Delete a entity
|
|
429
435
|
|
|
430
436
|
```bash
|
|
431
437
|
curl -X DELETE \
|
|
@@ -655,19 +661,19 @@ GET /api/collections
|
|
|
655
661
|
| `pagination.maxLimit` | `number` | `100` | Maximum allowed page size |
|
|
656
662
|
| `cors.origin` | `string \| string[] \| boolean` | — | CORS origin configuration |
|
|
657
663
|
| `cors.credentials` | `boolean` | `false` | Allow credentials in CORS |
|
|
658
|
-
| `collections` | `
|
|
664
|
+
| `collections` | `CollectionConfig[]` | `[]` | Collections to generate APIs for |
|
|
659
665
|
| `collectionsDir` | `string` | — | Directory to auto-discover collections |
|
|
660
666
|
|
|
661
667
|
## References
|
|
662
668
|
|
|
663
669
|
- **Documentation:** [rebase.pro/docs](https://rebase.pro/docs)
|
|
664
670
|
- **GitHub:** [github.com/rebasepro/rebase](https://github.com/rebasepro/rebase)
|
|
665
|
-
- **REST API Generator:** `packages/server
|
|
666
|
-
- **Query Parser:** `packages/server
|
|
667
|
-
- **GraphQL Generator:** `packages/server
|
|
668
|
-
- **OpenAPI Generator:** `packages/server
|
|
669
|
-
- **Error Handling:** `packages/server
|
|
670
|
-
- **Server Setup:** `packages/server
|
|
671
|
-
- **API Types:** `packages/server
|
|
672
|
-
- **Auth Middleware:** `packages/server
|
|
671
|
+
- **REST API Generator:** `packages/server/src/api/rest/api-generator.ts`
|
|
672
|
+
- **Query Parser:** `packages/server/src/api/rest/query-parser.ts`
|
|
673
|
+
- **GraphQL Generator:** `packages/server/src/api/graphql/graphql-schema-generator.ts`
|
|
674
|
+
- **OpenAPI Generator:** `packages/server/src/api/openapi-generator.ts`
|
|
675
|
+
- **Error Handling:** `packages/server/src/api/errors.ts`
|
|
676
|
+
- **Server Setup:** `packages/server/src/api/server.ts`
|
|
677
|
+
- **API Types:** `packages/server/src/api/types.ts`
|
|
678
|
+
- **Auth Middleware:** `packages/server/src/auth/middleware.ts`
|
|
673
679
|
- **DataHooks Types:** `packages/types/src/types/backend_hooks.ts`
|
|
@@ -39,12 +39,13 @@ Authentication is configured via the `auth` property of `initializeRebaseBackend
|
|
|
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
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. |
|
|
@@ -66,8 +67,8 @@ Authentication is configured via the `auth` property of `initializeRebaseBackend
|
|
|
66
67
|
### Minimal Example
|
|
67
68
|
|
|
68
69
|
```typescript
|
|
69
|
-
import { initializeRebaseBackend } from "@rebasepro/server
|
|
70
|
-
import { createPostgresAdapter } from "@rebasepro/server-
|
|
70
|
+
import { initializeRebaseBackend } from "@rebasepro/server";
|
|
71
|
+
import { createPostgresAdapter } from "@rebasepro/server-postgres";
|
|
71
72
|
|
|
72
73
|
await initializeRebaseBackend({
|
|
73
74
|
server,
|
|
@@ -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
|
|
@@ -208,7 +230,7 @@ You can register any OAuth provider by implementing the `OAuthProvider<T>` inter
|
|
|
208
230
|
|
|
209
231
|
```typescript
|
|
210
232
|
import { z } from "zod";
|
|
211
|
-
import type { OAuthProvider, OAuthProviderProfile } from "@rebasepro/server
|
|
233
|
+
import type { OAuthProvider, OAuthProviderProfile } from "@rebasepro/server";
|
|
212
234
|
|
|
213
235
|
const myProvider: OAuthProvider<{ token: string }> = {
|
|
214
236
|
id: "my-provider",
|
|
@@ -446,7 +468,7 @@ By default API keys get the `service` role (data access only). Set `"admin": tru
|
|
|
446
468
|
|
|
447
469
|
```bash
|
|
448
470
|
# CLI — create an admin API key
|
|
449
|
-
rebase api-keys create --name "My Agent" --admin
|
|
471
|
+
rebase api-keys create --name "My Agent" --admin --full-access
|
|
450
472
|
|
|
451
473
|
# REST
|
|
452
474
|
curl -X POST http://localhost:3000/api/admin/api-keys \
|
|
@@ -602,7 +624,7 @@ rebase api-keys list
|
|
|
602
624
|
rebase api-keys create --name "Read Only" --permissions '[{"collection":"orders","operations":["read"]}]'
|
|
603
625
|
|
|
604
626
|
# Create an admin key (for agents / MCP / CI)
|
|
605
|
-
rebase api-keys create --name "My Agent" --admin
|
|
627
|
+
rebase api-keys create --name "My Agent" --admin --full-access
|
|
606
628
|
|
|
607
629
|
# Revoke a key
|
|
608
630
|
rebase api-keys revoke <key-id>
|
|
@@ -859,7 +881,7 @@ API keys use a service identity for RLS scoping: `uid: "api-key:{id}"`, `roles:
|
|
|
859
881
|
|
|
860
882
|
### Reserved System Identities
|
|
861
883
|
|
|
862
|
-
The auth middleware assigns these reserved identities automatically. They are visible in `context.user` (
|
|
884
|
+
The auth middleware assigns these reserved identities automatically. They are visible in `context.user` (Collection Callbacks / DataHooks) and `c.get("user")` (custom functions):
|
|
863
885
|
|
|
864
886
|
| Auth Method | `userId` | `roles` | When It Occurs |
|
|
865
887
|
|---|---|---|---|
|
|
@@ -870,7 +892,7 @@ The auth middleware assigns these reserved identities automatically. They are vi
|
|
|
870
892
|
| Anonymous | `"anon"` | `["anon"]` | Unauthenticated when `requireAuth: false` |
|
|
871
893
|
| No token + `requireAuth: true` | — | — | **Rejected (401)** |
|
|
872
894
|
|
|
873
|
-
> **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
|
|
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.
|
|
874
896
|
|
|
875
897
|
---
|
|
876
898
|
|
|
@@ -914,7 +936,7 @@ API keys have their own per-key rate limiter. The `rate_limit` on each key speci
|
|
|
914
936
|
### Custom Rate Limiter
|
|
915
937
|
|
|
916
938
|
```typescript
|
|
917
|
-
import { createRateLimiter } from "@rebasepro/server
|
|
939
|
+
import { createRateLimiter } from "@rebasepro/server";
|
|
918
940
|
|
|
919
941
|
const myLimiter = createRateLimiter({
|
|
920
942
|
windowMs: 60 * 1000, // 1 minute
|
|
@@ -968,7 +990,7 @@ interface AuthenticatedUser {
|
|
|
968
990
|
The simplest way to plug an existing auth system into Rebase. Only `verifyRequest` is required:
|
|
969
991
|
|
|
970
992
|
```typescript
|
|
971
|
-
import { createCustomAuthAdapter } from "@rebasepro/server
|
|
993
|
+
import { createCustomAuthAdapter } from "@rebasepro/server";
|
|
972
994
|
import jwt from "jsonwebtoken";
|
|
973
995
|
|
|
974
996
|
const auth = createCustomAuthAdapter({
|
|
@@ -1092,7 +1114,7 @@ Admin user and role management is handled via dedicated admin routes (mounted un
|
|
|
1092
1114
|
|
|
1093
1115
|
## Backend Hooks
|
|
1094
1116
|
|
|
1095
|
-
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`.
|
|
1096
1118
|
|
|
1097
1119
|
### BackendHooks Interface
|
|
1098
1120
|
|
|
@@ -1256,7 +1278,7 @@ When a request includes `Authorization: Bearer <serviceKey>`:
|
|
|
1256
1278
|
- Comparison is done with constant-time comparison to prevent timing attacks.
|
|
1257
1279
|
- Must be ≥ 32 characters (validated at startup).
|
|
1258
1280
|
|
|
1259
|
-
> **TIP:** In
|
|
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.
|
|
1260
1282
|
|
|
1261
1283
|
### Token Rotation
|
|
1262
1284
|
|
|
@@ -1288,14 +1310,14 @@ All auth endpoints validate input with Zod schemas:
|
|
|
1288
1310
|
|
|
1289
1311
|
## References
|
|
1290
1312
|
|
|
1291
|
-
- Source: `packages/server
|
|
1292
|
-
- Source: `packages/server
|
|
1293
|
-
- Source: `packages/server
|
|
1294
|
-
- Source: `packages/server
|
|
1295
|
-
- Source: `packages/server
|
|
1296
|
-
- Source: `packages/server
|
|
1313
|
+
- Source: `packages/server/src/auth/` — All auth implementation
|
|
1314
|
+
- Source: `packages/server/src/auth/routes.ts` — REST auth endpoints
|
|
1315
|
+
- Source: `packages/server/src/auth/auth-hooks.ts` — Lifecycle hooks
|
|
1316
|
+
- Source: `packages/server/src/auth/api-keys/` — API key system
|
|
1317
|
+
- Source: `packages/server/src/auth/rate-limiter.ts` — Rate limiting
|
|
1318
|
+
- Source: `packages/server/src/init.ts` — `RebaseAuthConfig` and backend init
|
|
1297
1319
|
- Source: `packages/client/src/auth.ts` — Client SDK auth module
|
|
1298
1320
|
- Source: `packages/types/src/types/auth_adapter.ts` — `AuthAdapter` interface
|
|
1299
|
-
- Source: `packages/server
|
|
1300
|
-
- Source: `packages/server
|
|
1321
|
+
- Source: `packages/server/src/auth/rls-scope.ts` — RLS scoping
|
|
1322
|
+
- Source: `packages/server/src/email/types.ts` — Email configuration
|
|
1301
1323
|
- **Reserved Identities**: `"service"` / `"anon"` / `"api-key:{id}"` — see [Row-Level Security > Reserved System Identities](#reserved-system-identities)
|