@rebasepro/server 0.23.0 → 0.24.1-canary.g56af4a4
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-DivE9bAx.js +402 -0
- package/dist/GCSStorageController-DivE9bAx.js.map +1 -0
- package/dist/S3StorageController-D_vKs4kP.js +480 -0
- package/dist/S3StorageController-D_vKs4kP.js.map +1 -0
- package/dist/api/ast-schema-editor.d.ts +92 -1
- package/dist/api/errors.d.ts +9 -0
- package/dist/api/live-schema-routes.d.ts +38 -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 +97 -11
- package/dist/api/rest/auth-collection-writes.d.ts +28 -21
- package/dist/api/rest/field-access-query.d.ts +28 -8
- package/dist/api/rest/field-ops.d.ts +19 -7
- package/dist/api/rest/query-body.d.ts +10 -0
- package/dist/api/rest/write-validation.d.ts +9 -7
- package/dist/api/schema-editor-routes.d.ts +10 -1
- package/dist/api/sql-export-routes.d.ts +8 -0
- package/dist/api/types.d.ts +28 -1
- package/dist/{ast-schema-editor-Mvr50v_S.js → ast-schema-editor-CSdL0iCk.js} +310 -12
- package/dist/ast-schema-editor-CSdL0iCk.js.map +1 -0
- package/dist/auth/access.d.ts +121 -0
- package/dist/auth/adapter-middleware.d.ts +2 -1
- package/dist/auth/address-ownership.d.ts +16 -1
- 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 +24 -2
- package/dist/auth/admin-users-route.d.ts +2 -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 +46 -7
- package/dist/auth/builtin-auth-adapter.d.ts +8 -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 +71 -0
- package/dist/auth/impersonation.d.ts +110 -0
- package/dist/auth/index.d.ts +4 -2
- package/dist/auth/interfaces.d.ts +120 -59
- package/dist/auth/jwt-crypto.d.ts +7 -0
- package/dist/auth/jwt-keys.d.ts +4 -0
- package/dist/auth/jwt.d.ts +54 -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/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 +54 -1
- package/dist/auth/registration-policy.d.ts +17 -0
- package/dist/auth/routes.d.ts +45 -0
- package/dist/auth/scope-routes.d.ts +22 -0
- package/dist/auth/session-routes.d.ts +11 -6
- package/dist/auth/token-revocation.d.ts +50 -1
- package/dist/auth/user-picking.d.ts +35 -0
- package/dist/auth/verify-credential.d.ts +28 -0
- package/dist/{auth-B-GIMpDG.js → auth-OPq_FeMs.js} +3115 -638
- package/dist/auth-OPq_FeMs.js.map +1 -0
- package/dist/auth_adapter-CIItCTc8.js +21 -0
- package/dist/auth_adapter-CIItCTc8.js.map +1 -0
- package/dist/backend-DTAOsLQc.js.map +1 -1
- package/dist/backup/backup-common.d.ts +24 -3
- package/dist/backup/backup-routes.d.ts +46 -5
- package/dist/backup/backup-schedule.d.ts +33 -0
- package/dist/backup/backup-storage.d.ts +16 -0
- package/dist/backup/index.d.ts +5 -1
- package/dist/backup-5d7XhLX3.js +581 -0
- package/dist/backup-5d7XhLX3.js.map +1 -0
- package/dist/boot/bundle.d.ts +19 -0
- package/dist/boot/driver.d.ts +3 -0
- package/dist/boot/env.d.ts +56 -4
- package/dist/boot/http-server.d.ts +22 -0
- package/dist/boot/options.d.ts +16 -1
- package/dist/boot/runtime-cors.d.ts +17 -0
- package/dist/boot/security-headers.d.ts +26 -0
- package/dist/boot/static-routing.d.ts +65 -0
- package/dist/collection_patch-BRu-BvDv.js +472 -0
- package/dist/collection_patch-BRu-BvDv.js.map +1 -0
- package/dist/{contract-routes-CbFjuBwa.js → contract-routes-02lASyJI.js} +5 -8
- package/dist/contract-routes-02lASyJI.js.map +1 -0
- package/dist/cron/cron-routes.d.ts +1 -1
- package/dist/cron/cron-scheduler.d.ts +94 -23
- package/dist/cron/cron-store.d.ts +31 -4
- package/dist/cron/define-cron.d.ts +6 -2
- package/dist/cron/index.d.ts +1 -1
- package/dist/{cron-loader-DfTj2Hbi.js → cron-loader-D7OmleAb.js} +11 -7
- package/dist/cron-loader-D7OmleAb.js.map +1 -0
- package/dist/{cron-routes-eE8nif_b.js → cron-routes-CBfiaqEL.js} +34 -8
- package/dist/cron-routes-CBfiaqEL.js.map +1 -0
- package/dist/{cron-scheduler-B0pLfAix.js → cron-scheduler-C2vbETMo.js} +349 -65
- package/dist/cron-scheduler-C2vbETMo.js.map +1 -0
- package/dist/cron-store-B2Ih0gCN.js +540 -0
- package/dist/cron-store-B2Ih0gCN.js.map +1 -0
- package/dist/{ddl-bootstrap-C6mo0Kmz.js → ddl-bootstrap-BaqMSa4Y.js} +2 -2
- package/dist/{ddl-bootstrap-C6mo0Kmz.js.map → ddl-bootstrap-BaqMSa4Y.js.map} +1 -1
- package/dist/email/index.d.ts +2 -2
- package/dist/email/smtp-email-service.d.ts +23 -0
- package/dist/email/templates.d.ts +22 -0
- package/dist/email/types.d.ts +44 -0
- package/dist/env.d.ts +1 -39
- package/dist/{errors-DWsX4yTd.js → errors-D6_y86c5.js} +102 -8
- package/dist/errors-D6_y86c5.js.map +1 -0
- package/dist/filter-dialect-REl-TjZr.js +1628 -0
- package/dist/filter-dialect-REl-TjZr.js.map +1 -0
- package/dist/{function-loader-xnbDAPfa.js → function-loader-BDKKiBmy.js} +5 -4
- package/dist/function-loader-BDKKiBmy.js.map +1 -0
- package/dist/{function-routes-Chet4-lB.js → function-routes-DWB7BBsi.js} +25 -13
- package/dist/function-routes-DWB7BBsi.js.map +1 -0
- package/dist/functions/context.d.ts +26 -6
- package/dist/functions/define-function.d.ts +7 -4
- package/dist/functions/guards.d.ts +22 -5
- package/dist/functions/index.d.ts +2 -2
- package/dist/functions/index.js +114 -37
- package/dist/functions/index.js.map +1 -1
- package/dist/functions/request-timeout.d.ts +7 -5
- package/dist/history/history-routes.d.ts +9 -0
- package/dist/history/retention-sweep.d.ts +81 -0
- package/dist/{history-recorder-B4MpJfJK.js → history-recorder-DHenr3lm.js} +4 -4
- package/dist/{history-recorder-B4MpJfJK.js.map → history-recorder-DHenr3lm.js.map} +1 -1
- package/dist/{history-store-BhxWOuz9.js → history-store-DPofGVDp.js} +2 -2
- package/dist/{history-store-BhxWOuz9.js.map → history-store-DPofGVDp.js.map} +1 -1
- package/dist/index.d.ts +14 -7
- package/dist/index.es.js +23363 -17552
- package/dist/index.es.js.map +1 -1
- package/dist/init/health.d.ts +17 -2
- package/dist/init/shutdown.d.ts +20 -0
- package/dist/init.d.ts +70 -6
- package/dist/internal-tables-L2t39RdT.js +136 -0
- package/dist/internal-tables-L2t39RdT.js.map +1 -0
- package/dist/jobs/job-queue.d.ts +8 -0
- package/dist/jobs/job-store.d.ts +24 -0
- package/dist/jobs/types.d.ts +25 -4
- package/dist/{jobs-CazMYhyy.js → jobs-BpD4Q0qR.js} +235 -25
- package/dist/jobs-BpD4Q0qR.js.map +1 -0
- package/dist/{jwt-DnQHNFCl.js → jwt-Bqcu7cGt.js} +207 -77
- package/dist/jwt-Bqcu7cGt.js.map +1 -0
- package/dist/{keys-CogCQpxG.js → keys-GAVZqbqx.js} +3 -17
- package/dist/{keys-CogCQpxG.js.map → keys-GAVZqbqx.js.map} +1 -1
- package/dist/load-failure-UvzZgGXT.js +48 -0
- package/dist/load-failure-UvzZgGXT.js.map +1 -0
- 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-Bj4TYYUl.js → logs-routes-DAdv37GI.js} +48 -8
- 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 +7 -0
- package/dist/mcp/mcp-tools.d.ts +23 -9
- package/dist/mcp/oauth-metadata.d.ts +21 -16
- package/dist/mcp/oauth-routes.d.ts +7 -1
- package/dist/metrics/index.d.ts +18 -0
- package/dist/metrics/pool-wait.d.ts +50 -0
- package/dist/offline-8Ks3yp9n-CadBKm2D.js +3305 -0
- package/dist/offline-8Ks3yp9n-CadBKm2D.js.map +1 -0
- package/dist/offline-store-D9ytNNaa-BCr2vsFB.js +1903 -0
- package/dist/offline-store-D9ytNNaa-BCr2vsFB.js.map +1 -0
- package/dist/{openapi-generator-O_O24MAT.js → openapi-generator-BqoUh4Ij.js} +455 -80
- package/dist/openapi-generator-BqoUh4Ij.js.map +1 -0
- package/dist/policy-PdzX-Opd.js +121 -0
- package/dist/policy-PdzX-Opd.js.map +1 -0
- package/dist/project_manifest-R6y_KHms.js +59 -0
- package/dist/project_manifest-R6y_KHms.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-DGRVFNM3.js → query-parser-DK9eMkb9.js} +497 -52
- package/dist/query-parser-DK9eMkb9.js.map +1 -0
- package/dist/{request-timeout-C_4C2BeR.js → request-timeout-Dnl2_OBc.js} +17 -10
- package/dist/request-timeout-Dnl2_OBc.js.map +1 -0
- package/dist/resumable-upload-threshold-CKv-Ry0l.js +24 -0
- package/dist/resumable-upload-threshold-CKv-Ry0l.js.map +1 -0
- package/dist/schema-edit/apply-schema-change.d.ts +73 -3
- package/dist/schema-edit/local-source.d.ts +29 -0
- package/dist/schema-edit/project-root.d.ts +3 -2
- package/dist/schema-edit/remote-source.d.ts +20 -5
- package/dist/schema-edit/source-editor.d.ts +28 -0
- package/dist/schema-editor-routes-BFf3i8jm.js +136 -0
- package/dist/schema-editor-routes-BFf3i8jm.js.map +1 -0
- package/dist/serve-spa.d.ts +58 -0
- package/dist/services/outbound-post.d.ts +50 -0
- package/dist/services/outbound-url-guard.d.ts +34 -5
- package/dist/services/routed-realtime-service.d.ts +16 -0
- package/dist/services/webhook-service.d.ts +66 -14
- package/dist/soft-delete-params-47yBGs3_.js +668 -0
- package/dist/soft-delete-params-47yBGs3_.js.map +1 -0
- package/dist/sql-export-routes-BNNuGGLP.js +240 -0
- package/dist/sql-export-routes-BNNuGGLP.js.map +1 -0
- package/dist/{src-vkcwKXbT.js → src-CatHFUym.js} +439 -20
- package/dist/src-CatHFUym.js.map +1 -0
- package/dist/storage/GCSStorageController.d.ts +48 -2
- package/dist/storage/LocalStorageController.d.ts +69 -2
- package/dist/storage/S3StorageController.d.ts +39 -3
- package/dist/storage/image-transform.d.ts +5 -0
- package/dist/storage/index.d.ts +2 -2
- package/dist/storage/maintenance-routes.d.ts +23 -0
- package/dist/storage/maintenance.d.ts +126 -0
- package/dist/storage/property-limits.d.ts +41 -6
- package/dist/storage/rendition-cache.d.ts +9 -11
- package/dist/storage/request-keys.d.ts +15 -0
- package/dist/storage/request-principals.d.ts +30 -0
- package/dist/storage/requested-object.d.ts +74 -0
- package/dist/storage/routes.d.ts +52 -14
- package/dist/storage/source-variables.d.ts +10 -0
- package/dist/storage/streams.d.ts +42 -0
- package/dist/storage/tus-handler.d.ts +76 -7
- package/dist/storage/types.d.ts +101 -7
- package/dist/storage/upload-validation.d.ts +13 -0
- package/dist/storage-resumable-VO-cMpse-C_YX71pO.js +125 -0
- package/dist/storage-resumable-VO-cMpse-C_YX71pO.js.map +1 -0
- package/dist/strings.es-BeZWAodn.js +256 -0
- package/dist/strings.es-BeZWAodn.js.map +1 -0
- package/dist/upload-validation-Dd-fnsbA.js +172 -0
- package/dist/upload-validation-Dd-fnsbA.js.map +1 -0
- package/dist/utils/byte-size.d.ts +10 -0
- package/dist/utils/compression.d.ts +6 -0
- package/dist/utils/load-failure.d.ts +14 -0
- package/dist/utils/logger.d.ts +12 -0
- package/package.json +5 -5
- package/dist/GCSStorageController-CjrA4PMo.js +0 -242
- package/dist/GCSStorageController-CjrA4PMo.js.map +0 -1
- package/dist/S3StorageController-B6pKDNVj.js +0 -264
- package/dist/S3StorageController-B6pKDNVj.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-Mvr50v_S.js.map +0 -1
- package/dist/auth/api-keys/api-key-permission-guard.d.ts +0 -65
- package/dist/auth-B-GIMpDG.js.map +0 -1
- package/dist/backup-D7YR94N3.js +0 -253
- package/dist/backup-D7YR94N3.js.map +0 -1
- package/dist/contract-routes-CbFjuBwa.js.map +0 -1
- package/dist/cron-loader-DfTj2Hbi.js.map +0 -1
- package/dist/cron-routes-eE8nif_b.js.map +0 -1
- package/dist/cron-scheduler-B0pLfAix.js.map +0 -1
- package/dist/cron-store-TcoGz-xS.js +0 -305
- package/dist/cron-store-TcoGz-xS.js.map +0 -1
- package/dist/dynamic-import-X40pTZUQ.js +0 -23
- package/dist/dynamic-import-X40pTZUQ.js.map +0 -1
- package/dist/errors-DWsX4yTd.js.map +0 -1
- package/dist/function-loader-xnbDAPfa.js.map +0 -1
- package/dist/function-routes-Chet4-lB.js.map +0 -1
- package/dist/jobs-CazMYhyy.js.map +0 -1
- package/dist/jwt-DnQHNFCl.js.map +0 -1
- package/dist/logger-DO2PZc4i.js.map +0 -1
- package/dist/logs-routes-Bj4TYYUl.js.map +0 -1
- package/dist/openapi-generator-O_O24MAT.js.map +0 -1
- package/dist/query-parser-DGRVFNM3.js.map +0 -1
- package/dist/request-timeout-C_4C2BeR.js.map +0 -1
- package/dist/schema-editor-routes-C5-lh_jO.js +0 -87
- package/dist/schema-editor-routes-C5-lh_jO.js.map +0 -1
- package/dist/src-pmvW7BFx.js +0 -6688
- package/dist/src-pmvW7BFx.js.map +0 -1
- package/dist/src-vkcwKXbT.js.map +0 -1
- package/dist/types-BfKcm9do.js +0 -39
- package/dist/types-BfKcm9do.js.map +0 -1
|
@@ -44,6 +44,14 @@ interface RateLimiterOptions {
|
|
|
44
44
|
* `limit`; returning `null` skips the limiter for this request.
|
|
45
45
|
*/
|
|
46
46
|
resolveLimit?: (c: Parameters<MiddlewareHandler<HonoEnv>>[0]) => number | null | undefined | Promise<number | null | undefined>;
|
|
47
|
+
/**
|
|
48
|
+
* How many requests this one counts as. Default 1. For a request that
|
|
49
|
+
* does the work of several — a batch — so batching is cheaper than the
|
|
50
|
+
* requests it replaces without being free. Charged one hit at a time, and
|
|
51
|
+
* refused at the first that does not fit; the hits before it stay charged,
|
|
52
|
+
* as the requests a batch replaces would have been.
|
|
53
|
+
*/
|
|
54
|
+
cost?: (c: Parameters<MiddlewareHandler<HonoEnv>>[0]) => number | Promise<number>;
|
|
47
55
|
/**
|
|
48
56
|
* Number of trusted reverse-proxy hops in front of this server. Each hop
|
|
49
57
|
* appends the address it saw to `X-Forwarded-For`, so the real client IP is
|
|
@@ -83,6 +91,41 @@ export declare function setSharedRateLimitStore(store: RateLimitStore | undefine
|
|
|
83
91
|
* Uses a sliding window: only hits within the last `windowMs` are counted.
|
|
84
92
|
*/
|
|
85
93
|
export declare function createRateLimiter(options?: RateLimiterOptions): MiddlewareHandler<HonoEnv>;
|
|
94
|
+
/**
|
|
95
|
+
* Default key generator: the client's address, from the most trustworthy source
|
|
96
|
+
* this deployment has.
|
|
97
|
+
*
|
|
98
|
+
* `X-Forwarded-For` is a client-writable header; only the entries appended by
|
|
99
|
+
* trusted reverse proxies can be believed. With `trustedProxyHops` proxies in
|
|
100
|
+
* front, each appends the address it saw, so the real client IP is the
|
|
101
|
+
* `trustedProxyHops`-th entry from the right — everything further left is
|
|
102
|
+
* client-supplied and must be ignored. This is what prevents a caller from
|
|
103
|
+
* spoofing `X-Forwarded-For` to spread its requests across many rate-limit keys.
|
|
104
|
+
*
|
|
105
|
+
* `X-Real-IP` is the *same* kind of header and needs the same rule, which it
|
|
106
|
+
* did not have: it was read unconditionally, including under
|
|
107
|
+
* `trustedProxyHops === 0` — the mode whose entire meaning is "no proxy is in
|
|
108
|
+
* front of me". With no proxy there, nothing writes `X-Real-IP` except the
|
|
109
|
+
* caller, so the key was theirs to choose: one header per request bought an
|
|
110
|
+
* unlimited number of buckets, and the limiters on login, registration and
|
|
111
|
+
* password reset counted to one. The reasoning had been done carefully for one
|
|
112
|
+
* spelling of a proxy header and not carried to its twin.
|
|
113
|
+
*
|
|
114
|
+
* So `X-Real-IP` is now believed only where a proxy is declared to exist. With
|
|
115
|
+
* none, the connection's own address is used — unforgeable, and available
|
|
116
|
+
* because the server runs on `@hono/node-server`. `"unknown"` is the last
|
|
117
|
+
* resort only, and it is a single shared bucket by design: better that
|
|
118
|
+
* anonymous callers throttle each other than that any of them throttles nobody.
|
|
119
|
+
*/
|
|
120
|
+
/**
|
|
121
|
+
* Where a request comes from, as the rate limiters judge it: the socket's own
|
|
122
|
+
* address, or — only behind as many proxies as `TRUSTED_PROXY_HOPS` declares —
|
|
123
|
+
* the address they report. What a session row records as its IP, so the
|
|
124
|
+
* sessions list shows the same address the limiter counted, rather than the
|
|
125
|
+
* raw `X-Forwarded-For` (whose leftmost entry the caller chooses) or
|
|
126
|
+
* `"unknown"` for every direct connection.
|
|
127
|
+
*/
|
|
128
|
+
export declare function requestClientAddress(c: Parameters<MiddlewareHandler<HonoEnv>>[0]): string;
|
|
86
129
|
/**
|
|
87
130
|
* Pre-configured rate limiter for general auth endpoints (login, register).
|
|
88
131
|
* 200 requests per 15 minutes per IP.
|
|
@@ -209,6 +252,12 @@ export interface DataRateLimitConfig {
|
|
|
209
252
|
anonymousFunctions?: number | null;
|
|
210
253
|
/** Share counts across replicas. Defaults to this process's memory. */
|
|
211
254
|
store?: RateLimitStore;
|
|
255
|
+
/**
|
|
256
|
+
* The deployment's service key, recognised as a Bearer before any auth
|
|
257
|
+
* middleware has run — the storage router's limiter runs ahead of its
|
|
258
|
+
* routes' auth — and never limited. See {@link dataRateLimitBuckets}.
|
|
259
|
+
*/
|
|
260
|
+
serviceKey?: string;
|
|
212
261
|
}
|
|
213
262
|
/** @see DataRateLimitConfig.anonymousFunctions */
|
|
214
263
|
export declare const DEFAULT_FUNCTIONS_ANONYMOUS_LIMIT = 3000;
|
|
@@ -229,7 +278,11 @@ export declare const DEFAULT_FUNCTIONS_ANONYMOUS_LIMIT = 3000;
|
|
|
229
278
|
* set them, and one that already has a proxy doing this should pass
|
|
230
279
|
* `enabled: false` rather than pay for it twice.
|
|
231
280
|
*/
|
|
232
|
-
export declare function createDataRateLimiter(config?: DataRateLimitConfig
|
|
281
|
+
export declare function createDataRateLimiter(config?: DataRateLimitConfig,
|
|
282
|
+
/** See {@link RateLimiterOptions.cost}: what one request on this router counts as. */
|
|
283
|
+
options?: {
|
|
284
|
+
cost?: RateLimiterOptions["cost"];
|
|
285
|
+
}): MiddlewareHandler<HonoEnv>;
|
|
233
286
|
/**
|
|
234
287
|
* The data API's per-caller limit, as a check rather than a middleware — for
|
|
235
288
|
* the door into the same data that is not an HTTP request.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { AuthRepository } from "./interfaces.js";
|
|
1
2
|
/**
|
|
2
3
|
* Whether a registration may proceed — computed in exactly one place.
|
|
3
4
|
*
|
|
@@ -66,6 +67,21 @@ export interface RegistrationPolicy {
|
|
|
66
67
|
export declare function isBootstrapWindowOpen(env?: {
|
|
67
68
|
NODE_ENV?: string;
|
|
68
69
|
}): boolean;
|
|
70
|
+
type UserPresenceRepository = Pick<AuthRepository, "firstUserIds" | "listUsersPaginated">;
|
|
71
|
+
/**
|
|
72
|
+
* Whether the users table is empty — the question behind the bootstrap window.
|
|
73
|
+
*
|
|
74
|
+
* Through `AuthRepository.firstUserIds` when the repository has it: one
|
|
75
|
+
* unordered `LIMIT 1` read. Otherwise through `listUsersPaginated`, which also
|
|
76
|
+
* counts and sorts the whole table, so it is only the fallback.
|
|
77
|
+
*/
|
|
78
|
+
export declare function isUserTableEmpty(repo: UserPresenceRepository): Promise<boolean>;
|
|
79
|
+
/**
|
|
80
|
+
* Whether the account just created is the only one there is. Two ids at most:
|
|
81
|
+
* whether anyone else exists, and, when nobody does, whether it is this one.
|
|
82
|
+
* Same fallback as {@link isUserTableEmpty}.
|
|
83
|
+
*/
|
|
84
|
+
export declare function isOnlyUser(repo: UserPresenceRepository, uid: string): Promise<boolean>;
|
|
69
85
|
/**
|
|
70
86
|
* What to tell a caller who hit an empty production database with the window
|
|
71
87
|
* shut. Named here so the register route and the bootstrap route say the same
|
|
@@ -113,3 +129,4 @@ export declare function isAnonymousAuthOpen(policy: {
|
|
|
113
129
|
allowAnonymous?: boolean;
|
|
114
130
|
disableSelfRegistration?: boolean;
|
|
115
131
|
}): boolean;
|
|
132
|
+
export {};
|
package/dist/auth/routes.d.ts
CHANGED
|
@@ -4,6 +4,8 @@ import type { AuthHooks } from "./auth-hooks.js";
|
|
|
4
4
|
import { EmailService, EmailConfig } from "../email/index.js";
|
|
5
5
|
import { HonoEnv } from "../api/types.js";
|
|
6
6
|
import { type CaptchaConfig } from "./captcha.js";
|
|
7
|
+
import { isDeliverableAddress } from "./deliverable-address.js";
|
|
8
|
+
export { isDeliverableAddress };
|
|
7
9
|
/**
|
|
8
10
|
* Shared configuration for auth and admin route factories.
|
|
9
11
|
*/
|
|
@@ -86,7 +88,30 @@ export interface AuthModuleConfig {
|
|
|
86
88
|
* how long a captured token stays useful to someone who copied it.
|
|
87
89
|
*/
|
|
88
90
|
refreshTokenReuseIntervalSeconds?: number;
|
|
91
|
+
/**
|
|
92
|
+
* Let a magic-link or email-code request for an address with no account
|
|
93
|
+
* create one (no password, unverified until the link or code is used),
|
|
94
|
+
* while registration is open. Off by default. See `passwordless-signup.ts`.
|
|
95
|
+
*/
|
|
96
|
+
magicLinkCreatesUsers?: boolean;
|
|
97
|
+
/**
|
|
98
|
+
* What a refresh token presented after its reuse window does to its
|
|
99
|
+
* session. See `RebaseAuthConfig.refreshTokenReuse`. Default `"reject"`.
|
|
100
|
+
*/
|
|
101
|
+
refreshTokenReuse?: RefreshTokenReusePolicy;
|
|
102
|
+
/**
|
|
103
|
+
* Refuse password sign-in until the account's address is verified, and
|
|
104
|
+
* register confirm-first: `POST /auth/register` answers the same "check
|
|
105
|
+
* your inbox" whether or not the address already has an account, and
|
|
106
|
+
* signs nobody in. Off by default. Needs email; the boot refuses it
|
|
107
|
+
* without. See `RebaseAuthConfig.requireEmailVerification`.
|
|
108
|
+
*/
|
|
109
|
+
requireEmailVerification?: boolean;
|
|
89
110
|
}
|
|
111
|
+
/** What a refresh token replayed after its reuse window does to its session. */
|
|
112
|
+
export type RefreshTokenReusePolicy = "reject" | "revoke-session";
|
|
113
|
+
/** How long an email-verification link stays usable. */
|
|
114
|
+
export declare const EMAIL_VERIFICATION_TTL_MS: number;
|
|
90
115
|
/**
|
|
91
116
|
* Configuration for httpOnly refresh-token cookies.
|
|
92
117
|
*/
|
|
@@ -109,4 +134,24 @@ export interface CookieAuthConfig {
|
|
|
109
134
|
*/
|
|
110
135
|
secure?: boolean;
|
|
111
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* What {@link CreateSessionAndTokens} is told about the sign-in it opens.
|
|
139
|
+
*
|
|
140
|
+
* `method` is what `providerId` says for the session from now on — stored on
|
|
141
|
+
* its refresh token and carried across every rotation — so each door names
|
|
142
|
+
* its own rather than leaving it to a default.
|
|
143
|
+
*/
|
|
144
|
+
export interface SessionOptions {
|
|
145
|
+
/** `"password"`, `"anonymous"`, `"magic-link"`, `"otp"`, `"mfa"` or a provider id. */
|
|
146
|
+
method: string;
|
|
147
|
+
/** Only for the route that has just seen the second factor. */
|
|
148
|
+
skipMfaGate?: boolean;
|
|
149
|
+
aal?: "aal1" | "aal2";
|
|
150
|
+
}
|
|
151
|
+
/** Mint a session, as every sign-in door does. See `createSessionAndTokens`. */
|
|
152
|
+
export type CreateSessionAndTokens = (uid: string, userAgent: string, ipAddress: string, options: SessionOptions) => Promise<{
|
|
153
|
+
roleIds: string[];
|
|
154
|
+
accessToken: string;
|
|
155
|
+
refreshToken: string;
|
|
156
|
+
}>;
|
|
112
157
|
export declare function createAuthRoutes(config: AuthModuleConfig): Hono<HonoEnv>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `GET /auth/scopes` — every scope this backend knows, described, and the
|
|
3
|
+
* ones the caller holds.
|
|
4
|
+
*
|
|
5
|
+
* What a screen needs to offer scopes for a key or a role: the built-in ones,
|
|
6
|
+
* the app's own `auth.scopes`, their wording and what their targets name. Any
|
|
7
|
+
* authenticated caller may read it; it describes the backend's vocabulary,
|
|
8
|
+
* not anybody's data.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
import { Hono, type MiddlewareHandler } from "hono";
|
|
13
|
+
import type { AccessJudgeRepository } from "./token-revocation.js";
|
|
14
|
+
import type { HonoEnv } from "../api/types.js";
|
|
15
|
+
export interface ScopeRouteOptions {
|
|
16
|
+
serviceKey?: string;
|
|
17
|
+
resolveRoles?: (uid: string) => Promise<string[]>;
|
|
18
|
+
revocationRepo?: AccessJudgeRepository;
|
|
19
|
+
/** Authenticates `rk_` keys first, so a key can read what it holds. */
|
|
20
|
+
apiKeyPreAuth?: MiddlewareHandler<HonoEnv>;
|
|
21
|
+
}
|
|
22
|
+
export declare function createScopeRoutes(options: ScopeRouteOptions): Hono<HonoEnv>;
|
|
@@ -2,7 +2,7 @@ import { Hono } from "hono";
|
|
|
2
2
|
import { z } from "zod";
|
|
3
3
|
import { HonoEnv } from "../api/types.js";
|
|
4
4
|
import type { MiddlewareHandler } from "hono";
|
|
5
|
-
import type { AuthModuleConfig } from "./routes.js";
|
|
5
|
+
import type { AuthModuleConfig, CreateSessionAndTokens } from "./routes.js";
|
|
6
6
|
import type { AuthResponsePayload, TransformAuthResponseContext } from "@rebasepro/types";
|
|
7
7
|
import type { resolveAuthHooks } from "./auth-hooks.js";
|
|
8
8
|
interface SessionRoutesConfig {
|
|
@@ -28,11 +28,7 @@ interface SessionRoutesConfig {
|
|
|
28
28
|
isAnonymous?: boolean;
|
|
29
29
|
metadata?: Record<string, unknown> | null;
|
|
30
30
|
}, roleIds: string[], accessToken: string, refreshToken: string, providerId: string) => unknown;
|
|
31
|
-
createSessionAndTokens:
|
|
32
|
-
roleIds: string[];
|
|
33
|
-
accessToken: string;
|
|
34
|
-
refreshToken: string;
|
|
35
|
-
}>;
|
|
31
|
+
createSessionAndTokens: CreateSessionAndTokens;
|
|
36
32
|
applyTransformHook: (response: AuthResponsePayload, method: TransformAuthResponseContext["method"], request: Request, uid: string) => Promise<AuthResponsePayload>;
|
|
37
33
|
/**
|
|
38
34
|
* The `register` captcha, built by the caller so a misconfiguration fails
|
|
@@ -41,6 +37,15 @@ interface SessionRoutesConfig {
|
|
|
41
37
|
* `/register`. Absent when captcha is off or `register` is not protected.
|
|
42
38
|
*/
|
|
43
39
|
registerCaptcha?: MiddlewareHandler<HonoEnv>;
|
|
40
|
+
/**
|
|
41
|
+
* Mail the account a verification link, in the background. Upgrading a
|
|
42
|
+
* guest is registration, and registration starts the address proof.
|
|
43
|
+
*/
|
|
44
|
+
sendVerificationMail?: (user: {
|
|
45
|
+
id: string;
|
|
46
|
+
email: string;
|
|
47
|
+
displayName?: string | null;
|
|
48
|
+
}) => void;
|
|
44
49
|
}
|
|
45
50
|
export declare function mountSessionRoutes(opts: SessionRoutesConfig): void;
|
|
46
51
|
export {};
|
|
@@ -37,6 +37,55 @@ import type { AccessTokenPayload } from "./jwt.js";
|
|
|
37
37
|
* failure is logged at warn so it is visible rather than silent.
|
|
38
38
|
*/
|
|
39
39
|
export declare function isAccessTokenRevoked(authRepo: Pick<AuthRepository, "getTokensValidAfter">, payload: Pick<AccessTokenPayload, "uid" | "iat">): Promise<boolean>;
|
|
40
|
+
/**
|
|
41
|
+
* The repository reads {@link judgeAccessToken} may make. All optional: a
|
|
42
|
+
* repository answers what it can, and the judge says what it could not ask.
|
|
43
|
+
*/
|
|
44
|
+
export type AccessJudgeRepository = Partial<Pick<AuthRepository, "getAccountAccessState" | "getUserWithRoles" | "getTokensValidAfter">>;
|
|
45
|
+
/**
|
|
46
|
+
* Why an access token that verifies is not honoured.
|
|
47
|
+
*
|
|
48
|
+
* - `revoked`: issued before the account's revocation watermark — a sign-out
|
|
49
|
+
* everywhere, a password change or reset.
|
|
50
|
+
* - `session-revoked`: its own sign-in was ended — `POST /auth/logout`, or
|
|
51
|
+
* `DELETE /auth/sessions/:id` from another device. Needs the token's `sid`.
|
|
52
|
+
* - `account-deleted`: the account it names no longer exists.
|
|
53
|
+
* - `account-disabled`: an administrator switched the account off.
|
|
54
|
+
*/
|
|
55
|
+
export type AccessTokenRefusal = "revoked" | "session-revoked" | "account-deleted" | "account-disabled";
|
|
56
|
+
export type AccessTokenVerdict = {
|
|
57
|
+
live: true;
|
|
58
|
+
/**
|
|
59
|
+
* The account's roles now, or `undefined` when the repository could
|
|
60
|
+
* not say (it reads neither the account nor its roles).
|
|
61
|
+
*/
|
|
62
|
+
roles?: string[];
|
|
63
|
+
} | {
|
|
64
|
+
live: false;
|
|
65
|
+
refusal: AccessTokenRefusal;
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Is the account behind this verified access token still the one that may use
|
|
69
|
+
* it — and with which roles?
|
|
70
|
+
*
|
|
71
|
+
* A verified signature says who the token was minted for, an hour ago at
|
|
72
|
+
* most. This asks the database what has happened to that account since. Every
|
|
73
|
+
* door that honours an access token — the data plane, the admin gates, the
|
|
74
|
+
* realtime socket — asks it here, so they cannot disagree about it.
|
|
75
|
+
*
|
|
76
|
+
* They did. A deleted account read as "not revoked": the watermark lives on
|
|
77
|
+
* the user row, so once the row was gone there was no watermark, and the
|
|
78
|
+
* roles lookup answered `[]` rather than "nobody". A token its owner had
|
|
79
|
+
* revoked came back to life when an administrator deleted the account, as an
|
|
80
|
+
* authenticated principal with that uid, for the rest of its lifetime. MCP
|
|
81
|
+
* refresh and personal API keys already treated a missing account as revoked;
|
|
82
|
+
* the main door did not.
|
|
83
|
+
*
|
|
84
|
+
* Throws when the repository does. Unlike the watermark read on its own, this
|
|
85
|
+
* one decides the roles a request runs with, so a failure is a refusal (the
|
|
86
|
+
* callers answer 503) rather than a guess.
|
|
87
|
+
*/
|
|
88
|
+
export declare function judgeAccessToken(authRepo: AccessJudgeRepository, payload: Pick<AccessTokenPayload, "uid" | "iat" | "sid">): Promise<AccessTokenVerdict>;
|
|
40
89
|
/**
|
|
41
90
|
* End every session this user holds, on every device.
|
|
42
91
|
*
|
|
@@ -72,4 +121,4 @@ export declare function revokeAllSessions(authRepo: Pick<AuthRepository, "delete
|
|
|
72
121
|
* `null` removes the password instead, for the same reason and with the same
|
|
73
122
|
* revocation: see `confirmAddressOwnership`.
|
|
74
123
|
*/
|
|
75
|
-
export declare function replaceUserPassword(authRepo: Pick<AuthRepository, "updatePassword" | "deleteAllRefreshTokensForUser" | "setTokensValidAfter"
|
|
124
|
+
export declare function replaceUserPassword(authRepo: Pick<AuthRepository, "updatePassword" | "deleteAllRefreshTokensForUser" | "setTokensValidAfter"> & Partial<Pick<AuthRepository, "deleteAllPasswordResetTokensForUser">>, uid: string, passwordHash: string | null): Promise<void>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Who may read the user picker (`GET /api/admin/users/pick`).
|
|
3
|
+
*
|
|
4
|
+
* A `userSelect` field stores a user's id, and the person filling it in picks
|
|
5
|
+
* that user from a list. Listing the users is an admin-plane read
|
|
6
|
+
* (`users:read`), which an editor does not hold — so the picker answers a
|
|
7
|
+
* narrower question for a wider audience: id, name, email and avatar, to
|
|
8
|
+
* anyone who may write a collection that has such a field.
|
|
9
|
+
*
|
|
10
|
+
* "May write" is the collection's `securityRules` for an insert or an update,
|
|
11
|
+
* evaluated the way the admin panel decides whether to offer the form, with
|
|
12
|
+
* one difference. A rule that depends only on the row (an owner field) counts
|
|
13
|
+
* as allowing, since the person may write some row. A rule written as SQL the
|
|
14
|
+
* policy model cannot read cannot be judged ahead, and here it counts as
|
|
15
|
+
* refusing: read optimistically, it would let any signed-in person list every
|
|
16
|
+
* user's name and email. A key or token narrowed by scopes must also hold
|
|
17
|
+
* `data:write` on that collection.
|
|
18
|
+
*
|
|
19
|
+
* The collections are read through a getter configured at boot, so a schema
|
|
20
|
+
* edited live is what is judged.
|
|
21
|
+
*
|
|
22
|
+
* @module
|
|
23
|
+
*/
|
|
24
|
+
import type { Context } from "hono";
|
|
25
|
+
import { type CollectionConfig, type Properties } from "@rebasepro/types";
|
|
26
|
+
import type { HonoEnv } from "../api/types.js";
|
|
27
|
+
/** Tell the picker which collections this backend serves. Called once at boot. */
|
|
28
|
+
export declare function configureUserPicking(collections: () => readonly CollectionConfig[]): void;
|
|
29
|
+
/** Whether any property, at any depth, is a `userSelect` field. */
|
|
30
|
+
export declare function propertiesReferenceUsers(properties: Properties | undefined): boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Whether this request's caller may read the user picker: they hold
|
|
33
|
+
* `users:read`, or they may write a collection with a `userSelect` field.
|
|
34
|
+
*/
|
|
35
|
+
export declare function mayPickUsers(c: Context<HonoEnv>): boolean;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verify a bearer credential outside the HTTP middlewares — for a custom
|
|
3
|
+
* socket, a tunnel, anything an app authenticates from a frame or a header it
|
|
4
|
+
* read itself.
|
|
5
|
+
*
|
|
6
|
+
* One answer for the two kinds of credential a person can hold: a session
|
|
7
|
+
* token, and an API key (`rk_`). Both come back as who the caller acts as and
|
|
8
|
+
* what it may do, so the endpoint checks a scope the same way either way.
|
|
9
|
+
*
|
|
10
|
+
* @module
|
|
11
|
+
*/
|
|
12
|
+
import type { ApiKeyStore } from "./api-keys/api-key-store.js";
|
|
13
|
+
/** Who a verified credential acts as, and what it may do. */
|
|
14
|
+
export interface VerifiedCredential {
|
|
15
|
+
uid: string;
|
|
16
|
+
roles: string[];
|
|
17
|
+
scopes: string[];
|
|
18
|
+
/** `"api-key"` when an `rk_` key was presented, otherwise `"session"`. */
|
|
19
|
+
kind: "session" | "api-key";
|
|
20
|
+
}
|
|
21
|
+
/** Install the key store `verifyCredential` checks `rk_` keys against. Called once at boot. */
|
|
22
|
+
export declare function configureCredentialStore(store: ApiKeyStore | undefined): void;
|
|
23
|
+
/**
|
|
24
|
+
* The identity and scopes behind a bearer credential, or null when it does
|
|
25
|
+
* not verify — expired, revoked, unknown, or a key on a backend with no key
|
|
26
|
+
* store.
|
|
27
|
+
*/
|
|
28
|
+
export declare function verifyCredential(token: string): Promise<VerifiedCredential | null>;
|