@fuzdev/fuz_app 0.145.0 → 0.146.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 (59) hide show
  1. package/dist/actions/CLAUDE.md +7 -6
  2. package/dist/auth/CLAUDE.md +5 -2
  3. package/dist/auth/account_action_specs.d.ts.map +1 -1
  4. package/dist/auth/account_action_specs.js +2 -1
  5. package/dist/auth/account_route_schema.d.ts.map +1 -1
  6. package/dist/auth/account_route_schema.js +9 -2
  7. package/dist/auth/account_routes.d.ts +8 -0
  8. package/dist/auth/account_routes.d.ts.map +1 -1
  9. package/dist/auth/account_routes.js +12 -3
  10. package/dist/auth/request_context.d.ts +23 -0
  11. package/dist/auth/request_context.d.ts.map +1 -1
  12. package/dist/auth/request_context.js +32 -1
  13. package/dist/auth/token_scope.d.ts +22 -14
  14. package/dist/auth/token_scope.d.ts.map +1 -1
  15. package/dist/auth/token_scope.js +23 -14
  16. package/dist/http/CLAUDE.md +2 -2
  17. package/dist/http/auth_shape.d.ts.map +1 -1
  18. package/dist/http/auth_shape.js +11 -6
  19. package/dist/http/proxy.d.ts +22 -21
  20. package/dist/http/proxy.d.ts.map +1 -1
  21. package/dist/http/proxy.js +28 -33
  22. package/dist/http/route_spec.d.ts +8 -0
  23. package/dist/http/route_spec.d.ts.map +1 -1
  24. package/dist/server/env.d.ts.map +1 -1
  25. package/dist/server/env.js +1 -1
  26. package/dist/server/fact_security_headers.d.ts +5 -0
  27. package/dist/server/fact_security_headers.d.ts.map +1 -1
  28. package/dist/server/fact_security_headers.js +5 -0
  29. package/dist/server/serve_fact_route.d.ts +12 -7
  30. package/dist/server/serve_fact_route.d.ts.map +1 -1
  31. package/dist/server/serve_fact_route.js +30 -23
  32. package/dist/server/x_accel.d.ts +37 -9
  33. package/dist/server/x_accel.d.ts.map +1 -1
  34. package/dist/server/x_accel.js +136 -19
  35. package/dist/testing/CLAUDE.md +73 -22
  36. package/dist/testing/cross_backend/capabilities.d.ts +0 -18
  37. package/dist/testing/cross_backend/capabilities.d.ts.map +1 -1
  38. package/dist/testing/cross_backend/capabilities.js +1 -4
  39. package/dist/testing/cross_backend/default_backend_configs.d.ts.map +1 -1
  40. package/dist/testing/cross_backend/default_backend_configs.js +0 -7
  41. package/dist/testing/cross_backend/fact_serving.d.ts.map +1 -1
  42. package/dist/testing/cross_backend/fact_serving.js +85 -12
  43. package/dist/testing/cross_backend/identity_parity.d.ts +11 -0
  44. package/dist/testing/cross_backend/identity_parity.d.ts.map +1 -1
  45. package/dist/testing/cross_backend/identity_parity.js +124 -9
  46. package/dist/testing/cross_backend/login_security.d.ts.map +1 -1
  47. package/dist/testing/cross_backend/login_security.js +28 -0
  48. package/dist/testing/cross_backend/revocation_drivers.d.ts +70 -0
  49. package/dist/testing/cross_backend/revocation_drivers.d.ts.map +1 -0
  50. package/dist/testing/cross_backend/revocation_drivers.js +104 -0
  51. package/dist/testing/cross_backend/sse_round_trip.d.ts +6 -1
  52. package/dist/testing/cross_backend/sse_round_trip.d.ts.map +1 -1
  53. package/dist/testing/cross_backend/sse_round_trip.js +52 -16
  54. package/dist/testing/cross_backend/token_scope_surface.d.ts.map +1 -1
  55. package/dist/testing/cross_backend/token_scope_surface.js +33 -0
  56. package/dist/testing/cross_backend/ws_round_trip.d.ts +13 -1
  57. package/dist/testing/cross_backend/ws_round_trip.d.ts.map +1 -1
  58. package/dist/testing/cross_backend/ws_round_trip.js +155 -39
  59. package/package.json +1 -1
@@ -172,30 +172,30 @@ export const is_trusted_ip = (ip, proxies) => {
172
172
  /**
173
173
  * Resolve the real client IP from an `X-Forwarded-For` header value.
174
174
  *
175
- * Walks right-to-left, skipping trusted proxy entries AND any entry
176
- * that fails strict IP validation (`validate_ip_strict`). The first
177
- * untrusted, strictly-valid entry is the client IP. If every walked
178
- * entry is trusted or malformed, returns the leftmost strictly-valid
179
- * (trusted) entry (likely-misconfigured all-trusted case) or
180
- * `undefined` (everything was malformed — middleware falls back to
181
- * the connection IP). All entries are normalized before matching and
182
- * in the returned value.
175
+ * Walks right-to-left, skipping trusted proxy entries. The first untrusted
176
+ * entry is the client IP. The walk **stops** at the first entry that fails
177
+ * strict IP validation (`validate_ip_strict`) and returns `undefined`, so the
178
+ * middleware falls back to the connection IP: an entry is only as
179
+ * trustworthy as the hop that wrote it, and everything left of a malformed
180
+ * one was written before any trusted hop vouched for it. If every entry is
181
+ * trusted, returns the leftmost one (likely-misconfigured all-trusted case).
182
+ * Empty entries are dropped before the walk. All entries are normalized
183
+ * before matching and in the returned value.
183
184
  *
184
- * Skipping malformed entries is the rate-limit-key fix for the
185
- * "attacker controls XFF and the proxy passes it through" surface —
186
- * without the skip, an attacker could rotate arbitrary strings (incl.
185
+ * Stopping, not skipping, is the rate-limit-key rule. Returning a malformed
186
+ * entry would let an attacker rotate arbitrary strings (incl.
187
187
  * `'attacker:controlled'`, which Hono's lax `distinctRemoteAddr`
188
- * misclassifies as IPv6) as XFF values to get fresh per-IP rate-limit
189
- * buckets. Tradeoff: legitimate non-standard proxies that include
190
- * ports in XFF entries (e.g. `203.0.113.1:8080`) also fail strict
191
- * validation, so those entries get skipped and the rate-limit bucket
192
- * collapses to the proxy's connection IP (one bucket for everyone
193
- * behind that proxy). Standard proxies (nginx, cloud LBs) don't
194
- * include ports.
188
+ * misclassifies as IPv6) into fresh per-IP rate-limit buckets; skipping it
189
+ * and walking on would hand the key to the entry the client wrote whenever a
190
+ * trusted hop appends a non-bare-IP token (`ip:port`, `[v6]:port`,
191
+ * `unknown`, `unix:`). Tradeoff: behind such a proxy every client collapses
192
+ * to the proxy's connection IP in rate limiting (one bucket for everyone
193
+ * behind it). Standard proxies (nginx's `$remote_addr`, cloud LBs) append
194
+ * bare IPs.
195
195
  *
196
196
  * @param forwarded_for - the `X-Forwarded-For` header value
197
197
  * @param proxies - parsed trusted proxy entries
198
- * @returns the normalized client IP, or `undefined` if the header is empty / all entries malformed
198
+ * @returns the normalized client IP, or `undefined` if the header is empty or the walk met a malformed entry
199
199
  */
200
200
  export const resolve_client_ip = (forwarded_for, proxies) => {
201
201
  const entries = [];
@@ -206,26 +206,20 @@ export const resolve_client_ip = (forwarded_for, proxies) => {
206
206
  }
207
207
  if (entries.length === 0)
208
208
  return undefined;
209
- // Walk from right to left, skip trusted proxies and malformed entries.
210
- // Returning a malformed entry as the client IP would let an attacker
211
- // who controls XFF poison the per-IP rate-limit key.
209
+ // Walk from right to left, skipping trusted proxies; stop at a malformed
210
+ // entry. Everything left of it is client-written, so neither it nor any
211
+ // entry past it may pick the per-IP rate-limit key.
212
212
  for (let i = entries.length - 1; i >= 0; i--) {
213
213
  const entry = entries[i];
214
214
  if (!validate_ip_strict(entry))
215
- continue;
215
+ return undefined;
216
216
  if (!is_trusted_ip(entry, proxies)) {
217
217
  return entry;
218
218
  }
219
219
  }
220
- // Every entry was trusted or malformed. Prefer the leftmost
221
- // strictly-valid (trusted) entry — the misconfiguration warn in
222
- // the middleware fires on it. If none, fall through to undefined
223
- // and let the middleware fall back to the connection IP.
224
- for (const entry of entries) {
225
- if (validate_ip_strict(entry))
226
- return entry;
227
- }
228
- return undefined;
220
+ // Every entry was valid and trusted — the leftmost one; the
221
+ // misconfiguration warn in the middleware fires on it.
222
+ return entries[0];
229
223
  };
230
224
  /**
231
225
  * Create a Hono middleware that resolves the client IP from trusted proxies.
@@ -238,7 +232,8 @@ export const resolve_client_ip = (forwarded_for, proxies) => {
238
232
  * 2. `X-Forwarded-For` present but connection is untrusted → ignore header
239
233
  * (spoofed by a direct attacker), use connection IP.
240
234
  * 3. `X-Forwarded-For` present and connection is trusted → walk header
241
- * right-to-left, strip trusted entries, use first untrusted entry.
235
+ * right-to-left, strip trusted entries, use first untrusted entry; a
236
+ * malformed entry stops the walk and the connection IP is used.
242
237
  *
243
238
  * @param options - trusted proxy configuration
244
239
  * @mutates `c.var.client_ip` - set to the resolved (or `'unknown'`) client IP per request
@@ -169,6 +169,14 @@ export interface RouteSpec {
169
169
  * and it would see every caller as anonymous, so assembly refuses it
170
170
  * there (`assert_credential_routes_in_auth_scope`), as it does a route
171
171
  * whose `auth.account` is not `'none'`.
172
+ *
173
+ * The handler owns the token-scope rule a gate would otherwise apply: a
174
+ * scope-narrowed API token reaches no non-RPC surface that reads account
175
+ * data, and `auth.required_scope` is refused on a route that admits
176
+ * anonymous callers. Read the credential through `get_public_account_id`
177
+ * (`auth/request_context.ts`), not `ACCOUNT_ID_KEY`, so a narrowed token is
178
+ * answered as the anonymous caller. The RPC endpoint is the exception — its
179
+ * dispatcher gates each method against the scope.
172
180
  */
173
181
  reads_credential?: boolean;
174
182
  /**
@@ -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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"}
@@ -1 +1 @@
1
- {"version":3,"file":"env.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAA4B,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAG5E;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;kBAoDxB,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,EAAE,EAAE,IAAI,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACrC,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,wBAAwB,GAAG,qBAAqB,CAAC;IACxD,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACtB;AAED,MAAM,MAAM,sBAAsB,GAAG,gBAAgB,GAAG,qBAAqB,CAAC;AAE9E;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,GAAI,KAAK,aAAa,KAAG,sBAmBxD,CAAC"}
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,OAAO,EAA4B,KAAK,OAAO,EAAE,MAAM,oBAAoB,CAAC;AAG5E;;;;;;;GAOG;AACH,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;kBAqDxB,CAAC;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,aAAa,CAAC,CAAC;AAE1D;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAChC,EAAE,EAAE,IAAI,CAAC;IACT,OAAO,EAAE,OAAO,CAAC;IACjB,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC/B,oBAAoB,EAAE,MAAM,GAAG,IAAI,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACrC,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EAAE,wBAAwB,GAAG,qBAAqB,CAAC;IACxD,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACtB;AAED,MAAM,MAAM,sBAAsB,GAAG,gBAAgB,GAAG,qBAAqB,CAAC;AAE9E;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,GAAI,KAAK,aAAa,KAAG,sBAmBxD,CAAC"}
@@ -69,7 +69,7 @@ export const BaseServerEnv = z.strictObject({
69
69
  description: 'Directory for referenced (large) fact bytes, sharded <shard>/<rest>'
70
70
  }),
71
71
  FUZ_FACTS_X_ACCEL_REDIRECT_PREFIX: z.string().optional().meta({
72
- description: 'Internal nginx prefix for X-Accel-Redirect fact delivery (production only)'
72
+ description: 'Internal nginx prefix for X-Accel-Redirect fact delivery, ending in `/` (production only)'
73
73
  })
74
74
  });
75
75
  /**
@@ -33,6 +33,11 @@ export declare const FACT_X_CONTENT_TYPE_OPTIONS = "nosniff";
33
33
  * directly-served images (they load no sub-resources).
34
34
  */
35
35
  export declare const FACT_CONTENT_SECURITY_POLICY = "default-src 'none'; sandbox";
36
+ /**
37
+ * `Cache-Control` for fact responses — private, five minutes: the window a
38
+ * cached read outlives a revoked view.
39
+ */
40
+ export declare const FACT_CACHE_CONTROL = "private, max-age=300";
36
41
  /**
37
42
  * The fact hardening headers, in render order. `Content-Disposition:
38
43
  * attachment` is deliberately absent — it would force-download and break
@@ -1 +1 @@
1
- {"version":3,"file":"fact_security_headers.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/fact_security_headers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;;;GAGG;AACH,eAAO,MAAM,2BAA2B,YAAY,CAAC;AAErD;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,gCAAgC,CAAC;AAE1E;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;;CAGxB,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,+BAA+B,QAAO,KAAK,CAAC,MAAM,CAG7D,CAAC"}
1
+ {"version":3,"file":"fact_security_headers.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/fact_security_headers.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;;;GAGG;AACH,eAAO,MAAM,2BAA2B,YAAY,CAAC;AAErD;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,gCAAgC,CAAC;AAE1E;;;GAGG;AACH,eAAO,MAAM,kBAAkB,yBAAyB,CAAC;AAEzD;;;;GAIG;AACH,eAAO,MAAM,qBAAqB;;;CAGxB,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,+BAA+B,QAAO,KAAK,CAAC,MAAM,CAG7D,CAAC"}
@@ -33,6 +33,11 @@ export const FACT_X_CONTENT_TYPE_OPTIONS = 'nosniff';
33
33
  * directly-served images (they load no sub-resources).
34
34
  */
35
35
  export const FACT_CONTENT_SECURITY_POLICY = "default-src 'none'; sandbox";
36
+ /**
37
+ * `Cache-Control` for fact responses — private, five minutes: the window a
38
+ * cached read outlives a revoked view.
39
+ */
40
+ export const FACT_CACHE_CONTROL = 'private, max-age=300';
36
41
  /**
37
42
  * The fact hardening headers, in render order. `Content-Disposition:
38
43
  * attachment` is deliberately absent — it would force-download and break
@@ -70,14 +70,18 @@
70
70
  *
71
71
  * Auth shape on the cell-scoped route is `{account: 'none', actor: 'none'}`
72
72
  * — the dispatcher's authorization phase is skipped for pure-public routes,
73
- * so the handler builds the `RequestContext` itself from `c.var.account_id`
74
- * (populated by the `/api/*` session middleware) by resolving the caller's
75
- * single actor and loading their role_grants. Unauthed callers pass through
76
- * with `req_ctx: null` and are admitted only by a `cell.visibility ===
77
- * 'public'` cell whose `moderation` admits an audience (unmoderated or
73
+ * so the handler builds the `RequestContext` itself from the resolved account
74
+ * id (`get_public_account_id`, over what the `/api/*` auth middleware set) by
75
+ * resolving the caller's single actor and loading their role_grants.
76
+ * Unauthed callers pass through with `req_ctx: null` and are admitted only by
77
+ * a `cell.visibility === 'public'` cell whose `moderation` admits an audience (unmoderated or
78
78
  * `'approved'`). Multi-actor accounts fall through with `req_ctx: null`
79
79
  * — there's no `acting?` slot on a pure-public route, so multi-actor
80
- * callers are treated as anonymous.
80
+ * callers are treated as anonymous. A scope-narrowed API token is treated as
81
+ * anonymous too, not refused (`get_public_account_id`): a narrowed token
82
+ * reaches no non-RPC surface, but on a route that admits anonymous callers
83
+ * a 403 would enforce nothing — the holder drops the `Authorization` header and
84
+ * re-reads every public cell anyway.
81
85
  *
82
86
  * 404 is the universal "not viewable" response: missing fact, missing or
83
87
  * unviewable cell, or the cell doesn't reference the hash. We deliberately
@@ -156,7 +160,8 @@ export interface CreateServeFactRouteSpecOptions {
156
160
  * `(cell, hash)` edge — never unioned across the fact's other referrers.
157
161
  *
158
162
  * Pure-public auth — the handler builds the per-request `RequestContext`
159
- * from `c.var.account_id` and enforces visibility per-reference.
163
+ * from the resolved account id (`get_public_account_id`) and enforces
164
+ * visibility per-reference.
160
165
  */
161
166
  export declare const create_serve_cell_fact_route_spec: (options: CreateServeFactRouteSpecOptions) => RouteSpec;
162
167
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"serve_fact_route.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/serve_fact_route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwHG;AAMH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAetD,OAAO,EAAuC,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAE5F,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAO/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAuCjD,MAAM,WAAW,+BAA+B;IAC/C;;;;;;OAMG;IACH,IAAI,EAAE,OAAO,CAAC;IACd,kFAAkF;IAClF,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;CACZ;AAoHD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,iCAAiC,GAC7C,SAAS,+BAA+B,KACtC,SAuDF,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,4BAA4B,GACxC,SAAS,+BAA+B,KACtC,SA2CF,CAAC"}
1
+ {"version":3,"file":"serve_fact_route.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/serve_fact_route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4HG;AAMH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,yBAAyB,CAAC;AAetD,OAAO,EAAuC,KAAK,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAE5F,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAO/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAoCjD,MAAM,WAAW,+BAA+B;IAC/C;;;;;;OAMG;IACH,IAAI,EAAE,OAAO,CAAC;IACd,kFAAkF;IAClF,SAAS,EAAE,MAAM,CAAC;IAClB;;;;;;;OAOG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,GAAG,EAAE,MAAM,CAAC;CACZ;AAyHD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iCAAiC,GAC7C,SAAS,+BAA+B,KACtC,SAuDF,CAAC;AAEF;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,4BAA4B,GACxC,SAAS,+BAA+B,KACtC,SA2CF,CAAC"}
@@ -70,14 +70,18 @@
70
70
  *
71
71
  * Auth shape on the cell-scoped route is `{account: 'none', actor: 'none'}`
72
72
  * — the dispatcher's authorization phase is skipped for pure-public routes,
73
- * so the handler builds the `RequestContext` itself from `c.var.account_id`
74
- * (populated by the `/api/*` session middleware) by resolving the caller's
75
- * single actor and loading their role_grants. Unauthed callers pass through
76
- * with `req_ctx: null` and are admitted only by a `cell.visibility ===
77
- * 'public'` cell whose `moderation` admits an audience (unmoderated or
73
+ * so the handler builds the `RequestContext` itself from the resolved account
74
+ * id (`get_public_account_id`, over what the `/api/*` auth middleware set) by
75
+ * resolving the caller's single actor and loading their role_grants.
76
+ * Unauthed callers pass through with `req_ctx: null` and are admitted only by
77
+ * a `cell.visibility === 'public'` cell whose `moderation` admits an audience (unmoderated or
78
78
  * `'approved'`). Multi-actor accounts fall through with `req_ctx: null`
79
79
  * — there's no `acting?` slot on a pure-public route, so multi-actor
80
- * callers are treated as anonymous.
80
+ * callers are treated as anonymous. A scope-narrowed API token is treated as
81
+ * anonymous too, not refused (`get_public_account_id`): a narrowed token
82
+ * reaches no non-RPC surface, but on a route that admits anonymous callers
83
+ * a 403 would enforce nothing — the holder drops the `Authorization` header and
84
+ * re-reads every public cell anyway.
81
85
  *
82
86
  * 404 is the universal "not viewable" response: missing fact, missing or
83
87
  * unviewable cell, or the cell doesn't reference the hash. We deliberately
@@ -124,10 +128,9 @@ import { Readable } from 'node:stream';
124
128
  import { join } from 'node:path';
125
129
  import { FactHashSchema, Uuid } from '../primitive_schemas.js';
126
130
  import { z } from 'zod';
127
- import { build_request_context, get_request_context, has_scoped_role } from '../auth/request_context.js';
131
+ import { build_request_context, get_public_account_id, get_request_context, has_scoped_role } from '../auth/request_context.js';
128
132
  import { ROLE_ADMIN } from '../auth/role_schema.js';
129
133
  import { ActingActor } from '../http/auth_shape.js';
130
- import { ACCOUNT_ID_KEY } from '../hono_context.js';
131
134
  import { query_active_actors_by_account } from '../auth/account_queries.js';
132
135
  import { get_route_params } from '../http/route_spec.js';
133
136
  import { ERROR_INVALID_ROUTE_PARAMS } from '../http/error_schemas.js';
@@ -137,9 +140,7 @@ import { query_cell_grant_list_for_cell } from '../db/cell_grant_queries.js';
137
140
  import { can_view_cell } from '../auth/cell_authorize.js';
138
141
  import { cell_steward_admits } from '../auth/cell_steward.js';
139
142
  import { parse_file_fact_url } from '../db/file_fact_url.js';
140
- import { FACT_SECURITY_HEADERS } from './fact_security_headers.js';
141
- /** `Cache-Control` for fact responses — 5 min revocation window. */
142
- const CACHE_CONTROL = 'private, max-age=300';
143
+ import { FACT_CACHE_CONTROL, FACT_SECURITY_HEADERS } from './fact_security_headers.js';
143
144
  /**
144
145
  * Path-param schema for the bare-hash route. Matching the canonical
145
146
  * fact-hash form here pushes malformed-hash 400s through the framework's
@@ -202,7 +203,7 @@ const serve_fact_bytes = async (c, route, hash, config) => {
202
203
  return c.body(bytes, 200, {
203
204
  'Content-Type': content_type,
204
205
  'Content-Length': size,
205
- 'Cache-Control': CACHE_CONTROL,
206
+ 'Cache-Control': FACT_CACHE_CONTROL,
206
207
  ...FACT_SECURITY_HEADERS
207
208
  });
208
209
  }
@@ -221,7 +222,7 @@ const serve_fact_bytes = async (c, route, hash, config) => {
221
222
  return c.body(null, 200, {
222
223
  'Content-Type': content_type,
223
224
  'Content-Length': size,
224
- 'Cache-Control': CACHE_CONTROL,
225
+ 'Cache-Control': FACT_CACHE_CONTROL,
225
226
  'X-Accel-Redirect': `${x_accel.redirect_prefix}${shard}/${rest}`,
226
227
  ...FACT_SECURITY_HEADERS
227
228
  });
@@ -234,22 +235,27 @@ const serve_fact_bytes = async (c, route, hash, config) => {
234
235
  return c.body(web_stream, 200, {
235
236
  'Content-Type': content_type,
236
237
  'Content-Length': size,
237
- 'Cache-Control': CACHE_CONTROL,
238
+ 'Cache-Control': FACT_CACHE_CONTROL,
238
239
  ...FACT_SECURITY_HEADERS
239
240
  });
240
241
  };
241
242
  /**
242
243
  * Resolve the caller's `RequestContext` on a pure-public route from the
243
- * session-middleware-set account id. Multi-actor accounts return `null`
244
- * (no `acting?` slot on a public route to disambiguate); single active-actor
245
- * accounts resolve their actor and role_grants for owner / grant / admin
246
- * admission paths. Unauthenticated callers return `null`. Soft-deleted
247
- * (tombstoned) actors are excluded from the count
248
- * (`query_active_actors_by_account`), matching the acting-actor resolution
249
- * path — a tombstoned actor is never resolvable here.
244
+ * session-middleware-set account id, read through `get_public_account_id`, so
245
+ * a scope-narrowed API token returns `null` — downgraded to anonymous, not
246
+ * refused (see the module doc). Twin of the Rust
247
+ * `AuthGate::public_request_context`.
248
+ *
249
+ * Multi-actor accounts return `null` (no `acting?` slot on a public route to
250
+ * disambiguate); single active-actor accounts resolve their actor and
251
+ * role_grants for owner / grant / admin admission paths. Unauthenticated
252
+ * callers return `null`. Soft-deleted (tombstoned) actors are excluded from the
253
+ * count (`query_active_actors_by_account`), matching the acting-actor
254
+ * resolution path — a tombstoned actor is never resolvable here.
250
255
  */
251
256
  const build_public_request_context = async (c, route) => {
252
- const account_id = c.get(ACCOUNT_ID_KEY);
257
+ // a narrowed token is the anonymous caller here, never a refusal
258
+ const account_id = get_public_account_id(c);
253
259
  if (!account_id)
254
260
  return null;
255
261
  const actors = await query_active_actors_by_account({ db: route.db }, account_id);
@@ -268,7 +274,8 @@ const build_public_request_context = async (c, route) => {
268
274
  * `(cell, hash)` edge — never unioned across the fact's other referrers.
269
275
  *
270
276
  * Pure-public auth — the handler builds the per-request `RequestContext`
271
- * from `c.var.account_id` and enforces visibility per-reference.
277
+ * from the resolved account id (`get_public_account_id`) and enforces
278
+ * visibility per-reference.
272
279
  */
273
280
  export const create_serve_cell_fact_route_spec = (options) => {
274
281
  const { facts_dir, x_accel, log } = options;
@@ -33,6 +33,10 @@
33
33
  * - carry, as top-level directives of its own body, an exact `internal;` and
34
34
  * each `fact_security_header_directives` line (token-equal: whitespace and
35
35
  * quoting are free, the words are not);
36
+ * - set those headers with no other `add_header` — one naming a
37
+ * `FACT_SECURITY_HEADERS` header (ASCII case-insensitive) that is not
38
+ * token-equal to its required line is refused, since nginx sends both values
39
+ * and a client may read only the first (`sniff, nosniff`);
36
40
  * - hold only simple directives — any nested block (`location`, `if`,
37
41
  * `limit_except`, …) is refused, and so is `include`, since included files
38
42
  * are not followed.
@@ -53,13 +57,34 @@
53
57
  * own modifier and path words and the bodies of the locations serving the
54
58
  * prefix.
55
59
  *
60
+ * The prefix itself must be an absolute path ending in exactly one `/` — the
61
+ * server appends `<shard>/<rest>` straight onto it, so `/_facts` would redirect
62
+ * to `/_factsab/…`, outside the validated location. At least one location
63
+ * serving the prefix must sit exactly at it (`/_facts` or `/_facts/`): one only
64
+ * below it (`location ^~ /_facts/00/`) leaves every other redirect path to
65
+ * whatever location matches next, and nginx compares location paths
66
+ * byte-for-byte, so `/_facts//` sits below it too.
67
+ *
68
+ * Module directives that undo those guarantees are refused too:
69
+ *
70
+ * - `ssi` with any value but `off`, anywhere in the config. SSI `include
71
+ * virtual` is a subrequest, which `internal;` admits, so an SSI-processed
72
+ * response — a fact inheriting `ssi on` from `http` or `server`, or any page
73
+ * carrying user content — could include another fact's bytes.
74
+ * - `more_set_headers` / `more_clear_headers` (headers-more) everywhere except
75
+ * inside a `location` that doesn't serve the prefix (or a block within one):
76
+ * they run after `add_header` and can strip the hardening headers, so they
77
+ * are refused in the facts location and at every level above it, including
78
+ * any block there (`if`, another `server`).
79
+ *
56
80
  * Also refused: an `=` location on the prefix or below it (it can't serve the
57
81
  * nested paths the redirect emits); a regex location (`~` / `~*`) whose pattern
58
82
  * spells out the prefix (after unescaping `\/`, ASCII case-folded for `~*`) —
59
- * dead under the rules above, refused for the clearer message; and a config
60
- * with no location serving the prefix. `include` at server level is allowed,
61
- * but its file is not read — keep facts-related locations out of included
62
- * files.
83
+ * dead under the rules above, refused for the clearer message; a config with no
84
+ * location at the prefix; and blocks nested more than 64 deep (a parse error, so
85
+ * the walks can't exhaust the stack). `include` at server level is allowed, but
86
+ * its file is not read — keep facts-related locations and the directives above
87
+ * out of included files.
63
88
  *
64
89
  * The threat model is operator mistakes, not an adversarial config author: the
65
90
  * prefix check is textual, so a value assembled from pieces (`/_fac$1`) evades
@@ -73,8 +98,10 @@
73
98
  * the server is trusted to point into the prefix; an untrusted one needs
74
99
  * `proxy_ignore_headers X-Accel-Redirect;` (or the `fastcgi_` / `uwsgi_` /
75
100
  * `scgi_` equivalent).
76
- * - Module code can redirect internally too (ssi `include virtual`, njs
77
- * `internalRedirect`, perl, echo), so run trusted modules and content only.
101
+ * - Other module code can redirect internally too (njs `internalRedirect`, perl,
102
+ * echo), or strip the hardening headers as headers-more can (njs
103
+ * `js_header_filter`, lua-nginx-module `header_filter_by_lua*`), and the
104
+ * check sees none of it, so run trusted modules and content only.
78
105
  *
79
106
  * The Rust twin is `fuz_fact_serving`'s `nginx.rs`, held to the same rules and
80
107
  * the same fixture corpus.
@@ -145,12 +172,13 @@ export declare class XAccelConfigError extends Error {
145
172
  * The make-impossible-states gate: serving can only emit `X-Accel-Redirect`
146
173
  * into a location proven `internal;` and header-carrying at boot.
147
174
  *
148
- * @param redirect_prefix - the X-Accel redirect prefix (e.g. `/_facts/`)
175
+ * @param redirect_prefix - the X-Accel redirect prefix, ending in `/` (e.g. `/_facts/`)
149
176
  * @param nginx_config - the nginx config string to validate against
150
177
  * @returns the validated `XAccelConfig` carrying `redirect_prefix`
151
178
  * @throws `XAccelConfigError` carrying every violation
152
- * `validate_facts_internal_location` finds — a missing, public, header-less,
153
- * exact-match, or regex-shadowed facts location.
179
+ * `validate_facts_internal_location` finds — a prefix not ending in `/`, a
180
+ * missing, public, header-less, re-headered, exact-match, or regex-shadowed
181
+ * facts location, or `ssi` / headers-more reaching it.
154
182
  */
155
183
  export declare const create_x_accel_config: (redirect_prefix: string, nginx_config: string) => XAccelConfig;
156
184
  //# sourceMappingURL=x_accel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"x_accel.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/x_accel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgGG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,0CAA0C;AAC1C,MAAM,WAAW,oBAAoB;IACpC,qCAAqC;IACrC,EAAE,EAAE,OAAO,CAAC;IACZ,wDAAwD;IACxD,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,gCAAgC,GAC5C,QAAQ,MAAM,EACd,gBAAgB,MAAM,KACpB,oBAYF,CAAC;AAsHF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY;;0CAKF,CAAC;AACxB,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAExD;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC3C,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;gBACnB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;CAKjC;AAED;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,qBAAqB,GACjC,iBAAiB,MAAM,EACvB,cAAc,MAAM,KAClB,YAMF,CAAC"}
1
+ {"version":3,"file":"x_accel.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/x_accel.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2HG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB,0CAA0C;AAC1C,MAAM,WAAW,oBAAoB;IACpC,qCAAqC;IACrC,EAAE,EAAE,OAAO,CAAC;IACZ,wDAAwD;IACxD,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACtB;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,gCAAgC,GAC5C,QAAQ,MAAM,EACd,gBAAgB,MAAM,KACpB,oBAYF,CAAC;AA+IF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,YAAY;;0CAKF,CAAC;AACxB,MAAM,MAAM,YAAY,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,YAAY,CAAC,CAAC;AAExD;;;GAGG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC3C,0DAA0D;IAC1D,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;gBACnB,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC;CAKjC;AAED;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,qBAAqB,GACjC,iBAAiB,MAAM,EACvB,cAAc,MAAM,KAClB,YAMF,CAAC"}