@rebasepro/server 0.22.0 → 0.23.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.
Files changed (114) hide show
  1. package/dist/{GCSStorageController-CLIJXwGS.js → GCSStorageController-CjrA4PMo.js} +37 -23
  2. package/dist/GCSStorageController-CjrA4PMo.js.map +1 -0
  3. package/dist/{S3StorageController-Dcuf8lMA.js → S3StorageController-B6pKDNVj.js} +2 -2
  4. package/dist/{S3StorageController-Dcuf8lMA.js.map → S3StorageController-B6pKDNVj.js.map} +1 -1
  5. package/dist/api/ast-schema-editor.d.ts +35 -0
  6. package/dist/api/live-schema-routes.d.ts +14 -0
  7. package/dist/api/rest/api-generator.d.ts +117 -35
  8. package/dist/api/rest/auth-collection-writes.d.ts +85 -0
  9. package/dist/api/rest/field-access-query.d.ts +6 -2
  10. package/dist/api/rest/idempotency.d.ts +7 -1
  11. package/dist/api/rest/nested-write-access.d.ts +46 -0
  12. package/dist/api/rest/write-validation.d.ts +32 -0
  13. package/dist/{ast-schema-editor-CslO8Oje.js → ast-schema-editor-Mvr50v_S.js} +104 -4
  14. package/dist/ast-schema-editor-Mvr50v_S.js.map +1 -0
  15. package/dist/auth/address-ownership.d.ts +53 -0
  16. package/dist/auth/admin-user-ops.d.ts +35 -2
  17. package/dist/auth/auth-hooks.d.ts +4 -0
  18. package/dist/auth/captcha.d.ts +5 -0
  19. package/dist/auth/interfaces.d.ts +36 -6
  20. package/dist/auth/jwt.d.ts +17 -0
  21. package/dist/auth/oauth-signin-policy.d.ts +25 -8
  22. package/dist/auth/rate-limiter.d.ts +31 -1
  23. package/dist/auth/session-routes.d.ts +7 -0
  24. package/dist/auth/token-revocation.d.ts +4 -1
  25. package/dist/{auth-CCDpk2rn.js → auth-B-GIMpDG.js} +639 -228
  26. package/dist/auth-B-GIMpDG.js.map +1 -0
  27. package/dist/backend-DTAOsLQc.js +30 -0
  28. package/dist/backend-DTAOsLQc.js.map +1 -0
  29. package/dist/backup/backup-common.d.ts +19 -0
  30. package/dist/{backup-DzI9jLwc.js → backup-D7YR94N3.js} +69 -8
  31. package/dist/backup-D7YR94N3.js.map +1 -0
  32. package/dist/boot/driver.d.ts +10 -0
  33. package/dist/boot/env.d.ts +2 -2
  34. package/dist/boot/fetch-bundle.d.ts +18 -1
  35. package/dist/boot/rls-audit-option.d.ts +26 -0
  36. package/dist/boot/sources.d.ts +1 -0
  37. package/dist/{contract-routes-eLxV0le1.js → contract-routes-CbFjuBwa.js} +2 -2
  38. package/dist/{contract-routes-eLxV0le1.js.map → contract-routes-CbFjuBwa.js.map} +1 -1
  39. package/dist/cron/cron-routes.d.ts +7 -2
  40. package/dist/cron/cron-scheduler.d.ts +128 -8
  41. package/dist/cron/cron-store.d.ts +72 -8
  42. package/dist/cron/index.d.ts +1 -1
  43. package/dist/{cron-loader-CQjvjpEw.js → cron-loader-DfTj2Hbi.js} +2 -2
  44. package/dist/{cron-loader-CQjvjpEw.js.map → cron-loader-DfTj2Hbi.js.map} +1 -1
  45. package/dist/{cron-routes-B7CRGfiq.js → cron-routes-eE8nif_b.js} +33 -12
  46. package/dist/cron-routes-eE8nif_b.js.map +1 -0
  47. package/dist/{cron-scheduler-COPQxlEq.js → cron-scheduler-B0pLfAix.js} +394 -68
  48. package/dist/cron-scheduler-B0pLfAix.js.map +1 -0
  49. package/dist/{cron-store-BYGZFNWk.js → cron-store-TcoGz-xS.js} +133 -12
  50. package/dist/cron-store-TcoGz-xS.js.map +1 -0
  51. package/dist/{ddl-bootstrap-CfNvxMuK.js → ddl-bootstrap-C6mo0Kmz.js} +2 -25
  52. package/dist/ddl-bootstrap-C6mo0Kmz.js.map +1 -0
  53. package/dist/email/link-base.d.ts +5 -4
  54. package/dist/email/smtp-email-service.d.ts +13 -1
  55. package/dist/email/templates.d.ts +9 -0
  56. package/dist/email/types.d.ts +3 -2
  57. package/dist/env.d.ts +24 -5
  58. package/dist/{history-recorder-BQmB0P_j.js → history-recorder-B4MpJfJK.js} +8 -6
  59. package/dist/history-recorder-B4MpJfJK.js.map +1 -0
  60. package/dist/{history-store-CetkrBBD.js → history-store-BhxWOuz9.js} +2 -2
  61. package/dist/{history-store-CetkrBBD.js.map → history-store-BhxWOuz9.js.map} +1 -1
  62. package/dist/index.d.ts +6 -2
  63. package/dist/index.es.js +2717 -866
  64. package/dist/index.es.js.map +1 -1
  65. package/dist/init/docs.d.ts +5 -2
  66. package/dist/init/shutdown.d.ts +8 -3
  67. package/dist/jobs/index.d.ts +2 -2
  68. package/dist/jobs/job-queue.d.ts +23 -2
  69. package/dist/jobs/job-store.d.ts +37 -5
  70. package/dist/jobs/types.d.ts +8 -6
  71. package/dist/{jobs-Bjr8DZAi.js → jobs-CazMYhyy.js} +305 -166
  72. package/dist/jobs-CazMYhyy.js.map +1 -0
  73. package/dist/{jwt-C4OW-DNq.js → jwt-DnQHNFCl.js} +77 -25
  74. package/dist/{jwt-C4OW-DNq.js.map → jwt-DnQHNFCl.js.map} +1 -1
  75. package/dist/{keys-Qfc4XieN.js → keys-CogCQpxG.js} +18 -3
  76. package/dist/{keys-Qfc4XieN.js.map → keys-CogCQpxG.js.map} +1 -1
  77. package/dist/{logs-routes-3EEzPjhl.js → logs-routes-Bj4TYYUl.js} +7 -4
  78. package/dist/{logs-routes-3EEzPjhl.js.map → logs-routes-Bj4TYYUl.js.map} +1 -1
  79. package/dist/mcp/mcp-routes.d.ts +38 -2
  80. package/dist/mcp/mcp-tools.d.ts +7 -1
  81. package/dist/mcp/oauth-routes.d.ts +27 -0
  82. package/dist/mcp/oauth-store.d.ts +29 -13
  83. package/dist/metrics/history-recorder.d.ts +1 -1
  84. package/dist/{openapi-generator-D8uFz-LW.js → openapi-generator-O_O24MAT.js} +34 -12
  85. package/dist/openapi-generator-O_O24MAT.js.map +1 -0
  86. package/dist/{query-parser-BleZmY18.js → query-parser-DGRVFNM3.js} +39 -30
  87. package/dist/query-parser-DGRVFNM3.js.map +1 -0
  88. package/dist/rls-audit/index.d.ts +4 -0
  89. package/dist/{schema-editor-routes-DdLihzp0.js → schema-editor-routes-C5-lh_jO.js} +2 -2
  90. package/dist/{schema-editor-routes-DdLihzp0.js.map → schema-editor-routes-C5-lh_jO.js.map} +1 -1
  91. package/dist/{src-1vL-I1Po.js → src-pmvW7BFx.js} +122 -14
  92. package/dist/src-pmvW7BFx.js.map +1 -0
  93. package/dist/{src-Br6ARbs6.js → src-vkcwKXbT.js} +2 -27
  94. package/dist/{src-Br6ARbs6.js.map → src-vkcwKXbT.js.map} +1 -1
  95. package/dist/storage/GCSStorageController.d.ts +11 -1
  96. package/dist/storage/keys.d.ts +12 -0
  97. package/dist/storage/rendition-cache.d.ts +11 -1
  98. package/dist/storage/request-keys.d.ts +67 -0
  99. package/dist/storage/types.d.ts +17 -1
  100. package/dist/types-BfKcm9do.js.map +1 -1
  101. package/package.json +9 -9
  102. package/dist/GCSStorageController-CLIJXwGS.js.map +0 -1
  103. package/dist/ast-schema-editor-CslO8Oje.js.map +0 -1
  104. package/dist/auth-CCDpk2rn.js.map +0 -1
  105. package/dist/backup-DzI9jLwc.js.map +0 -1
  106. package/dist/cron-routes-B7CRGfiq.js.map +0 -1
  107. package/dist/cron-scheduler-COPQxlEq.js.map +0 -1
  108. package/dist/cron-store-BYGZFNWk.js.map +0 -1
  109. package/dist/ddl-bootstrap-CfNvxMuK.js.map +0 -1
  110. package/dist/history-recorder-BQmB0P_j.js.map +0 -1
  111. package/dist/jobs-Bjr8DZAi.js.map +0 -1
  112. package/dist/openapi-generator-D8uFz-LW.js.map +0 -1
  113. package/dist/query-parser-BleZmY18.js.map +0 -1
  114. package/dist/src-1vL-I1Po.js.map +0 -1
@@ -133,6 +133,18 @@ isAnonymous?: boolean): Promise<string>;
133
133
  * Get the expiration time of an access token in milliseconds from now
134
134
  */
135
135
  export declare function getAccessTokenExpiryMs(): number;
136
+ /**
137
+ * A lifetime setting in milliseconds, or null when it is not one.
138
+ *
139
+ * The grammar is vercel/ms, because that is what `jsonwebtoken` reads
140
+ * `expiresIn` with: the token's `exp` and the expiry this module reports
141
+ * have to come from one reading of the same string, and they used to come
142
+ * from two — ours understood `<integer><d|h|m|s>` and nothing else.
143
+ *
144
+ * Stricter than ms in two ways, both about values nobody means: a bare number
145
+ * (ms reads "3600" as 3.6 seconds) and a lifetime of zero or less.
146
+ */
147
+ export declare function parseDurationMs(value: string): number | null;
136
148
  /**
137
149
  * Get the expiration timestamp for an access token
138
150
  */
@@ -205,9 +217,14 @@ export declare function generateMfaPendingToken(uid: string, expiresInSeconds?:
205
217
  *
206
218
  * Returns `null` for anything else — including a perfectly valid *access*
207
219
  * token, which must not be interchangeable with this one in either direction.
220
+ *
221
+ * `iat` comes back with the uid because this token is a first factor that was
222
+ * accepted at that instant, and a sign-out everywhere after it has to void it
223
+ * the way it voids an access token — see `isAccessTokenRevoked`.
208
224
  */
209
225
  export declare function verifyMfaPendingToken(token: string): Promise<{
210
226
  uid: string;
227
+ iat?: number;
211
228
  } | null>;
212
229
  export interface DownloadTokenPayload {
213
230
  purpose: "file-read";
@@ -13,7 +13,16 @@ export type AutoLinkRefusal =
13
13
  * address. Attaching a provider identity to it would hand the session to
14
14
  * whoever registered the address first — the classic pre-hijack.
15
15
  */
16
- | "local-account-unverified";
16
+ | "local-account-unverified"
17
+ /**
18
+ * The local account has no password, and its address was never proven
19
+ * either: it was made by a sign-in through a provider that did not vouch
20
+ * for the address, or by someone who never had to. Its sign-in methods are
21
+ * whatever that someone attached, so this is the same pre-hijack as a
22
+ * password would be. Reported apart from `local-account-unverified` only
23
+ * so a login screen does not tell its owner to use a password.
24
+ */
25
+ | "local-account-unverified-passwordless";
17
26
  export type AutoLinkDecision = {
18
27
  allowed: true;
19
28
  } | {
@@ -28,17 +37,25 @@ export interface AutoLinkExistingUser {
28
37
  /**
29
38
  * May an OAuth identity be attached to a pre-existing account found *by email*?
30
39
  *
31
- * Both sides have to be trustworthy, and only one of them used to be checked:
40
+ * Both sides have to be trustworthy:
32
41
  *
33
42
  * - the **provider** must have verified the address, or the caller has not
34
43
  * shown they control it;
35
- * - the **local account** must itself be trustworthy — either its address was
36
- * verified, or it has no password at all (it was created by an OAuth
37
- * sign-in or an invitation, so there is no credential an attacker could
38
- * have planted in advance).
44
+ * - the **local account**'s address must have been verified too. Whoever
45
+ * made an unverified account never proved the address, and every way in
46
+ * they left on it — a password, an identity from a provider that did not
47
+ * vouch for the address — would go on opening the account the owner is
48
+ * about to be signed into.
49
+ *
50
+ * The second rule used to exempt an account with no password, on the theory
51
+ * that one made by an OAuth sign-in holds no credential an attacker could have
52
+ * planted. It holds exactly one: the identity it was made with, which is an
53
+ * attacker's whenever the provider did not vouch for the address.
39
54
  *
40
- * A refusal is not a dead end: `POST /auth/link/<provider>` attaches the
41
- * identity once the caller proves ownership by holding a session.
55
+ * A refusal is not a dead end. `POST /auth/link/<provider>` attaches the
56
+ * identity once the caller proves ownership by holding a session, and proving
57
+ * the address (a magic link, an email code, a password reset) verifies the
58
+ * account — removing what nobody proved — after which this answers yes.
42
59
  */
43
60
  export declare function decideOAuthAutoLink(args: {
44
61
  providerEmailVerified: boolean | undefined;
@@ -1,6 +1,7 @@
1
1
  import { MiddlewareHandler } from "hono";
2
+ import { type DataRateLimitCaller } from "@rebasepro/types";
2
3
  import { HonoEnv } from "../api/types.js";
3
- import { RateLimitStore } from "./rate-limit-store.js";
4
+ import { RateLimitDecision, RateLimitStore } from "./rate-limit-store.js";
4
5
  /**
5
6
  * Sliding-window rate limiting for Hono.
6
7
  *
@@ -28,6 +29,15 @@ interface RateLimiterOptions {
28
29
  * shared one to have several limiters (or several processes) agree.
29
30
  */
30
31
  store?: RateLimitStore;
32
+ /**
33
+ * Count in the deployment's shared store once one is configured, under
34
+ * this name. For a limiter declared at module load, which runs before any
35
+ * configuration exists and so cannot be handed a `store` — see
36
+ * {@link setSharedRateLimitStore}. The name namespaces the limiter's keys
37
+ * there: two limiters keyed by the same IP must not share one count.
38
+ * Ignored when `store` is given.
39
+ */
40
+ name?: string;
31
41
  /**
32
42
  * Per-request limit override, for buckets whose allowance is data rather
33
43
  * than config (an API key's own `rate_limit`). Returning `undefined` uses
@@ -59,6 +69,14 @@ interface RateLimiterOptions {
59
69
  */
60
70
  trustedProxyHops?: number;
61
71
  }
72
+ /**
73
+ * Point every named limiter at the deployment's shared store — or, with
74
+ * `undefined`, back at its own memory. Called once per boot with the store
75
+ * the data limiters use, and only when that store is shared (SQL, or one the
76
+ * operator supplied): the default memory store is swept on the data window,
77
+ * which is not every limiter's window.
78
+ */
79
+ export declare function setSharedRateLimitStore(store: RateLimitStore | undefined): void;
62
80
  /**
63
81
  * Create a rate-limiting middleware.
64
82
  *
@@ -212,4 +230,16 @@ export declare const DEFAULT_FUNCTIONS_ANONYMOUS_LIMIT = 3000;
212
230
  * `enabled: false` rather than pay for it twice.
213
231
  */
214
232
  export declare function createDataRateLimiter(config?: DataRateLimitConfig): MiddlewareHandler<HonoEnv>;
233
+ /**
234
+ * The data API's per-caller limit, as a check rather than a middleware — for
235
+ * the door into the same data that is not an HTTP request.
236
+ *
237
+ * The realtime socket serves the rows the data API serves, one frame per
238
+ * request. It counted them per connection only, so a caller bought more budget
239
+ * by opening more sockets, and a frame never met the per-person limit its HTTP
240
+ * twin does. Built from the same config and store as
241
+ * {@link createDataRateLimiter}, it puts a caller in the same bucket under the
242
+ * same key: one person's allowance, spent through either door.
243
+ */
244
+ export declare function createDataRateLimitCheck(config?: DataRateLimitConfig): (caller: DataRateLimitCaller) => Promise<RateLimitDecision | null>;
215
245
  export {};
@@ -34,6 +34,13 @@ interface SessionRoutesConfig {
34
34
  refreshToken: string;
35
35
  }>;
36
36
  applyTransformHook: (response: AuthResponsePayload, method: TransformAuthResponseContext["method"], request: Request, uid: string) => Promise<AuthResponsePayload>;
37
+ /**
38
+ * The `register` captcha, built by the caller so a misconfiguration fails
39
+ * the boot once. `/anonymous/link` is registration — it is where a guest
40
+ * becomes an account — so it is guarded by the same challenge as
41
+ * `/register`. Absent when captcha is off or `register` is not protected.
42
+ */
43
+ registerCaptcha?: MiddlewareHandler<HonoEnv>;
37
44
  }
38
45
  export declare function mountSessionRoutes(opts: SessionRoutesConfig): void;
39
46
  export {};
@@ -68,5 +68,8 @@ export declare function revokeAllSessions(authRepo: Pick<AuthRepository, "delete
68
68
  * `test/password-change-revokes-sessions.test.ts` holds every route that sets a
69
69
  * password to this, and fails if anything but this function calls
70
70
  * `updatePassword`.
71
+ *
72
+ * `null` removes the password instead, for the same reason and with the same
73
+ * revocation: see `confirmAddressOwnership`.
71
74
  */
72
- export declare function replaceUserPassword(authRepo: Pick<AuthRepository, "updatePassword" | "deleteAllRefreshTokensForUser" | "setTokensValidAfter">, uid: string, passwordHash: string): Promise<void>;
75
+ export declare function replaceUserPassword(authRepo: Pick<AuthRepository, "updatePassword" | "deleteAllRefreshTokensForUser" | "setTokensValidAfter">, uid: string, passwordHash: string | null): Promise<void>;