@rebasepro/server 0.23.0 → 0.24.1-canary.g19596ef

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.
Files changed (287) hide show
  1. package/README.md +28 -3
  2. package/bin/rebase-server.js +4 -2
  3. package/dist/GCSStorageController-DEga1ULx.js +402 -0
  4. package/dist/GCSStorageController-DEga1ULx.js.map +1 -0
  5. package/dist/S3StorageController-Btx-6bJ5.js +480 -0
  6. package/dist/S3StorageController-Btx-6bJ5.js.map +1 -0
  7. package/dist/api/ast-schema-editor.d.ts +92 -1
  8. package/dist/api/errors.d.ts +41 -0
  9. package/dist/api/live-schema-routes.d.ts +64 -10
  10. package/dist/api/logs-routes.d.ts +39 -1
  11. package/dist/api/mount-path.d.ts +30 -0
  12. package/dist/api/mount.d.ts +6 -13
  13. package/dist/api/openapi-generator.d.ts +17 -0
  14. package/dist/api/rest/api-generator.d.ts +97 -11
  15. package/dist/api/rest/auth-collection-writes.d.ts +28 -21
  16. package/dist/api/rest/field-access-query.d.ts +28 -8
  17. package/dist/api/rest/field-ops.d.ts +19 -7
  18. package/dist/api/rest/query-body.d.ts +10 -0
  19. package/dist/api/rest/write-validation.d.ts +9 -7
  20. package/dist/api/schema-editor-routes.d.ts +10 -1
  21. package/dist/api/sql-export-routes.d.ts +8 -0
  22. package/dist/api/types.d.ts +52 -1
  23. package/dist/{ast-schema-editor-Mvr50v_S.js → ast-schema-editor-mCeSC03x.js} +310 -12
  24. package/dist/ast-schema-editor-mCeSC03x.js.map +1 -0
  25. package/dist/auth/access.d.ts +156 -0
  26. package/dist/auth/adapter-middleware.d.ts +2 -1
  27. package/dist/auth/address-ownership.d.ts +16 -1
  28. package/dist/auth/admin-roles-route.d.ts +4 -2
  29. package/dist/auth/admin-roles.d.ts +17 -20
  30. package/dist/auth/admin-user-ops.d.ts +24 -2
  31. package/dist/auth/admin-users-route.d.ts +2 -0
  32. package/dist/auth/api-keys/api-key-middleware.d.ts +64 -56
  33. package/dist/auth/api-keys/api-key-routes.d.ts +44 -11
  34. package/dist/auth/api-keys/api-key-store.d.ts +31 -8
  35. package/dist/auth/api-keys/api-key-types.d.ts +14 -16
  36. package/dist/auth/api-keys/http-operation.d.ts +19 -0
  37. package/dist/auth/api-keys/index.d.ts +11 -11
  38. package/dist/auth/api-keys/key-grant.d.ts +41 -0
  39. package/dist/auth/api-keys/legacy-permissions.d.ts +33 -0
  40. package/dist/auth/auth-hooks.d.ts +46 -7
  41. package/dist/auth/builtin-auth-adapter.d.ts +21 -0
  42. package/dist/auth/cookie-utils.d.ts +7 -0
  43. package/dist/auth/deliverable-address.d.ts +6 -0
  44. package/dist/auth/email-change-routes.d.ts +44 -0
  45. package/dist/auth/expired-token-sweep.d.ts +71 -0
  46. package/dist/auth/impersonation.d.ts +110 -0
  47. package/dist/auth/index.d.ts +4 -2
  48. package/dist/auth/interfaces.d.ts +120 -59
  49. package/dist/auth/jwks-routes.d.ts +5 -1
  50. package/dist/auth/jwt-crypto.d.ts +7 -0
  51. package/dist/auth/jwt-keys.d.ts +4 -0
  52. package/dist/auth/jwt.d.ts +319 -157
  53. package/dist/auth/magic-link-routes.d.ts +5 -6
  54. package/dist/auth/mfa-crypto.d.ts +9 -3
  55. package/dist/auth/mfa-gate.d.ts +4 -2
  56. package/dist/auth/mfa-routes.d.ts +8 -9
  57. package/dist/auth/middleware.d.ts +26 -7
  58. package/dist/auth/otp-routes.d.ts +5 -6
  59. package/dist/auth/passwordless-signup.d.ts +27 -0
  60. package/dist/auth/platform-token.d.ts +122 -0
  61. package/dist/auth/rate-limiter.d.ts +99 -31
  62. package/dist/auth/registration-policy.d.ts +17 -0
  63. package/dist/auth/require-auth.d.ts +1 -1
  64. package/dist/auth/routes.d.ts +61 -0
  65. package/dist/auth/scope-routes.d.ts +22 -0
  66. package/dist/auth/session-routes.d.ts +17 -6
  67. package/dist/auth/token-revocation.d.ts +56 -1
  68. package/dist/auth/user-picking.d.ts +37 -0
  69. package/dist/auth/verify-credential.d.ts +49 -0
  70. package/dist/{auth-B-GIMpDG.js → auth-CSBky1mt.js} +4564 -1929
  71. package/dist/auth-CSBky1mt.js.map +1 -0
  72. package/dist/auth_adapter-CIItCTc8.js +21 -0
  73. package/dist/auth_adapter-CIItCTc8.js.map +1 -0
  74. package/dist/backend/create-backend.d.ts +281 -0
  75. package/dist/backend/default-backend.d.ts +35 -0
  76. package/dist/backend/no-collections.d.ts +19 -0
  77. package/dist/backend/options.d.ts +912 -0
  78. package/dist/backend/scope.d.ts +23 -0
  79. package/dist/backend/services.d.ts +54 -0
  80. package/dist/backend-DTAOsLQc.js.map +1 -1
  81. package/dist/backup/backup-common.d.ts +24 -3
  82. package/dist/backup/backup-routes.d.ts +46 -5
  83. package/dist/backup/backup-schedule.d.ts +33 -0
  84. package/dist/backup/backup-storage.d.ts +16 -0
  85. package/dist/backup/index.d.ts +5 -1
  86. package/dist/backup-DBGRUVTS.js +585 -0
  87. package/dist/backup-DBGRUVTS.js.map +1 -0
  88. package/dist/boot/boot.d.ts +2 -2
  89. package/dist/boot/bundle.d.ts +19 -0
  90. package/dist/boot/driver.d.ts +3 -0
  91. package/dist/boot/env.d.ts +58 -6
  92. package/dist/boot/http-server.d.ts +22 -0
  93. package/dist/boot/options.d.ts +16 -1
  94. package/dist/boot/provision.d.ts +4 -2
  95. package/dist/boot/resource-adapters.d.ts +11 -14
  96. package/dist/boot/runtime-cors.d.ts +17 -0
  97. package/dist/boot/security-headers.d.ts +26 -0
  98. package/dist/boot/sources.d.ts +9 -0
  99. package/dist/boot/static-routing.d.ts +65 -0
  100. package/dist/collection_patch-BRu-BvDv.js +472 -0
  101. package/dist/collection_patch-BRu-BvDv.js.map +1 -0
  102. package/dist/{contract-routes-CbFjuBwa.js → contract-routes-DiFwiLg2.js} +5 -8
  103. package/dist/contract-routes-DiFwiLg2.js.map +1 -0
  104. package/dist/cron/cron-loader.d.ts +77 -18
  105. package/dist/cron/cron-routes.d.ts +1 -1
  106. package/dist/cron/cron-scheduler.d.ts +94 -23
  107. package/dist/cron/cron-store.d.ts +37 -5
  108. package/dist/cron/define-cron.d.ts +6 -2
  109. package/dist/cron/index.d.ts +3 -3
  110. package/dist/cron-loader-NHqRfKF0.js +202 -0
  111. package/dist/cron-loader-NHqRfKF0.js.map +1 -0
  112. package/dist/{cron-routes-eE8nif_b.js → cron-routes-DsH8Jwn5.js} +34 -8
  113. package/dist/cron-routes-DsH8Jwn5.js.map +1 -0
  114. package/dist/{cron-scheduler-B0pLfAix.js → cron-scheduler-D1DT0nw5.js} +349 -65
  115. package/dist/cron-scheduler-D1DT0nw5.js.map +1 -0
  116. package/dist/cron-store-DEpVstUU.js +577 -0
  117. package/dist/cron-store-DEpVstUU.js.map +1 -0
  118. package/dist/{ddl-bootstrap-C6mo0Kmz.js → ddl-bootstrap-BNqi2NZe.js} +2 -2
  119. package/dist/{ddl-bootstrap-C6mo0Kmz.js.map → ddl-bootstrap-BNqi2NZe.js.map} +1 -1
  120. package/dist/email/index.d.ts +2 -2
  121. package/dist/email/smtp-email-service.d.ts +23 -0
  122. package/dist/email/templates.d.ts +22 -0
  123. package/dist/email/types.d.ts +44 -0
  124. package/dist/env.d.ts +1 -39
  125. package/dist/{errors-DWsX4yTd.js → errors-Cqp86KnA.js} +263 -10
  126. package/dist/errors-Cqp86KnA.js.map +1 -0
  127. package/dist/filter-dialect-O1HK6Nvr.js +1628 -0
  128. package/dist/filter-dialect-O1HK6Nvr.js.map +1 -0
  129. package/dist/{function-loader-xnbDAPfa.js → function-loader-DbCSoNJj.js} +69 -39
  130. package/dist/function-loader-DbCSoNJj.js.map +1 -0
  131. package/dist/{function-routes-Chet4-lB.js → function-routes-BSTClQNa.js} +28 -15
  132. package/dist/function-routes-BSTClQNa.js.map +1 -0
  133. package/dist/functions/context.d.ts +26 -6
  134. package/dist/functions/define-function.d.ts +10 -6
  135. package/dist/functions/function-loader.d.ts +75 -18
  136. package/dist/functions/function-routes.d.ts +2 -1
  137. package/dist/functions/guards.d.ts +22 -5
  138. package/dist/functions/index.d.ts +6 -5
  139. package/dist/functions/index.js +148 -50
  140. package/dist/functions/index.js.map +1 -1
  141. package/dist/functions/internal.d.ts +2 -2
  142. package/dist/functions/proxy.d.ts +6 -2
  143. package/dist/functions/request-timeout.d.ts +7 -5
  144. package/dist/history/history-routes.d.ts +9 -0
  145. package/dist/history/retention-sweep.d.ts +81 -0
  146. package/dist/{history-recorder-B4MpJfJK.js → history-recorder-RZ1Ow4YY.js} +4 -4
  147. package/dist/{history-recorder-B4MpJfJK.js.map → history-recorder-RZ1Ow4YY.js.map} +1 -1
  148. package/dist/{history-store-BhxWOuz9.js → history-store-DPofGVDp.js} +2 -2
  149. package/dist/{history-store-BhxWOuz9.js.map → history-store-DPofGVDp.js.map} +1 -1
  150. package/dist/index.d.ts +32 -13
  151. package/dist/index.es.js +25329 -18393
  152. package/dist/index.es.js.map +1 -1
  153. package/dist/init/docs.d.ts +35 -10
  154. package/dist/init/health.d.ts +17 -2
  155. package/dist/init/process-safety.d.ts +7 -2
  156. package/dist/init/shutdown.d.ts +26 -1
  157. package/dist/init.d.ts +49 -811
  158. package/dist/internal-tables-L2t39RdT.js +136 -0
  159. package/dist/internal-tables-L2t39RdT.js.map +1 -0
  160. package/dist/jobs/job-queue.d.ts +8 -0
  161. package/dist/jobs/job-store.d.ts +24 -0
  162. package/dist/jobs/types.d.ts +25 -4
  163. package/dist/{jobs-CazMYhyy.js → jobs-8G-_agld.js} +235 -25
  164. package/dist/jobs-8G-_agld.js.map +1 -0
  165. package/dist/{jwt-DnQHNFCl.js → jwt-CBaFc34Y.js} +546 -447
  166. package/dist/jwt-CBaFc34Y.js.map +1 -0
  167. package/dist/{keys-CogCQpxG.js → keys-COzQ2aE8.js} +3 -17
  168. package/dist/{keys-CogCQpxG.js.map → keys-COzQ2aE8.js.map} +1 -1
  169. package/dist/load-failure-L5hvfDoG.js +80 -0
  170. package/dist/load-failure-L5hvfDoG.js.map +1 -0
  171. package/dist/{logger-DO2PZc4i.js → logger-Bt32sHFw.js} +41 -5
  172. package/dist/logger-Bt32sHFw.js.map +1 -0
  173. package/dist/{logs-routes-Bj4TYYUl.js → logs-routes-DQJhrf-b.js} +48 -8
  174. package/dist/logs-routes-DQJhrf-b.js.map +1 -0
  175. package/dist/mcp/consent-page.d.ts +1 -1
  176. package/dist/mcp/mcp-routes.d.ts +13 -0
  177. package/dist/mcp/mcp-tools.d.ts +23 -9
  178. package/dist/mcp/oauth-metadata.d.ts +21 -16
  179. package/dist/mcp/oauth-routes.d.ts +14 -1
  180. package/dist/metrics/index.d.ts +18 -0
  181. package/dist/metrics/pool-wait.d.ts +50 -0
  182. package/dist/offline-QNQgsPOq-B2yGeXkn.js +3305 -0
  183. package/dist/offline-QNQgsPOq-B2yGeXkn.js.map +1 -0
  184. package/dist/offline-store-Cm5sAX81-CALiO4Gn.js +1915 -0
  185. package/dist/offline-store-Cm5sAX81-CALiO4Gn.js.map +1 -0
  186. package/dist/{openapi-generator-O_O24MAT.js → openapi-generator-CeGW2dLC.js} +455 -80
  187. package/dist/openapi-generator-CeGW2dLC.js.map +1 -0
  188. package/dist/policy-PdzX-Opd.js +121 -0
  189. package/dist/policy-PdzX-Opd.js.map +1 -0
  190. package/dist/project_manifest-R6y_KHms.js +59 -0
  191. package/dist/project_manifest-R6y_KHms.js.map +1 -0
  192. package/dist/{proxy-Czngl3p9.js → proxy-BEKbsil6.js} +5 -4
  193. package/dist/proxy-BEKbsil6.js.map +1 -0
  194. package/dist/{query-parser-DGRVFNM3.js → query-parser-ECxP0nDw.js} +497 -52
  195. package/dist/query-parser-ECxP0nDw.js.map +1 -0
  196. package/dist/{request-timeout-C_4C2BeR.js → request-timeout-BiRelY-U.js} +17 -10
  197. package/dist/request-timeout-BiRelY-U.js.map +1 -0
  198. package/dist/resumable-upload-threshold-CKv-Ry0l.js +24 -0
  199. package/dist/resumable-upload-threshold-CKv-Ry0l.js.map +1 -0
  200. package/dist/schema-edit/apply-schema-change.d.ts +73 -3
  201. package/dist/schema-edit/local-source.d.ts +29 -0
  202. package/dist/schema-edit/project-root.d.ts +3 -2
  203. package/dist/schema-edit/remote-source.d.ts +20 -5
  204. package/dist/schema-edit/source-editor.d.ts +28 -0
  205. package/dist/schema-editor-routes-DRXBAbZy.js +136 -0
  206. package/dist/schema-editor-routes-DRXBAbZy.js.map +1 -0
  207. package/dist/serve-spa.d.ts +58 -0
  208. package/dist/services/outbound-post.d.ts +50 -0
  209. package/dist/services/outbound-url-guard.d.ts +34 -5
  210. package/dist/services/routed-realtime-service.d.ts +16 -0
  211. package/dist/services/webhook-service.d.ts +66 -14
  212. package/dist/singleton.d.ts +9 -5
  213. package/dist/soft-delete-params-CBryZXMq.js +668 -0
  214. package/dist/soft-delete-params-CBryZXMq.js.map +1 -0
  215. package/dist/sql-export-routes-D8ZaRvoR.js +240 -0
  216. package/dist/sql-export-routes-D8ZaRvoR.js.map +1 -0
  217. package/dist/{src-vkcwKXbT.js → src-D5Y3N-S4.js} +440 -20
  218. package/dist/src-D5Y3N-S4.js.map +1 -0
  219. package/dist/storage/GCSStorageController.d.ts +48 -2
  220. package/dist/storage/LocalStorageController.d.ts +69 -2
  221. package/dist/storage/S3StorageController.d.ts +39 -3
  222. package/dist/storage/image-transform.d.ts +15 -0
  223. package/dist/storage/index.d.ts +2 -2
  224. package/dist/storage/maintenance-routes.d.ts +23 -0
  225. package/dist/storage/maintenance.d.ts +126 -0
  226. package/dist/storage/property-limits.d.ts +41 -6
  227. package/dist/storage/rendition-cache.d.ts +9 -11
  228. package/dist/storage/request-keys.d.ts +15 -0
  229. package/dist/storage/request-principals.d.ts +30 -0
  230. package/dist/storage/requested-object.d.ts +74 -0
  231. package/dist/storage/routes.d.ts +52 -14
  232. package/dist/storage/source-variables.d.ts +10 -0
  233. package/dist/storage/streams.d.ts +42 -0
  234. package/dist/storage/tus-handler.d.ts +76 -7
  235. package/dist/storage/types.d.ts +101 -7
  236. package/dist/storage/upload-validation.d.ts +13 -0
  237. package/dist/storage-resumable-VO-cMpse-C_YX71pO.js +125 -0
  238. package/dist/storage-resumable-VO-cMpse-C_YX71pO.js.map +1 -0
  239. package/dist/strings.es-BeZWAodn.js +256 -0
  240. package/dist/strings.es-BeZWAodn.js.map +1 -0
  241. package/dist/upload-validation-CVobI5xO.js +172 -0
  242. package/dist/upload-validation-CVobI5xO.js.map +1 -0
  243. package/dist/utils/byte-size.d.ts +10 -0
  244. package/dist/utils/compression.d.ts +6 -0
  245. package/dist/utils/load-failure.d.ts +14 -0
  246. package/dist/utils/logger.d.ts +21 -0
  247. package/package.json +5 -5
  248. package/dist/GCSStorageController-CjrA4PMo.js +0 -242
  249. package/dist/GCSStorageController-CjrA4PMo.js.map +0 -1
  250. package/dist/S3StorageController-B6pKDNVj.js +0 -264
  251. package/dist/S3StorageController-B6pKDNVj.js.map +0 -1
  252. package/dist/admin-roles-vYdp_Pil.js +0 -36
  253. package/dist/admin-roles-vYdp_Pil.js.map +0 -1
  254. package/dist/admin_block-DxKLmdiv.js +0 -206
  255. package/dist/admin_block-DxKLmdiv.js.map +0 -1
  256. package/dist/ast-schema-editor-Mvr50v_S.js.map +0 -1
  257. package/dist/auth/api-keys/api-key-permission-guard.d.ts +0 -65
  258. package/dist/auth-B-GIMpDG.js.map +0 -1
  259. package/dist/backup-D7YR94N3.js +0 -253
  260. package/dist/backup-D7YR94N3.js.map +0 -1
  261. package/dist/contract-routes-CbFjuBwa.js.map +0 -1
  262. package/dist/cron-loader-DfTj2Hbi.js +0 -118
  263. package/dist/cron-loader-DfTj2Hbi.js.map +0 -1
  264. package/dist/cron-routes-eE8nif_b.js.map +0 -1
  265. package/dist/cron-scheduler-B0pLfAix.js.map +0 -1
  266. package/dist/cron-store-TcoGz-xS.js +0 -305
  267. package/dist/cron-store-TcoGz-xS.js.map +0 -1
  268. package/dist/dynamic-import-X40pTZUQ.js +0 -23
  269. package/dist/dynamic-import-X40pTZUQ.js.map +0 -1
  270. package/dist/errors-DWsX4yTd.js.map +0 -1
  271. package/dist/function-loader-xnbDAPfa.js.map +0 -1
  272. package/dist/function-routes-Chet4-lB.js.map +0 -1
  273. package/dist/jobs-CazMYhyy.js.map +0 -1
  274. package/dist/jwt-DnQHNFCl.js.map +0 -1
  275. package/dist/logger-DO2PZc4i.js.map +0 -1
  276. package/dist/logs-routes-Bj4TYYUl.js.map +0 -1
  277. package/dist/openapi-generator-O_O24MAT.js.map +0 -1
  278. package/dist/proxy-Czngl3p9.js.map +0 -1
  279. package/dist/query-parser-DGRVFNM3.js.map +0 -1
  280. package/dist/request-timeout-C_4C2BeR.js.map +0 -1
  281. package/dist/schema-editor-routes-C5-lh_jO.js +0 -87
  282. package/dist/schema-editor-routes-C5-lh_jO.js.map +0 -1
  283. package/dist/src-pmvW7BFx.js +0 -6688
  284. package/dist/src-pmvW7BFx.js.map +0 -1
  285. package/dist/src-vkcwKXbT.js.map +0 -1
  286. package/dist/types-BfKcm9do.js +0 -39
  287. package/dist/types-BfKcm9do.js.map +0 -1
@@ -67,14 +67,15 @@ export type { RebaseFunctionContext } from "./define-function.js";
67
67
  *
68
68
  * It is safe to hold at module scope, unlike a configuration value, because it
69
69
  * is a lazy Proxy: nothing is resolved until a property is read, which happens
70
- * inside a request. That indirection is also the whole of what a future
71
- * isolate-based host has to hook — see `_setRebaseResolver` in
72
- * `../singleton.ts`.
70
+ * inside a request — and it resolves to the backend serving that request, so
71
+ * with two backends in one process each one's functions see their own. That
72
+ * indirection is the whole of what a host hooks — the Node server per request,
73
+ * an isolate host per isolate — see `_setRebaseResolver` in `../singleton.ts`.
73
74
  */
74
75
  export { rebase } from "../singleton.js";
75
- export { getUser, getUserId, getRoles, hasRole, isAdmin, isAuthenticated, getDriver, requireDriver, getApiKey, getRequestId, identityResolved } from "./context.js";
76
+ export { getUser, getUserId, getRoles, hasRole, isAdmin, getScopes, hasScope, isAuthenticated, getDriver, requireDriver, getApiKey, getRequestId, getSignal, identityResolved } from "./context.js";
76
77
  export type { FunctionUser } from "./context.js";
77
- export { requireAuth, requireAdmin, requireRole } from "./guards.js";
78
+ export { requireAuth, requireAdmin, requireRole, requireScope } from "./guards.js";
78
79
  export { getEnv, env, requireEnv, runtimeKey, isNodeRuntime, lazyResource } from "./runtime-env.js";
79
80
  export { waitUntil } from "./wait-until.js";
80
81
  /**
@@ -96,13 +96,15 @@ var INSTANCE_SLOT = Symbol.for("@rebasepro/server:singleton-instance");
96
96
  * A *function* that answers "which client is this call for", for hosts where
97
97
  * one answer per process is the wrong shape.
98
98
  *
99
- * A Node server boots once and serves every request from the same client, so
100
- * {@link INSTANCE_SLOT} is the whole story. An isolate-based host is different
101
- * in a way that matters: the environment arrives attached to the **request**,
102
- * not to the module, so there is nothing to publish at import time, and an
103
- * isolate can be reused across requests that must not share state. Such a host
104
- * registers a resolver — typically reading an `AsyncLocalStorage` populated per
105
- * request — and it is consulted first.
99
+ * {@link INSTANCE_SLOT} is one answer per process: the default backend's. A
100
+ * Node process can hold several backends, and the code each one runs — a
101
+ * function, a cron job, a hook — must see that one, so the server registers a
102
+ * resolver reading the backend scope it enters per request (an
103
+ * `AsyncLocalStorage`, host-side, in `backend/scope.ts`). An isolate-based
104
+ * host is different in the same way: the environment arrives attached to the
105
+ * **request**, not to the module, so there is nothing to publish at import
106
+ * time, and an isolate can be reused across requests that must not share
107
+ * state. The resolver is consulted first.
106
108
  *
107
109
  * This exists now, before there is a host that needs it, because of what it
108
110
  * protects: `rebase` is a lazy Proxy, so every property access already goes
@@ -123,10 +125,13 @@ function getInstance() {
123
125
  return global[INSTANCE_SLOT] ?? null;
124
126
  }
125
127
  /**
126
- * The server-side Rebase singleton.
128
+ * The server-side Rebase client, as a module-level handle.
127
129
  *
128
- * Initialized automatically during server startup. Provides access to all
129
- * app-scoped services: **data**, **auth**, **storage**, and **email**.
130
+ * Inside a request, cron run or job a backend serves, it is that backend's
131
+ * client (`backend.rebase`) — so with two backends in one process, each one's
132
+ * functions see their own. Anywhere else it is the process default's, which
133
+ * `initializeRebaseBackend` (or `setDefaultBackend`) installs. Provides access
134
+ * to all app-scoped services: **data**, **auth**, **storage**, and **email**.
130
135
  *
131
136
  * **Admin data plane** (`rebase.dataAsAdmin`):
132
137
  * Backed by the native DataDriver — calls go directly to the database without
@@ -185,12 +190,25 @@ var rebase = new Proxy({}, {
185
190
  return instance[prop];
186
191
  },
187
192
  set(_, prop) {
188
- throw new Error(`Cannot set rebase.${String(prop)} directly. The singleton is read-only. Use _initRebase() during server startup.`);
193
+ throw new Error(`Cannot set rebase.${String(prop)} directly. The singleton is read-only. Install a backend with setDefaultBackend(backend), or use backend.rebase.`);
189
194
  }
190
195
  });
191
196
  //#endregion
192
197
  //#region src/functions/define-function.ts
193
198
  /**
199
+ * The `rebase` handle, seen through the `Database` a function names.
200
+ *
201
+ * One object serves every function; `DB` only describes it. It resolves, per
202
+ * call, to the backend serving the request — the same answer the imported
203
+ * `rebase` gives. Each collection accessor on `dataAsAdmin` is resolved by
204
+ * name at call time, so a generated `Database` adds compile-time checks and
205
+ * changes nothing the object does — the same reason the browser client's
206
+ * `createRebaseClient<Database>()` is one implementation for every `Database`.
207
+ */
208
+ function typedSingleton() {
209
+ return rebase;
210
+ }
211
+ /**
194
212
  * Typed authoring contract for a custom backend function.
195
213
  *
196
214
  * A custom function is a file in the `functionsDir` that default-exports a
@@ -227,37 +245,39 @@ var rebase = new Proxy({}, {
227
245
  */
228
246
  function defineFunction(definition) {
229
247
  const app = new Hono();
230
- const returned = definition(app, { rebase });
248
+ const returned = definition(app, { rebase: typedSingleton() });
231
249
  return returned instanceof Hono ? returned : app;
232
250
  }
233
251
  //#endregion
234
252
  //#region src/auth/admin-roles.ts
235
253
  /**
236
- * Which role names carry administrative privilege.
237
- *
238
- * One definition, because there used to be several and they disagreed.
239
- * `requireAdmin` accepted `admin` **or** `schema-admin`; the guard that refuses
240
- * a dangerous `defaultRole` compared against `admin` alone. So
241
- * `AUTH_DEFAULT_ROLE=schema-admin` passed the guard and made every public
242
- * registrant an administrator — and, since a `schema-admin` may edit users, one
243
- * of them could then grant themselves real `admin` and keep it.
244
- *
245
- * The guard and the check have to read the same list or the gap comes back, so
246
- * neither of them owns it.
247
- *
248
- * `schema-admin` is here deliberately: it can reach the schema editor and the
249
- * SQL surfaces, which is administrative by any definition that matters. If a
250
- * genuinely lesser role is added later, it does not belong in this list — it
251
- * belongs in a capability check of its own.
254
+ * The admin role and scope matching, for code that may not import
255
+ * `@rebasepro/types`.
256
+ *
257
+ * The custom-functions surface (`@rebasepro/server/functions`) must bundle for
258
+ * a runtime with no Node built-ins and imports nothing but `hono`, so its
259
+ * guards cannot reach the canonical definitions in `@rebasepro/types`
260
+ * (`ADMIN_ROLE`, `hasAdminRole`, `scopeGrants`). These are the same rules,
261
+ * restated, and `test/admin-roles.test.ts` holds them equal.
262
+ *
263
+ * Everything else imports the `@rebasepro/types` versions.
252
264
  */
253
- var ADMINISTRATIVE_ROLES = ["admin", "schema-admin"];
254
- /** Does this single role name carry administrative privilege? */
255
- function isAdministrativeRole(role) {
256
- return ADMINISTRATIVE_ROLES.includes(role);
265
+ /** The one built-in role. It holds every scope. */
266
+ var ADMIN_ROLE_NAME = "admin";
267
+ /** Does this list of roles include the admin role? */
268
+ function holdsAdminRole(roles) {
269
+ return !!roles?.includes(ADMIN_ROLE_NAME);
257
270
  }
258
- /** Does any role in this list carry administrative privilege? */
259
- function hasAdministrativeRole(roles) {
260
- return !!roles?.some(isAdministrativeRole);
271
+ /**
272
+ * Does a set of held scopes grant `scope`, optionally on one `target`? The
273
+ * unqualified grant covers every target; `scope:target` covers its own.
274
+ */
275
+ function heldScopesGrant(held, scope, target) {
276
+ for (const entry of held) {
277
+ if (entry === scope) return true;
278
+ if (target !== void 0 && entry === `${scope}:${target}`) return true;
279
+ }
280
+ return false;
261
281
  }
262
282
  //#endregion
263
283
  //#region src/functions/context.ts
@@ -310,16 +330,31 @@ function hasRole(c, ...roles) {
310
330
  const held = new Set(getRoles(c));
311
331
  return roles.some((role) => held.has(role));
312
332
  }
333
+ /** Whether the caller holds the `admin` role, which holds every scope. */
334
+ function isAdmin(c) {
335
+ return holdsAdminRole(getRoles(c));
336
+ }
313
337
  /**
314
- * Whether the caller holds an administrative role.
338
+ * Everything the caller may do, as `resource:action[:target]` scope strings —
339
+ * the data plane, the app's own `auth.scopes`, and whatever their roles (or
340
+ * their API key) hold. Empty for an anonymous request.
315
341
  *
316
- * Delegates to the single definition in `auth/admin-roles.ts` — which is
317
- * `admin` **or** `schema-admin` — rather than comparing against `"admin"`.
318
- * Those two lists disagreed once, and the gap made every public registrant an
319
- * administrator; see that file.
342
+ * Resolved by the framework before the handler runs; `undefined` only when no
343
+ * Rebase auth middleware ran (see {@link identityResolved}).
320
344
  */
321
- function isAdmin(c) {
322
- return hasAdministrativeRole(getRoles(c));
345
+ function getScopes(c) {
346
+ return read(c, "scopes");
347
+ }
348
+ /**
349
+ * Whether the caller holds `scope`, on `target` when one is given.
350
+ *
351
+ * For an app scope declared under `auth.scopes` — `project:deploy` — a
352
+ * signed-in person always holds it, so this narrows only API keys and tokens.
353
+ * Whether the *person* may deploy *this* project is still the handler's to
354
+ * decide.
355
+ */
356
+ function hasScope(c, scope, target) {
357
+ return heldScopesGrant(getScopes(c) ?? [], scope, target);
323
358
  }
324
359
  /** Whether the request carries an identity at all. */
325
360
  function isAuthenticated(c) {
@@ -376,6 +411,17 @@ function getRequestId(c) {
376
411
  return read(c, "requestId");
377
412
  }
378
413
  /**
414
+ * The signal aborted when this request outlasts the functions timeout and is
415
+ * answered `504 FUNCTION_TIMEOUT`. Pass it to `fetch` and anything else that
416
+ * takes one, so the work stops with the request instead of running on after
417
+ * the caller was told it failed.
418
+ *
419
+ * Never aborts when the timeout is off, or outside the functions router.
420
+ */
421
+ function getSignal(c) {
422
+ return read(c, "functionSignal") ?? new AbortController().signal;
423
+ }
424
+ /**
379
425
  * Whether a Rebase auth middleware has run on this request.
380
426
  *
381
427
  * Both middlewares populate `driver` for *every* outcome, anonymous included,
@@ -428,15 +474,14 @@ var requireAuth = async (c, next) => {
428
474
  } }, 401);
429
475
  };
430
476
  /**
431
- * Reject callers without an administrative role with 403.
477
+ * Reject callers without the `admin` role with 403.
432
478
  *
433
479
  * Must come **after** {@link requireAuth}: on its own it answers 401 for an
434
480
  * anonymous caller, which is right, but pairing them keeps the two failures
435
481
  * distinguishable — 401 "who are you", 403 "not you".
436
482
  *
437
- * Administrative means `admin` or `schema-admin`, from the single list in
438
- * `auth/admin-roles.ts`. Do not compare against `"admin"` by hand; that is the
439
- * divergence that list exists to prevent.
483
+ * Prefer {@link requireScope} for anything an app declares a scope for: a
484
+ * scope can be granted to a narrower role and to a key, and `admin` cannot.
440
485
  */
441
486
  var requireAdmin = async (c, next) => {
442
487
  if (!getUser(c)) {
@@ -483,6 +528,44 @@ function requireRole(...roles) {
483
528
  return next();
484
529
  };
485
530
  }
531
+ /**
532
+ * Reject callers who do not hold `scope` with 403.
533
+ *
534
+ * `scope` is a built-in scope or one the app declares under `auth.scopes` on
535
+ * the users collection. `target` narrows it to one resource — a key holding
536
+ * `project:deploy:p1` passes `requireScope("project:deploy", c => c.req.param("project"))`
537
+ * for `p1` only — and may be read from the request.
538
+ *
539
+ * A signed-in person holds every app scope, so for a person this is no
540
+ * authorization at all: it narrows API keys and tokens. Decide whether the
541
+ * person may act in the handler, as you would without it.
542
+ *
543
+ * @example
544
+ * ```ts
545
+ * app.post("/deploy/:project", requireAuth, requireScope("project:deploy", c => c.req.param("project")), handler);
546
+ * ```
547
+ */
548
+ function requireScope(scope, target) {
549
+ return async (c, next) => {
550
+ if (!getUser(c)) {
551
+ if (!identityResolved(c)) return c.json(unresolvedIdentity(), 500);
552
+ return c.json({ error: {
553
+ message: "Authentication required",
554
+ code: "UNAUTHORIZED"
555
+ } }, 401);
556
+ }
557
+ const resolvedTarget = typeof target === "function" ? target(c) : target;
558
+ if (!hasScope(c, scope, resolvedTarget)) {
559
+ const wanted = resolvedTarget !== void 0 ? `${scope}:${resolvedTarget}` : scope;
560
+ return c.json({ error: {
561
+ message: `This credential does not hold the "${wanted}" scope.`,
562
+ code: "SCOPE_MISSING",
563
+ details: { requiredScope: wanted }
564
+ } }, 403);
565
+ }
566
+ return next();
567
+ };
568
+ }
486
569
  //#endregion
487
570
  //#region src/functions/runtime-env.ts
488
571
  /**
@@ -632,9 +715,11 @@ function isProduction() {
632
715
  * not be undone, because the originals were gone.
633
716
  */
634
717
  var configuredLevel;
718
+ /** Every line to stderr, when a command's stdout is its result. See {@link setLogOutput}. */
719
+ var everyLineToStderr = false;
635
720
  function getMinLevel() {
636
721
  if (configuredLevel) return configuredLevel;
637
- const env = (hostEnv().LOG_LEVEL || "info").toLowerCase();
722
+ const env = (hostEnv().LOG_LEVEL || "info").trim().toLowerCase();
638
723
  if (env in LOG_PRIORITY) return env;
639
724
  return "info";
640
725
  }
@@ -853,13 +938,13 @@ function createLogger(rawDefaultFields = {}) {
853
938
  ...merged
854
939
  };
855
940
  const line = JSON.stringify(entry);
856
- if (level === "error") writeLine("err", line);
941
+ if (level === "error" || everyLineToStderr) writeLine("err", line);
857
942
  else writeLine("out", line);
858
943
  } else {
859
944
  const prefix = level === "error" ? "❌" : level === "warn" ? "⚠️" : level === "info" ? "ℹ️" : "🐛";
860
945
  const extra = Object.keys(merged).length > 0 ? ` ${JSON.stringify(merged)}` : "";
861
946
  const out = `${prefix} [${level.toUpperCase()}] ${safeMessage}${extra}`;
862
- if (level === "error") console.error(out);
947
+ if (level === "error" || everyLineToStderr) console.error(out);
863
948
  else if (level === "warn") console.warn(out);
864
949
  else console.log(out);
865
950
  }
@@ -950,6 +1035,8 @@ function logBackgroundFailure(c, error) {
950
1035
  }
951
1036
  //#endregion
952
1037
  //#region src/api/errors.ts
1038
+ /** What a caller is told when the database cannot be reached. Retryable, and not about them. */
1039
+ var DATABASE_UNAVAILABLE_MESSAGE = "The database could not be reached, so this request was not served. Retry shortly; if it keeps happening, the server's database is down or unreachable from it.";
953
1040
  /**
954
1041
  * Standardized API error class.
955
1042
  * Throw this from any route handler — the errorHandler middleware
@@ -1022,8 +1109,19 @@ var ApiError = class ApiError extends Error {
1022
1109
  static serviceUnavailable(message, code = "SERVICE_UNAVAILABLE") {
1023
1110
  return new ApiError(503, code, message);
1024
1111
  }
1112
+ /**
1113
+ * `503 DATABASE_UNAVAILABLE`: the database could not be reached. What
1114
+ * every door answers then — the data API, sign-in, the admin routes and
1115
+ * the realtime socket — so a client sees one retryable answer, sent with
1116
+ * `Retry-After`, rather than a permission failure or a crash.
1117
+ *
1118
+ * @see isDatabaseUnreachable
1119
+ */
1120
+ static databaseUnavailable(message = DATABASE_UNAVAILABLE_MESSAGE) {
1121
+ return new ApiError(503, "DATABASE_UNAVAILABLE", message);
1122
+ }
1025
1123
  };
1026
1124
  //#endregion
1027
- export { ApiError, defineFunction, env, getApiKey, getDriver, getEnv, getRequestId, getRoles, getUser, getUserId, hasRole, identityResolved, isAdmin, isAuthenticated, isNodeRuntime, lazyResource, rebase, requireAdmin, requireAuth, requireDriver, requireEnv, requireRole, runtimeKey, waitUntil };
1125
+ export { ApiError, defineFunction, env, getApiKey, getDriver, getEnv, getRequestId, getRoles, getScopes, getSignal, getUser, getUserId, hasRole, hasScope, identityResolved, isAdmin, isAuthenticated, isNodeRuntime, lazyResource, rebase, requireAdmin, requireAuth, requireDriver, requireEnv, requireRole, requireScope, runtimeKey, waitUntil };
1028
1126
 
1029
1127
  //# sourceMappingURL=index.js.map