@rebasepro/server 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/README.md +1 -1
- package/bin/rebase-server.js +4 -2
- package/dist/{GCSStorageController-CLIJXwGS.js → GCSStorageController-BSiP1c-f.js} +57 -29
- package/dist/GCSStorageController-BSiP1c-f.js.map +1 -0
- package/dist/{S3StorageController-Dcuf8lMA.js → S3StorageController-CAwFRgjV.js} +19 -7
- package/dist/S3StorageController-CAwFRgjV.js.map +1 -0
- package/dist/api/ast-schema-editor.d.ts +127 -1
- package/dist/api/errors.d.ts +9 -0
- package/dist/api/live-schema-routes.d.ts +52 -8
- package/dist/api/logs-routes.d.ts +39 -1
- package/dist/api/openapi-generator.d.ts +17 -0
- package/dist/api/rest/api-generator.d.ts +158 -42
- package/dist/api/rest/auth-collection-writes.d.ts +85 -0
- package/dist/api/rest/field-access-query.d.ts +6 -2
- package/dist/api/rest/idempotency.d.ts +7 -1
- package/dist/api/rest/nested-write-access.d.ts +46 -0
- package/dist/api/rest/write-validation.d.ts +34 -2
- package/dist/api/types.d.ts +17 -1
- package/dist/{ast-schema-editor-CslO8Oje.js → ast-schema-editor-CWqS_sLJ.js} +411 -13
- package/dist/ast-schema-editor-CWqS_sLJ.js.map +1 -0
- package/dist/auth/access.d.ts +105 -0
- package/dist/auth/adapter-middleware.d.ts +2 -1
- package/dist/auth/address-ownership.d.ts +68 -0
- package/dist/auth/admin-roles-route.d.ts +4 -2
- package/dist/auth/admin-roles.d.ts +17 -20
- package/dist/auth/admin-user-ops.d.ts +35 -2
- package/dist/auth/admin-users-route.d.ts +1 -0
- package/dist/auth/api-keys/api-key-middleware.d.ts +56 -55
- package/dist/auth/api-keys/api-key-routes.d.ts +41 -11
- package/dist/auth/api-keys/api-key-store.d.ts +31 -8
- package/dist/auth/api-keys/api-key-types.d.ts +14 -16
- package/dist/auth/api-keys/http-operation.d.ts +19 -0
- package/dist/auth/api-keys/index.d.ts +11 -11
- package/dist/auth/api-keys/key-grant.d.ts +41 -0
- package/dist/auth/api-keys/legacy-permissions.d.ts +33 -0
- package/dist/auth/auth-hooks.d.ts +50 -7
- package/dist/auth/builtin-auth-adapter.d.ts +8 -0
- package/dist/auth/captcha.d.ts +5 -0
- package/dist/auth/cookie-utils.d.ts +7 -0
- package/dist/auth/deliverable-address.d.ts +6 -0
- package/dist/auth/email-change-routes.d.ts +41 -0
- package/dist/auth/expired-token-sweep.d.ts +67 -0
- package/dist/auth/impersonation.d.ts +110 -0
- package/dist/auth/index.d.ts +4 -2
- package/dist/auth/interfaces.d.ts +146 -65
- package/dist/auth/jwt.d.ts +66 -3
- package/dist/auth/magic-link-routes.d.ts +2 -6
- package/dist/auth/mfa-routes.d.ts +2 -9
- package/dist/auth/middleware.d.ts +17 -5
- package/dist/auth/oauth-signin-policy.d.ts +25 -8
- package/dist/auth/otp-routes.d.ts +2 -6
- package/dist/auth/passwordless-signup.d.ts +27 -0
- package/dist/auth/platform-token.d.ts +122 -0
- package/dist/auth/rate-limiter.d.ts +72 -1
- package/dist/auth/routes.d.ts +45 -0
- package/dist/auth/scope-routes.d.ts +22 -0
- package/dist/auth/session-routes.d.ts +18 -6
- package/dist/auth/token-revocation.d.ts +53 -1
- package/dist/auth/verify-credential.d.ts +28 -0
- package/dist/{auth-CCDpk2rn.js → auth-DMLngxn_.js} +2712 -711
- package/dist/auth-DMLngxn_.js.map +1 -0
- package/dist/backend-DTAOsLQc.js +30 -0
- package/dist/backend-DTAOsLQc.js.map +1 -0
- package/dist/backup/backup-common.d.ts +29 -0
- package/dist/backup/backup-routes.d.ts +24 -4
- package/dist/backup/backup-schedule.d.ts +33 -0
- package/dist/backup/backup-storage.d.ts +14 -0
- package/dist/backup/index.d.ts +2 -0
- package/dist/backup-CN0s50D2.js +444 -0
- package/dist/backup-CN0s50D2.js.map +1 -0
- package/dist/boot/bundle.d.ts +19 -0
- package/dist/boot/driver.d.ts +10 -0
- package/dist/boot/env.d.ts +51 -6
- package/dist/boot/fetch-bundle.d.ts +18 -1
- package/dist/boot/rls-audit-option.d.ts +26 -0
- package/dist/boot/security-headers.d.ts +26 -0
- package/dist/boot/sources.d.ts +1 -0
- package/dist/boot/static-routing.d.ts +56 -0
- package/dist/collection_patch-BRu-BvDv.js +472 -0
- package/dist/collection_patch-BRu-BvDv.js.map +1 -0
- package/dist/{contract-routes-eLxV0le1.js → contract-routes-fz8i4pxs.js} +17 -4
- package/dist/contract-routes-fz8i4pxs.js.map +1 -0
- package/dist/cron/cron-routes.d.ts +7 -2
- package/dist/cron/cron-scheduler.d.ts +146 -21
- package/dist/cron/cron-store.d.ts +76 -8
- package/dist/cron/index.d.ts +1 -1
- package/dist/{cron-loader-CQjvjpEw.js → cron-loader-CwaANlOG.js} +4 -4
- package/dist/cron-loader-CwaANlOG.js.map +1 -0
- package/dist/cron-routes-Bc-SB0Se.js +96 -0
- package/dist/cron-routes-Bc-SB0Se.js.map +1 -0
- package/dist/{cron-scheduler-COPQxlEq.js → cron-scheduler-CYQgco86.js} +427 -83
- package/dist/cron-scheduler-CYQgco86.js.map +1 -0
- package/dist/{cron-store-BYGZFNWk.js → cron-store-D2Q9-Aco.js} +139 -23
- package/dist/cron-store-D2Q9-Aco.js.map +1 -0
- package/dist/{ddl-bootstrap-CfNvxMuK.js → ddl-bootstrap-BaqMSa4Y.js} +3 -26
- package/dist/ddl-bootstrap-BaqMSa4Y.js.map +1 -0
- package/dist/email/index.d.ts +2 -2
- package/dist/email/link-base.d.ts +5 -4
- package/dist/email/smtp-email-service.d.ts +13 -1
- package/dist/email/templates.d.ts +31 -0
- package/dist/email/types.d.ts +29 -2
- package/dist/env.d.ts +25 -7
- package/dist/{errors-DWsX4yTd.js → errors-D6_y86c5.js} +102 -8
- package/dist/errors-D6_y86c5.js.map +1 -0
- package/dist/{function-loader-xnbDAPfa.js → function-loader-D7o5Epjj.js} +2 -2
- package/dist/{function-loader-xnbDAPfa.js.map → function-loader-D7o5Epjj.js.map} +1 -1
- package/dist/{function-routes-Chet4-lB.js → function-routes-CaNG4waN.js} +24 -12
- package/dist/function-routes-CaNG4waN.js.map +1 -0
- package/dist/functions/context.d.ts +17 -6
- package/dist/functions/guards.d.ts +22 -5
- package/dist/functions/index.d.ts +2 -2
- package/dist/functions/index.js +90 -36
- package/dist/functions/index.js.map +1 -1
- package/dist/{history-recorder-BQmB0P_j.js → history-recorder-Nr8zLvoU.js} +9 -7
- package/dist/history-recorder-Nr8zLvoU.js.map +1 -0
- package/dist/{history-store-CetkrBBD.js → history-store-rcAm_xFR.js} +2 -2
- package/dist/{history-store-CetkrBBD.js.map → history-store-rcAm_xFR.js.map} +1 -1
- package/dist/index.d.ts +14 -4
- package/dist/index.es.js +5733 -1551
- package/dist/index.es.js.map +1 -1
- package/dist/init/docs.d.ts +5 -2
- package/dist/init/health.d.ts +17 -2
- package/dist/init/shutdown.d.ts +18 -3
- package/dist/init.d.ts +54 -0
- package/dist/jobs/index.d.ts +2 -2
- package/dist/jobs/job-queue.d.ts +23 -2
- package/dist/jobs/job-store.d.ts +37 -5
- package/dist/jobs/types.d.ts +8 -6
- package/dist/{jobs-Bjr8DZAi.js → jobs-DqYNfquG.js} +306 -167
- package/dist/jobs-DqYNfquG.js.map +1 -0
- package/dist/{jwt-C4OW-DNq.js → jwt-R6bSPMjk.js} +114 -38
- package/dist/{jwt-C4OW-DNq.js.map → jwt-R6bSPMjk.js.map} +1 -1
- package/dist/{keys-Qfc4XieN.js → keys-GAVZqbqx.js} +18 -17
- package/dist/{keys-Qfc4XieN.js.map → keys-GAVZqbqx.js.map} +1 -1
- package/dist/{logger-DO2PZc4i.js → logger-D-S-hO5e.js} +26 -3
- package/dist/logger-D-S-hO5e.js.map +1 -0
- package/dist/{logs-routes-3EEzPjhl.js → logs-routes-DAdv37GI.js} +54 -11
- package/dist/logs-routes-DAdv37GI.js.map +1 -0
- package/dist/mcp/consent-page.d.ts +1 -1
- package/dist/mcp/mcp-routes.d.ts +45 -2
- package/dist/mcp/mcp-tools.d.ts +22 -10
- package/dist/mcp/oauth-metadata.d.ts +21 -16
- package/dist/mcp/oauth-routes.d.ts +34 -1
- package/dist/mcp/oauth-store.d.ts +29 -13
- package/dist/metrics/history-recorder.d.ts +1 -1
- package/dist/{openapi-generator-D8uFz-LW.js → openapi-generator-DAq_XVDu.js} +135 -22
- package/dist/openapi-generator-DAq_XVDu.js.map +1 -0
- package/dist/{proxy-Czngl3p9.js → proxy-qRlqeUmO.js} +2 -2
- package/dist/{proxy-Czngl3p9.js.map → proxy-qRlqeUmO.js.map} +1 -1
- package/dist/{query-parser-BleZmY18.js → query-parser-BgiKJKvc.js} +41 -82
- package/dist/query-parser-BgiKJKvc.js.map +1 -0
- package/dist/{request-timeout-C_4C2BeR.js → request-timeout-DgH7j8qO.js} +3 -3
- package/dist/{request-timeout-C_4C2BeR.js.map → request-timeout-DgH7j8qO.js.map} +1 -1
- package/dist/rls-audit/index.d.ts +4 -0
- package/dist/schema-edit/apply-schema-change.d.ts +63 -3
- package/dist/schema-edit/project-root.d.ts +3 -2
- package/dist/schema-edit/remote-source.d.ts +9 -4
- package/dist/{schema-editor-routes-DdLihzp0.js → schema-editor-routes-oIyuWl3L.js} +12 -7
- package/dist/schema-editor-routes-oIyuWl3L.js.map +1 -0
- package/dist/serve-spa.d.ts +58 -0
- package/dist/services/routed-realtime-service.d.ts +11 -0
- package/dist/soft-delete-params-BWPilMPF.js +59 -0
- package/dist/soft-delete-params-BWPilMPF.js.map +1 -0
- package/dist/{src-Br6ARbs6.js → src-CatHFUym.js} +439 -45
- package/dist/src-CatHFUym.js.map +1 -0
- package/dist/{src-1vL-I1Po.js → src-I3aG1PcY.js} +371 -81
- package/dist/src-I3aG1PcY.js.map +1 -0
- package/dist/storage/GCSStorageController.d.ts +13 -1
- package/dist/storage/LocalStorageController.d.ts +2 -0
- package/dist/storage/S3StorageController.d.ts +2 -0
- package/dist/storage/index.d.ts +2 -2
- package/dist/storage/keys.d.ts +12 -0
- package/dist/storage/property-limits.d.ts +41 -6
- package/dist/storage/rendition-cache.d.ts +11 -1
- package/dist/storage/request-keys.d.ts +82 -0
- package/dist/storage/requested-object.d.ts +74 -0
- package/dist/storage/routes.d.ts +36 -18
- package/dist/storage/tus-handler.d.ts +30 -5
- package/dist/storage/types.d.ts +36 -1
- package/dist/types-BfKcm9do.js.map +1 -1
- package/dist/utils/logger.d.ts +12 -0
- package/package.json +9 -9
- package/dist/GCSStorageController-CLIJXwGS.js.map +0 -1
- package/dist/S3StorageController-Dcuf8lMA.js.map +0 -1
- package/dist/admin-roles-vYdp_Pil.js +0 -36
- package/dist/admin-roles-vYdp_Pil.js.map +0 -1
- package/dist/admin_block-DxKLmdiv.js +0 -206
- package/dist/admin_block-DxKLmdiv.js.map +0 -1
- package/dist/ast-schema-editor-CslO8Oje.js.map +0 -1
- package/dist/auth/api-keys/api-key-permission-guard.d.ts +0 -65
- package/dist/auth-CCDpk2rn.js.map +0 -1
- package/dist/backup-DzI9jLwc.js +0 -192
- package/dist/backup-DzI9jLwc.js.map +0 -1
- package/dist/contract-routes-eLxV0le1.js.map +0 -1
- package/dist/cron-loader-CQjvjpEw.js.map +0 -1
- package/dist/cron-routes-B7CRGfiq.js +0 -72
- package/dist/cron-routes-B7CRGfiq.js.map +0 -1
- package/dist/cron-scheduler-COPQxlEq.js.map +0 -1
- package/dist/cron-store-BYGZFNWk.js.map +0 -1
- package/dist/ddl-bootstrap-CfNvxMuK.js.map +0 -1
- package/dist/errors-DWsX4yTd.js.map +0 -1
- package/dist/function-routes-Chet4-lB.js.map +0 -1
- package/dist/history-recorder-BQmB0P_j.js.map +0 -1
- package/dist/jobs-Bjr8DZAi.js.map +0 -1
- package/dist/logger-DO2PZc4i.js.map +0 -1
- package/dist/logs-routes-3EEzPjhl.js.map +0 -1
- package/dist/openapi-generator-D8uFz-LW.js.map +0 -1
- package/dist/query-parser-BleZmY18.js.map +0 -1
- package/dist/schema-editor-routes-DdLihzp0.js.map +0 -1
- package/dist/src-1vL-I1Po.js.map +0 -1
- package/dist/src-Br6ARbs6.js.map +0 -1
|
@@ -268,12 +268,29 @@ var DEFAULT_CAPABILITIES = {
|
|
|
268
268
|
supportsDocumentAdmin: true,
|
|
269
269
|
supportsSchemaAdmin: true
|
|
270
270
|
};
|
|
271
|
-
var
|
|
272
|
-
postgres
|
|
273
|
-
firestore
|
|
274
|
-
mongodb
|
|
275
|
-
"(default)"
|
|
276
|
-
|
|
271
|
+
var BUILT_IN_CAPABILITIES = /* @__PURE__ */ new Map([
|
|
272
|
+
["postgres", POSTGRES_CAPABILITIES],
|
|
273
|
+
["firestore", FIREBASE_CAPABILITIES],
|
|
274
|
+
["mongodb", MONGODB_CAPABILITIES],
|
|
275
|
+
["(default)", DEFAULT_CAPABILITIES]
|
|
276
|
+
]);
|
|
277
|
+
/**
|
|
278
|
+
* Capabilities registered at runtime, on `globalThis` rather than in a module
|
|
279
|
+
* local: a third-party driver inlines its own copy of this package and
|
|
280
|
+
* registers through it, while the app and the server read through theirs. A
|
|
281
|
+
* module local made the registration land in a copy nobody else reads.
|
|
282
|
+
* See `module-state-across-copies.test.ts`.
|
|
283
|
+
*/
|
|
284
|
+
var REGISTERED_CAPABILITIES_KEY = Symbol.for("@rebasepro/types.dataSourceCapabilities.v1");
|
|
285
|
+
function registeredCapabilities() {
|
|
286
|
+
const g = globalThis;
|
|
287
|
+
let registered = g[REGISTERED_CAPABILITIES_KEY];
|
|
288
|
+
if (!registered) {
|
|
289
|
+
registered = /* @__PURE__ */ new Map();
|
|
290
|
+
g[REGISTERED_CAPABILITIES_KEY] = registered;
|
|
291
|
+
}
|
|
292
|
+
return registered;
|
|
293
|
+
}
|
|
277
294
|
/**
|
|
278
295
|
* Look up capabilities for a given engine key.
|
|
279
296
|
* If `engine` is undefined or not found, returns `DEFAULT_CAPABILITIES`.
|
|
@@ -281,7 +298,7 @@ var CAPABILITIES_REGISTRY = {
|
|
|
281
298
|
*/
|
|
282
299
|
function getDataSourceCapabilities(engine) {
|
|
283
300
|
if (!engine) return POSTGRES_CAPABILITIES;
|
|
284
|
-
return
|
|
301
|
+
return registeredCapabilities().get(engine) ?? BUILT_IN_CAPABILITIES.get(engine) ?? DEFAULT_CAPABILITIES;
|
|
285
302
|
}
|
|
286
303
|
//#endregion
|
|
287
304
|
//#region ../types/src/types/collections.ts
|
|
@@ -761,31 +778,6 @@ function storageEnvSuffix(key, defaultKey = DEFAULT_STORAGE_SOURCE_KEY) {
|
|
|
761
778
|
if (!normalized) throw new Error(`Source key "${key}" cannot be turned into an environment variable name. Use a key containing at least one letter or digit.`);
|
|
762
779
|
return `__${normalized}`;
|
|
763
780
|
}
|
|
764
|
-
/**
|
|
765
|
-
* Two distinct keys that collapse onto the same variable name, or `null`.
|
|
766
|
-
*
|
|
767
|
-
* `media-cdn` and `media_cdn` are different source keys but the same suffix, so
|
|
768
|
-
* without this one of them silently reads the other's configuration. Returns the
|
|
769
|
-
* offending pair rather than throwing, so each caller can raise it in its own
|
|
770
|
-
* idiom — a `BundleError` at boot, a build failure in the CLI, a rejected deploy
|
|
771
|
-
* in a control plane.
|
|
772
|
-
*
|
|
773
|
-
* @group Models
|
|
774
|
-
*/
|
|
775
|
-
function findStorageSuffixCollision(keys, defaultKey = DEFAULT_STORAGE_SOURCE_KEY) {
|
|
776
|
-
const seen = /* @__PURE__ */ new Map();
|
|
777
|
-
for (const key of keys) {
|
|
778
|
-
const suffix = storageEnvSuffix(key, defaultKey);
|
|
779
|
-
const existing = seen.get(suffix);
|
|
780
|
-
if (existing !== void 0 && existing !== key) return {
|
|
781
|
-
a: existing,
|
|
782
|
-
b: key,
|
|
783
|
-
suffix
|
|
784
|
-
};
|
|
785
|
-
seen.set(suffix, key);
|
|
786
|
-
}
|
|
787
|
-
return null;
|
|
788
|
-
}
|
|
789
781
|
//#endregion
|
|
790
782
|
//#region ../types/src/types/resource_kinds.ts
|
|
791
783
|
/**
|
|
@@ -885,10 +877,15 @@ amendResourceKind("bucket", {
|
|
|
885
877
|
"S3_FORCE_PATH_STYLE",
|
|
886
878
|
"GCS_BUCKET",
|
|
887
879
|
"GCS_PROJECT_ID",
|
|
888
|
-
"GCS_KEY_FILENAME"
|
|
880
|
+
"GCS_KEY_FILENAME",
|
|
881
|
+
"STORAGE_MAX_FILE_SIZE"
|
|
889
882
|
],
|
|
890
883
|
envBasesByEngine: {
|
|
891
|
-
local: [
|
|
884
|
+
local: [
|
|
885
|
+
"STORAGE_TYPE",
|
|
886
|
+
"STORAGE_PATH",
|
|
887
|
+
"STORAGE_MAX_FILE_SIZE"
|
|
888
|
+
],
|
|
892
889
|
s3: [
|
|
893
890
|
"STORAGE_TYPE",
|
|
894
891
|
"S3_BUCKET",
|
|
@@ -896,13 +893,15 @@ amendResourceKind("bucket", {
|
|
|
896
893
|
"S3_ACCESS_KEY_ID",
|
|
897
894
|
"S3_SECRET_ACCESS_KEY",
|
|
898
895
|
"S3_ENDPOINT",
|
|
899
|
-
"S3_FORCE_PATH_STYLE"
|
|
896
|
+
"S3_FORCE_PATH_STYLE",
|
|
897
|
+
"STORAGE_MAX_FILE_SIZE"
|
|
900
898
|
],
|
|
901
899
|
gcs: [
|
|
902
900
|
"STORAGE_TYPE",
|
|
903
901
|
"GCS_BUCKET",
|
|
904
902
|
"GCS_PROJECT_ID",
|
|
905
|
-
"GCS_KEY_FILENAME"
|
|
903
|
+
"GCS_KEY_FILENAME",
|
|
904
|
+
"STORAGE_MAX_FILE_SIZE"
|
|
906
905
|
],
|
|
907
906
|
azure: [],
|
|
908
907
|
firebase: []
|
|
@@ -917,14 +916,48 @@ registerResourceKind({
|
|
|
917
916
|
implicitDefault: false
|
|
918
917
|
});
|
|
919
918
|
amendResourceKind("topic", { envBases: [] });
|
|
920
|
-
|
|
919
|
+
/**
|
|
920
|
+
* Declared handlers and installed runtimes, for topics and queues — on
|
|
921
|
+
* `globalThis` under a shared symbol, never in module locals.
|
|
922
|
+
*
|
|
923
|
+
* A module local is one per COPY of this package, and two copies in one
|
|
924
|
+
* process is the normal layout rather than an accident: `@rebasepro/server`
|
|
925
|
+
* inlines this package into its own dist, while `config/resources.ts` imports
|
|
926
|
+
* it from `node_modules`. With locals, a project's `.handler()` and
|
|
927
|
+
* `.subscription()` went into the project's copy and the worker read the
|
|
928
|
+
* server's empty one (`Job queue started {"tasks":0}`), and the runtime the
|
|
929
|
+
* server installed was invisible to the project's `enqueue`/`publish` — so
|
|
930
|
+
* every queue and topic threw "no runtime is installed" inside a running
|
|
931
|
+
* backend. The CLI deriving the graph had the same split. Same mechanism and
|
|
932
|
+
* reasoning as `registry()` in resources.ts; `module-state-across-copies.test.ts`
|
|
933
|
+
* loads two copies to hold it, and scans for any other module-level state that
|
|
934
|
+
* would split the same way.
|
|
935
|
+
*
|
|
936
|
+
* The version is in the symbol: a change to this object's SHAPE takes a new
|
|
937
|
+
* suffix, so no copy ever reads a shape it does not know.
|
|
938
|
+
*/
|
|
939
|
+
var WORK_KEY = Symbol.for("@rebasepro/types.workRegistry.v1");
|
|
940
|
+
function work() {
|
|
941
|
+
const g = globalThis;
|
|
942
|
+
let shared = g[WORK_KEY];
|
|
943
|
+
if (!shared) {
|
|
944
|
+
shared = {
|
|
945
|
+
topicRuntime: null,
|
|
946
|
+
subscriptions: [],
|
|
947
|
+
queueRuntime: null,
|
|
948
|
+
queueConsumers: /* @__PURE__ */ new Map()
|
|
949
|
+
};
|
|
950
|
+
g[WORK_KEY] = shared;
|
|
951
|
+
}
|
|
952
|
+
return shared;
|
|
953
|
+
}
|
|
921
954
|
/** Install the transport topics publish through. Called by the server at boot. */
|
|
922
955
|
function setTopicRuntime(runtime) {
|
|
923
|
-
|
|
956
|
+
work().topicRuntime = runtime;
|
|
924
957
|
}
|
|
925
|
-
var subscriptions = [];
|
|
926
958
|
/** Every declared subscription, for the worker to wire and the graph to record. */
|
|
927
959
|
function declaredSubscriptions(topic) {
|
|
960
|
+
const { subscriptions } = work();
|
|
928
961
|
return topic ? subscriptions.filter((s) => s.topic === topic) : subscriptions.slice();
|
|
929
962
|
}
|
|
930
963
|
registerResourceKind({
|
|
@@ -975,15 +1008,13 @@ registerResourceKind({
|
|
|
975
1008
|
optionKeys: ["maxAttempts"],
|
|
976
1009
|
implicitDefault: false
|
|
977
1010
|
});
|
|
978
|
-
var queueRuntimeHolder = { current: null };
|
|
979
1011
|
/** Install the transport queues enqueue through. Called by the server at boot. */
|
|
980
1012
|
function setQueueRuntime(runtime) {
|
|
981
|
-
|
|
1013
|
+
work().queueRuntime = runtime;
|
|
982
1014
|
}
|
|
983
|
-
var queueConsumers = /* @__PURE__ */ new Map();
|
|
984
1015
|
/** Every declared queue handler, for the worker to wire. */
|
|
985
1016
|
function declaredQueueConsumers() {
|
|
986
|
-
return [...queueConsumers.values()];
|
|
1017
|
+
return [...work().queueConsumers.values()];
|
|
987
1018
|
}
|
|
988
1019
|
/**
|
|
989
1020
|
* One declaration, as the data layer's definition.
|
|
@@ -1021,6 +1052,369 @@ function resourceToStorageSource(declaration) {
|
|
|
1021
1052
|
};
|
|
1022
1053
|
}
|
|
1023
1054
|
//#endregion
|
|
1024
|
-
|
|
1055
|
+
//#region ../types/src/types/scopes.ts
|
|
1056
|
+
/**
|
|
1057
|
+
* Scopes — what a credential may do, named `resource:action`.
|
|
1058
|
+
*
|
|
1059
|
+
* One vocabulary for every way of reaching a Rebase backend: a person's
|
|
1060
|
+
* session, a service key, a personal key and an OAuth token for `/mcp` all
|
|
1061
|
+
* answer "may this caller do X?" with the same strings, so a grant reads the
|
|
1062
|
+
* same on a key, on a role and on a consent screen.
|
|
1063
|
+
*
|
|
1064
|
+
* A scope may carry a target — `data:read:posts` is `data:read` on the `posts`
|
|
1065
|
+
* collection only. The unqualified scope covers every target. Only the data
|
|
1066
|
+
* plane and app scopes take targets; see {@link SCOPE_TARGETS}.
|
|
1067
|
+
*
|
|
1068
|
+
* Two planes, held differently:
|
|
1069
|
+
*
|
|
1070
|
+
* - **The data plane** (`data:*`, `storage:*`, `functions:invoke`). Every
|
|
1071
|
+
* signed-in person holds all of it, because what a person may do with data
|
|
1072
|
+
* is decided row by row by the collection's `securityRules` and by storage
|
|
1073
|
+
* policies, never by a scope. On a key or a token these scopes narrow: a key
|
|
1074
|
+
* holding `data:read:posts` reaches nothing else, whatever RLS would allow.
|
|
1075
|
+
* - **The admin plane** (everything else). Nobody holds it implicitly. The
|
|
1076
|
+
* `admin` role holds all of it; any other role holds what the app declares
|
|
1077
|
+
* for it under `auth.roles` on the users collection.
|
|
1078
|
+
*
|
|
1079
|
+
* Apps declare their own scopes too (`auth.scopes`), named the same way —
|
|
1080
|
+
* `project:deploy`. Every signed-in person holds every app scope: like the data
|
|
1081
|
+
* plane, the function behind it decides whether the person may act, and the
|
|
1082
|
+
* scope exists so a key can be narrowed to that one action.
|
|
1083
|
+
*
|
|
1084
|
+
* @module
|
|
1085
|
+
*/
|
|
1086
|
+
/** @group Auth */
|
|
1087
|
+
var DATA_PLANE_SCOPES = [
|
|
1088
|
+
"data:read",
|
|
1089
|
+
"data:write",
|
|
1090
|
+
"data:delete",
|
|
1091
|
+
"storage:read",
|
|
1092
|
+
"storage:write",
|
|
1093
|
+
"storage:delete",
|
|
1094
|
+
"functions:invoke"
|
|
1095
|
+
];
|
|
1096
|
+
/** @group Auth */
|
|
1097
|
+
var ADMIN_SCOPES = [
|
|
1098
|
+
"users:read",
|
|
1099
|
+
"users:write",
|
|
1100
|
+
"schema:read",
|
|
1101
|
+
"schema:write",
|
|
1102
|
+
"database:read",
|
|
1103
|
+
"database:write",
|
|
1104
|
+
"backups:read",
|
|
1105
|
+
"cron:read",
|
|
1106
|
+
"cron:write",
|
|
1107
|
+
"logs:read",
|
|
1108
|
+
"keys:read",
|
|
1109
|
+
"keys:write"
|
|
1110
|
+
];
|
|
1111
|
+
/** Every scope Rebase itself defines, in display order. @group Auth */
|
|
1112
|
+
var BUILT_IN_SCOPES = [...DATA_PLANE_SCOPES, ...ADMIN_SCOPES];
|
|
1113
|
+
/**
|
|
1114
|
+
* Scopes no key may hold.
|
|
1115
|
+
*
|
|
1116
|
+
* A key that could manage keys could mint its own successor, widen itself, or
|
|
1117
|
+
* revoke the keys other integrations run on — and revoking it would undo none
|
|
1118
|
+
* of that. Managing keys is for a person (or the service key).
|
|
1119
|
+
*
|
|
1120
|
+
* @group Auth
|
|
1121
|
+
*/
|
|
1122
|
+
var KEY_MANAGEMENT_SCOPES = ["keys:read", "keys:write"];
|
|
1123
|
+
/** The one built-in role. It holds every scope and is the RLS `admin` role. @group Auth */
|
|
1124
|
+
var ADMIN_ROLE = "admin";
|
|
1125
|
+
/**
|
|
1126
|
+
* The built-in scopes that accept a target, and what the target names.
|
|
1127
|
+
*
|
|
1128
|
+
* - `data:*` — a collection slug
|
|
1129
|
+
* - `storage:*` — a storage source id (`(default)` for the default source)
|
|
1130
|
+
* - `functions:invoke` — a custom function's name
|
|
1131
|
+
*
|
|
1132
|
+
* @group Auth
|
|
1133
|
+
*/
|
|
1134
|
+
var SCOPE_TARGETS = {
|
|
1135
|
+
"data:read": "collection",
|
|
1136
|
+
"data:write": "collection",
|
|
1137
|
+
"data:delete": "collection",
|
|
1138
|
+
"storage:read": "bucket",
|
|
1139
|
+
"storage:write": "bucket",
|
|
1140
|
+
"storage:delete": "bucket",
|
|
1141
|
+
"functions:invoke": "function"
|
|
1142
|
+
};
|
|
1143
|
+
/** @group Auth */
|
|
1144
|
+
var BUILT_IN_SCOPE_DESCRIPTIONS = {
|
|
1145
|
+
"data:read": {
|
|
1146
|
+
label: "Read data",
|
|
1147
|
+
description: "Read rows from collections, through the caller's row-level security."
|
|
1148
|
+
},
|
|
1149
|
+
"data:write": {
|
|
1150
|
+
label: "Create and update data",
|
|
1151
|
+
description: "Create and update rows in collections, through the caller's row-level security."
|
|
1152
|
+
},
|
|
1153
|
+
"data:delete": {
|
|
1154
|
+
label: "Delete data",
|
|
1155
|
+
description: "Delete rows from collections, through the caller's row-level security."
|
|
1156
|
+
},
|
|
1157
|
+
"storage:read": {
|
|
1158
|
+
label: "Read files",
|
|
1159
|
+
description: "List and download stored files."
|
|
1160
|
+
},
|
|
1161
|
+
"storage:write": {
|
|
1162
|
+
label: "Upload files",
|
|
1163
|
+
description: "Upload files and create folders."
|
|
1164
|
+
},
|
|
1165
|
+
"storage:delete": {
|
|
1166
|
+
label: "Delete files",
|
|
1167
|
+
description: "Delete stored files."
|
|
1168
|
+
},
|
|
1169
|
+
"functions:invoke": {
|
|
1170
|
+
label: "Call functions",
|
|
1171
|
+
description: "Call the backend's custom functions. A function can do anything its code does."
|
|
1172
|
+
},
|
|
1173
|
+
"users:read": {
|
|
1174
|
+
label: "See users",
|
|
1175
|
+
description: "List user accounts and their roles."
|
|
1176
|
+
},
|
|
1177
|
+
"users:write": {
|
|
1178
|
+
label: "Manage users",
|
|
1179
|
+
description: "Create, edit and delete accounts, reset passwords and second factors, and assign roles up to the holder's own."
|
|
1180
|
+
},
|
|
1181
|
+
"schema:read": {
|
|
1182
|
+
label: "See the schema",
|
|
1183
|
+
description: "Read the collection schema, plan schema changes and run the RLS audit."
|
|
1184
|
+
},
|
|
1185
|
+
"schema:write": {
|
|
1186
|
+
label: "Change the schema",
|
|
1187
|
+
description: "Apply schema changes: edits collection files and alters the database."
|
|
1188
|
+
},
|
|
1189
|
+
"database:read": {
|
|
1190
|
+
label: "Inspect the database",
|
|
1191
|
+
description: "List databases, tables, Postgres roles and branches."
|
|
1192
|
+
},
|
|
1193
|
+
"database:write": {
|
|
1194
|
+
label: "Run SQL",
|
|
1195
|
+
description: "Run SQL as the database owner, outside row-level security, and create or delete branches."
|
|
1196
|
+
},
|
|
1197
|
+
"backups:read": {
|
|
1198
|
+
label: "Download backups",
|
|
1199
|
+
description: "List and download database backups — every row, outside row-level security."
|
|
1200
|
+
},
|
|
1201
|
+
"cron:read": {
|
|
1202
|
+
label: "See cron jobs",
|
|
1203
|
+
description: "List cron jobs and read their run history."
|
|
1204
|
+
},
|
|
1205
|
+
"cron:write": {
|
|
1206
|
+
label: "Run cron jobs",
|
|
1207
|
+
description: "Trigger cron jobs and switch them on or off."
|
|
1208
|
+
},
|
|
1209
|
+
"logs:read": {
|
|
1210
|
+
label: "Read server logs",
|
|
1211
|
+
description: "Read the server's request and application logs."
|
|
1212
|
+
},
|
|
1213
|
+
"keys:read": {
|
|
1214
|
+
label: "See service keys",
|
|
1215
|
+
description: "List the project's service keys. Never grantable to a key."
|
|
1216
|
+
},
|
|
1217
|
+
"keys:write": {
|
|
1218
|
+
label: "Manage service keys",
|
|
1219
|
+
description: "Create, change and revoke the project's service keys. Never grantable to a key."
|
|
1220
|
+
}
|
|
1221
|
+
};
|
|
1222
|
+
/** The access model of an app that declares nothing: built-ins only. @group Auth */
|
|
1223
|
+
var EMPTY_ACCESS_MODEL = {
|
|
1224
|
+
roles: {},
|
|
1225
|
+
scopes: {}
|
|
1226
|
+
};
|
|
1227
|
+
var SCOPE_PART = /^[a-z][a-z0-9-]*$/;
|
|
1228
|
+
/**
|
|
1229
|
+
* Split `resource:action[:target]`. Returns null for anything else.
|
|
1230
|
+
*
|
|
1231
|
+
* The target is everything after the second colon, so a target may itself
|
|
1232
|
+
* contain colons. Resource and action are lower-case words.
|
|
1233
|
+
*
|
|
1234
|
+
* @group Auth
|
|
1235
|
+
*/
|
|
1236
|
+
function parseScope(value) {
|
|
1237
|
+
if (typeof value !== "string") return null;
|
|
1238
|
+
const first = value.indexOf(":");
|
|
1239
|
+
if (first < 0) return null;
|
|
1240
|
+
const second = value.indexOf(":", first + 1);
|
|
1241
|
+
const resource = value.slice(0, first);
|
|
1242
|
+
const action = second < 0 ? value.slice(first + 1) : value.slice(first + 1, second);
|
|
1243
|
+
if (!SCOPE_PART.test(resource) || !SCOPE_PART.test(action)) return null;
|
|
1244
|
+
if (second < 0) return { scope: `${resource}:${action}` };
|
|
1245
|
+
const target = value.slice(second + 1);
|
|
1246
|
+
if (target.length === 0 || /\s/.test(target)) return null;
|
|
1247
|
+
return {
|
|
1248
|
+
scope: `${resource}:${action}`,
|
|
1249
|
+
target
|
|
1250
|
+
};
|
|
1251
|
+
}
|
|
1252
|
+
/** @group Auth */
|
|
1253
|
+
function isBuiltInScope(scope) {
|
|
1254
|
+
return BUILT_IN_SCOPES.includes(scope);
|
|
1255
|
+
}
|
|
1256
|
+
/** @group Auth */
|
|
1257
|
+
function isDataPlaneScope(scope) {
|
|
1258
|
+
return DATA_PLANE_SCOPES.includes(scope);
|
|
1259
|
+
}
|
|
1260
|
+
/** @group Auth */
|
|
1261
|
+
function isAdminScope(scope) {
|
|
1262
|
+
return ADMIN_SCOPES.includes(scope);
|
|
1263
|
+
}
|
|
1264
|
+
/** Does this list of roles include the built-in `admin` role? @group Auth */
|
|
1265
|
+
function hasAdminRole(roles) {
|
|
1266
|
+
return !!roles?.includes(ADMIN_ROLE);
|
|
1267
|
+
}
|
|
1268
|
+
/**
|
|
1269
|
+
* Does a set of held scopes grant `scope`, optionally on one `target`?
|
|
1270
|
+
*
|
|
1271
|
+
* The unqualified grant covers every target. A qualified grant covers its own
|
|
1272
|
+
* target only, and never answers an unqualified question: a key holding
|
|
1273
|
+
* `data:read:posts` is not asked "may you read data?" and told yes.
|
|
1274
|
+
*
|
|
1275
|
+
* @group Auth
|
|
1276
|
+
*/
|
|
1277
|
+
function scopeGrants(held, scope, target) {
|
|
1278
|
+
for (const entry of held) {
|
|
1279
|
+
if (entry === scope) return true;
|
|
1280
|
+
if (target !== void 0 && entry === `${scope}:${target}`) return true;
|
|
1281
|
+
}
|
|
1282
|
+
return false;
|
|
1283
|
+
}
|
|
1284
|
+
/**
|
|
1285
|
+
* Does a set of held scopes grant `scope` on at least one target?
|
|
1286
|
+
*
|
|
1287
|
+
* For a surface that lists what is reachable — the collections an MCP client
|
|
1288
|
+
* may query — and filters per item afterwards.
|
|
1289
|
+
*
|
|
1290
|
+
* @group Auth
|
|
1291
|
+
*/
|
|
1292
|
+
function scopeGrantsAny(held, scope) {
|
|
1293
|
+
const prefix = `${scope}:`;
|
|
1294
|
+
return held.some((entry) => entry === scope || entry.startsWith(prefix));
|
|
1295
|
+
}
|
|
1296
|
+
/**
|
|
1297
|
+
* Every scope a person holding `roles` has.
|
|
1298
|
+
*
|
|
1299
|
+
* The data plane and every app scope always; the whole admin plane with the
|
|
1300
|
+
* `admin` role; otherwise each declared role's scopes. A role nobody declared
|
|
1301
|
+
* adds nothing — it may still mean something to an RLS policy.
|
|
1302
|
+
*
|
|
1303
|
+
* @group Auth
|
|
1304
|
+
*/
|
|
1305
|
+
function scopesForRoles(roles, model = EMPTY_ACCESS_MODEL) {
|
|
1306
|
+
const held = /* @__PURE__ */ new Set([...DATA_PLANE_SCOPES, ...Object.keys(model.scopes)]);
|
|
1307
|
+
if (hasAdminRole(roles)) {
|
|
1308
|
+
for (const scope of ADMIN_SCOPES) held.add(scope);
|
|
1309
|
+
return [...held];
|
|
1310
|
+
}
|
|
1311
|
+
for (const role of roles ?? []) {
|
|
1312
|
+
const definition = Object.prototype.hasOwnProperty.call(model.roles, role) ? model.roles[role] : void 0;
|
|
1313
|
+
for (const scope of definition?.scopes ?? []) held.add(scope);
|
|
1314
|
+
}
|
|
1315
|
+
return [...held];
|
|
1316
|
+
}
|
|
1317
|
+
/**
|
|
1318
|
+
* Every scope this access model knows, unqualified: the built-ins, then the
|
|
1319
|
+
* app's own.
|
|
1320
|
+
*
|
|
1321
|
+
* @group Auth
|
|
1322
|
+
*/
|
|
1323
|
+
function knownScopes(model = EMPTY_ACCESS_MODEL) {
|
|
1324
|
+
return [...BUILT_IN_SCOPES, ...Object.keys(model.scopes)];
|
|
1325
|
+
}
|
|
1326
|
+
/** Does this scope accept a target? @group Auth */
|
|
1327
|
+
function scopeAcceptsTarget(scope, model = EMPTY_ACCESS_MODEL) {
|
|
1328
|
+
if (isBuiltInScope(scope)) return SCOPE_TARGETS[scope] !== void 0;
|
|
1329
|
+
return (Object.prototype.hasOwnProperty.call(model.scopes, scope) ? model.scopes[scope] : void 0)?.target !== void 0;
|
|
1330
|
+
}
|
|
1331
|
+
/**
|
|
1332
|
+
* Check a list of scope strings against an access model. Returns the
|
|
1333
|
+
* problems, empty when every entry is a known scope with an acceptable target.
|
|
1334
|
+
*
|
|
1335
|
+
* @group Auth
|
|
1336
|
+
*/
|
|
1337
|
+
function validateScopes(values, model = EMPTY_ACCESS_MODEL) {
|
|
1338
|
+
const known = new Set(knownScopes(model));
|
|
1339
|
+
const problems = [];
|
|
1340
|
+
for (const value of values) {
|
|
1341
|
+
const text = typeof value === "string" ? value : String(value);
|
|
1342
|
+
const parsed = typeof value === "string" ? parseScope(value) : null;
|
|
1343
|
+
if (!parsed) problems.push({
|
|
1344
|
+
scope: text,
|
|
1345
|
+
reason: "malformed"
|
|
1346
|
+
});
|
|
1347
|
+
else if (!known.has(parsed.scope)) problems.push({
|
|
1348
|
+
scope: text,
|
|
1349
|
+
reason: "unknown"
|
|
1350
|
+
});
|
|
1351
|
+
else if (parsed.target !== void 0 && !scopeAcceptsTarget(parsed.scope, model)) problems.push({
|
|
1352
|
+
scope: text,
|
|
1353
|
+
reason: "target-not-accepted"
|
|
1354
|
+
});
|
|
1355
|
+
}
|
|
1356
|
+
return problems;
|
|
1357
|
+
}
|
|
1358
|
+
/**
|
|
1359
|
+
* The entries of `requested` that `held` does not cover — what a credential
|
|
1360
|
+
* would hold beyond its minter. Empty means the request is within reach.
|
|
1361
|
+
*
|
|
1362
|
+
* `data:read:posts` is covered by `data:read`; `data:read` is not covered by
|
|
1363
|
+
* `data:read:posts`.
|
|
1364
|
+
*
|
|
1365
|
+
* @group Auth
|
|
1366
|
+
*/
|
|
1367
|
+
function scopesBeyond(requested, held) {
|
|
1368
|
+
return requested.filter((entry) => {
|
|
1369
|
+
const parsed = parseScope(entry);
|
|
1370
|
+
if (!parsed) return true;
|
|
1371
|
+
return !scopeGrants(held, parsed.scope, parsed.target);
|
|
1372
|
+
});
|
|
1373
|
+
}
|
|
1374
|
+
/**
|
|
1375
|
+
* Narrow `requested` to what `held` covers, entry by entry. What a personal
|
|
1376
|
+
* key holds today when its owner has lost a role since it was minted.
|
|
1377
|
+
*
|
|
1378
|
+
* @group Auth
|
|
1379
|
+
*/
|
|
1380
|
+
function intersectScopes(requested, held) {
|
|
1381
|
+
const beyond = new Set(scopesBeyond(requested, held));
|
|
1382
|
+
return requested.filter((entry) => !beyond.has(entry));
|
|
1383
|
+
}
|
|
1384
|
+
/** The roles of an access model, `admin` first. @group Auth */
|
|
1385
|
+
function summarizeRoles(model = EMPTY_ACCESS_MODEL) {
|
|
1386
|
+
return [{
|
|
1387
|
+
id: ADMIN_ROLE,
|
|
1388
|
+
name: "Admin",
|
|
1389
|
+
description: "Holds every scope. Row-level security does not limit it: it reads, changes and deletes every row.",
|
|
1390
|
+
scopes: [...ADMIN_SCOPES],
|
|
1391
|
+
builtIn: true
|
|
1392
|
+
}, ...Object.entries(model.roles).map(([id, definition]) => ({
|
|
1393
|
+
id,
|
|
1394
|
+
name: definition.name ?? id,
|
|
1395
|
+
...definition.description ? { description: definition.description } : {},
|
|
1396
|
+
scopes: [...definition.scopes],
|
|
1397
|
+
builtIn: false
|
|
1398
|
+
}))];
|
|
1399
|
+
}
|
|
1400
|
+
/** Every scope of an access model, described, in display order. @group Auth */
|
|
1401
|
+
function summarizeScopes(model = EMPTY_ACCESS_MODEL) {
|
|
1402
|
+
const builtIn = BUILT_IN_SCOPES.map((scope) => ({
|
|
1403
|
+
scope,
|
|
1404
|
+
...BUILT_IN_SCOPE_DESCRIPTIONS[scope],
|
|
1405
|
+
...SCOPE_TARGETS[scope] ? { target: SCOPE_TARGETS[scope] } : {},
|
|
1406
|
+
plane: isDataPlaneScope(scope) ? "data" : "admin"
|
|
1407
|
+
}));
|
|
1408
|
+
const app = Object.entries(model.scopes).map(([scope, definition]) => ({
|
|
1409
|
+
scope,
|
|
1410
|
+
label: definition.label,
|
|
1411
|
+
description: definition.description ?? "",
|
|
1412
|
+
...definition.target ? { target: definition.target } : {},
|
|
1413
|
+
plane: "app"
|
|
1414
|
+
}));
|
|
1415
|
+
return [...builtIn, ...app];
|
|
1416
|
+
}
|
|
1417
|
+
//#endregion
|
|
1418
|
+
export { parseRelationAggregateSort as $, DEFAULT_RESOURCE_KEY as A, rewriteLegacyRlsFunctions as B, declaredSubscriptions as C, setTopicRuntime as D, setQueueRuntime as E, resourceKind as F, DEFAULT_DATA_SOURCE_KEY as G, getDeclaredSubcollections as H, resourceKinds as I, CANONICAL_TO_REST as J, getDataSourceCapabilities as K, RLS_JWT_SQL as L, resolveResourceRefs as M, resourceEnvSuffix as N, DEFAULT_STORAGE_SOURCE_KEY as O, resourceKeyOf as P, isRelationAggregateSort as Q, RLS_ROLES_SQL as R, declaredQueueConsumers as S, resourceToStorageSource as T, isPostgresCollectionConfig as U, getCollectionDataPath as V, isRelationalCollectionConfig as W, NULL_OPS as X, LIST_OPS as Y, REST_TO_CANONICAL as Z, scopesForRoles as _, KEY_MANAGEMENT_SCOPES as a, validateScopes as b, intersectScopes as c, isDataPlaneScope as d, sortKeyToString as et, knownScopes as f, scopesBeyond as g, scopeGrantsAny as h, EMPTY_ACCESS_MODEL as i, buildResourceGraph as j, storageEnvSuffix as k, isAdminScope as l, scopeGrants as m, ADMIN_SCOPES as n, SCOPE_TARGETS as o, parseScope as p, ALL_WHERE_FILTER_OPS as q, BUILT_IN_SCOPES as r, hasAdminRole as s, ADMIN_ROLE as t, toCanonicalOp as tt, isBuiltInScope as u, summarizeRoles as v, resourceToDataSource as w, declareCron as x, summarizeScopes as y, RLS_UID_SQL as z };
|
|
1025
1419
|
|
|
1026
|
-
//# sourceMappingURL=src-
|
|
1420
|
+
//# sourceMappingURL=src-CatHFUym.js.map
|