@rebasepro/agent-skills 0.9.0 → 0.9.1-canary.0de22e0

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.9.0",
3
+ "version": "0.9.1-canary.0de22e0",
4
4
  "private": false,
5
5
  "description": "Bundled AI agent skills for Rebase",
6
6
  "type": "module",
@@ -17,7 +17,7 @@ The `@rebasepro/admin` package provides the CMS layer for Rebase. It handles col
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` |
20
+ | Add custom top-level views | `<RebaseAdmin views={[...]}>` | `@rebasepro/admin` |
21
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` |
@@ -566,7 +566,7 @@ 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
 
@@ -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,13 +745,43 @@ 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
787
  | `DataCollectionView` | The collection view component |
@@ -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
 
@@ -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
@@ -662,12 +668,12 @@ GET /api/collections
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`
@@ -67,8 +67,8 @@ Authentication is configured via the `auth` property of `initializeRebaseBackend
67
67
  ### Minimal Example
68
68
 
69
69
  ```typescript
70
- import { initializeRebaseBackend } from "@rebasepro/server-core";
71
- import { createPostgresAdapter } from "@rebasepro/server-postgresql";
70
+ import { initializeRebaseBackend } from "@rebasepro/server";
71
+ import { createPostgresAdapter } from "@rebasepro/server-postgres";
72
72
 
73
73
  await initializeRebaseBackend({
74
74
  server,
@@ -219,18 +219,55 @@ Twitter uses OAuth 2.0 with PKCE. The client must send `codeVerifier` alongside
219
219
 
220
220
  ### OAuth Account Linking
221
221
 
222
- When an OAuth user signs in:
223
- 1. If an identity record exists for `(providerId, provider)` → log in that user.
224
- 2. If no identity exists but a user with the same email exists **link** the provider to the existing account.
222
+ When an OAuth user signs in via `POST /api/auth/{provider}`:
223
+
224
+ 1. If an identity record exists for `(provider, providerId)` log in that user. The email is not consulted.
225
+ 2. If no identity exists but a user with the same email exists:
226
+ - **The provider asserted `emailVerified: true`** → **link** the provider to the existing account and log in as that user. One account, two sign-in methods.
227
+ - **The provider did NOT verify the email** → reject with `403 EMAIL_NOT_VERIFIED`. Nothing is created or modified.
225
228
  3. If neither exists → create a new user, link the identity, assign `defaultRole`.
226
229
 
230
+ > **IMPORTANT FOR AGENTS:** A second account is **never** silently created for
231
+ > an email that already exists. If asked "does signing in with Google create a
232
+ > duplicate user?", the answer is no — it either links (verified) or errors
233
+ > (unverified). This is **not configurable**; there is deliberately no option to
234
+ > auto-link on unverified emails, because that would let anyone who can make a
235
+ > provider emit an address they don't own take over the matching account.
236
+ > Google always asserts `email_verified` for real Google accounts, so linking
237
+ > is the normal path for Google sign-in.
238
+
239
+ ### Linking a Provider to a Signed-In Account
240
+
241
+ `POST /api/auth/link/{provider}` attaches a provider identity to the **already
242
+ authenticated** account (requires `Authorization: Bearer <token>`). The body is
243
+ the same payload the provider's sign-in route takes, e.g. `{ idToken }`.
244
+
245
+ This is the escape hatch from an `EMAIL_NOT_VERIFIED` rejection, and the way to
246
+ attach a provider whose email differs from the account's.
247
+
248
+ Unlike sign-in, linking here does **not** require a verified email and does not
249
+ require the emails to match — on sign-in the provider's email is the only
250
+ evidence tying the identity to an account, whereas here the caller has already
251
+ proven ownership by holding a valid session.
252
+
253
+ - `409 IDENTITY_ALREADY_LINKED` if that provider identity belongs to another user.
254
+ - Idempotent (`alreadyLinked: true`) if already linked to the caller.
255
+
256
+ ### Adding a Password to a Provider-Only Account
257
+
258
+ A user who signed up via OAuth has no `passwordHash`:
259
+
260
+ - `POST /auth/register` with the same email → `409 EMAIL_EXISTS`.
261
+ - `POST /auth/change-password` → `400 INVALID_ACCOUNT` (no existing password to verify).
262
+ - **`forgot-password` → `reset-password` is the supported path.** It re-proves ownership of the address by email, after which the account has both sign-in methods.
263
+
227
264
  ### Custom OAuth Provider
228
265
 
229
266
  You can register any OAuth provider by implementing the `OAuthProvider<T>` interface:
230
267
 
231
268
  ```typescript
232
269
  import { z } from "zod";
233
- import type { OAuthProvider, OAuthProviderProfile } from "@rebasepro/server-core";
270
+ import type { OAuthProvider, OAuthProviderProfile } from "@rebasepro/server";
234
271
 
235
272
  const myProvider: OAuthProvider<{ token: string }> = {
236
273
  id: "my-provider",
@@ -468,7 +505,7 @@ By default API keys get the `service` role (data access only). Set `"admin": tru
468
505
 
469
506
  ```bash
470
507
  # CLI — create an admin API key
471
- rebase api-keys create --name "My Agent" --admin
508
+ rebase api-keys create --name "My Agent" --admin --full-access
472
509
 
473
510
  # REST
474
511
  curl -X POST http://localhost:3000/api/admin/api-keys \
@@ -624,7 +661,7 @@ rebase api-keys list
624
661
  rebase api-keys create --name "Read Only" --permissions '[{"collection":"orders","operations":["read"]}]'
625
662
 
626
663
  # Create an admin key (for agents / MCP / CI)
627
- rebase api-keys create --name "My Agent" --admin
664
+ rebase api-keys create --name "My Agent" --admin --full-access
628
665
 
629
666
  # Revoke a key
630
667
  rebase api-keys revoke <key-id>
@@ -659,6 +696,7 @@ All auth endpoints are mounted under `/api/auth`. Admin endpoints are under `/ap
659
696
  | `PATCH` | `/auth/me` | Required | Update profile. Body: `{ displayName?, photoURL? }`. |
660
697
  | `POST` | `/auth/change-password` | Required | Change password. Body: `{ oldPassword, newPassword }`. Invalidates all sessions. |
661
698
  | `POST` | `/auth/send-verification` | Required | Send email verification link. Requires email service. |
699
+ | `POST` | `/auth/link/{provider}` | Required | Link an OAuth provider to the current account. Body: the provider's sign-in payload (e.g. `{ idToken }`). `409 IDENTITY_ALREADY_LINKED` if it belongs to another user. |
662
700
  | `GET` | `/auth/sessions` | Required | List active sessions (refresh tokens). |
663
701
  | `DELETE` | `/auth/sessions` | Required | Revoke all sessions (remote logout). |
664
702
  | `DELETE` | `/auth/sessions/:id` | Required | Revoke a specific session. |
@@ -936,7 +974,7 @@ API keys have their own per-key rate limiter. The `rate_limit` on each key speci
936
974
  ### Custom Rate Limiter
937
975
 
938
976
  ```typescript
939
- import { createRateLimiter } from "@rebasepro/server-core";
977
+ import { createRateLimiter } from "@rebasepro/server";
940
978
 
941
979
  const myLimiter = createRateLimiter({
942
980
  windowMs: 60 * 1000, // 1 minute
@@ -990,7 +1028,7 @@ interface AuthenticatedUser {
990
1028
  The simplest way to plug an existing auth system into Rebase. Only `verifyRequest` is required:
991
1029
 
992
1030
  ```typescript
993
- import { createCustomAuthAdapter } from "@rebasepro/server-core";
1031
+ import { createCustomAuthAdapter } from "@rebasepro/server";
994
1032
  import jwt from "jsonwebtoken";
995
1033
 
996
1034
  const auth = createCustomAuthAdapter({
@@ -1310,14 +1348,14 @@ All auth endpoints validate input with Zod schemas:
1310
1348
 
1311
1349
  ## References
1312
1350
 
1313
- - Source: `packages/server-core/src/auth/` — All auth implementation
1314
- - Source: `packages/server-core/src/auth/routes.ts` — REST auth endpoints
1315
- - Source: `packages/server-core/src/auth/auth-hooks.ts` — Lifecycle hooks
1316
- - Source: `packages/server-core/src/auth/api-keys/` — API key system
1317
- - Source: `packages/server-core/src/auth/rate-limiter.ts` — Rate limiting
1318
- - Source: `packages/server-core/src/init.ts` — `RebaseAuthConfig` and backend init
1351
+ - Source: `packages/server/src/auth/` — All auth implementation
1352
+ - Source: `packages/server/src/auth/routes.ts` — REST auth endpoints
1353
+ - Source: `packages/server/src/auth/auth-hooks.ts` — Lifecycle hooks
1354
+ - Source: `packages/server/src/auth/api-keys/` — API key system
1355
+ - Source: `packages/server/src/auth/rate-limiter.ts` — Rate limiting
1356
+ - Source: `packages/server/src/init.ts` — `RebaseAuthConfig` and backend init
1319
1357
  - Source: `packages/client/src/auth.ts` — Client SDK auth module
1320
1358
  - Source: `packages/types/src/types/auth_adapter.ts` — `AuthAdapter` interface
1321
- - Source: `packages/server-core/src/auth/rls-scope.ts` — RLS scoping
1322
- - Source: `packages/server-core/src/email/types.ts` — Email configuration
1359
+ - Source: `packages/server/src/auth/rls-scope.ts` — RLS scoping
1360
+ - Source: `packages/server/src/email/types.ts` — Email configuration
1323
1361
  - **Reserved Identities**: `"service"` / `"anon"` / `"api-key:{id}"` — see [Row-Level Security > Reserved System Identities](#reserved-system-identities)
@@ -5,7 +5,7 @@ description: Guide for setting up and managing the Rebase PostgreSQL backend wit
5
5
 
6
6
  # Rebase PostgreSQL Backend
7
7
 
8
- > **WARNING FOR AGENTS**: If you are writing a script or performing data tasks (e.g., seeding, migrating content), **default to using the Rebase SDK** (`@rebasepro/client` or `@rebasepro/server-core`). **NEVER** use `psql` or raw SQL to manipulate data directly unless specifically instructed to do so for low-level debugging. Bypassing the SDK circumvents schema validation, access controls, and lifecycle hooks.
8
+ > **WARNING FOR AGENTS**: If you are writing a script or performing data tasks (e.g., seeding, migrating content), **default to using the Rebase SDK** (`@rebasepro/client` or `@rebasepro/server`). **NEVER** use `psql` or raw SQL to manipulate data directly unless specifically instructed to do so for low-level debugging. Bypassing the SDK circumvents schema validation, access controls, and lifecycle hooks.
9
9
 
10
10
  Rebase uses PostgreSQL as its primary database, with Drizzle ORM for type-safe schema management and migrations.
11
11
 
@@ -67,20 +67,20 @@ rebase db migrate
67
67
 
68
68
  | Package | Purpose |
69
69
  |---------|---------|
70
- | `@rebasepro/server-core` | Hono server coordinator, API generation, auth, storage, env validation |
71
- | `@rebasepro/server-postgresql` | PostgreSQL bootstrapper, data driver, connection helpers, realtime (LISTEN/NOTIFY) |
70
+ | `@rebasepro/server` | Hono server coordinator, API generation, auth, storage, env validation |
71
+ | `@rebasepro/server-postgres` | PostgreSQL bootstrapper, data driver, connection helpers, realtime (LISTEN/NOTIFY) |
72
72
  | `@rebasepro/types` | Shared TypeScript type definitions (`PostgresCollectionConfig`, etc.) |
73
73
 
74
74
  ## Connection Functions
75
75
 
76
- All connection functions are exported from `@rebasepro/server-postgresql`.
76
+ All connection functions are exported from `@rebasepro/server-postgres`.
77
77
 
78
78
  ### createPostgresDatabaseConnection()
79
79
 
80
80
  The primary connection factory. Creates a Drizzle-backed Postgres connection with a production-grade pool.
81
81
 
82
82
  ```typescript
83
- import { createPostgresDatabaseConnection } from "@rebasepro/server-postgresql";
83
+ import { createPostgresDatabaseConnection } from "@rebasepro/server-postgres";
84
84
 
85
85
  const { db, pool, connectionString } = createPostgresDatabaseConnection(
86
86
  process.env.DATABASE_URL!,
@@ -95,7 +95,7 @@ const { db, pool, connectionString } = createPostgresDatabaseConnection(
95
95
 
96
96
  **Signature:**
97
97
 
98
- ```typescript
98
+ ```typescript no-verify
99
99
  function createPostgresDatabaseConnection(
100
100
  connectionString: string,
101
101
  schema?: Record<string, unknown>,
@@ -110,7 +110,7 @@ function createPostgresDatabaseConnection(
110
110
  Creates a connection to a read replica for distributing read queries. Uses a default pool max of **10**.
111
111
 
112
112
  ```typescript
113
- import { createReadReplicaConnection } from "@rebasepro/server-postgresql";
113
+ import { createReadReplicaConnection } from "@rebasepro/server-postgres";
114
114
 
115
115
  const readResources = createReadReplicaConnection(
116
116
  process.env.DATABASE_READ_URL!,
@@ -120,7 +120,7 @@ const readResources = createReadReplicaConnection(
120
120
 
121
121
  **Signature:**
122
122
 
123
- ```typescript
123
+ ```typescript no-verify
124
124
  function createReadReplicaConnection(
125
125
  connectionString: string,
126
126
  schema?: Record<string, unknown>,
@@ -135,7 +135,7 @@ function createReadReplicaConnection(
135
135
  Creates a direct (non-pooled) connection for session-level features incompatible with PgBouncer transaction mode: **LISTEN/NOTIFY**, prepared statements, advisory locks. Uses a smaller default pool max of **5**.
136
136
 
137
137
  ```typescript
138
- import { createDirectDatabaseConnection } from "@rebasepro/server-postgresql";
138
+ import { createDirectDatabaseConnection } from "@rebasepro/server-postgres";
139
139
 
140
140
  const directResources = createDirectDatabaseConnection(
141
141
  process.env.DATABASE_DIRECT_URL!,
@@ -145,7 +145,7 @@ const directResources = createDirectDatabaseConnection(
145
145
 
146
146
  **Signature:**
147
147
 
148
- ```typescript
148
+ ```typescript no-verify
149
149
  function createDirectDatabaseConnection(
150
150
  connectionString: string,
151
151
  schema?: Record<string, unknown>,
@@ -173,7 +173,7 @@ All three connection functions accept an optional `PostgresPoolConfig` for progr
173
173
  The `DatabasePoolManager` manages multiple database connection pools dynamically. Used internally by the bootstrapper when `adminConnectionString` is configured — enables cross-database operations like branching and SQL execution against arbitrary databases.
174
174
 
175
175
  ```typescript
176
- import { DatabasePoolManager } from "@rebasepro/server-postgresql";
176
+ import { DatabasePoolManager } from "@rebasepro/server-postgres";
177
177
 
178
178
  const poolManager = new DatabasePoolManager(process.env.ADMIN_CONNECTION_STRING!);
179
179
 
@@ -223,8 +223,8 @@ import path from "path";
223
223
  import {
224
224
  initializeRebaseBackend,
225
225
  HonoEnv
226
- } from "@rebasepro/server-core";
227
- import { createPostgresDatabaseConnection, createPostgresAdapter } from "@rebasepro/server-postgresql";
226
+ } from "@rebasepro/server";
227
+ import { createPostgresDatabaseConnection, createPostgresAdapter } from "@rebasepro/server-postgres";
228
228
  import { tables, enums, relations } from "./schema.generated.js";
229
229
 
230
230
  const app = new Hono<HonoEnv>();
@@ -266,7 +266,7 @@ server.listen(3001);
266
266
  The bootstrapper protocol — database-specific logic is encapsulated in bootstrapper objects:
267
267
 
268
268
  ```typescript
269
- import { createPostgresDatabaseConnection, createPostgresBootstrapper } from "@rebasepro/server-postgresql";
269
+ import { createPostgresDatabaseConnection, createPostgresBootstrapper } from "@rebasepro/server-postgres";
270
270
  import { tables, enums, relations } from "./schema.generated.js";
271
271
 
272
272
  const { db, pool, connectionString } = createPostgresDatabaseConnection(process.env.DATABASE_URL!);
@@ -327,12 +327,13 @@ The `initializeRebaseBackend()` coordinator calls bootstrapper methods in this o
327
327
  | `auth` | `RebaseAuthConfig \| AuthAdapter` | — | Authentication configuration or external adapter |
328
328
  | `storage` | `BackendStorageConfig \| StorageController \| Record<string, ...>` | — | File storage configuration |
329
329
  | `history` | `true \| { retention?: number }` | — | Enable entity audit trail. Pass `true` or `{ retention: 90 }` for TTL in days |
330
- | `defaultSecurityRules` | `SecurityRule[]` | — | Default RLS rules for collections without explicit rules |
331
330
  | `enableSwagger` | `boolean` | `true` | Enable OpenAPI/Swagger documentation |
332
331
  | `cronPersistence` | `boolean` | `true` | Persist cron execution logs to database |
333
332
  | `maxBodySize` | `number` | `10485760` (10MB) | Max request body size in bytes. `0` to disable |
334
333
  | `csrf` | `{ origin: string \| string[] \| (origin: string) => boolean }` | — | CSRF protection (opt-in, disabled by default) |
335
- | `hooks` | `BackendHooks` | — | Backend-level hooks for intercepting admin data |
334
+ | `callbacks` | `CollectionCallbacks` | — | Global lifecycle callbacks applied to every collection, on every data path (REST, realtime, server-side `rebase.data`) |
335
+ | `mode` | `"cms" \| "baas"` | `"cms"` | `baas` derives collections from the live database at boot instead of config files, and turns the schema editor off |
336
+ | `baas` | `BaasOptions` | — | `baas` mode only: `{ unprotectedTables?: "exclude" \| "serve" }`. Default `"exclude"` — a table without RLS has no authorization model, so serving it would hand every row to every logged-in user. `"serve"` overrides, for trusted callers only |
336
337
  | `logging` | `{ level?: "error" \| "warn" \| "info" \| "debug" }` | — | Log level configuration |
337
338
 
338
339
  ### Auth Configuration (RebaseAuthConfig)
@@ -369,13 +370,13 @@ The `initializeRebaseBackend()` coordinator calls bootstrapper methods in this o
369
370
 
370
371
  ### loadEnv()
371
372
 
372
- The `loadEnv()` function validates all environment variables at startup using Zod. It is exported from `@rebasepro/server-core`.
373
+ The `loadEnv()` function validates all environment variables at startup using Zod. It is exported from `@rebasepro/server`.
373
374
 
374
375
  **Basic usage:**
375
376
 
376
377
  ```typescript
377
378
  import dotenv from "dotenv";
378
- import { loadEnv } from "@rebasepro/server-core";
379
+ import { loadEnv } from "@rebasepro/server";
379
380
 
380
381
  dotenv.config({ path: "../../.env" });
381
382
 
@@ -386,7 +387,8 @@ export const env = loadEnv();
386
387
 
387
388
  ```typescript
388
389
  import dotenv from "dotenv";
389
- import { loadEnv, z } from "@rebasepro/server-core";
390
+ import { loadEnv } from "@rebasepro/server";
391
+ import { z } from "zod";
390
392
 
391
393
  dotenv.config({ path: "../../.env" });
392
394
 
@@ -436,9 +438,9 @@ In non-production mode, `loadEnv()` **auto-generates** ephemeral `JWT_SECRET` an
436
438
  | `ALLOW_LOCALHOST_IN_PRODUCTION` | No | `false` | Allow localhost URLs in production env vars |
437
439
  | `CORS_ORIGINS` | No (⚠ required in prod) | — | Comma-separated allowed origins |
438
440
  | `FRONTEND_URL` | No | — | Frontend URL (used for CORS) |
439
- | `STORAGE_TYPE` | No | `local` | `local` or `s3` |
441
+ | `STORAGE_TYPE` | No | `local` | `local`, `s3`, or `gcs` |
440
442
  | `STORAGE_PATH` | No | — | Path for local file storage |
441
- | `FORCE_LOCAL_STORAGE` | No | `false` | Suppress local storage warning in production |
443
+ | `FORCE_LOCAL_STORAGE` | No | `false` | Allow local storage in production — **the backend refuses to boot without it** |
442
444
  | `S3_BUCKET` | No (if s3) | — | S3 bucket name |
443
445
  | `S3_REGION` | No | — | S3 region |
444
446
  | `S3_ACCESS_KEY_ID` | No (if s3) | — | S3 access key |
@@ -581,11 +583,11 @@ The `shutdown(timeoutMs?: number)` method (default timeout: 15000ms) performs:
581
583
 
582
584
  > [!WARNING]
583
585
  > **JWT Dual-Package Hazard (Monorepos / pnpm)**
584
- > When running a backend inside a monorepo workspace (especially with `tsx` and `--preserve-symlinks`), you may encounter a `RebaseApiError: JWT secret not configured. Call configureJwt() first` error. This occurs because Node.js resolves two different module instances of `@rebasepro/server-core`.
586
+ > When running a backend inside a monorepo workspace (especially with `tsx` and `--preserve-symlinks`), you may encounter a `RebaseApiError: JWT secret not configured. Call configureJwt() first` error. This occurs because Node.js resolves two different module instances of `@rebasepro/server`.
585
587
  >
586
588
  > **Fix:** Explicitly call `configureJwt` in your backend's entry point **before** `initializeRebaseBackend`:
587
589
  > ```typescript
588
- > import { initializeRebaseBackend, configureJwt } from "@rebasepro/server-core";
590
+ > import { initializeRebaseBackend, configureJwt } from "@rebasepro/server";
589
591
  >
590
592
  > configureJwt({
591
593
  > secret: process.env.JWT_SECRET!,