@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rebasepro/agent-skills",
3
- "version": "0.8.0",
3
+ "version": "0.9.1-canary.09aaf62",
4
4
  "private": false,
5
5
  "description": "Bundled AI agent skills for Rebase",
6
6
  "type": "module",
@@ -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 an 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.
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 | `useSideEntityController()` | `@rebasepro/admin` |
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 | `<RebaseCMS views={[...]}>` | `@rebasepro/admin` |
21
- | Open an entity selection dialog | `useEntitySelectionDialog()` | `@rebasepro/admin` |
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 `useSideEntityController()` to open, replace, or close entity side panels (the sliding drawer that shows entity forms).
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 { useSideEntityController } from "@rebasepro/admin";
34
+ import { useSidePanel } from "@rebasepro/admin";
35
35
  ```
36
36
 
37
- ### SideEntityController Interface
37
+ ### SidePanelController Interface
38
38
 
39
39
  ```typescript
40
- interface SideEntityController {
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?: EntityCollection<M>;
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 = useSideEntityController();
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 EntityCollection = EntityCollection
239
+ EC extends CollectionConfig = CollectionConfig
240
240
  > = {
241
241
  /** All registered collections */
242
- collections?: EntityCollection[];
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<EntityCollection>;
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 `useEntitySelectionDialog()` to open a side dialog for selecting entities (same mechanism used by reference fields).
359
+ Use `useSelectionDialog()` to open a side dialog for selecting entities (same mechanism used by reference fields).
360
360
 
361
361
  ```typescript
362
- import { useEntitySelectionDialog } from "@rebasepro/admin";
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 } = useEntitySelectionDialog<Product>({
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 `EntitySelectionProps` except `path` (which you pass separately), plus an `onClose` callback.
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: 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/core` when you only need core context (auth, data, storage).
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 an entity
575
+ ### Navigate to a collection and open a entity
576
576
 
577
577
  ```tsx
578
- import { useUrlController, useSideEntityController } from "@rebasepro/admin";
578
+ import { useUrlController, useSidePanel } from "@rebasepro/admin";
579
579
 
580
580
  function navigateAndOpen() {
581
581
  const urlController = useUrlController();
582
- const sideEntityController = useSideEntityController();
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 { useSideEntityController } from "@rebasepro/admin";
598
+ import { useSidePanel } from "@rebasepro/admin";
599
599
 
600
600
  function MyCustomView() {
601
- const sideEntityController = useSideEntityController();
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 { useSideEntityController } from "@rebasepro/admin";
618
+ import { useSidePanel } from "@rebasepro/admin";
619
619
 
620
620
  function CreateButton() {
621
- const sideEntity = useSideEntityController();
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 `<RebaseCMS>`. Views appear alongside collections in the sidebar and home page.
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
- <RebaseCMS
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
- <RebaseCMS
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
- <RebaseCMS plugins={[myPlugin]} />
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
- <RebaseCMS
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
- | `RebaseCMS` | Declarative CMS config (collections, views, editor) — renders nothing |
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
- | `EntityCollectionView` | The collection view component |
758
- | `EntityView` | Entity detail/edit view |
787
+ | `DataCollectionView` | The collection view component |
788
+ | `EntityCustomView` | Entity detail/edit view |
759
789
  | `EntityPreview` | Reference/relation preview chip |
760
- | `EntityCard` | Card representation of an entity |
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
- | `useSideEntityController()` | Open/close entity side panels |
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
- | `useEntitySelectionDialog()` | Open entity selection dialog |
813
+ | `useSelectionDialog()` | Open entity selection dialog |
784
814
  | `useSelectionController()` | Multi-select controller |
785
- | `useEntityHistory()` | Entity version history |
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 an entity action |
800
- | `resolveEntityView(...)` | Resolve an entity view |
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-core`) 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.
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 an entity | `200` |
47
- | `DELETE` | `/api/data/{slug}/:id` | Delete an entity | `204` |
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
- **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.). Use this for agents, MCP servers, and CI pipelines:
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 an entity
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 an entity
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 an entity
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` | `EntityCollection[]` | `[]` | Collections to generate APIs for |
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-core/src/api/rest/api-generator.ts`
666
- - **Query Parser:** `packages/server-core/src/api/rest/query-parser.ts`
667
- - **GraphQL Generator:** `packages/server-core/src/api/graphql/graphql-schema-generator.ts`
668
- - **OpenAPI Generator:** `packages/server-core/src/api/openapi-generator.ts`
669
- - **Error Handling:** `packages/server-core/src/api/errors.ts`
670
- - **Server Setup:** `packages/server-core/src/api/server.ts`
671
- - **API Types:** `packages/server-core/src/api/types.ts`
672
- - **Auth Middleware:** `packages/server-core/src/auth/middleware.ts`
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` | `EntityCollection` | 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. |
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-core";
70
- import { createPostgresAdapter } from "@rebasepro/server-postgresql";
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 { PostgresCollection } from "@rebasepro/types";
111
+ import { PostgresCollectionConfig } from "@rebasepro/types";
111
112
 
112
- const membersCollection: PostgresCollection = {
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-core";
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` (Entity Callbacks / DataHooks) and `c.get("user")` (custom functions):
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 Entity Callbacks fire with `userId: "service"`, `roles: ["admin"]`. This lets developers distinguish server-internal reads from end-user reads in callbacks.
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-core";
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-core";
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 `EntityCallbacks`.
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 Entity 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.
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-core/src/auth/` — All auth implementation
1292
- - Source: `packages/server-core/src/auth/routes.ts` — REST auth endpoints
1293
- - Source: `packages/server-core/src/auth/auth-hooks.ts` — Lifecycle hooks
1294
- - Source: `packages/server-core/src/auth/api-keys/` — API key system
1295
- - Source: `packages/server-core/src/auth/rate-limiter.ts` — Rate limiting
1296
- - Source: `packages/server-core/src/init.ts` — `RebaseAuthConfig` and backend init
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-core/src/auth/rls-scope.ts` — RLS scoping
1300
- - Source: `packages/server-core/src/email/types.ts` — Email configuration
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)