@rebasepro/types 0.22.0 → 0.24.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/controllers/client.d.ts +61 -17
- package/dist/controllers/collection_registry.d.ts +17 -0
- package/dist/controllers/data.d.ts +161 -49
- package/dist/controllers/data_driver.d.ts +10 -0
- package/dist/controllers/storage.d.ts +132 -13
- package/dist/errors.d.ts +15 -1
- package/dist/index.es.js +1094 -37
- package/dist/index.es.js.map +1 -1
- package/dist/types/admin_block.d.ts +1 -1
- package/dist/types/api_keys.d.ts +68 -36
- package/dist/types/auth_adapter.d.ts +99 -1
- package/dist/types/backend.d.ts +222 -3
- package/dist/types/backup.d.ts +83 -0
- package/dist/types/collection_patch.d.ts +74 -0
- package/dist/types/collections.d.ts +23 -0
- package/dist/types/cron.d.ts +44 -5
- package/dist/types/database_adapter.d.ts +6 -2
- package/dist/types/index.d.ts +2 -0
- package/dist/types/postgres_introspection.d.ts +10 -0
- package/dist/types/project_manifest.d.ts +65 -1
- package/dist/types/properties.d.ts +11 -0
- package/dist/types/schema_editing.d.ts +40 -14
- package/dist/types/scopes.d.ts +272 -0
- package/dist/types/security_rules.d.ts +28 -1
- package/dist/types/storage_authorize.d.ts +5 -1
- package/dist/users/user.d.ts +7 -0
- package/package.json +2 -2
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Scopes — what a credential may do, named `resource:action`.
|
|
3
|
+
*
|
|
4
|
+
* One vocabulary for every way of reaching a Rebase backend: a person's
|
|
5
|
+
* session, a service key, a personal key and an OAuth token for `/mcp` all
|
|
6
|
+
* answer "may this caller do X?" with the same strings, so a grant reads the
|
|
7
|
+
* same on a key, on a role and on a consent screen.
|
|
8
|
+
*
|
|
9
|
+
* A scope may carry a target — `data:read:posts` is `data:read` on the `posts`
|
|
10
|
+
* collection only. The unqualified scope covers every target. Only the data
|
|
11
|
+
* plane and app scopes take targets; see {@link SCOPE_TARGETS}.
|
|
12
|
+
*
|
|
13
|
+
* Two planes, held differently:
|
|
14
|
+
*
|
|
15
|
+
* - **The data plane** (`data:*`, `storage:*`, `functions:invoke`). Every
|
|
16
|
+
* signed-in person holds all of it, because what a person may do with data
|
|
17
|
+
* is decided row by row by the collection's `securityRules` and by storage
|
|
18
|
+
* policies, never by a scope. On a key or a token these scopes narrow: a key
|
|
19
|
+
* holding `data:read:posts` reaches nothing else, whatever RLS would allow.
|
|
20
|
+
* - **The admin plane** (everything else). Nobody holds it implicitly. The
|
|
21
|
+
* `admin` role holds all of it; any other role holds what the app declares
|
|
22
|
+
* for it under `auth.roles` on the users collection.
|
|
23
|
+
*
|
|
24
|
+
* Apps declare their own scopes too (`auth.scopes`), named the same way —
|
|
25
|
+
* `project:deploy`. Every signed-in person holds every app scope: like the data
|
|
26
|
+
* plane, the function behind it decides whether the person may act, and the
|
|
27
|
+
* scope exists so a key can be narrowed to that one action.
|
|
28
|
+
*
|
|
29
|
+
* @module
|
|
30
|
+
*/
|
|
31
|
+
/** @group Auth */
|
|
32
|
+
export declare const DATA_PLANE_SCOPES: readonly ["data:read", "data:write", "data:delete", "storage:read", "storage:write", "storage:delete", "functions:invoke"];
|
|
33
|
+
/** @group Auth */
|
|
34
|
+
export declare const ADMIN_SCOPES: readonly ["users:read", "users:write", "schema:read", "schema:write", "database:read", "database:write", "backups:read", "cron:read", "cron:write", "logs:read", "keys:read", "keys:write"];
|
|
35
|
+
/** @group Auth */
|
|
36
|
+
export type DataPlaneScope = (typeof DATA_PLANE_SCOPES)[number];
|
|
37
|
+
/** @group Auth */
|
|
38
|
+
export type AdminScope = (typeof ADMIN_SCOPES)[number];
|
|
39
|
+
/** @group Auth */
|
|
40
|
+
export type BuiltInScope = DataPlaneScope | AdminScope;
|
|
41
|
+
/** Every scope Rebase itself defines, in display order. @group Auth */
|
|
42
|
+
export declare const BUILT_IN_SCOPES: readonly BuiltInScope[];
|
|
43
|
+
/**
|
|
44
|
+
* Scopes no key may hold.
|
|
45
|
+
*
|
|
46
|
+
* A key that could manage keys could mint its own successor, widen itself, or
|
|
47
|
+
* revoke the keys other integrations run on — and revoking it would undo none
|
|
48
|
+
* of that. Managing keys is for a person (or the service key).
|
|
49
|
+
*
|
|
50
|
+
* @group Auth
|
|
51
|
+
*/
|
|
52
|
+
export declare const KEY_MANAGEMENT_SCOPES: readonly AdminScope[];
|
|
53
|
+
/** The one built-in role. It holds every scope and is the RLS `admin` role. @group Auth */
|
|
54
|
+
export declare const ADMIN_ROLE = "admin";
|
|
55
|
+
/** What a scope's target names. @group Auth */
|
|
56
|
+
export type ScopeTargetKind = "collection" | "bucket" | "function";
|
|
57
|
+
/**
|
|
58
|
+
* The built-in scopes that accept a target, and what the target names.
|
|
59
|
+
*
|
|
60
|
+
* - `data:*` — a collection slug
|
|
61
|
+
* - `storage:*` — a storage source id (`(default)` for the default source)
|
|
62
|
+
* - `functions:invoke` — a custom function's name
|
|
63
|
+
*
|
|
64
|
+
* @group Auth
|
|
65
|
+
*/
|
|
66
|
+
export declare const SCOPE_TARGETS: Readonly<Partial<Record<BuiltInScope, ScopeTargetKind>>>;
|
|
67
|
+
/** A scope's wording, for the screens that ask a person to grant it. @group Auth */
|
|
68
|
+
export interface ScopeDescription {
|
|
69
|
+
/** Short, imperative: what a holder may do. */
|
|
70
|
+
label: string;
|
|
71
|
+
/** One sentence on what that reaches, including anything surprising. */
|
|
72
|
+
description: string;
|
|
73
|
+
}
|
|
74
|
+
/** @group Auth */
|
|
75
|
+
export declare const BUILT_IN_SCOPE_DESCRIPTIONS: Readonly<Record<BuiltInScope, ScopeDescription>>;
|
|
76
|
+
/**
|
|
77
|
+
* An app-declared scope, under `auth.scopes` on the users collection.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* auth: {
|
|
82
|
+
* enabled: true,
|
|
83
|
+
* scopes: {
|
|
84
|
+
* "project:deploy": { label: "Deploy projects", target: "project" }
|
|
85
|
+
* }
|
|
86
|
+
* }
|
|
87
|
+
* ```
|
|
88
|
+
*
|
|
89
|
+
* @group Auth
|
|
90
|
+
*/
|
|
91
|
+
export interface ScopeDefinition {
|
|
92
|
+
/** Short, imperative: what a holder may do. Shown wherever the scope is granted. */
|
|
93
|
+
label: string;
|
|
94
|
+
/** One sentence on what that reaches. */
|
|
95
|
+
description?: string;
|
|
96
|
+
/**
|
|
97
|
+
* What a target names, when the scope accepts one — `"project"` lets a
|
|
98
|
+
* key hold `project:deploy:<id>`. Unset, the scope takes no target.
|
|
99
|
+
*/
|
|
100
|
+
target?: string;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* An app-declared role, under `auth.roles` on the users collection.
|
|
104
|
+
*
|
|
105
|
+
* A role is a name the database sees (RLS policies match it) and a bundle of
|
|
106
|
+
* admin-plane and app scopes. Data-plane scopes are not role scopes: what a
|
|
107
|
+
* person may do with data is the collection's `securityRules`, so listing
|
|
108
|
+
* `data:write` here would read as a grant it is not, and is refused.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```ts
|
|
112
|
+
* auth: {
|
|
113
|
+
* enabled: true,
|
|
114
|
+
* roles: {
|
|
115
|
+
* support: { name: "Support", scopes: ["users:read", "users:write", "logs:read"] },
|
|
116
|
+
* developer: { name: "Developer", scopes: ["schema:read", "database:read", "logs:read", "cron:read"] }
|
|
117
|
+
* }
|
|
118
|
+
* }
|
|
119
|
+
* ```
|
|
120
|
+
*
|
|
121
|
+
* @group Auth
|
|
122
|
+
*/
|
|
123
|
+
export interface RoleDefinition {
|
|
124
|
+
/** Display name. Defaults to the role id. */
|
|
125
|
+
name?: string;
|
|
126
|
+
/** One sentence on who holds it. */
|
|
127
|
+
description?: string;
|
|
128
|
+
/** Admin-plane and app scopes the role holds. */
|
|
129
|
+
scopes: readonly string[];
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* The declared access model: the app's own scopes and roles beside the
|
|
133
|
+
* built-in ones. What `scopesForRoles` and `validateScopes` read.
|
|
134
|
+
*
|
|
135
|
+
* @group Auth
|
|
136
|
+
*/
|
|
137
|
+
export interface AccessModel {
|
|
138
|
+
roles: Readonly<Record<string, RoleDefinition>>;
|
|
139
|
+
scopes: Readonly<Record<string, ScopeDefinition>>;
|
|
140
|
+
}
|
|
141
|
+
/** The access model of an app that declares nothing: built-ins only. @group Auth */
|
|
142
|
+
export declare const EMPTY_ACCESS_MODEL: AccessModel;
|
|
143
|
+
/** A scope string split into its scope and optional target. @group Auth */
|
|
144
|
+
export interface ParsedScope {
|
|
145
|
+
/** `resource:action`. */
|
|
146
|
+
scope: string;
|
|
147
|
+
/** The one collection, bucket, function or app resource it is narrowed to. */
|
|
148
|
+
target?: string;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Split `resource:action[:target]`. Returns null for anything else.
|
|
152
|
+
*
|
|
153
|
+
* The target is everything after the second colon, so a target may itself
|
|
154
|
+
* contain colons. Resource and action are lower-case words.
|
|
155
|
+
*
|
|
156
|
+
* @group Auth
|
|
157
|
+
*/
|
|
158
|
+
export declare function parseScope(value: string): ParsedScope | null;
|
|
159
|
+
/** @group Auth */
|
|
160
|
+
export declare function isBuiltInScope(scope: string): scope is BuiltInScope;
|
|
161
|
+
/** @group Auth */
|
|
162
|
+
export declare function isDataPlaneScope(scope: string): scope is DataPlaneScope;
|
|
163
|
+
/** @group Auth */
|
|
164
|
+
export declare function isAdminScope(scope: string): scope is AdminScope;
|
|
165
|
+
/** Does this list of roles include the built-in `admin` role? @group Auth */
|
|
166
|
+
export declare function hasAdminRole(roles: readonly string[] | null | undefined): boolean;
|
|
167
|
+
/**
|
|
168
|
+
* Does a set of held scopes grant `scope`, optionally on one `target`?
|
|
169
|
+
*
|
|
170
|
+
* The unqualified grant covers every target. A qualified grant covers its own
|
|
171
|
+
* target only, and never answers an unqualified question: a key holding
|
|
172
|
+
* `data:read:posts` is not asked "may you read data?" and told yes.
|
|
173
|
+
*
|
|
174
|
+
* @group Auth
|
|
175
|
+
*/
|
|
176
|
+
export declare function scopeGrants(held: readonly string[], scope: string, target?: string): boolean;
|
|
177
|
+
/**
|
|
178
|
+
* Does a set of held scopes grant `scope` on at least one target?
|
|
179
|
+
*
|
|
180
|
+
* For a surface that lists what is reachable — the collections an MCP client
|
|
181
|
+
* may query — and filters per item afterwards.
|
|
182
|
+
*
|
|
183
|
+
* @group Auth
|
|
184
|
+
*/
|
|
185
|
+
export declare function scopeGrantsAny(held: readonly string[], scope: string): boolean;
|
|
186
|
+
/**
|
|
187
|
+
* The targets a held set narrows `scope` to: `"all"` when it holds the
|
|
188
|
+
* unqualified scope, otherwise the listed targets (possibly none).
|
|
189
|
+
*
|
|
190
|
+
* @group Auth
|
|
191
|
+
*/
|
|
192
|
+
export declare function scopeTargets(held: readonly string[], scope: string): "all" | string[];
|
|
193
|
+
/**
|
|
194
|
+
* Every scope a person holding `roles` has.
|
|
195
|
+
*
|
|
196
|
+
* The data plane and every app scope always; the whole admin plane with the
|
|
197
|
+
* `admin` role; otherwise each declared role's scopes. A role nobody declared
|
|
198
|
+
* adds nothing — it may still mean something to an RLS policy.
|
|
199
|
+
*
|
|
200
|
+
* @group Auth
|
|
201
|
+
*/
|
|
202
|
+
export declare function scopesForRoles(roles: readonly string[] | null | undefined, model?: AccessModel): string[];
|
|
203
|
+
/**
|
|
204
|
+
* Every scope this access model knows, unqualified: the built-ins, then the
|
|
205
|
+
* app's own.
|
|
206
|
+
*
|
|
207
|
+
* @group Auth
|
|
208
|
+
*/
|
|
209
|
+
export declare function knownScopes(model?: AccessModel): string[];
|
|
210
|
+
/** Does this scope accept a target? @group Auth */
|
|
211
|
+
export declare function scopeAcceptsTarget(scope: string, model?: AccessModel): boolean;
|
|
212
|
+
/** How a scope string failed to validate. @group Auth */
|
|
213
|
+
export interface ScopeProblem {
|
|
214
|
+
scope: string;
|
|
215
|
+
reason: "malformed" | "unknown" | "target-not-accepted";
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Check a list of scope strings against an access model. Returns the
|
|
219
|
+
* problems, empty when every entry is a known scope with an acceptable target.
|
|
220
|
+
*
|
|
221
|
+
* @group Auth
|
|
222
|
+
*/
|
|
223
|
+
export declare function validateScopes(values: readonly unknown[], model?: AccessModel): ScopeProblem[];
|
|
224
|
+
/**
|
|
225
|
+
* The entries of `requested` that `held` does not cover — what a credential
|
|
226
|
+
* would hold beyond its minter. Empty means the request is within reach.
|
|
227
|
+
*
|
|
228
|
+
* `data:read:posts` is covered by `data:read`; `data:read` is not covered by
|
|
229
|
+
* `data:read:posts`.
|
|
230
|
+
*
|
|
231
|
+
* @group Auth
|
|
232
|
+
*/
|
|
233
|
+
export declare function scopesBeyond(requested: readonly string[], held: readonly string[]): string[];
|
|
234
|
+
/**
|
|
235
|
+
* Narrow `requested` to what `held` covers, entry by entry. What a personal
|
|
236
|
+
* key holds today when its owner has lost a role since it was minted.
|
|
237
|
+
*
|
|
238
|
+
* @group Auth
|
|
239
|
+
*/
|
|
240
|
+
export declare function intersectScopes(requested: readonly string[], held: readonly string[]): string[];
|
|
241
|
+
/**
|
|
242
|
+
* How a scope is worded for a person: the built-in description, the app's
|
|
243
|
+
* declared label, or the raw string when nothing describes it. A target is
|
|
244
|
+
* named after the label.
|
|
245
|
+
*
|
|
246
|
+
* @group Auth
|
|
247
|
+
*/
|
|
248
|
+
export declare function describeScope(value: string, model?: AccessModel): ScopeDescription;
|
|
249
|
+
/** A role as a person managing access sees it. @group Auth */
|
|
250
|
+
export interface RoleSummary {
|
|
251
|
+
id: string;
|
|
252
|
+
name: string;
|
|
253
|
+
description?: string;
|
|
254
|
+
/** Admin-plane and app scopes. The `admin` role lists every admin-plane scope. */
|
|
255
|
+
scopes: string[];
|
|
256
|
+
/** True for `admin`, which the app does not declare. */
|
|
257
|
+
builtIn: boolean;
|
|
258
|
+
}
|
|
259
|
+
/** A scope as a screen that grants it lists it. @group Auth */
|
|
260
|
+
export interface ScopeSummary {
|
|
261
|
+
scope: string;
|
|
262
|
+
label: string;
|
|
263
|
+
description: string;
|
|
264
|
+
/** What a target names, when the scope takes one. */
|
|
265
|
+
target?: string;
|
|
266
|
+
/** `data`, `admin` or `app`: which plane the scope belongs to. */
|
|
267
|
+
plane: "data" | "admin" | "app";
|
|
268
|
+
}
|
|
269
|
+
/** The roles of an access model, `admin` first. @group Auth */
|
|
270
|
+
export declare function summarizeRoles(model?: AccessModel): RoleSummary[];
|
|
271
|
+
/** Every scope of an access model, described, in display order. @group Auth */
|
|
272
|
+
export declare function summarizeScopes(model?: AccessModel): ScopeSummary[];
|
|
@@ -53,7 +53,7 @@ export type SecurityOperation = "select" | "insert" | "update" | "delete" | "all
|
|
|
53
53
|
*
|
|
54
54
|
* @group Models
|
|
55
55
|
*/
|
|
56
|
-
export type SecurityRule = OwnerSecurityRule | PublicSecurityRule | StructuredSecurityRule | RawSQLSecurityRule | RolesOnlySecurityRule;
|
|
56
|
+
export type SecurityRule = OwnerSecurityRule | PublicSecurityRule | StructuredSecurityRule | RawSQLSecurityRule | RawSQLCheckOnlySecurityRule | RolesOnlySecurityRule;
|
|
57
57
|
/**
|
|
58
58
|
* Shared fields for all SecurityRule variants.
|
|
59
59
|
* @group Models
|
|
@@ -297,6 +297,33 @@ export interface RawSQLSecurityRule extends SecurityRuleBase {
|
|
|
297
297
|
condition?: never;
|
|
298
298
|
check?: never;
|
|
299
299
|
}
|
|
300
|
+
/**
|
|
301
|
+
* Security rule with a raw SQL `WITH CHECK` clause and no `USING` clause — the
|
|
302
|
+
* shape of every INSERT policy, which checks the row being written and has no
|
|
303
|
+
* existing row to filter.
|
|
304
|
+
*
|
|
305
|
+
* On an operation that takes a `USING` clause, the missing one grants no rows,
|
|
306
|
+
* as a Postgres policy without one does.
|
|
307
|
+
*
|
|
308
|
+
* @example
|
|
309
|
+
* // Anyone may insert a row they own
|
|
310
|
+
* { operation: "insert", withCheck: "{owner_id} = rebase.uid()" }
|
|
311
|
+
*
|
|
312
|
+
* @group Models
|
|
313
|
+
*/
|
|
314
|
+
export interface RawSQLCheckOnlySecurityRule extends SecurityRuleBase {
|
|
315
|
+
/**
|
|
316
|
+
* Raw SQL expression for the `WITH CHECK` clause.
|
|
317
|
+
* This controls which *new/updated* row values are allowed.
|
|
318
|
+
* Applied to INSERT and UPDATE.
|
|
319
|
+
*/
|
|
320
|
+
withCheck: string;
|
|
321
|
+
using?: never;
|
|
322
|
+
ownerField?: never;
|
|
323
|
+
access?: never;
|
|
324
|
+
condition?: never;
|
|
325
|
+
check?: never;
|
|
326
|
+
}
|
|
300
327
|
/**
|
|
301
328
|
* Security rule that only filters by application roles, without any
|
|
302
329
|
* row-level condition (USING/WITH CHECK).
|
|
@@ -22,7 +22,11 @@ export interface StorageAuthorizeContext {
|
|
|
22
22
|
operation: StorageOperation;
|
|
23
23
|
/** Null when the route allows unauthenticated access. */
|
|
24
24
|
user: StorageAuthorizeUser | null;
|
|
25
|
-
/**
|
|
25
|
+
/**
|
|
26
|
+
* Named backend the request targeted, when one was given — as its canonical
|
|
27
|
+
* key, the one the request is served from (`" media "` arrives as
|
|
28
|
+
* `"media"`). Absent for the default source, however the request named it.
|
|
29
|
+
*/
|
|
26
30
|
storageId?: string;
|
|
27
31
|
/**
|
|
28
32
|
* Trusted, RLS-bypassing data access, so the hook can answer the question it
|
package/dist/users/user.d.ts
CHANGED
|
@@ -45,6 +45,13 @@ export type User = {
|
|
|
45
45
|
* Whether the user's email address has been verified.
|
|
46
46
|
*/
|
|
47
47
|
readonly emailVerified?: boolean;
|
|
48
|
+
/**
|
|
49
|
+
* The address this account is moving to, while the link mailed there is
|
|
50
|
+
* waiting to be followed (`client.auth.changeEmail`). `email` stays the
|
|
51
|
+
* account's address until then. `null` or absent when no change is
|
|
52
|
+
* waiting.
|
|
53
|
+
*/
|
|
54
|
+
readonly pendingEmail?: string | null;
|
|
48
55
|
/**
|
|
49
56
|
* Role IDs assigned to this user (e.g. `["admin", "editor"]`).
|
|
50
57
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@rebasepro/types",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"description": "Rebase type definitions — shared interfaces and controller types",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"rebase",
|
|
@@ -46,7 +46,7 @@
|
|
|
46
46
|
"@types/node": "^26.1.2",
|
|
47
47
|
"@types/object-hash": "^3.0.6",
|
|
48
48
|
"@types/react-measure": "^2.0.12",
|
|
49
|
-
"hono": "^4.13.
|
|
49
|
+
"hono": "^4.13.5",
|
|
50
50
|
"jest": "^30.4.2",
|
|
51
51
|
"ts-jest": "^29.4.12",
|
|
52
52
|
"typescript": "^6.0.3",
|