@fuzdev/fuz_app 0.107.0 → 0.108.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 (58) hide show
  1. package/dist/auth/account_route_schema.d.ts +10 -1
  2. package/dist/auth/account_route_schema.d.ts.map +1 -1
  3. package/dist/auth/account_route_schema.js +10 -1
  4. package/dist/auth/account_routes.d.ts +18 -4
  5. package/dist/auth/account_routes.d.ts.map +1 -1
  6. package/dist/auth/account_routes.js +32 -29
  7. package/dist/auth/api_token_queries.d.ts +4 -0
  8. package/dist/auth/api_token_queries.d.ts.map +1 -1
  9. package/dist/auth/api_token_queries.js +5 -1
  10. package/dist/auth/bearer_auth.d.ts +9 -6
  11. package/dist/auth/bearer_auth.d.ts.map +1 -1
  12. package/dist/auth/bearer_auth.js +12 -21
  13. package/dist/auth/bootstrap_routes.d.ts +12 -2
  14. package/dist/auth/bootstrap_routes.d.ts.map +1 -1
  15. package/dist/auth/bootstrap_routes.js +15 -9
  16. package/dist/auth/middleware.d.ts +0 -3
  17. package/dist/auth/middleware.d.ts.map +1 -1
  18. package/dist/auth/middleware.js +11 -10
  19. package/dist/auth/migrations.d.ts.map +1 -1
  20. package/dist/auth/migrations.js +24 -0
  21. package/dist/auth/session_queries.d.ts +13 -2
  22. package/dist/auth/session_queries.d.ts.map +1 -1
  23. package/dist/auth/session_queries.js +14 -3
  24. package/dist/auth/signup_routes.d.ts +10 -0
  25. package/dist/auth/signup_routes.d.ts.map +1 -1
  26. package/dist/auth/signup_routes.js +14 -11
  27. package/dist/http/error_schemas.d.ts +1 -1
  28. package/dist/http/error_schemas.js +1 -1
  29. package/dist/rate_limiter.d.ts +36 -3
  30. package/dist/rate_limiter.d.ts.map +1 -1
  31. package/dist/rate_limiter.js +36 -3
  32. package/dist/server/app_server.d.ts +27 -10
  33. package/dist/server/app_server.d.ts.map +1 -1
  34. package/dist/server/app_server.js +30 -20
  35. package/dist/server/app_server_context.d.ts +10 -2
  36. package/dist/server/app_server_context.d.ts.map +1 -1
  37. package/dist/testing/CLAUDE.md +21 -8
  38. package/dist/testing/app_server.d.ts.map +1 -1
  39. package/dist/testing/app_server.js +6 -4
  40. package/dist/testing/cross_backend/default_spine_surface.d.ts.map +1 -1
  41. package/dist/testing/cross_backend/default_spine_surface.js +9 -8
  42. package/dist/testing/cross_backend/login_security.d.ts.map +1 -1
  43. package/dist/testing/cross_backend/login_security.js +59 -0
  44. package/dist/testing/cross_backend/session_cap.d.ts +19 -0
  45. package/dist/testing/cross_backend/session_cap.d.ts.map +1 -0
  46. package/dist/testing/cross_backend/session_cap.js +93 -0
  47. package/dist/testing/middleware.d.ts +2 -5
  48. package/dist/testing/middleware.d.ts.map +1 -1
  49. package/dist/testing/middleware.js +5 -5
  50. package/dist/testing/rate_limiting.d.ts +10 -16
  51. package/dist/testing/rate_limiting.d.ts.map +1 -1
  52. package/dist/testing/rate_limiting.js +11 -95
  53. package/dist/testing/stubs.d.ts.map +1 -1
  54. package/dist/testing/stubs.js +3 -1
  55. package/dist/testing/testing_rate_limiter.d.ts +7 -1
  56. package/dist/testing/testing_rate_limiter.d.ts.map +1 -1
  57. package/dist/testing/testing_rate_limiter.js +7 -1
  58. package/package.json +1 -1
@@ -143,8 +143,19 @@ export const query_session_list_for_account = async (deps, account_id, limit = 5
143
143
  * both commit above `max_sessions`. A transaction is necessary here but not
144
144
  * sufficient. Closing this needs one serialization point per
145
145
  * `(account_id, credential_kind)` — a locked parent row or a transaction-scoped
146
- * advisory lock — taken before count/evict/insert, plus a stable tie-breaker
147
- * alongside `created_at` so the survivors are deterministic.
146
+ * advisory lock — taken before count/evict/insert.
147
+ *
148
+ * Ordering is `created_at DESC, id DESC`. The `id` leg is a **stability**
149
+ * tie-breaker, not a recency one: `created_at` defaults to `NOW()`, the
150
+ * *transaction* timestamp, so two sessions born in one transaction — or in two
151
+ * transactions that started in the same microsecond — tie, and an untied
152
+ * `OFFSET` may keep a different set on two evaluations of the same rows. `id` is
153
+ * the blake3 token hash, so the tie-break is arbitrary but deterministic; it
154
+ * makes the survivors reproducible, it does not make the row just inserted a
155
+ * guaranteed survivor. Only the serialization point above does that.
156
+ *
157
+ * Expired-but-unreaped rows count toward the cap (the predicate is `account_id`
158
+ * alone). Matches the Rust twin `query_session_enforce_limit`.
148
159
  *
149
160
  * @param deps - query dependencies (must be transaction-scoped)
150
161
  * @param account_id - the account to enforce the limit for
@@ -157,7 +168,7 @@ export const query_session_enforce_limit = async (deps, account_id, max_sessions
157
168
  WHERE id IN (
158
169
  SELECT id FROM auth_session
159
170
  WHERE account_id = $1
160
- ORDER BY created_at DESC
171
+ ORDER BY created_at DESC, id DESC
161
172
  OFFSET $2
162
173
  ) RETURNING id`, [account_id, max_sessions]);
163
174
  return rows.length;
@@ -36,6 +36,16 @@ export declare const DEFAULT_SIGNUP_FAIL_JITTER_MS = 25;
36
36
  * Per-factory configuration for signup route specs.
37
37
  */
38
38
  export interface SignupRouteOptions extends AuthSessionRouteOptions {
39
+ /**
40
+ * Rate limiter for signup attempts, keyed by client IP. Pass `null` to
41
+ * disable. Its own instance, not login's: signup failures bound username
42
+ * *enumeration* (the 403/409 split), not credential guessing, and an
43
+ * open-signup deployment lets any unauthenticated caller spend this budget
44
+ * — which must not cost anyone their login attempts. Never refunded on
45
+ * success (see `RateLimiter.reset`). Mirrors the Rust spine's
46
+ * `signup_ip_rate_limiter`.
47
+ */
48
+ signup_ip_rate_limiter: RateLimiter | null;
39
49
  /** Rate limiter for signup attempts, keyed by submitted username. Pass `null` to disable. */
40
50
  signup_account_rate_limiter: RateLimiter | null;
41
51
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"signup_routes.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/signup_routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAaH,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAExE,OAAO,EAAgC,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAGlD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAEnE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAEhD;;;;;;;GAOG;AACH,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAQhD;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,uBAAuB;IAClE,6FAA6F;IAC7F,2BAA2B,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAID;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GACrC,MAAM,gBAAgB,EACtB,SAAS,kBAAkB,KACzB,KAAK,CAAC,SAAS,CA4KjB,CAAC"}
1
+ {"version":3,"file":"signup_routes.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/signup_routes.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAaH,OAAO,EAAmB,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAExE,OAAO,EAAgC,KAAK,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACpF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAGlD,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAC;AAEnE;;;;;;;;;;GAUG;AACH,eAAO,MAAM,4BAA4B,MAAM,CAAC;AAEhD;;;;;;;GAOG;AACH,eAAO,MAAM,6BAA6B,KAAK,CAAC;AAQhD;;GAEG;AACH,MAAM,WAAW,kBAAmB,SAAQ,uBAAuB;IAClE;;;;;;;;OAQG;IACH,sBAAsB,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3C,6FAA6F;IAC7F,2BAA2B,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD;;;;OAIG;IACH,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAID;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GACrC,MAAM,gBAAgB,EACtB,SAAS,kBAAkB,KACzB,KAAK,CAAC,SAAS,CAgLjB,CAAC"}
@@ -55,7 +55,7 @@ const signup_fail_delay = (floor_ms, jitter_ms) => {
55
55
  */
56
56
  export const create_signup_route_specs = (deps, options) => {
57
57
  const { keyring, password } = deps;
58
- const { session_options, ip_rate_limiter, signup_account_rate_limiter, signup_fail_floor_ms = DEFAULT_SIGNUP_FAIL_FLOOR_MS, signup_fail_jitter_ms = DEFAULT_SIGNUP_FAIL_JITTER_MS } = options;
58
+ const { session_options, signup_ip_rate_limiter, signup_account_rate_limiter, signup_fail_floor_ms = DEFAULT_SIGNUP_FAIL_FLOOR_MS, signup_fail_jitter_ms = DEFAULT_SIGNUP_FAIL_JITTER_MS } = options;
59
59
  return [
60
60
  {
61
61
  ...create_signup_route_shape({
@@ -63,9 +63,9 @@ export const create_signup_route_specs = (deps, options) => {
63
63
  }),
64
64
  handler: async (c, route) => {
65
65
  // Per-IP rate limit check (before any work). 429 stays fast.
66
- const ip = ip_rate_limiter ? get_client_ip(c) : null;
67
- if (ip_rate_limiter && ip) {
68
- const check = ip_rate_limiter.check(ip);
66
+ const ip = signup_ip_rate_limiter ? get_client_ip(c) : null;
67
+ if (signup_ip_rate_limiter && ip) {
68
+ const check = signup_ip_rate_limiter.check(ip);
69
69
  if (!check.allowed) {
70
70
  return rate_limit_exceeded_response(c, check.retry_after);
71
71
  }
@@ -157,8 +157,8 @@ export const create_signup_route_specs = (deps, options) => {
157
157
  }
158
158
  catch (e) {
159
159
  if (e instanceof NoMatchingInviteError) {
160
- if (ip_rate_limiter && ip)
161
- ip_rate_limiter.record(ip);
160
+ if (signup_ip_rate_limiter && ip)
161
+ signup_ip_rate_limiter.record(ip);
162
162
  if (signup_account_rate_limiter)
163
163
  signup_account_rate_limiter.record(account_key);
164
164
  emit_failure_audit('no_match');
@@ -167,8 +167,8 @@ export const create_signup_route_specs = (deps, options) => {
167
167
  }
168
168
  // Unique constraint violation: username or email already exists.
169
169
  if (is_pg_unique_violation(e)) {
170
- if (ip_rate_limiter && ip)
171
- ip_rate_limiter.record(ip);
170
+ if (signup_ip_rate_limiter && ip)
171
+ signup_ip_rate_limiter.record(ip);
172
172
  if (signup_account_rate_limiter)
173
173
  signup_account_rate_limiter.record(account_key);
174
174
  emit_failure_audit('signup_conflict');
@@ -185,9 +185,12 @@ export const create_signup_route_specs = (deps, options) => {
185
185
  emit_failure_audit('internal_error');
186
186
  throw e;
187
187
  }
188
- // Reset rate limiters on success
189
- if (ip_rate_limiter && ip)
190
- ip_rate_limiter.reset(ip);
188
+ // Clear the account-grain bucket only — the IP aggregate stands.
189
+ // This is the cheapest version of the spray path `RateLimiter.reset`
190
+ // describes: where login at least costs the attacker a credential,
191
+ // an open-signup deployment let an *unauthenticated* caller zero a
192
+ // shared IP budget by creating throwaway accounts, and the
193
+ // per-account limiter never applies to the attacker's own signups.
191
194
  if (signup_account_rate_limiter)
192
195
  signup_account_rate_limiter.reset(account_key);
193
196
  deps.audit.emit(route, {
@@ -272,7 +272,7 @@ export type RouteErrorSchemas = Partial<Record<number, z.ZodType>>;
272
272
  * Rate limit key type — declares what a route or RPC action's rate limiter
273
273
  * is keyed on.
274
274
  *
275
- * - `'ip'` — per-IP rate limiting (bootstrap, password change, bearer auth)
275
+ * - `'ip'` — per-IP rate limiting (login, bootstrap, password change, signup)
276
276
  * - `'account'` — per-account rate limiting. On REST auth routes the key is
277
277
  * the submitted identifier (login). On RPC actions (post-auth) the key is
278
278
  * the resolved actor id (`request_context.actor.id`) — separate namespace.
@@ -261,7 +261,7 @@ export const AccountVanishedError = z.looseObject({
261
261
  * Rate limit key type — declares what a route or RPC action's rate limiter
262
262
  * is keyed on.
263
263
  *
264
- * - `'ip'` — per-IP rate limiting (bootstrap, password change, bearer auth)
264
+ * - `'ip'` — per-IP rate limiting (login, bootstrap, password change, signup)
265
265
  * - `'account'` — per-account rate limiting. On REST auth routes the key is
266
266
  * the submitted identifier (login). On RPC actions (post-auth) the key is
267
267
  * the resolved actor id (`request_context.actor.id`) — separate namespace.
@@ -42,7 +42,18 @@ export interface RateLimiterOptions {
42
42
  */
43
43
  max_keys?: number | null;
44
44
  }
45
- /** Default options for per-IP login rate limiting: 5 attempts per 15 minutes. */
45
+ /**
46
+ * Default options for per-IP auth rate limiting: 5 attempts per 15 minutes.
47
+ * The default for each of the three per-surface IP limiters (login + password
48
+ * change, signup, bootstrap) and the shared cap the Rust spine's
49
+ * `DEFAULT_LOGIN_IP_RATE_LIMIT` pins.
50
+ *
51
+ * Deliberately **not** widened when the buckets became monotone (a success no
52
+ * longer refunds them — see `RateLimiter.reset`). Widening would have bought
53
+ * NAT'd egress headroom by loosening the one bound that caps credential
54
+ * guessing from a single address; splitting one shared bucket into three
55
+ * per-surface ones buys the same headroom without touching that bound.
56
+ */
46
57
  export declare const default_login_ip_rate_limit: RateLimiterOptions;
47
58
  /** Default options for per-account login rate limiting: 10 attempts per 30 minutes. */
48
59
  export declare const default_login_account_rate_limit: RateLimiterOptions;
@@ -86,7 +97,7 @@ export interface RateLimitResult {
86
97
  * key-enumeration attack at the cost of a slight per-op overhead and the
87
98
  * LRU trade-off described on `RateLimiterOptions.max_keys`.
88
99
  *
89
- * Parameters that accept `RateLimiter | null` (e.g. `ip_rate_limiter`,
100
+ * Parameters that accept `RateLimiter | null` (e.g. `login_ip_rate_limiter`,
90
101
  * `login_account_rate_limiter`) silently disable rate limiting when `null`
91
102
  * is passed — no checks are performed and all requests are allowed through.
92
103
  */
@@ -117,7 +128,29 @@ export declare class RateLimiter {
117
128
  */
118
129
  record(key: string, now?: number): RateLimitResult;
119
130
  /**
120
- * Clear all attempts for `key` (e.g. after successful login).
131
+ * Clear all attempts for `key`.
132
+ *
133
+ * **Account-grain keys only.** Called after a successful auth to forgive a
134
+ * user's own typos, which is safe because the key *is* the account being
135
+ * attacked — clearing it requires that account's credential and can only
136
+ * widen the budget against an account the caller already holds.
137
+ *
138
+ * Never call this on an **IP-aggregate** key. That bucket is the
139
+ * distributed-spray backstop, and success on one account must not zero the
140
+ * budget shared by every other account reachable from the same IP;
141
+ * otherwise an attacker interleaves their own logins (or, under open signup,
142
+ * throwaway account creations needing no credential at all) with guesses
143
+ * against arbitrary victims and sprays indefinitely from one address.
144
+ * Nothing records on the IP bucket on success on any path, so with no reset
145
+ * it is a pure monotone-within-window failure counter that only time clears.
146
+ *
147
+ * Because they are monotone, the IP buckets are **one instance per auth
148
+ * surface** (`login_ip_rate_limiter`, `signup_ip_rate_limiter`,
149
+ * `bootstrap_ip_rate_limiter`) rather than one shared across all of them.
150
+ * A single instance meant a failure on any surface spent the budget that
151
+ * bounds guessing on every other one, and one caller's exhaustion denied
152
+ * four routes at once — a cost that used to be masked by the reset this
153
+ * doc forbids.
121
154
  *
122
155
  * @mutates internal map - removes the entry for `key`
123
156
  */
@@ -1 +1 @@
1
- {"version":3,"file":"rate_limiter.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/rate_limiter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAKpC;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,SAAU,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED,iFAAiF;AACjF,eAAO,MAAM,2BAA2B,EAAE,kBAKzC,CAAC;AAEF,uFAAuF;AACvF,eAAO,MAAM,gCAAgC,EAAE,kBAK9C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,EAAE,kBAK1C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,iCAAiC,EAAE,kBAK/C,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,WAAW,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,WAAW;;IACvB,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;gBAOzB,OAAO,EAAE,kBAAkB;IAcvC,8BAA8B;IAC9B,IAAI,IAAI,IAAI,MAAM,CAEjB;IAcD;;;;;;;;;;OAUG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,eAAe;IA2B7D;;;;;;OAMG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,eAAe;IA0B9D;;;;OAIG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIxB;;;;;OAKG;IACH,OAAO,CAAC,GAAG,GAAE,MAAmB,GAAG,IAAI;IAgBvC;;;;OAIG;IACH,OAAO,IAAI,IAAI;CAMf;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,UAAU,OAAO,CAAC,kBAAkB,CAAC,KAAG,WAE3E,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,GAAI,GAAG,OAAO,EAAE,aAAa,MAAM,KAAG,QAI7E,CAAC"}
1
+ {"version":3,"file":"rate_limiter.d.ts","sourceRoot":"../src/lib/","sources":["../src/lib/rate_limiter.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAKpC;;;;;;GAMG;AACH,eAAO,MAAM,6BAA6B,SAAU,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,kDAAkD;IAClD,YAAY,EAAE,MAAM,CAAC;IACrB,+CAA+C;IAC/C,SAAS,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,2BAA2B,EAAE,kBAKzC,CAAC;AAEF,uFAAuF;AACvF,eAAO,MAAM,gCAAgC,EAAE,kBAK9C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,EAAE,kBAK1C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,iCAAiC,EAAE,kBAK/C,CAAC;AAEF;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,sCAAsC;IACtC,OAAO,EAAE,OAAO,CAAC;IACjB,0CAA0C;IAC1C,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,WAAW,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,qBAAa,WAAW;;IACvB,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;gBAOzB,OAAO,EAAE,kBAAkB;IAcvC,8BAA8B;IAC9B,IAAI,IAAI,IAAI,MAAM,CAEjB;IAcD;;;;;;;;;;OAUG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,eAAe;IA2B7D;;;;;;OAMG;IACH,MAAM,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,GAAE,MAAmB,GAAG,eAAe;IA0B9D;;;;;;;;;;;;;;;;;;;;;;;;;;OA0BG;IACH,KAAK,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI;IAIxB;;;;;OAKG;IACH,OAAO,CAAC,GAAG,GAAE,MAAmB,GAAG,IAAI;IAgBvC;;;;OAIG;IACH,OAAO,IAAI,IAAI;CAMf;AAED;;;;GAIG;AACH,eAAO,MAAM,mBAAmB,GAAI,UAAU,OAAO,CAAC,kBAAkB,CAAC,KAAG,WAE3E,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,GAAI,GAAG,OAAO,EAAE,aAAa,MAAM,KAAG,QAI7E,CAAC"}
@@ -16,7 +16,18 @@ import { ERROR_RATE_LIMIT_EXCEEDED } from './http/error_schemas.js';
16
16
  * MB in the worst case.
17
17
  */
18
18
  export const DEFAULT_RATE_LIMITER_MAX_KEYS = 100_000;
19
- /** Default options for per-IP login rate limiting: 5 attempts per 15 minutes. */
19
+ /**
20
+ * Default options for per-IP auth rate limiting: 5 attempts per 15 minutes.
21
+ * The default for each of the three per-surface IP limiters (login + password
22
+ * change, signup, bootstrap) and the shared cap the Rust spine's
23
+ * `DEFAULT_LOGIN_IP_RATE_LIMIT` pins.
24
+ *
25
+ * Deliberately **not** widened when the buckets became monotone (a success no
26
+ * longer refunds them — see `RateLimiter.reset`). Widening would have bought
27
+ * NAT'd egress headroom by loosening the one bound that caps credential
28
+ * guessing from a single address; splitting one shared bucket into three
29
+ * per-surface ones buys the same headroom without touching that bound.
30
+ */
20
31
  export const default_login_ip_rate_limit = {
21
32
  max_attempts: 5,
22
33
  window_ms: 15 * 60_000,
@@ -69,7 +80,7 @@ export const default_action_account_rate_limit = {
69
80
  * key-enumeration attack at the cost of a slight per-op overhead and the
70
81
  * LRU trade-off described on `RateLimiterOptions.max_keys`.
71
82
  *
72
- * Parameters that accept `RateLimiter | null` (e.g. `ip_rate_limiter`,
83
+ * Parameters that accept `RateLimiter | null` (e.g. `login_ip_rate_limiter`,
73
84
  * `login_account_rate_limiter`) silently disable rate limiting when `null`
74
85
  * is passed — no checks are performed and all requests are allowed through.
75
86
  */
@@ -170,7 +181,29 @@ export class RateLimiter {
170
181
  return { allowed: false, remaining: 0, retry_after };
171
182
  }
172
183
  /**
173
- * Clear all attempts for `key` (e.g. after successful login).
184
+ * Clear all attempts for `key`.
185
+ *
186
+ * **Account-grain keys only.** Called after a successful auth to forgive a
187
+ * user's own typos, which is safe because the key *is* the account being
188
+ * attacked — clearing it requires that account's credential and can only
189
+ * widen the budget against an account the caller already holds.
190
+ *
191
+ * Never call this on an **IP-aggregate** key. That bucket is the
192
+ * distributed-spray backstop, and success on one account must not zero the
193
+ * budget shared by every other account reachable from the same IP;
194
+ * otherwise an attacker interleaves their own logins (or, under open signup,
195
+ * throwaway account creations needing no credential at all) with guesses
196
+ * against arbitrary victims and sprays indefinitely from one address.
197
+ * Nothing records on the IP bucket on success on any path, so with no reset
198
+ * it is a pure monotone-within-window failure counter that only time clears.
199
+ *
200
+ * Because they are monotone, the IP buckets are **one instance per auth
201
+ * surface** (`login_ip_rate_limiter`, `signup_ip_rate_limiter`,
202
+ * `bootstrap_ip_rate_limiter`) rather than one shared across all of them.
203
+ * A single instance meant a failure on any surface spent the budget that
204
+ * bounds guessing on every other one, and one caller's exhaustion denied
205
+ * four routes at once — a cost that used to be masked by the reset this
206
+ * doc forbids.
174
207
  *
175
208
  * @mutates internal map - removes the entry for `key`
176
209
  */
@@ -95,12 +95,35 @@ export interface AppServerOptions {
95
95
  get_connection_ip: (c: Context) => string | undefined;
96
96
  };
97
97
  /**
98
- * Shared IP rate limiter for login, bootstrap, and bearer auth.
99
- * Omit or `undefined` to use a default limiter (5 attempts per 15 minutes).
100
- * Pass `null` to explicitly disable rate limiting.
98
+ * Per-IP rate limiter for login + password change — the distributed-spray
99
+ * backstop. Omit or `undefined` to use a default limiter (5 attempts per
100
+ * 15 minutes). Pass `null` to explicitly disable rate limiting.
101
101
  * Also available on `AppServerContext` for route factory callbacks.
102
+ *
103
+ * One instance per auth surface, not one shared across all four. These
104
+ * buckets are monotone within their window — a success never refunds them
105
+ * (see `RateLimiter.reset`) — so a shared instance let a failure on any
106
+ * surface spend the budget that bounds guessing on every other one, and
107
+ * let one caller's exhaustion deny four routes at once. Pass the same
108
+ * limiter to two of these fields to opt back into a shared budget.
102
109
  */
103
- ip_rate_limiter?: RateLimiter | null;
110
+ login_ip_rate_limiter?: RateLimiter | null;
111
+ /**
112
+ * Per-IP rate limiter for signup. Omit or `undefined` to use a default
113
+ * limiter (5 attempts per 15 minutes). Pass `null` to explicitly disable.
114
+ * Separate from `login_ip_rate_limiter` because an open-signup deployment
115
+ * lets any unauthenticated caller spend it. Also available on
116
+ * `AppServerContext` for route factory callbacks.
117
+ */
118
+ signup_ip_rate_limiter?: RateLimiter | null;
119
+ /**
120
+ * Per-IP rate limiter for bootstrap. Omit or `undefined` to use a default
121
+ * limiter (5 attempts per 15 minutes). Pass `null` to explicitly disable.
122
+ * Separate from `login_ip_rate_limiter` so a fumbled bootstrap token can't
123
+ * spend the operator's login budget. Wired directly into the factory-managed
124
+ * bootstrap route; also on `AppServerContext` for symmetry.
125
+ */
126
+ bootstrap_ip_rate_limiter?: RateLimiter | null;
104
127
  /**
105
128
  * Per-account rate limiter for login attempts.
106
129
  * Omit or `undefined` to use a default limiter (10 attempts per 30 minutes).
@@ -115,12 +138,6 @@ export interface AppServerOptions {
115
138
  * Also available on `AppServerContext` for route factory callbacks.
116
139
  */
117
140
  signup_account_rate_limiter?: RateLimiter | null;
118
- /**
119
- * Rate limiter for bearer token auth attempts (per-IP).
120
- * Omit or `undefined` to use a default limiter (5 attempts per 15 minutes).
121
- * Pass `null` to explicitly disable rate limiting.
122
- */
123
- bearer_ip_rate_limiter?: RateLimiter | null;
124
141
  /**
125
142
  * Per-IP rate limiter for the action dispatchers (HTTP RPC + WebSocket).
126
143
  * Consulted for actions whose spec declares `rate_limit: 'ip'` or `'both'`.
@@ -1 +1 @@
1
- {"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/app_server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,IAAI,EAAE,KAAK,OAAO,EAAE,MAAM,MAAM,CAAC;AAG1C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAEN,KAAK,cAAc,EAEnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AACpD,OAAO,EAGN,KAAK,WAAW,EAChB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAKN,KAAK,WAAW,EAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACxD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,OAAO,oBAAoB,CAAC;AAE5B,OAAO,EAA4B,KAAK,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEhF,OAAO,EAEN,KAAK,cAAc,EAEnB,KAAK,eAAe,EACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAIN,KAAK,SAAS,EACd,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AACjE,OAAO,EAGN,KAAK,eAAe,EACpB,MAAM,6BAA6B,CAAC;AASrC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAKrE,OAAO,EAAE,yBAAyB,EAAE,MAAM,qCAAqC,CAAC;AAEhF;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;CACb;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,MAAM,sBAAsB,GACjC,wBAAwB,GAAG,2BAA2B,GAAG,oBAAoB,CAAC;AAE/E,MAAM,WAAW,wBAAwB;IACxC,IAAI,EAAE,UAAU,CAAC;CACjB;AAED,MAAM,WAAW,2BAA2B;IAC3C,IAAI,EAAE,cAAc,CAAC;IACrB,qEAAqE;IACrE,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,oBAAoB;IACpC,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,uBAAuB,EAAE,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9E;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAChC,2DAA2D;IAC3D,OAAO,EAAE,UAAU,CAAC;IACpB,6CAA6C;IAC7C,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,sCAAsC;IACtC,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAE/B,6BAA6B;IAC7B,KAAK,EAAE;QACN,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/B,iBAAiB,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,CAAC;KACtD,CAAC;IAEF;;;;;OAKG;IACH,eAAe,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACrC;;;;;OAKG;IACH,0BAA0B,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD;;;;;OAKG;IACH,2BAA2B,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACjD;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5C;;;;;;;;OAQG;IACH,sBAAsB,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5C;;;;;;;;OAQG;IACH,2BAA2B,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACjD;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,2DAA2D;IAC3D,kBAAkB,CAAC,EAAE,gBAAgB,CAAC;IAEtC,yEAAyE;IACzE,SAAS,CAAC,EAAE,sBAAsB,CAAC;IAEnC;;;OAGG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC;IAEtB;;;OAGG;IACH,kBAAkB,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAEpE,4DAA4D;IAC5D,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,KAAK,CAAC,cAAc,CAAC,CAAC;IAE/E;;;;;;;;;;;;;;OAcG;IACH,aAAa,CAAC,EAAE,IAAI,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAEzC,gFAAgF;IAChF,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IAE/B;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,gBAAgB,KAAK,KAAK,CAAC,eAAe,CAAC,CAAC,CAAC;IAEjG;;;;;;;;;;;OAWG;IACH,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IAEpC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,YAAY,CAAC,EACZ,aAAa,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,gBAAgB,KAAK,aAAa,CAAC,cAAc,CAAC,CAAC,CAAC;IAEhG;;;;OAIG;IACH,UAAU,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC;IAEzB,mFAAmF;IACnF,qBAAqB,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IAE9C,6DAA6D;IAC7D,cAAc,CAAC,EAAE;QAChB,YAAY,EAAE,kBAAkB,CAAC;QACjC,4DAA4D;QAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,gEAAgE;QAChE,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB;;;;WAIG;QACH,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC;KACzC,CAAC;IAEF;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAExE,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,uCAAuC;AACvC,MAAM,WAAW,SAAS;IACzB,GAAG,EAAE,IAAI,CAAC;IACV,wEAAwE;IACxE,YAAY,EAAE,cAAc,CAAC;IAC7B,gBAAgB,EAAE,eAAe,CAAC;IAClC,oGAAoG;IACpG,iBAAiB,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAClD;;;;OAIG;IACH,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;IAC9B;;;;;;;;;;;OAWG;IACH,YAAY,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC,CAAC;IAClE,mEAAmE;IACnE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,iBAAiB,GAAI,QAAQ;IAAE,SAAS,EAAE,WAAW,GAAG,IAAI,CAAA;CAAE,KAAG,WAO7E,CAAC;AAEF,gDAAgD;AAChD,eAAO,MAAM,qBAAqB,QAAc,CAAC;AAEjD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,iBAAiB,GAAU,SAAS,gBAAgB,KAAG,OAAO,CAAC,SAAS,CA0XpF,CAAC"}
1
+ {"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/app_server.ts"],"names":[],"mappings":"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"}
@@ -81,16 +81,23 @@ export const create_app_server = async (options) => {
81
81
  const { deps } = backend;
82
82
  const { log } = deps;
83
83
  // Rate limiter defaults (undefined = default, null = disable)
84
- const ip_rate_limiter = options.ip_rate_limiter === undefined ? create_rate_limiter() : options.ip_rate_limiter;
84
+ // One instance per surface — see `AppServerOptions.login_ip_rate_limiter`
85
+ // for why these are not a single shared bucket.
86
+ const login_ip_rate_limiter = options.login_ip_rate_limiter === undefined
87
+ ? create_rate_limiter()
88
+ : options.login_ip_rate_limiter;
89
+ const signup_ip_rate_limiter = options.signup_ip_rate_limiter === undefined
90
+ ? create_rate_limiter()
91
+ : options.signup_ip_rate_limiter;
92
+ const bootstrap_ip_rate_limiter = options.bootstrap_ip_rate_limiter === undefined
93
+ ? create_rate_limiter()
94
+ : options.bootstrap_ip_rate_limiter;
85
95
  const login_account_rate_limiter = options.login_account_rate_limiter === undefined
86
96
  ? create_rate_limiter(default_login_account_rate_limit)
87
97
  : options.login_account_rate_limiter;
88
98
  const signup_account_rate_limiter = options.signup_account_rate_limiter === undefined
89
99
  ? create_rate_limiter(default_login_account_rate_limit)
90
100
  : options.signup_account_rate_limiter;
91
- const bearer_ip_rate_limiter = options.bearer_ip_rate_limiter === undefined
92
- ? create_rate_limiter()
93
- : options.bearer_ip_rate_limiter;
94
101
  const action_ip_rate_limiter = options.action_ip_rate_limiter === undefined
95
102
  ? create_rate_limiter(default_action_ip_rate_limit)
96
103
  : options.action_ip_rate_limiter;
@@ -115,7 +122,6 @@ export const create_app_server = async (options) => {
115
122
  const auth_middleware = await create_auth_middleware_specs(deps, {
116
123
  allowed_origins: options.allowed_origins,
117
124
  session_options: options.session_options,
118
- bearer_ip_rate_limiter,
119
125
  daemon_token_state: options.daemon_token_state
120
126
  });
121
127
  let middleware_specs = [proxy_spec, ...auth_middleware];
@@ -147,7 +153,9 @@ export const create_app_server = async (options) => {
147
153
  backend,
148
154
  bootstrap_status,
149
155
  session_options: options.session_options,
150
- ip_rate_limiter,
156
+ login_ip_rate_limiter,
157
+ signup_ip_rate_limiter,
158
+ bootstrap_ip_rate_limiter,
151
159
  login_account_rate_limiter,
152
160
  signup_account_rate_limiter,
153
161
  action_ip_rate_limiter,
@@ -166,7 +174,7 @@ export const create_app_server = async (options) => {
166
174
  session_options: options.session_options,
167
175
  bootstrap_status,
168
176
  on_bootstrap: options.bootstrap.mode === 'live' ? options.bootstrap.on_bootstrap : undefined,
169
- ip_rate_limiter
177
+ bootstrap_ip_rate_limiter
170
178
  });
171
179
  const prefix = options.bootstrap.route_prefix ?? '/api/account';
172
180
  factory_routes.push(...prefix_route_specs(prefix, bootstrap_routes));
@@ -243,19 +251,21 @@ export const create_app_server = async (options) => {
243
251
  });
244
252
  }
245
253
  }
246
- if (ip_rate_limiter === null) {
247
- config_diagnostics.push({
248
- level: 'warning',
249
- category: 'config',
250
- message: 'IP rate limiter explicitly disabled (null)'
251
- });
252
- }
253
- if (bearer_ip_rate_limiter === null) {
254
- config_diagnostics.push({
255
- level: 'warning',
256
- category: 'config',
257
- message: 'Bearer IP rate limiter explicitly disabled (null)'
258
- });
254
+ // One diagnostic per surface — a deployment that disables login's limiter
255
+ // but keeps signup's is a different posture than one that disables both,
256
+ // and a single collapsed warning hid which surface was open.
257
+ for (const [name, limiter] of [
258
+ ['login', login_ip_rate_limiter],
259
+ ['signup', signup_ip_rate_limiter],
260
+ ['bootstrap', bootstrap_ip_rate_limiter]
261
+ ]) {
262
+ if (limiter === null) {
263
+ config_diagnostics.push({
264
+ level: 'warning',
265
+ category: 'config',
266
+ message: `${name} IP rate limiter explicitly disabled (null)`
267
+ });
268
+ }
259
269
  }
260
270
  if (config_diagnostics.length) {
261
271
  surface_spec.surface.diagnostics = [...surface_spec.surface.diagnostics, ...config_diagnostics];
@@ -25,8 +25,16 @@ export interface AppServerContext {
25
25
  backend: AppBackend;
26
26
  bootstrap_status: BootstrapStatus;
27
27
  session_options: SessionOptions<string>;
28
- /** Shared IP rate limiter (from options). `null` when not configured. */
29
- ip_rate_limiter: RateLimiter | null;
28
+ /**
29
+ * Per-IP login + password-change rate limiter (from options). `null` when
30
+ * not configured. One instance per auth surface — see
31
+ * `AppServerOptions.login_ip_rate_limiter` for why these aren't shared.
32
+ */
33
+ login_ip_rate_limiter: RateLimiter | null;
34
+ /** Per-IP signup rate limiter (from options). `null` when not configured. */
35
+ signup_ip_rate_limiter: RateLimiter | null;
36
+ /** Per-IP bootstrap rate limiter (from options). `null` when not configured. */
37
+ bootstrap_ip_rate_limiter: RateLimiter | null;
30
38
  /** Per-account login rate limiter (from options). `null` when not configured. */
31
39
  login_account_rate_limiter: RateLimiter | null;
32
40
  /** Per-account signup rate limiter (from options). `null` when not configured. */
@@ -1 +1 @@
1
- {"version":3,"file":"app_server_context.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/app_server_context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAEjE,8CAA8C;AAC9C,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,UAAU,CAAC;IACpB,gBAAgB,EAAE,eAAe,CAAC;IAClC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,yEAAyE;IACzE,eAAe,EAAE,WAAW,GAAG,IAAI,CAAC;IACpC,iFAAiF;IACjF,0BAA0B,EAAE,WAAW,GAAG,IAAI,CAAC;IAC/C,kFAAkF;IAClF,2BAA2B,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD,uGAAuG;IACvG,sBAAsB,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3C,0GAA0G;IAC1G,2BAA2B,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD;;;;OAIG;IACH,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;CAC9B"}
1
+ {"version":3,"file":"app_server_context.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/app_server_context.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAEjE,8CAA8C;AAC9C,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,UAAU,CAAC;IACpB,gBAAgB,EAAE,eAAe,CAAC;IAClC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC;;;;OAIG;IACH,qBAAqB,EAAE,WAAW,GAAG,IAAI,CAAC;IAC1C,6EAA6E;IAC7E,sBAAsB,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3C,gFAAgF;IAChF,yBAAyB,EAAE,WAAW,GAAG,IAAI,CAAC;IAC9C,iFAAiF;IACjF,0BAA0B,EAAE,WAAW,GAAG,IAAI,CAAC;IAC/C,kFAAkF;IAClF,2BAA2B,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD,uGAAuG;IACvG,sBAAsB,EAAE,WAAW,GAAG,IAAI,CAAC;IAC3C,0GAA0G;IAC1G,2BAA2B,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD;;;;OAIG;IACH,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;CAC9B"}
@@ -457,8 +457,8 @@ file that imports from `middleware.ts` gets these mocks globally. Pair with
457
457
  - `BearerAuthTestOptions`, `BearerAuthTestCase` — test-case table shape for the bearer auth runner.
458
458
  - `create_bearer_auth_mocks(tc)` — configures the module-level mocks per test case; returns spy references.
459
459
  - `TEST_CLIENT_IP = '127.0.0.1'` — IP set by the proxy stub in `create_bearer_auth_test_app`.
460
- - `create_bearer_auth_test_app(tc, ip_rate_limiter?)` — Hono app with bearer middleware + echo route at `/api/test` returning `{ok, account_id, credential_type, api_token_id, request_context_set}` — the account-grain identity bearer auth writes, plus a flag for tests that pre-populate `REQUEST_CONTEXT_KEY` via `pre_context`.
461
- - `describe_bearer_auth_cases(suite_name, cases, ip_rate_limiter?)` — table-driven runner; one `test()` per case; asserts status, error, body fields, `api_token_id`, context preservation.
460
+ - `create_bearer_auth_test_app(tc)` — Hono app with bearer middleware + echo route at `/api/test` returning `{ok, account_id, credential_type, api_token_id, request_context_set}` — the account-grain identity bearer auth writes, plus a flag for tests that pre-populate `REQUEST_CONTEXT_KEY` via `pre_context`.
461
+ - `describe_bearer_auth_cases(suite_name, cases)` — table-driven runner; one `test()` per case; asserts status, error, body fields, `api_token_id`, context preservation.
462
462
  - `TEST_MIDDLEWARE_PATH = '/api/test'` — path used by the echo route in the stack factory.
463
463
  - `create_test_middleware_stack_app(options?)` — real proxy + origin + bearer middleware for integration-shape testing. Echo route returns `{ok, client_ip, has_context}`.
464
464
 
@@ -571,17 +571,19 @@ Options: `{setup_test, surface_source, capabilities, sensitive_fields?, admin_on
571
571
 
572
572
  ### `rate_limiting.ts` — `describe_rate_limiting_tests`
573
573
 
574
- Three test groups:
574
+ Two test groups:
575
575
 
576
576
  1. IP rate limiting on login — fires `max_attempts + 1` requests; last should be 429 with `RateLimitError` body + valid `Retry-After` header.
577
577
  2. Per-account rate limiting on login — same username exhausts the bucket; a different username is not blocked.
578
- 3. Bearer auth IP rate limiting — invalid bearer tokens exhaust the IP bucket via the `account_verify` RPC method.
578
+
579
+ No bearer group — the bearer path carries no rate limiter on either spine
580
+ (`auth/bearer_auth.ts`), which is also why `rpc_endpoints` is optional here.
579
581
 
580
582
  Each group asserts its required route exists with a descriptive message.
581
583
  Creates a tight rate limiter (default `max_attempts: 2`, `window_ms: 60_000`)
582
584
  per test and disposes it in `finally`.
583
585
 
584
- Options: `{session_options, create_route_specs, rpc_endpoints, app_options?, db_factories?, max_attempts?}`.
586
+ Options: `{session_options, create_route_specs, rpc_endpoints?, app_options?, db_factories?, max_attempts?}`.
585
587
  Reads inputs directly from the options bag instead of going through the
586
588
  `setup_test` fixture protocol — the per-test rate-limiter overrides need a
587
589
  fresh `TestApp` per test that the single-fixture model can't carry.
@@ -1495,7 +1497,7 @@ pay the 250ms denial floor.
1495
1497
 
1496
1498
  `describe_login_security_cross_tests({setup_test, login_path?})` — the imperative
1497
1499
  suite pinning **login rate limiting + `X-Forwarded-For` client-IP resolution**
1498
- over real HTTP on both spines. Two cases:
1500
+ over real HTTP on both spines:
1499
1501
 
1500
1502
  - **per-IP limit fires** — `default_login_ip_rate_limit.max_attempts` (5, the
1501
1503
  shared cap on both impls) failed logins from one forwarded IP → 401, the next →
@@ -1505,15 +1507,26 @@ over real HTTP on both spines. Two cases:
1505
1507
  - **XFF keying** — exhaust one forwarded IP to 429, then a _distinct_ forwarded IP
1506
1508
  → 401 (not 429), proving the limiter keys on the resolved `X-Forwarded-For` IP,
1507
1509
  not the loopback TCP peer (a backend ignoring XFF would 429 the fresh IP too).
1510
+ - **a success does not refund the per-IP budget** — the distributed-spray
1511
+ backstop. Failed guesses against distinct usernames from one forwarded IP,
1512
+ interleaved with the attacker's own successful logins, must still 429 within a
1513
+ bounded total-request budget. Both spines used to clear the IP bucket on
1514
+ success; only the account-grain bucket is forgiven now. The **budget bound** is
1515
+ what makes this adversarial — a decrement-instead-of-zero implementation loops
1516
+ to the iteration cap and fails here. Either leg may trip: the aggregate governs
1517
+ the address, so once it fills the attacker's own login is refused too.
1508
1518
 
1509
1519
  **Cross-process only**, on a **dedicated dual-spawn project** (`cross_backend_security`
1510
1520
  via `global_setup_login_security.ts`) — the limiters can't be enabled on a backend
1511
1521
  the standard suites share (they fire many loopback logins a live limiter would
1512
1522
  429), so the standard backends keep every limiter null. Determinism without a
1513
1523
  limiter reset: each case uses its own forwarded IP (a fresh bucket) plus its own
1514
- non-existent username. Zero Rust code change — the stub's `FUZ_LOGIN_RATE_LIMIT_ENABLED`
1524
+ non-existent username; the spray case additionally mints its attacker account
1525
+ over the setup path (loopback, no XFF), so minting can't touch the bucket under
1526
+ test. Zero Rust code change — the stub's `FUZ_LOGIN_RATE_LIMIT_ENABLED`
1515
1527
  and `FUZ_TRUSTED_PROXIES` env-gates were already wired; the TS side env-gates the
1516
- limiters in the binary, and `create_spine_route_specs` honors `ctx.ip_rate_limiter`.
1528
+ limiters in the binary, and `create_spine_route_specs` honors
1529
+ `ctx.login_ip_rate_limiter`.
1517
1530
  The in-process counterparts already exist (`describe_rate_limiting_tests` plus the
1518
1531
  proxy middleware tests), so there's no in-process leg. `npm run test:cross:security`.
1519
1532
  Cited property: `docs/security.md` §"Rate Limiting" + §"Trusted Proxy / Client IP".
@@ -1 +1 @@
1
- {"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/app_server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/app_server.ts"],"names":[],"mappings":"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"}
@@ -276,10 +276,11 @@ export const create_test_app = async (options) => {
276
276
  allowed_origins: [/^http:\/\/localhost/],
277
277
  proxy: { trusted_proxies: ['127.0.0.1'], get_connection_ip: () => '127.0.0.1' },
278
278
  env_schema: z.object({}),
279
- ip_rate_limiter: null,
279
+ login_ip_rate_limiter: null,
280
+ signup_ip_rate_limiter: null,
281
+ bootstrap_ip_rate_limiter: null,
280
282
  login_account_rate_limiter: null,
281
283
  signup_account_rate_limiter: null,
282
- bearer_ip_rate_limiter: null,
283
284
  await_pending_effects: true,
284
285
  daemon_token_state,
285
286
  rpc_endpoints: options.rpc_endpoints,
@@ -402,10 +403,11 @@ export const create_test_app_for_bootstrap = async (options) => {
402
403
  allowed_origins: [/^http:\/\/localhost/],
403
404
  proxy: { trusted_proxies: ['127.0.0.1'], get_connection_ip: () => '127.0.0.1' },
404
405
  env_schema: z.object({}),
405
- ip_rate_limiter: null,
406
+ login_ip_rate_limiter: null,
407
+ signup_ip_rate_limiter: null,
408
+ bootstrap_ip_rate_limiter: null,
406
409
  login_account_rate_limiter: null,
407
410
  signup_account_rate_limiter: null,
408
- bearer_ip_rate_limiter: null,
409
411
  await_pending_effects: true,
410
412
  daemon_token_state,
411
413
  rpc_endpoints: options.rpc_endpoints,
@@ -1 +1 @@
1
- {"version":3,"file":"default_spine_surface.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/default_spine_surface.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAItD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAC;AACvF,OAAO,EAAsB,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAEtF,OAAO,EAAyB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAI1F,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAe3E;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,cAAc,CAAC,MAAM,CAAwC,CAAC;AAElG;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,EAAE,gBAGxB,CAAC;AAEH,+CAA+C;AAC/C,MAAM,WAAW,wBAAwB;IACxC;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACzD;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,mBAAmB,GAC/B,KAAK,gBAAgB,EACrB,UAAU,wBAAwB,KAChC,KAAK,CAAC,eAAe,CAQvB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,GAAI,KAAK,gBAAgB,KAAG,KAAK,CAAC,SAAS,CA+B/E,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,6BAA6B,GAAI,MAAM,MAAM,KAAG,SAC+B,CAAC;AAE7F;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,QAAO,cAM1C,CAAC"}
1
+ {"version":3,"file":"default_spine_surface.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/default_spine_surface.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAItD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,8CAA8C,CAAC;AACvF,OAAO,EAAsB,KAAK,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAEtF,OAAO,EAAyB,KAAK,cAAc,EAAE,MAAM,8BAA8B,CAAC;AAI1F,OAAO,EAAsB,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAC;AAC9E,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7E,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AAe3E;;;GAGG;AACH,eAAO,MAAM,qBAAqB,EAAE,cAAc,CAAC,MAAM,CAAwC,CAAC;AAElG;;;;;;;;;;GAUG;AACH,eAAO,MAAM,WAAW,EAAE,gBAGxB,CAAC;AAEH,+CAA+C;AAC/C,MAAM,WAAW,wBAAwB;IACxC;;;;;;;;;;;;;;;OAeG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;CACzD;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,mBAAmB,GAC/B,KAAK,gBAAgB,EACrB,UAAU,wBAAwB,KAChC,KAAK,CAAC,eAAe,CAQvB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,wBAAwB,GAAI,KAAK,gBAAgB,KAAG,KAAK,CAAC,SAAS,CAgC/E,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,6BAA6B,GAAI,MAAM,MAAM,KAAG,SAC+B,CAAC;AAE7F;;;;;;;;GAQG;AACH,eAAO,MAAM,yBAAyB,QAAO,cAM1C,CAAC"}