@fuzdev/fuz_app 0.106.1 → 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 (115) hide show
  1. package/dist/actions/CLAUDE.md +42 -23
  2. package/dist/actions/action_bridge.d.ts +34 -3
  3. package/dist/actions/action_bridge.d.ts.map +1 -1
  4. package/dist/actions/action_bridge.js +32 -1
  5. package/dist/actions/action_rpc.d.ts +5 -4
  6. package/dist/actions/action_rpc.d.ts.map +1 -1
  7. package/dist/actions/action_rpc.js +4 -3
  8. package/dist/actions/action_spec.d.ts +8 -2
  9. package/dist/actions/action_spec.d.ts.map +1 -1
  10. package/dist/actions/action_spec.js +5 -2
  11. package/dist/actions/compile_action_registry.d.ts +26 -14
  12. package/dist/actions/compile_action_registry.d.ts.map +1 -1
  13. package/dist/actions/compile_action_registry.js +29 -14
  14. package/dist/actions/perform_action.d.ts +26 -16
  15. package/dist/actions/perform_action.d.ts.map +1 -1
  16. package/dist/actions/perform_action.js +69 -44
  17. package/dist/actions/register_action_ws.d.ts +4 -4
  18. package/dist/actions/register_action_ws.js +5 -5
  19. package/dist/actions/register_ws_endpoint.d.ts +13 -5
  20. package/dist/actions/register_ws_endpoint.d.ts.map +1 -1
  21. package/dist/actions/register_ws_endpoint.js +15 -6
  22. package/dist/auth/CLAUDE.md +16 -9
  23. package/dist/auth/account_route_schema.d.ts +10 -1
  24. package/dist/auth/account_route_schema.d.ts.map +1 -1
  25. package/dist/auth/account_route_schema.js +10 -1
  26. package/dist/auth/account_routes.d.ts +18 -4
  27. package/dist/auth/account_routes.d.ts.map +1 -1
  28. package/dist/auth/account_routes.js +32 -29
  29. package/dist/auth/api_token_queries.d.ts +4 -0
  30. package/dist/auth/api_token_queries.d.ts.map +1 -1
  31. package/dist/auth/api_token_queries.js +5 -1
  32. package/dist/auth/audit_log_route_schema.d.ts.map +1 -1
  33. package/dist/auth/audit_log_route_schema.js +11 -1
  34. package/dist/auth/audit_log_routes.d.ts.map +1 -1
  35. package/dist/auth/audit_log_routes.js +4 -9
  36. package/dist/auth/auth_guard_resolver.d.ts +48 -21
  37. package/dist/auth/auth_guard_resolver.d.ts.map +1 -1
  38. package/dist/auth/auth_guard_resolver.js +60 -26
  39. package/dist/auth/bearer_auth.d.ts +10 -7
  40. package/dist/auth/bearer_auth.d.ts.map +1 -1
  41. package/dist/auth/bearer_auth.js +13 -22
  42. package/dist/auth/bootstrap_routes.d.ts +12 -2
  43. package/dist/auth/bootstrap_routes.d.ts.map +1 -1
  44. package/dist/auth/bootstrap_routes.js +15 -9
  45. package/dist/auth/middleware.d.ts +0 -3
  46. package/dist/auth/middleware.d.ts.map +1 -1
  47. package/dist/auth/middleware.js +11 -10
  48. package/dist/auth/migrations.d.ts.map +1 -1
  49. package/dist/auth/migrations.js +24 -0
  50. package/dist/auth/request_context.d.ts +54 -24
  51. package/dist/auth/request_context.d.ts.map +1 -1
  52. package/dist/auth/request_context.js +117 -39
  53. package/dist/auth/session_queries.d.ts +13 -2
  54. package/dist/auth/session_queries.d.ts.map +1 -1
  55. package/dist/auth/session_queries.js +14 -3
  56. package/dist/auth/signup_routes.d.ts +10 -0
  57. package/dist/auth/signup_routes.d.ts.map +1 -1
  58. package/dist/auth/signup_routes.js +14 -11
  59. package/dist/auth/token_scope.d.ts +109 -21
  60. package/dist/auth/token_scope.d.ts.map +1 -1
  61. package/dist/auth/token_scope.js +106 -21
  62. package/dist/http/CLAUDE.md +23 -11
  63. package/dist/http/auth_shape.d.ts +58 -3
  64. package/dist/http/auth_shape.d.ts.map +1 -1
  65. package/dist/http/auth_shape.js +63 -5
  66. package/dist/http/error_schemas.d.ts +25 -2
  67. package/dist/http/error_schemas.d.ts.map +1 -1
  68. package/dist/http/error_schemas.js +37 -15
  69. package/dist/http/route_spec.d.ts +29 -26
  70. package/dist/http/route_spec.d.ts.map +1 -1
  71. package/dist/http/route_spec.js +12 -16
  72. package/dist/http/surface_query.d.ts +2 -2
  73. package/dist/http/surface_query.js +2 -2
  74. package/dist/rate_limiter.d.ts +36 -3
  75. package/dist/rate_limiter.d.ts.map +1 -1
  76. package/dist/rate_limiter.js +36 -3
  77. package/dist/server/app_server.d.ts +27 -10
  78. package/dist/server/app_server.d.ts.map +1 -1
  79. package/dist/server/app_server.js +30 -20
  80. package/dist/server/app_server_context.d.ts +10 -2
  81. package/dist/server/app_server_context.d.ts.map +1 -1
  82. package/dist/server/serve_fact_route.d.ts.map +1 -1
  83. package/dist/server/serve_fact_route.js +12 -10
  84. package/dist/testing/CLAUDE.md +60 -11
  85. package/dist/testing/app_server.d.ts.map +1 -1
  86. package/dist/testing/app_server.js +6 -4
  87. package/dist/testing/cross_backend/conformance_case.js +1 -1
  88. package/dist/testing/cross_backend/default_spine_surface.d.ts.map +1 -1
  89. package/dist/testing/cross_backend/default_spine_surface.js +9 -8
  90. package/dist/testing/cross_backend/login_security.d.ts.map +1 -1
  91. package/dist/testing/cross_backend/login_security.js +59 -0
  92. package/dist/testing/cross_backend/session_cap.d.ts +19 -0
  93. package/dist/testing/cross_backend/session_cap.d.ts.map +1 -0
  94. package/dist/testing/cross_backend/session_cap.js +93 -0
  95. package/dist/testing/cross_backend/testing_backdoor.d.ts.map +1 -1
  96. package/dist/testing/cross_backend/testing_backdoor.js +6 -5
  97. package/dist/testing/cross_backend/token_scope_surface.d.ts +9 -0
  98. package/dist/testing/cross_backend/token_scope_surface.d.ts.map +1 -0
  99. package/dist/testing/cross_backend/token_scope_surface.js +170 -0
  100. package/dist/testing/integration.d.ts.map +1 -1
  101. package/dist/testing/integration.js +3 -2
  102. package/dist/testing/middleware.d.ts +2 -5
  103. package/dist/testing/middleware.d.ts.map +1 -1
  104. package/dist/testing/middleware.js +5 -5
  105. package/dist/testing/rate_limiting.d.ts +10 -16
  106. package/dist/testing/rate_limiting.d.ts.map +1 -1
  107. package/dist/testing/rate_limiting.js +11 -95
  108. package/dist/testing/rpc_attack_surface.d.ts.map +1 -1
  109. package/dist/testing/rpc_attack_surface.js +4 -2
  110. package/dist/testing/stubs.d.ts.map +1 -1
  111. package/dist/testing/stubs.js +3 -1
  112. package/dist/testing/testing_rate_limiter.d.ts +7 -1
  113. package/dist/testing/testing_rate_limiter.d.ts.map +1 -1
  114. package/dist/testing/testing_rate_limiter.js +7 -1
  115. package/package.json +1 -1
@@ -189,6 +189,25 @@ export declare const CredentialTypeRequiredError: z.ZodObject<{
189
189
  required_credential_types: z.ZodReadonly<z.ZodArray<z.ZodString>>;
190
190
  }, z.core.$loose>;
191
191
  export type CredentialTypeRequiredError = z.infer<typeof CredentialTypeRequiredError>;
192
+ /**
193
+ * Token-scope error — returned by the `require_token_scope` guard (and its
194
+ * direct-call twin `token_scope_surface_denial`) when a **narrowed** api token
195
+ * reaches a capability its scope does not admit. See
196
+ * `docs/security.md` §Token scoping.
197
+ *
198
+ * `required_scope` carries the capability string the route demands, verbatim
199
+ * from its `auth.required_scope` — `surface:audit_stream` for a non-RPC
200
+ * surface, `rpc:<method>` for a bridged action — matching the Rust
201
+ * `token_scope_surface_denied_response` and the dispatcher's own per-method
202
+ * denial. Third in the family with `PermissionError` and
203
+ * `CredentialTypeRequiredError` — each names what the route demanded rather
204
+ * than what the caller holds.
205
+ */
206
+ export declare const TokenScopeRequiredError: z.ZodObject<{
207
+ error: z.ZodLiteral<"token_scope_required">;
208
+ required_scope: z.ZodString;
209
+ }, z.core.$loose>;
210
+ export type TokenScopeRequiredError = z.infer<typeof TokenScopeRequiredError>;
192
211
  /** Rate limit error — returned when a rate limiter rejects the request. */
193
212
  export declare const RateLimitError: z.ZodObject<{
194
213
  error: z.ZodLiteral<"rate_limit_exceeded">;
@@ -253,7 +272,7 @@ export type RouteErrorSchemas = Partial<Record<number, z.ZodType>>;
253
272
  * Rate limit key type — declares what a route or RPC action's rate limiter
254
273
  * is keyed on.
255
274
  *
256
- * - `'ip'` — per-IP rate limiting (bootstrap, password change, bearer auth)
275
+ * - `'ip'` — per-IP rate limiting (login, bootstrap, password change, signup)
257
276
  * - `'account'` — per-account rate limiting. On REST auth routes the key is
258
277
  * the submitted identifier (login). On RPC actions (post-auth) the key is
259
278
  * the resolved actor id (`request_context.actor.id`) — separate namespace.
@@ -275,12 +294,16 @@ export type RateLimitKey = z.infer<typeof RateLimitKey>;
275
294
  * Derivation rules under the new flat-record auth shape:
276
295
  * - **Has input / params / query schema**: 400 (`ValidationError`).
277
296
  * - **`auth.account === 'required'`** or **`auth.actor === 'required'`**: 401
278
- * (`ApiError`) — pre-validation 401 fires when the credential isn't there.
297
+ * (`ApiError`) — pre-authorization 401 fires when the credential isn't there.
279
298
  * `'optional'` does not derive 401.
280
299
  * - **`auth.roles?.length`**: 403 (`PermissionError` carrying `required_roles`).
281
300
  * - **`auth.credential_types?.length`**: 403 (`CredentialTypeRequiredError`
282
301
  * carrying `required_credential_types` — symmetric with `PermissionError`).
283
302
  * Today the only credential gate is keeper; future gates reuse the literal.
303
+ * - **`auth.required_scope`**: 403 (`TokenScopeRequiredError` carrying
304
+ * `required_scope`) — the refusal `require_token_scope` emits.
305
+ * A route declaring more than one of these three gates derives the union
306
+ * of their shapes, since any of them can be the one that answers.
284
307
  * - **`auth.actor !== 'none'`** (`'optional'` or `'required'`): extends 400
285
308
  * with `ActorRequiredError` / `ActorNotOnAccountError` and adds 500 union
286
309
  * of `NoActorsOnAccountError` / `AccountVanishedError`. The dispatcher's
@@ -1 +1 @@
1
- {"version":3,"file":"error_schemas.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/error_schemas.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"error_schemas.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/error_schemas.ts"],"names":[],"mappings":"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"}
@@ -195,6 +195,24 @@ export const CredentialTypeRequiredError = z.looseObject({
195
195
  error: z.literal(ERROR_CREDENTIAL_TYPE_REQUIRED),
196
196
  required_credential_types: z.array(z.string()).readonly()
197
197
  });
198
+ /**
199
+ * Token-scope error — returned by the `require_token_scope` guard (and its
200
+ * direct-call twin `token_scope_surface_denial`) when a **narrowed** api token
201
+ * reaches a capability its scope does not admit. See
202
+ * `docs/security.md` §Token scoping.
203
+ *
204
+ * `required_scope` carries the capability string the route demands, verbatim
205
+ * from its `auth.required_scope` — `surface:audit_stream` for a non-RPC
206
+ * surface, `rpc:<method>` for a bridged action — matching the Rust
207
+ * `token_scope_surface_denied_response` and the dispatcher's own per-method
208
+ * denial. Third in the family with `PermissionError` and
209
+ * `CredentialTypeRequiredError` — each names what the route demanded rather
210
+ * than what the caller holds.
211
+ */
212
+ export const TokenScopeRequiredError = z.looseObject({
213
+ error: z.literal(ERROR_TOKEN_SCOPE_REQUIRED),
214
+ required_scope: z.string()
215
+ });
198
216
  /** Rate limit error — returned when a rate limiter rejects the request. */
199
217
  export const RateLimitError = z.looseObject({
200
218
  error: z.literal(ERROR_RATE_LIMIT_EXCEEDED),
@@ -243,7 +261,7 @@ export const AccountVanishedError = z.looseObject({
243
261
  * Rate limit key type — declares what a route or RPC action's rate limiter
244
262
  * is keyed on.
245
263
  *
246
- * - `'ip'` — per-IP rate limiting (bootstrap, password change, bearer auth)
264
+ * - `'ip'` — per-IP rate limiting (login, bootstrap, password change, signup)
247
265
  * - `'account'` — per-account rate limiting. On REST auth routes the key is
248
266
  * the submitted identifier (login). On RPC actions (post-auth) the key is
249
267
  * the resolved actor id (`request_context.actor.id`) — separate namespace.
@@ -262,27 +280,31 @@ export const derive_error_schemas = ({ auth, has_input = false, has_params = fal
262
280
  else if (has_validation) {
263
281
  errors[400] = ValidationError;
264
282
  }
265
- // 401 fires when the dispatcher's pre-validation gate rejects an
283
+ // 401 fires when the dispatcher's pre-authorization gate rejects an
266
284
  // unauthenticated caller — `account === 'required'` (no credential) or
267
285
  // `actor === 'required'` (no credential to resolve an actor against,
268
286
  // per registry-time invariant 3 forbidding accountless actors in v1).
269
287
  if (auth.account === 'required' || auth.actor === 'required') {
270
288
  errors[401] = ApiError;
271
289
  }
272
- // 403 fires when `auth.roles` or `auth.credential_types` rejects a
273
- // resolved request context. With both axes set, the 403 body could be
274
- // either shape — emit the union so DEV-mode error-schema validation
275
- // accepts whichever the dispatcher produced.
276
- const has_role_gate = !!auth.roles?.length;
277
- const has_credential_gate = !!auth.credential_types?.length;
278
- if (has_role_gate && has_credential_gate) {
279
- errors[403] = z.union([PermissionError, CredentialTypeRequiredError]);
280
- }
281
- else if (has_role_gate) {
282
- errors[403] = PermissionError;
290
+ // 403 fires from any of three gates: the token-scope refusal
291
+ // (`auth.required_scope`, pre-authorization), the credential-type gate, and
292
+ // the role gate (both post-authorization). A route can declare any
293
+ // combination, so collect the shapes its gates can emit — in the order they
294
+ // fire — and union them when there's more than one, so DEV-mode
295
+ // error-schema validation accepts whichever the pipeline produced.
296
+ const forbidden_shapes = [];
297
+ if (auth.required_scope !== undefined)
298
+ forbidden_shapes.push(TokenScopeRequiredError);
299
+ if (auth.credential_types?.length)
300
+ forbidden_shapes.push(CredentialTypeRequiredError);
301
+ if (auth.roles?.length)
302
+ forbidden_shapes.push(PermissionError);
303
+ if (forbidden_shapes.length === 1) {
304
+ errors[403] = forbidden_shapes[0];
283
305
  }
284
- else if (has_credential_gate) {
285
- errors[403] = CredentialTypeRequiredError;
306
+ else if (forbidden_shapes.length > 1) {
307
+ errors[403] = z.union(forbidden_shapes);
286
308
  }
287
309
  if (rate_limit) {
288
310
  errors[429] = RateLimitError;
@@ -22,14 +22,20 @@ import { type RouteAuth } from './auth_shape.js';
22
22
  /**
23
23
  * Two-phase auth guard set returned by `AuthGuardResolver`.
24
24
  *
25
- * `pre_validation` runs before input validation — 401 checks live here
26
- * so unauthenticated callers never see route-shape information from
27
- * input parsing failures. `post_authorization` runs after the
28
- * authorization phase has populated `RequestContext` — role / keeper
29
- * checks live here because they read `c.var.request_context.role_grants`.
25
+ * `pre_authorization` runs before the authorization phase — the 401 check
26
+ * and the rule-3 token-scope refusal live here, so a caller either one turns
27
+ * away never reaches the actor resolution or the route's body.
28
+ * `post_authorization` runs after the authorization phase has populated
29
+ * `RequestContext` — credential / role checks live here because they read
30
+ * `c.var.request_context.role_grants`.
31
+ *
32
+ * Both phases run ahead of body validation, which is why neither is named
33
+ * for it: route-shape information stays behind every authority gate. The
34
+ * names say which side of the authorization phase a guard sits on, the only
35
+ * axis that still distinguishes them.
30
36
  */
31
37
  export interface AuthGuards {
32
- pre_validation: Array<MiddlewareHandler>;
38
+ pre_authorization: Array<MiddlewareHandler>;
33
39
  post_authorization: Array<MiddlewareHandler>;
34
40
  }
35
41
  /**
@@ -41,12 +47,13 @@ export interface AuthGuards {
41
47
  */
42
48
  export type AuthGuardResolver = (auth: RouteAuth) => AuthGuards;
43
49
  /**
44
- * Per-route authorization phase. Runs after pre-validation auth guards
45
- * AND input validation; resolves the acting actor (when `auth.actor !== 'none'`)
46
- * by reading `c.var.validated_input.acting` and sets the request context on
47
- * the Hono context. Per-route order in `apply_route_specs`: params → query
48
- * → pre-validation auth (401) → input validation (400) → authorization
49
- * phase → post-authorization auth (403) → handler.
50
+ * Per-route authorization phase. Runs after the pre-authorization auth guards
51
+ * and before input validation; resolves the acting actor (when `auth.actor !==
52
+ * 'none'`) from the `acting` selector — `c.var.validated_query.acting` on GETs,
53
+ * read off the raw body on mutations — and sets the request context on the Hono
54
+ * context. Per-route order in `apply_route_specs`: params → query →
55
+ * pre-authorization auth (401 + rule-3 scope) → authorization phase →
56
+ * post-authorization auth (403) → input validation (400) → handler.
50
57
  *
51
58
  * Returns a `Response` to short-circuit (resolution failure → 400 / 500),
52
59
  * or `void` to continue. The http framework stays auth-agnostic — fuz_app
@@ -221,19 +228,15 @@ export declare const apply_middleware_specs: (app: Hono, specs: Array<Middleware
221
228
  * validation, wraps with error catch layer (catches `ThrownJsonrpcError`
222
229
  * and generic errors), and registers the route.
223
230
  *
224
- * Per-route middleware order: params → query → pre-validation auth
225
- * guards (401) → input validation (400) → authorization phase →
226
- * post-authorization auth guards (403) → handler. The 401 check runs
227
- * before any body parsing so unauthenticated callers never see
228
- * route-shape information from parse failures. Input validation runs
229
- * before the authorization phase (validate first, authorize after) so
230
- * the authorization phase reads `c.var.validated_input.acting` as a
231
- * typed Zod field instead of pre-parsing the raw body. Role /
232
- * credential-type denials still surface 403 last; trade-off is that
233
- * authenticated-but-unauthorized callers can distinguish 400
234
- * (validation) from 403 (authorization), a defense-in-depth concession
235
- * deemed acceptable because the route surface is public via
236
- * spec/codegen JSON.
231
+ * Per-route middleware order: params → query → pre-authorization auth
232
+ * guards (401 + rule-3 scope) → authorization phase →
233
+ * post-authorization auth guards (403) → input validation (400) →
234
+ * handler. Body validation runs behind every authority gate, so a caller
235
+ * any of them refuse never sees route-shape information from a parse
236
+ * failure — a 400 there would confirm the route exists and describe how
237
+ * to call it. Params and query still validate first (they address the
238
+ * route rather than carry its payload, and the authorization phase reads
239
+ * `acting` off the query on GETs).
237
240
  *
238
241
  * Each handler receives a `RouteContext` with:
239
242
  * - `db`: transaction-scoped when `RouteSpec.transaction` is true; pool-level otherwise
@@ -248,7 +251,7 @@ export declare const apply_middleware_specs: (app: Hono, specs: Array<Middleware
248
251
  * `input` only — `ActionSpec` has no `query` shape.
249
252
  *
250
253
  * @param resolve_auth_guards - maps `RouteAuth` to middleware — use `fuz_auth_guard_resolver` from `auth/auth_guard_resolver.ts`
251
- * @param authorize - optional authorization phase; runs after input validation
254
+ * @param authorize - optional authorization phase; runs after the pre-authorization guards and before the post-authorization guards
252
255
  * @param db - used for transaction wrapping and `RouteContext`
253
256
  * @mutates `app`
254
257
  * @throws Error if two specs share the same `method` + `path` (each combination must be unique), or if any spec violates the actor-acting biconditional
@@ -1 +1 @@
1
- {"version":3,"file":"route_spec.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/route_spec.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"route_spec.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/route_spec.ts"],"names":[],"mappings":"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"}
@@ -266,19 +266,15 @@ const build_rest_error_body = (err) => {
266
266
  * validation, wraps with error catch layer (catches `ThrownJsonrpcError`
267
267
  * and generic errors), and registers the route.
268
268
  *
269
- * Per-route middleware order: params → query → pre-validation auth
270
- * guards (401) → input validation (400) → authorization phase →
271
- * post-authorization auth guards (403) → handler. The 401 check runs
272
- * before any body parsing so unauthenticated callers never see
273
- * route-shape information from parse failures. Input validation runs
274
- * before the authorization phase (validate first, authorize after) so
275
- * the authorization phase reads `c.var.validated_input.acting` as a
276
- * typed Zod field instead of pre-parsing the raw body. Role /
277
- * credential-type denials still surface 403 last; trade-off is that
278
- * authenticated-but-unauthorized callers can distinguish 400
279
- * (validation) from 403 (authorization), a defense-in-depth concession
280
- * deemed acceptable because the route surface is public via
281
- * spec/codegen JSON.
269
+ * Per-route middleware order: params → query → pre-authorization auth
270
+ * guards (401 + rule-3 scope) → authorization phase →
271
+ * post-authorization auth guards (403) → input validation (400) →
272
+ * handler. Body validation runs behind every authority gate, so a caller
273
+ * any of them refuse never sees route-shape information from a parse
274
+ * failure — a 400 there would confirm the route exists and describe how
275
+ * to call it. Params and query still validate first (they address the
276
+ * route rather than carry its payload, and the authorization phase reads
277
+ * `acting` off the query on GETs).
282
278
  *
283
279
  * Each handler receives a `RouteContext` with:
284
280
  * - `db`: transaction-scoped when `RouteSpec.transaction` is true; pool-level otherwise
@@ -293,7 +289,7 @@ const build_rest_error_body = (err) => {
293
289
  * `input` only — `ActionSpec` has no `query` shape.
294
290
  *
295
291
  * @param resolve_auth_guards - maps `RouteAuth` to middleware — use `fuz_auth_guard_resolver` from `auth/auth_guard_resolver.ts`
296
- * @param authorize - optional authorization phase; runs after input validation
292
+ * @param authorize - optional authorization phase; runs after the pre-authorization guards and before the post-authorization guards
297
293
  * @param db - used for transaction wrapping and `RouteContext`
298
294
  * @mutates `app`
299
295
  * @throws Error if two specs share the same `method` + `path` (each combination must be unique), or if any spec violates the actor-acting biconditional
@@ -307,7 +303,7 @@ export const apply_route_specs = (app, specs, resolve_auth_guards, log, db, auth
307
303
  }
308
304
  registered.add(route_key);
309
305
  assert_route_auth_acting_biconditional(spec.auth, { input: spec.input, query: spec.query }, `Route "${route_key}"`);
310
- const { pre_validation: pre_validation_guards, post_authorization: post_authorization_guards } = resolve_auth_guards(spec.auth);
306
+ const { pre_authorization: pre_authorization_guards, post_authorization: post_authorization_guards } = resolve_auth_guards(spec.auth);
311
307
  const params_validation = create_params_validation(spec.params);
312
308
  const query_validation = create_query_validation(spec.query);
313
309
  const input_validation = create_input_validation(spec.input, spec.method);
@@ -344,7 +340,7 @@ export const apply_route_specs = (app, specs, resolve_auth_guards, log, db, auth
344
340
  handler = wrap_output_validation(handler, spec.output, merged_errors, log);
345
341
  // Step 3: error catch layer
346
342
  handler = wrap_error_catch(handler, log);
347
- app.on(spec.method, [spec.path], ...params_validation, ...query_validation, ...pre_validation_guards, ...input_validation, ...authorization, ...post_authorization_guards, handler);
343
+ app.on(spec.method, [spec.path], ...params_validation, ...query_validation, ...pre_authorization_guards, ...authorization, ...post_authorization_guards, ...input_validation, handler);
348
344
  }
349
345
  };
350
346
  /**
@@ -8,7 +8,7 @@
8
8
  * `filter_keeper_routes`) group the new flat-record `RouteAuth` shape into
9
9
  * the legacy categorical buckets (`'authenticated'`, `'role'`, `'keeper'`)
10
10
  * for adversarial test runners and the surface explorer. The buckets are
11
- * derived views over the four axes (`account`, `actor`, `roles`,
11
+ * derived views over the authority axes (`account`, `actor`, `roles`,
12
12
  * `credential_types`) — see `http/auth_shape.ts` for the canonical shape.
13
13
  *
14
14
  * @module
@@ -65,7 +65,7 @@ export declare const format_route_key: (route: AppSurfaceRoute) => string;
65
65
  /**
66
66
  * Summarize route auth distribution across the surface.
67
67
  *
68
- * Categorical view over the four-axis flat record. Multi-role specs
68
+ * Categorical view over the flat auth record. Multi-role specs
69
69
  * contribute one count per role they admit.
70
70
  *
71
71
  * @returns counts by auth category, with role counts broken out by role name
@@ -8,7 +8,7 @@
8
8
  * `filter_keeper_routes`) group the new flat-record `RouteAuth` shape into
9
9
  * the legacy categorical buckets (`'authenticated'`, `'role'`, `'keeper'`)
10
10
  * for adversarial test runners and the surface explorer. The buckets are
11
- * derived views over the four axes (`account`, `actor`, `roles`,
11
+ * derived views over the authority axes (`account`, `actor`, `roles`,
12
12
  * `credential_types`) — see `http/auth_shape.ts` for the canonical shape.
13
13
  *
14
14
  * @module
@@ -87,7 +87,7 @@ export const format_route_key = (route) => `${route.method} ${route.path}`;
87
87
  /**
88
88
  * Summarize route auth distribution across the surface.
89
89
  *
90
- * Categorical view over the four-axis flat record. Multi-role specs
90
+ * Categorical view over the flat auth record. Multi-role specs
91
91
  * contribute one count per role they admit.
92
92
  *
93
93
  * @returns counts by auth category, with role counts broken out by role name
@@ -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":"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"}
1
+ {"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/app_server.ts"],"names":[],"mappings":"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"}