@fuzdev/fuz_app 0.132.0 → 0.132.1

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 (46) hide show
  1. package/dist/actions/action_dispatcher.js +1 -0
  2. package/dist/actions/action_event_data.d.ts +2 -2
  3. package/dist/actions/action_event_types.d.ts +2 -2
  4. package/dist/actions/action_rpc.js +1 -0
  5. package/dist/actions/action_spec.d.ts +19 -19
  6. package/dist/actions/perform_action.js +1 -0
  7. package/dist/actions/register_action_ws.js +1 -0
  8. package/dist/auth/account_routes.js +1 -1
  9. package/dist/auth/audit_log_schema.d.ts +5 -5
  10. package/dist/auth/cell_action_specs.d.ts +3 -3
  11. package/dist/auth/credential_type_schema.d.ts +1 -1
  12. package/dist/cli/daemon.js +1 -0
  13. package/dist/cli/logger.js +1 -0
  14. package/dist/env/load.js +1 -0
  15. package/dist/hono_context.d.ts +1 -1
  16. package/dist/http/CLAUDE.md +2 -2
  17. package/dist/http/auth_shape.d.ts +6 -6
  18. package/dist/http/error_schemas.d.ts +7 -2
  19. package/dist/http/error_schemas.d.ts.map +1 -1
  20. package/dist/http/error_schemas.js +5 -1
  21. package/dist/http/surface.js +1 -0
  22. package/dist/realtime/sse.js +1 -0
  23. package/dist/server/app_server.js +1 -0
  24. package/dist/testing/CLAUDE.md +1 -0
  25. package/dist/testing/admin_integration.d.ts.map +1 -1
  26. package/dist/testing/admin_integration.js +2 -1
  27. package/dist/testing/adversarial_404.d.ts.map +1 -1
  28. package/dist/testing/adversarial_404.js +5 -3
  29. package/dist/testing/adversarial_input.d.ts.map +1 -1
  30. package/dist/testing/adversarial_input.js +9 -3
  31. package/dist/testing/attack_surface.js +4 -4
  32. package/dist/testing/cross_backend/action_manifest.d.ts +10 -10
  33. package/dist/testing/cross_backend/standard.d.ts +6 -0
  34. package/dist/testing/cross_backend/standard.d.ts.map +1 -1
  35. package/dist/testing/cross_backend/standard.js +2 -1
  36. package/dist/testing/cross_backend/testing_reset_actions.d.ts +5 -5
  37. package/dist/testing/data_exposure.d.ts.map +1 -1
  38. package/dist/testing/data_exposure.js +11 -8
  39. package/dist/testing/round_trip.d.ts.map +1 -1
  40. package/dist/testing/round_trip.js +3 -9
  41. package/dist/testing/rpc_helpers.js +1 -0
  42. package/dist/testing/schema_generators.d.ts +12 -0
  43. package/dist/testing/schema_generators.d.ts.map +1 -1
  44. package/dist/testing/schema_generators.js +10 -0
  45. package/dist/testing/transports/ws_client.js +1 -0
  46. package/package.json +2 -2
@@ -6,6 +6,7 @@
6
6
  *
7
7
  * @module
8
8
  */
9
+ import { JsonrpcMessageFromClientToServer, JsonrpcMessageFromServerToClient, JsonrpcNotification, JsonrpcRequest, JsonrpcResponseOrError, JsonrpcErrorResponse } from '../http/jsonrpc.js';
9
10
  import { create_jsonrpc_error_response, create_jsonrpc_error_response_from_thrown, to_jsonrpc_message_id, is_jsonrpc_request, is_jsonrpc_notification } from '../http/jsonrpc_helpers.js';
10
11
  import { jsonrpc_error_messages } from '../http/jsonrpc_errors.js';
11
12
  import { to_input_params } from '../http/schema_helpers.js';
@@ -28,11 +28,11 @@ export declare const ActionEventData: z.ZodObject<{
28
28
  execute: "execute";
29
29
  }>;
30
30
  step: z.ZodEnum<{
31
- failed: "failed";
32
- parsed: "parsed";
33
31
  initial: "initial";
32
+ parsed: "parsed";
34
33
  handling: "handling";
35
34
  handled: "handled";
35
+ failed: "failed";
36
36
  }>;
37
37
  method: z.ZodString;
38
38
  executor: z.ZodEnum<{
@@ -12,11 +12,11 @@ export declare const ActionExecutor: z.ZodEnum<{
12
12
  }>;
13
13
  export type ActionExecutor = z.infer<typeof ActionExecutor>;
14
14
  export declare const ActionEventStep: z.ZodEnum<{
15
- failed: "failed";
16
- parsed: "parsed";
17
15
  initial: "initial";
16
+ parsed: "parsed";
18
17
  handling: "handling";
19
18
  handled: "handled";
19
+ failed: "failed";
20
20
  }>;
21
21
  export type ActionEventStep = z.infer<typeof ActionEventStep>;
22
22
  export declare const action_event_step_transitions: Record<ActionEventStep, ReadonlyArray<ActionEventStep>>;
@@ -13,6 +13,7 @@
13
13
  */
14
14
  import { z } from 'zod';
15
15
  import { DEV } from 'esm-env';
16
+ import {} from '../http/route_spec.js';
16
17
  import { get_client_ip } from '../http/client_ip.js';
17
18
  import { get_request_context } from '../auth/request_context.js';
18
19
  import { ACCOUNT_ID_KEY, CREDENTIAL_TYPE_KEY, TOKEN_SCOPE_KEY, TEST_CONTEXT_PRESET_KEY } from '../hono_context.js';
@@ -51,14 +51,14 @@ export declare const ActionSpec: z.ZodObject<{
51
51
  */
52
52
  auth: z.ZodNullable<z.ZodObject<{
53
53
  account: z.ZodEnum<{
54
- required: "required";
55
- none: "none";
56
54
  optional: "optional";
55
+ none: "none";
56
+ required: "required";
57
57
  }>;
58
58
  actor: z.ZodEnum<{
59
- required: "required";
60
- none: "none";
61
59
  optional: "optional";
60
+ none: "none";
61
+ required: "required";
62
62
  }>;
63
63
  roles: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
64
64
  credential_types: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
@@ -108,9 +108,9 @@ export declare const ActionSpec: z.ZodObject<{
108
108
  * dispatchers don't read it.
109
109
  */
110
110
  rate_limit: z.ZodOptional<z.ZodEnum<{
111
- both: "both";
112
111
  account: "account";
113
112
  ip: "ip";
113
+ both: "both";
114
114
  }>>;
115
115
  }, z.core.$strict>;
116
116
  export type ActionSpec = z.infer<typeof ActionSpec>;
@@ -128,21 +128,21 @@ export declare const RequestResponseActionSpec: z.ZodObject<{
128
128
  streams: z.ZodOptional<z.ZodString>;
129
129
  error_reasons: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
130
130
  rate_limit: z.ZodOptional<z.ZodEnum<{
131
- both: "both";
132
131
  account: "account";
133
132
  ip: "ip";
133
+ both: "both";
134
134
  }>>;
135
135
  kind: z.ZodDefault<z.ZodLiteral<"request_response">>;
136
136
  auth: z.ZodObject<{
137
137
  account: z.ZodEnum<{
138
- required: "required";
139
- none: "none";
140
138
  optional: "optional";
139
+ none: "none";
140
+ required: "required";
141
141
  }>;
142
142
  actor: z.ZodEnum<{
143
- required: "required";
144
- none: "none";
145
143
  optional: "optional";
144
+ none: "none";
145
+ required: "required";
146
146
  }>;
147
147
  roles: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
148
148
  credential_types: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
@@ -163,9 +163,9 @@ export declare const RemoteNotificationActionSpec: z.ZodObject<{
163
163
  streams: z.ZodOptional<z.ZodString>;
164
164
  error_reasons: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
165
165
  rate_limit: z.ZodOptional<z.ZodEnum<{
166
- both: "both";
167
166
  account: "account";
168
167
  ip: "ip";
168
+ both: "both";
169
169
  }>>;
170
170
  kind: z.ZodDefault<z.ZodLiteral<"remote_notification">>;
171
171
  auth: z.ZodDefault<z.ZodNull>;
@@ -193,9 +193,9 @@ export declare const LocalCallActionSpec: z.ZodObject<{
193
193
  streams: z.ZodOptional<z.ZodString>;
194
194
  error_reasons: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
195
195
  rate_limit: z.ZodOptional<z.ZodEnum<{
196
- both: "both";
197
196
  account: "account";
198
197
  ip: "ip";
198
+ both: "both";
199
199
  }>>;
200
200
  kind: z.ZodDefault<z.ZodLiteral<"local_call">>;
201
201
  auth: z.ZodDefault<z.ZodNull>;
@@ -215,21 +215,21 @@ export declare const ActionSpecUnion: z.ZodUnion<readonly [z.ZodObject<{
215
215
  streams: z.ZodOptional<z.ZodString>;
216
216
  error_reasons: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
217
217
  rate_limit: z.ZodOptional<z.ZodEnum<{
218
- both: "both";
219
218
  account: "account";
220
219
  ip: "ip";
220
+ both: "both";
221
221
  }>>;
222
222
  kind: z.ZodDefault<z.ZodLiteral<"request_response">>;
223
223
  auth: z.ZodObject<{
224
224
  account: z.ZodEnum<{
225
- required: "required";
226
- none: "none";
227
225
  optional: "optional";
226
+ none: "none";
227
+ required: "required";
228
228
  }>;
229
229
  actor: z.ZodEnum<{
230
- required: "required";
231
- none: "none";
232
230
  optional: "optional";
231
+ none: "none";
232
+ required: "required";
233
233
  }>;
234
234
  roles: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
235
235
  credential_types: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
@@ -248,9 +248,9 @@ export declare const ActionSpecUnion: z.ZodUnion<readonly [z.ZodObject<{
248
248
  streams: z.ZodOptional<z.ZodString>;
249
249
  error_reasons: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
250
250
  rate_limit: z.ZodOptional<z.ZodEnum<{
251
- both: "both";
252
251
  account: "account";
253
252
  ip: "ip";
253
+ both: "both";
254
254
  }>>;
255
255
  kind: z.ZodDefault<z.ZodLiteral<"remote_notification">>;
256
256
  auth: z.ZodDefault<z.ZodNull>;
@@ -272,9 +272,9 @@ export declare const ActionSpecUnion: z.ZodUnion<readonly [z.ZodObject<{
272
272
  streams: z.ZodOptional<z.ZodString>;
273
273
  error_reasons: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
274
274
  rate_limit: z.ZodOptional<z.ZodEnum<{
275
- both: "both";
276
275
  account: "account";
277
276
  ip: "ip";
277
+ both: "both";
278
278
  }>>;
279
279
  kind: z.ZodDefault<z.ZodLiteral<"local_call">>;
280
280
  auth: z.ZodDefault<z.ZodNull>;
@@ -56,6 +56,7 @@
56
56
  */
57
57
  import { DEV } from 'esm-env';
58
58
  import { apply_authorization_phase, has_any_scoped_role } from '../auth/request_context.js';
59
+ import {} from '../hono_context.js';
59
60
  import { to_input_params } from '../http/schema_helpers.js';
60
61
  import { dispatch_with_post_commit_rollback } from '../http/pending_effects.js';
61
62
  import { JSONRPC_VERSION } from '../http/jsonrpc.js';
@@ -104,6 +104,7 @@ import { JsonrpcRequest } from '../http/jsonrpc.js';
104
104
  import { dev_only, jsonrpc_error_messages } from '../http/jsonrpc_errors.js';
105
105
  import { create_jsonrpc_error_response, create_jsonrpc_notification, to_jsonrpc_envelope_id, to_jsonrpc_message_id, to_jsonrpc_params, is_jsonrpc_object, is_jsonrpc_request, is_jsonrpc_request_id } from '../http/jsonrpc_helpers.js';
106
106
  import { TOKEN_SCOPE_KEY, TEST_CONTEXT_PRESET_KEY } from '../hono_context.js';
107
+ import {} from './action_types.js';
107
108
  import { compile_action_registry } from './compile_action_registry.js';
108
109
  import { cancel_action_spec, CancelNotificationParams } from './cancel.js';
109
110
  import { DEFAULT_WS_MAX_MESSAGE_BYTES, WS_CLOSE_INTERNAL_ERROR, WS_CLOSE_MESSAGE_TOO_BIG, WS_CLOSE_POLICY_VIOLATION, WS_CLOSE_SERVER_HEARTBEAT_TIMEOUT, WS_CLOSE_SESSION_REVOKED, WS_CLOSE_SESSION_REVOKED_REASON, utf8_length, utf8_length_over } from './transports.js';
@@ -22,7 +22,7 @@
22
22
  * @module
23
23
  */
24
24
  import { clear_session_cookie, create_session_and_set_cookie } from './session_middleware.js';
25
- import { to_session_account } from './account_schema.js';
25
+ import { RoleGrantSummaryJson, to_session_account } from './account_schema.js';
26
26
  import { account_status_route_shape, create_account_route_shapes, DEFAULT_MAX_SESSIONS } from './account_route_schema.js';
27
27
  import { hash_session_token, query_session_revoke_all_for_account, query_session_revoke_by_hash_unscoped } from './session_queries.js';
28
28
  import { query_account_by_username_or_email, query_update_account_password } from './account_queries.js';
@@ -141,16 +141,16 @@ export declare const audit_metadata_schemas: Readonly<{
141
141
  concurrent_change: "concurrent_change";
142
142
  }>>;
143
143
  credential_type: z.ZodOptional<z.ZodEnum<{
144
- session: "session";
145
144
  daemon_token: "daemon_token";
145
+ session: "session";
146
146
  api_token: "api_token";
147
147
  }>>;
148
148
  }, z.core.$loose>>;
149
149
  session_revoke: z.ZodObject<{
150
150
  session_id: z.core.$ZodBranded<z.ZodString, "SessionId", "out">;
151
151
  credential_type: z.ZodOptional<z.ZodEnum<{
152
- session: "session";
153
152
  daemon_token: "daemon_token";
153
+ session: "session";
154
154
  api_token: "api_token";
155
155
  }>>;
156
156
  }, z.core.$loose>;
@@ -159,8 +159,8 @@ export declare const audit_metadata_schemas: Readonly<{
159
159
  reason: z.ZodOptional<z.ZodString>;
160
160
  attempted_account_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
161
161
  credential_type: z.ZodOptional<z.ZodEnum<{
162
- session: "session";
163
162
  daemon_token: "daemon_token";
163
+ session: "session";
164
164
  api_token: "api_token";
165
165
  }>>;
166
166
  }, z.core.$loose>;
@@ -168,16 +168,16 @@ export declare const audit_metadata_schemas: Readonly<{
168
168
  token_id: z.ZodString;
169
169
  name: z.ZodString;
170
170
  credential_type: z.ZodOptional<z.ZodEnum<{
171
- session: "session";
172
171
  daemon_token: "daemon_token";
172
+ session: "session";
173
173
  api_token: "api_token";
174
174
  }>>;
175
175
  }, z.core.$loose>;
176
176
  token_revoke: z.ZodObject<{
177
177
  token_id: z.ZodString;
178
178
  credential_type: z.ZodOptional<z.ZodEnum<{
179
- session: "session";
180
179
  daemon_token: "daemon_token";
180
+ session: "session";
181
181
  api_token: "api_token";
182
182
  }>>;
183
183
  }, z.core.$loose>;
@@ -385,8 +385,8 @@ export declare const CellListInput: z.ZodDefault<z.ZodObject<{
385
385
  updated_at: "updated_at";
386
386
  }>>;
387
387
  order_direction: z.ZodOptional<z.ZodEnum<{
388
- desc: "desc";
389
388
  asc: "asc";
389
+ desc: "desc";
390
390
  }>>;
391
391
  limit: z.ZodOptional<z.ZodNumber>;
392
392
  offset: z.ZodOptional<z.ZodNumber>;
@@ -737,8 +737,8 @@ export declare const cell_list_action_spec: {
737
737
  updated_at: "updated_at";
738
738
  }>>;
739
739
  order_direction: z.ZodOptional<z.ZodEnum<{
740
- desc: "desc";
741
740
  asc: "asc";
741
+ desc: "desc";
742
742
  }>>;
743
743
  limit: z.ZodOptional<z.ZodNumber>;
744
744
  offset: z.ZodOptional<z.ZodNumber>;
@@ -1090,8 +1090,8 @@ export declare const all_cell_action_specs: readonly [{
1090
1090
  updated_at: "updated_at";
1091
1091
  }>>;
1092
1092
  order_direction: z.ZodOptional<z.ZodEnum<{
1093
- desc: "desc";
1094
1093
  asc: "asc";
1094
+ desc: "desc";
1095
1095
  }>>;
1096
1096
  limit: z.ZodOptional<z.ZodNumber>;
1097
1097
  offset: z.ZodOptional<z.ZodNumber>;
@@ -45,8 +45,8 @@ export declare const CREDENTIAL_TYPE_DAEMON_TOKEN = "daemon_token";
45
45
  export declare const BUILTIN_CREDENTIAL_TYPES: readonly ["session", "api_token", "daemon_token"];
46
46
  /** Zod enum for builtin credential types only. */
47
47
  export declare const BuiltinCredentialType: z.ZodEnum<{
48
- session: "session";
49
48
  daemon_token: "daemon_token";
49
+ session: "session";
50
50
  api_token: "api_token";
51
51
  }>;
52
52
  export type BuiltinCredentialType = z.infer<typeof BuiltinCredentialType>;
@@ -8,6 +8,7 @@
8
8
  * @module
9
9
  */
10
10
  import { z } from 'zod';
11
+ import {} from '../runtime/deps.js';
11
12
  import { write_file_atomic } from '../runtime/fs.js';
12
13
  import { get_app_dir } from './config.js';
13
14
  /**
@@ -11,6 +11,7 @@
11
11
  *
12
12
  * @module
13
13
  */
14
+ import { Logger } from '@fuzdev/fuz_util/log.ts';
14
15
  /**
15
16
  * Creates a CLI logger wrapping a Logger with semantic output methods.
16
17
  *
package/dist/env/load.js CHANGED
@@ -6,6 +6,7 @@
6
6
  *
7
7
  * @module
8
8
  */
9
+ import { z } from 'zod';
9
10
  /**
10
11
  * Error thrown when environment validation fails.
11
12
  *
@@ -24,8 +24,8 @@ import type { RequestContext } from './auth/request_context.js';
24
24
  export declare const CREDENTIAL_TYPES: readonly ["session", "api_token", "daemon_token"];
25
25
  /** Credential type — how a request was authenticated. */
26
26
  export declare const CredentialType: z.ZodEnum<{
27
- session: "session";
28
27
  daemon_token: "daemon_token";
28
+ session: "session";
29
29
  api_token: "api_token";
30
30
  }>;
31
31
  export type CredentialType = z.infer<typeof CredentialType>;
@@ -151,7 +151,7 @@ WS); see ../../../docs/architecture.md §DEV-only Output Validation.
151
151
  `http/error_schemas.ts` is the **declarative** error surface:
152
152
 
153
153
  - `ERROR_*` `snake_case` string constants — single source of truth; use `.literal(ERROR_*)` in Zod schemas and inline checks in handlers
154
- - `ApiError`, `ValidationError`, `PermissionError`, `CredentialTypeRequiredError`, `RateLimitError`, `PayloadTooLargeError`, `ForeignKeyError` — standard shapes
154
+ - `ApiError`, `ValidationError`, `PermissionError`, `CredentialTypeRequiredError`, `RateLimitError`, `PayloadTooLargeError`, `UnsupportedContentTypeError`, `ForeignKeyError` — standard shapes
155
155
  - `RouteErrorSchemas = Partial<Record<number, z.ZodType>>`
156
156
  - `RateLimitKey = 'ip' | 'account' | 'both'`
157
157
 
@@ -173,7 +173,7 @@ merges three layers, later overrides earlier at the same status code:
173
173
  - `auth.roles?.length` → 403 `PermissionError` (carries `required_roles`)
174
174
  - `auth.credential_types?.length` → 403 `CredentialTypeRequiredError` (carries `required_credential_types`; both gates set yields `z.union([PermissionError, CredentialTypeRequiredError])`)
175
175
  - `rate_limit` → 429 `RateLimitError`
176
- - `checks_content_type` (every `POST`) → 415 `ApiError` (`unsupported_content_type`)
176
+ - `checks_content_type` (every `POST`) → 415 `UnsupportedContentTypeError`
177
177
  - `auth.actor !== 'none'` → widens 400 to a union with `ActorRequiredError` / `ActorNotOnAccountError` and adds 500 union of `NoActorsOnAccountError` / `AccountVanishedError`. Mirrors what the dispatcher's authorization phase actually emits on routes whose input declares `acting?: ActingActor` (per registry-time invariant 2) — so DEV-mode error-schema validation doesn't reject the auth phase's body.
178
178
  2. **Middleware** — from `MiddlewareSpec.errors` that apply to the route's path (via `middleware_applies`)
179
179
  3. **Explicit** — `RouteSpec.errors` — always wins
@@ -91,9 +91,9 @@ export declare const parse_acting: (value: unknown) => string | undefined;
91
91
  * without an actor binding).
92
92
  */
93
93
  export declare const AuthAxisState: z.ZodEnum<{
94
- required: "required";
95
- none: "none";
96
94
  optional: "optional";
95
+ none: "none";
96
+ required: "required";
97
97
  }>;
98
98
  export type AuthAxisState = z.infer<typeof AuthAxisState>;
99
99
  /**
@@ -123,14 +123,14 @@ export type AuthAxisState = z.infer<typeof AuthAxisState>;
123
123
  */
124
124
  export declare const RouteAuth: z.ZodObject<{
125
125
  account: z.ZodEnum<{
126
- required: "required";
127
- none: "none";
128
126
  optional: "optional";
127
+ none: "none";
128
+ required: "required";
129
129
  }>;
130
130
  actor: z.ZodEnum<{
131
- required: "required";
132
- none: "none";
133
131
  optional: "optional";
132
+ none: "none";
133
+ required: "required";
134
134
  }>;
135
135
  roles: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
136
136
  credential_types: z.ZodOptional<z.ZodReadonly<z.ZodArray<z.ZodString>>>;
@@ -236,6 +236,11 @@ export declare const PayloadTooLargeError: z.ZodObject<{
236
236
  error: z.ZodLiteral<"payload_too_large">;
237
237
  }, z.core.$loose>;
238
238
  export type PayloadTooLargeError = z.infer<typeof PayloadTooLargeError>;
239
+ /** Unsupported content type error — returned when a `POST` route refuses the request's `Content-Type`. */
240
+ export declare const UnsupportedContentTypeError: z.ZodObject<{
241
+ error: z.ZodLiteral<"unsupported_content_type">;
242
+ }, z.core.$loose>;
243
+ export type UnsupportedContentTypeError = z.infer<typeof UnsupportedContentTypeError>;
239
244
  /** Foreign key violation error — returned when a delete is blocked by references. */
240
245
  export declare const ForeignKeyError: z.ZodObject<{
241
246
  error: z.ZodLiteral<"foreign_key_violation">;
@@ -296,9 +301,9 @@ export type RouteErrorSchemas = Partial<Record<number, z.ZodType>>;
296
301
  * - `'both'` — both keys.
297
302
  */
298
303
  export declare const RateLimitKey: z.ZodEnum<{
299
- both: "both";
300
304
  account: "account";
301
305
  ip: "ip";
306
+ both: "both";
302
307
  }>;
303
308
  export type RateLimitKey = z.infer<typeof RateLimitKey>;
304
309
  /**
@@ -326,7 +331,7 @@ export type RateLimitKey = z.infer<typeof RateLimitKey>;
326
331
  * of `NoActorsOnAccountError` / `AccountVanishedError`. The dispatcher's
327
332
  * authorization phase emits these whenever it tries to resolve an actor.
328
333
  * - **rate_limit**: 429 (`RateLimitError` with `retry_after`).
329
- * - **checks_content_type**: 415 (`ApiError`, `unsupported_content_type`) —
334
+ * - **checks_content_type**: 415 (`UnsupportedContentTypeError`) —
330
335
  * every `POST` route (see `is_post_content_type_refused` in
331
336
  * `http/simple_request.ts`).
332
337
  */
@@ -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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"}
@@ -239,6 +239,10 @@ export const RateLimitError = z.looseObject({
239
239
  export const PayloadTooLargeError = z.looseObject({
240
240
  error: z.literal(ERROR_PAYLOAD_TOO_LARGE)
241
241
  });
242
+ /** Unsupported content type error — returned when a `POST` route refuses the request's `Content-Type`. */
243
+ export const UnsupportedContentTypeError = z.looseObject({
244
+ error: z.literal(ERROR_UNSUPPORTED_CONTENT_TYPE)
245
+ });
242
246
  /** Foreign key violation error — returned when a delete is blocked by references. */
243
247
  export const ForeignKeyError = z.looseObject({
244
248
  error: z.literal(ERROR_FOREIGN_KEY_VIOLATION)
@@ -327,7 +331,7 @@ export const derive_error_schemas = ({ auth, has_input = false, has_params = fal
327
331
  errors[429] = RateLimitError;
328
332
  }
329
333
  if (checks_content_type) {
330
- errors[415] = ApiError;
334
+ errors[415] = UnsupportedContentTypeError;
331
335
  }
332
336
  return errors;
333
337
  };
@@ -6,6 +6,7 @@
6
6
  *
7
7
  * @module
8
8
  */
9
+ import { z } from 'zod';
9
10
  import { schema_to_surface, middleware_applies, merge_error_schemas, is_null_schema, is_strict_object_schema } from './schema_helpers.js';
10
11
  // --- Surface generation ---
11
12
  /**
@@ -7,6 +7,7 @@
7
7
  * @module
8
8
  */
9
9
  import { streamSSE } from 'hono/streaming';
10
+ import { z } from 'zod';
10
11
  import { DEV } from 'esm-env';
11
12
  import { SSE_CONNECTED_COMMENT } from './sse_constants.js';
12
13
  const is_node_connection_stream = (value) => {
@@ -10,6 +10,7 @@
10
10
  import { Hono } from 'hono';
11
11
  import { logger } from 'hono/logger';
12
12
  import { bodyLimit } from 'hono/body-limit';
13
+ import { z } from 'zod';
13
14
  import { session_cookie_options } from '../auth/session_cookie.js';
14
15
  import { create_audit_log_sse, create_sse_connection_closer, audit_log_event_specs } from '../realtime/sse_auth_guard.js';
15
16
  import { BaseServerEnv } from './env.js';
@@ -383,6 +383,7 @@ Walks Zod schemas to generate valid values for adversarial/round-trip tests.
383
383
  - `detect_format(field_schema)` — reads `format` / `pattern` from the JSON Schema representation.
384
384
  - `generate_valid_value(field, field_schema)` — base-type switch producing a valid sample (UUIDs → nil UUID, strings → `'xxxxxxxxxx'`, numbers → `1`, objects → recurse, enums → first entry, etc.). For branded-string refinements, walks a fallback chain synthesized from the `pattern` string the JSON Schema representation exposes: fixed-length hex (`^[0-9a-f]{N}$` — blake3 / sha256 / md5 digests; `0`.repeat(N)), prefix-lengthed slug (`^<prefix>_[A-Za-z0-9_-]{N}$` — `ApiTokenId`-style ids; `<prefix>_` + `x`.repeat(N)), absolute path prefix, URL prefix. First candidate that `safeParse` accepts is used.
385
385
  - `resolve_valid_path(path, params_schema?)` — swaps `:param` for a value the params schema accepts. Prefers `test_<name>` wherever the field schema admits it (the param name keeps failure messages readable); otherwise a UUID param takes the nil UUID and anything else is synthesized from the schema, percent-encoded. A synthesized value containing `/` is refused (it would route elsewhere) and falls back to `test_<name>`.
386
+ - `to_route_content_type(route)` — the `Content-Type` a well-formed request to the route sends: `application/json`, or `application/octet-stream` for a `raw_body` route. Every `POST` route refuses anything else with 415 before its other gates, so every probe in the harnesses (auth, params and query fuzz, 404, data exposure, round trip) sends it, body or not.
386
387
  - `generate_valid_body(input_schema) => Record<string, unknown> | undefined` — builds a body satisfying the input schema. Throws with Zod `issues` if the generated body fails validation — surfaces broken generation logic with a descriptive error rather than a confusing 400 downstream.
387
388
 
388
389
  ### `integration_helpers.ts` — route lookup + body checks
@@ -1 +1 @@
1
- {"version":3,"file":"admin_integration.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/admin_integration.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAgC7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAc,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAW3E,OAAO,EAKN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAmB1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,0BAA0B,CAAC;AAYvE;;GAEG;AACH,MAAM,WAAW,mCAAmC;IACnD;;;;OAIG;IACH,UAAU,EAAE,SAAS,CAAC;IACtB;;;;OAIG;IACH,cAAc,EAAE,cAAc,CAAC;IAC/B,uFAAuF;IACvF,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,4GAA4G;IAC5G,KAAK,EAAE,gBAAgB,CAAC;IACxB;;;OAGG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAiBD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yCAAyC,GACrD,SAAS,mCAAmC,KAC1C,IAm5BF,CAAC"}
1
+ {"version":3,"file":"admin_integration.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/admin_integration.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAgC7B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAChE,OAAO,EAAc,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAW3E,OAAO,EAKN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAmB1B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,0BAA0B,CAAC;AAavE;;GAEG;AACH,MAAM,WAAW,mCAAmC;IACnD;;;;OAIG;IACH,UAAU,EAAE,SAAS,CAAC;IACtB;;;;OAIG;IACH,cAAc,EAAE,cAAc,CAAC;IAC/B,uFAAuF;IACvF,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,4GAA4G;IAC5G,KAAK,EAAE,gBAAgB,CAAC;IACxB;;;OAGG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC;;;;;OAKG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACtB;AAiBD;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yCAAyC,GACrD,SAAS,mCAAmC,KAC1C,IAm5BF,CAAC"}
@@ -36,6 +36,7 @@ import { rpc_call_for_spec, require_rpc_endpoint_path, resolve_rpc_endpoints_for
36
36
  import { role_grant_offer_create_action_spec, role_grant_revoke_action_spec } from '../auth/role_grant_offer_action_specs.js';
37
37
  import { admin_account_list_action_spec, ADMIN_ACCOUNT_LIST_LIMIT_MAX, admin_session_list_action_spec, admin_session_revoke_all_action_spec, admin_token_revoke_all_action_spec, audit_log_list_action_spec, audit_log_role_grant_history_action_spec } from '../auth/admin_action_specs.js';
38
38
  import { account_token_create_action_spec, account_verify_action_spec } from '../auth/account_action_specs.js';
39
+ import { to_route_content_type } from './schema_generators.js';
39
40
  /**
40
41
  * How long a failure-audit read waits for the pool-routed row to land.
41
42
  */
@@ -805,7 +806,7 @@ export const describe_standard_admin_integration_tests = (options) => {
805
806
  for (const route of admin_routes) {
806
807
  const res = await fixture.transport(route.path, {
807
808
  method: route.method,
808
- headers: { host: 'localhost' }
809
+ headers: { host: 'localhost', 'content-type': to_route_content_type(route) }
809
810
  });
810
811
  if (res.status === 401 || res.status === 403) {
811
812
  error_collector.record(route_specs, route.method, route.path, res.status);
@@ -1 +1 @@
1
- {"version":3,"file":"adversarial_404.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/adversarial_404.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAoB7B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAyBlE;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,GAAI,SAAS,sBAAsB,KAAG,IA6E1E,CAAC"}
1
+ {"version":3,"file":"adversarial_404.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/adversarial_404.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAoB7B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AA6BlE;;;;;;;;GAQG;AACH,eAAO,MAAM,wBAAwB,GAAI,SAAS,sBAAsB,KAAG,IA+E1E,CAAC"}
@@ -14,7 +14,7 @@ import { test, assert, describe } from 'vitest';
14
14
  import { z } from 'zod';
15
15
  import { is_null_schema } from '../http/schema_helpers.js';
16
16
  import { create_auth_test_apps, create_route_skip_filter, select_auth_app } from './auth_apps.js';
17
- import { resolve_valid_path, generate_valid_body } from './schema_generators.js';
17
+ import { resolve_valid_path, generate_valid_body, to_route_content_type } from './schema_generators.js';
18
18
  /**
19
19
  * Extract the error code from a 404 Zod schema for use in the stub handler.
20
20
  *
@@ -98,12 +98,14 @@ export const describe_adversarial_404 = (options) => {
98
98
  const route = surface.routes.find((r) => `${r.method} ${r.path}` === key);
99
99
  const app = select_auth_app(apps, route.auth);
100
100
  const url = resolve_valid_path(route.path, spec.params);
101
- const request_init = { method: route.method };
101
+ const request_init = {
102
+ method: route.method,
103
+ headers: { 'content-type': to_route_content_type(spec) }
104
+ };
102
105
  // Send valid body for routes with input
103
106
  if (!is_null_schema(spec.input)) {
104
107
  const body = generate_valid_body(spec.input);
105
108
  if (body !== undefined) {
106
- request_init.headers = { 'Content-Type': 'application/json' };
107
109
  request_init.body = JSON.stringify(body);
108
110
  }
109
111
  }
@@ -1 +1 @@
1
- {"version":3,"file":"adversarial_input.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/adversarial_input.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAiB7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB,OAAO,EAEN,0BAA0B,EAC1B,uBAAuB,EAGvB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AA8ClE,UAAU,aAAa;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,cAAc,EAAE,OAAO,0BAA0B,GAAG,OAAO,uBAAuB,CAAC;CACnF;AAED,UAAU,cAAc;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,UAAU,aAAa;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAID;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yBAAyB,GAAI,cAAc,CAAC,CAAC,OAAO,KAAG,KAAK,CAAC,aAAa,CAsMtF,CAAC;AAIF;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,GAAI,eAAe,CAAC,CAAC,SAAS,KAAG,KAAK,CAAC,cAAc,CA+B3F,CAAC;AAIF;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GAAI,cAAc,CAAC,CAAC,SAAS,KAAG,KAAK,CAAC,aAAa,CA4CxF,CAAC;AAqBF;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,GAAI,SAAS,sBAAsB,KAAG,IAmN5E,CAAC"}
1
+ {"version":3,"file":"adversarial_input.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/adversarial_input.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAiB7B,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAUxB,OAAO,EAEN,0BAA0B,EAC1B,uBAAuB,EAGvB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,qBAAqB,CAAC;AAmDlE,UAAU,aAAa;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,CAAC;IACd,cAAc,EAAE,OAAO,0BAA0B,GAAG,OAAO,uBAAuB,CAAC;CACnF;AAED,UAAU,cAAc;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC/B;AAED,UAAU,aAAa;IACtB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAID;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yBAAyB,GAAI,cAAc,CAAC,CAAC,OAAO,KAAG,KAAK,CAAC,aAAa,CAsMtF,CAAC;AAIF;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,GAAI,eAAe,CAAC,CAAC,SAAS,KAAG,KAAK,CAAC,cAAc,CA+B3F,CAAC;AAIF;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,GAAI,cAAc,CAAC,CAAC,SAAS,KAAG,KAAK,CAAC,aAAa,CA4CxF,CAAC;AAqBF;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,GAAI,SAAS,sBAAsB,KAAG,IAyN5E,CAAC"}
@@ -19,7 +19,7 @@ import { is_null_schema } from '../http/schema_helpers.js';
19
19
  import { filter_routes_with_input, filter_routes_with_params, filter_routes_with_query } from '../http/surface_query.js';
20
20
  import { ValidationError, ERROR_INVALID_REQUEST_BODY, ERROR_INVALID_JSON_BODY, ERROR_INVALID_ROUTE_PARAMS, ERROR_INVALID_QUERY_PARAMS } from '../http/error_schemas.js';
21
21
  import { create_auth_test_apps, create_route_skip_filter, select_auth_app } from './auth_apps.js';
22
- import { detect_format, generate_valid_value, resolve_valid_path } from './schema_generators.js';
22
+ import { detect_format, generate_valid_value, resolve_valid_path, to_route_content_type } from './schema_generators.js';
23
23
  // --- Payload generation ---
24
24
  /** One wrong-type value per base type — one representative is sufficient. */
25
25
  const wrong_type_for = (base_type) => {
@@ -466,7 +466,10 @@ export const describe_adversarial_input = (options) => {
466
466
  for (const tc of test_cases) {
467
467
  test(tc.label, async () => {
468
468
  const url = build_fuzz_url(route.path, tc.params);
469
- const res = await app.request(url, { method: route.method });
469
+ const res = await app.request(url, {
470
+ method: route.method,
471
+ headers: { 'content-type': to_route_content_type(route) }
472
+ });
470
473
  assert.strictEqual(res.status, 400, `Expected 400 for ${key} [${tc.label}], got ${res.status}`);
471
474
  const body = await res.json();
472
475
  assert.strictEqual(body.error, ERROR_INVALID_ROUTE_PARAMS, `Expected ${ERROR_INVALID_ROUTE_PARAMS} for ${key} [${tc.label}], got: ${body.error}`);
@@ -504,7 +507,10 @@ export const describe_adversarial_input = (options) => {
504
507
  for (const tc of test_cases) {
505
508
  test(tc.label, async () => {
506
509
  const url = build_query_url(base_url, tc.query);
507
- const res = await app.request(url, { method: route.method });
510
+ const res = await app.request(url, {
511
+ method: route.method,
512
+ headers: { 'content-type': to_route_content_type(route) }
513
+ });
508
514
  assert.strictEqual(res.status, 400, `Expected 400 for ${key} [${tc.label}], got ${res.status}`);
509
515
  const body = await res.json();
510
516
  assert.strictEqual(body.error, ERROR_INVALID_QUERY_PARAMS, `Expected ${ERROR_INVALID_QUERY_PARAMS} for ${key} [${tc.label}], got: ${body.error}`);
@@ -19,7 +19,7 @@ import { assert_surface_invariants, assert_rpc_ws_surface_invariants, assert_sur
19
19
  import { describe_adversarial_input } from './adversarial_input.js';
20
20
  import { describe_adversarial_404 } from './adversarial_404.js';
21
21
  import { create_auth_test_apps, create_route_skip_filter, select_auth_app } from './auth_apps.js';
22
- import { resolve_valid_path } from './schema_generators.js';
22
+ import { resolve_valid_path, to_route_content_type } from './schema_generators.js';
23
23
  import { assert_surface_matches_snapshot, assert_surface_deterministic, assert_only_expected_public_routes, assert_full_middleware_stack, assert_error_schema_valid } from './assertions.js';
24
24
  import { merge_error_schemas } from '../http/schema_helpers.js';
25
25
  import { collect_middleware_errors } from '../http/surface.js';
@@ -91,11 +91,11 @@ export const describe_adversarial_auth = (options) => {
91
91
  const spec_lookup = build_route_spec_lookup(route_specs);
92
92
  const test_path = (route) => resolve_valid_path(route.path, spec_lookup.get(`${route.method} ${route.path}`)?.params);
93
93
  const apps = create_auth_test_apps(route_specs, roles);
94
- // every route's request carries the JSON content type a real client sends, so
95
- // the per-route content-type check (415) never answers ahead of the auth gate
94
+ // every probe carries the content type a real client sends, so the
95
+ // per-route content-type check (415) never answers ahead of the auth gate
96
96
  const probe_init = (route) => ({
97
97
  method: route.method,
98
- headers: { 'content-type': 'application/json' }
98
+ headers: { 'content-type': to_route_content_type(route) }
99
99
  });
100
100
  describe('adversarial HTTP auth enforcement', () => {
101
101
  describe('unauthenticated → 401', () => {
@@ -49,15 +49,15 @@ export declare const ActionManifestEntry: z.ZodObject<{
49
49
  side_effects: z.ZodBoolean;
50
50
  /** The `account` auth axis. */
51
51
  account: z.ZodEnum<{
52
- required: "required";
53
- none: "none";
54
52
  optional: "optional";
53
+ none: "none";
54
+ required: "required";
55
55
  }>;
56
56
  /** The `actor` auth axis. */
57
57
  actor: z.ZodEnum<{
58
- required: "required";
59
- none: "none";
60
58
  optional: "optional";
59
+ none: "none";
60
+ required: "required";
61
61
  }>;
62
62
  /** Required roles (any-of), sorted; `[]` when the action declares no role gate. */
63
63
  roles: z.ZodArray<z.ZodString>;
@@ -65,9 +65,9 @@ export declare const ActionManifestEntry: z.ZodObject<{
65
65
  credential_types: z.ZodArray<z.ZodString>;
66
66
  /** Per-action rate-limit class, or `null` when the action declares none. */
67
67
  rate_limit: z.ZodNullable<z.ZodEnum<{
68
- both: "both";
69
68
  account: "account";
70
69
  ip: "ip";
70
+ both: "both";
71
71
  }>>;
72
72
  }, z.core.$strict>;
73
73
  export type ActionManifestEntry = z.infer<typeof ActionManifestEntry>;
@@ -80,15 +80,15 @@ export declare const ActionManifest: z.ZodObject<{
80
80
  side_effects: z.ZodBoolean;
81
81
  /** The `account` auth axis. */
82
82
  account: z.ZodEnum<{
83
- required: "required";
84
- none: "none";
85
83
  optional: "optional";
84
+ none: "none";
85
+ required: "required";
86
86
  }>;
87
87
  /** The `actor` auth axis. */
88
88
  actor: z.ZodEnum<{
89
- required: "required";
90
- none: "none";
91
89
  optional: "optional";
90
+ none: "none";
91
+ required: "required";
92
92
  }>;
93
93
  /** Required roles (any-of), sorted; `[]` when the action declares no role gate. */
94
94
  roles: z.ZodArray<z.ZodString>;
@@ -96,9 +96,9 @@ export declare const ActionManifest: z.ZodObject<{
96
96
  credential_types: z.ZodArray<z.ZodString>;
97
97
  /** Per-action rate-limit class, or `null` when the action declares none. */
98
98
  rate_limit: z.ZodNullable<z.ZodEnum<{
99
- both: "both";
100
99
  account: "account";
101
100
  ip: "ip";
101
+ both: "both";
102
102
  }>>;
103
103
  }, z.core.$strict>>;
104
104
  }, z.core.$strict>;
@@ -98,6 +98,12 @@ export interface StandardCrossProcessTestOptions {
98
98
  * / `info/refs`) which stream git protocol bytes.
99
99
  */
100
100
  round_trip_skip_routes?: Array<string>;
101
+ /**
102
+ * Forwarded to `describe_data_exposure_tests` as `skip_routes`
103
+ * (`'METHOD /path'` keys), as the in-process bundle's consumers pass it
104
+ * directly.
105
+ */
106
+ data_exposure_skip_routes?: Array<string>;
101
107
  /**
102
108
  * Forwarded to `describe_rpc_round_trip_tests` as `success_fixtures`
103
109
  * (method name → async params factory). Drives a populated **success**
@@ -1 +1 @@
1
- {"version":3,"file":"standard.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/standard.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAM5D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzD;;;;;;GAMG;AACH,MAAM,WAAW,+BAA+B;IAC/C,2CAA2C;IAC3C,UAAU,EAAE,SAAS,CAAC;IACtB;;;OAGG;IACH,cAAc,EAAE,cAAc,CAAC;IAC/B;;;;OAIG;IACH,YAAY,EAAE,mBAAmB,CAAC;IAClC,uFAAuF;IACvF,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC;;;;;OAKG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC;;;OAGG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;;OAMG;IACH,sBAAsB,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACvC;;;;;;;OAOG;IACH,oBAAoB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAC/F;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,GAAG,CAC1B,MAAM,EACN,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CACnF,CAAC;CACF;AAED;;;;GAIG;AACH,eAAO,MAAM,qCAAqC,GACjD,SAAS,+BAA+B,KACtC,IAoCF,CAAC"}
1
+ {"version":3,"file":"standard.d.ts","sourceRoot":"../src/lib/","sources":["../../../src/lib/testing/cross_backend/standard.ts"],"names":[],"mappings":"AAAA,OAAO,sBAAsB,CAAC;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,8BAA8B,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAC;AAClE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAM5D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AACjE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAC7D,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEzD;;;;;;GAMG;AACH,MAAM,WAAW,+BAA+B;IAC/C,2CAA2C;IAC3C,UAAU,EAAE,SAAS,CAAC;IACtB;;;OAGG;IACH,cAAc,EAAE,cAAc,CAAC;IAC/B;;;;OAIG;IACH,YAAY,EAAE,mBAAmB,CAAC;IAClC,uFAAuF;IACvF,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC;;;;;OAKG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC;;;OAGG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;;;;;;OAMG;IACH,sBAAsB,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IACvC;;;;OAIG;IACH,yBAAyB,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC1C;;;;;;;OAOG;IACH,oBAAoB,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAC/F;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,GAAG,CAC1B,MAAM,EACN,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CACnF,CAAC;CACF;AAED;;;;GAIG;AACH,eAAO,MAAM,qCAAqC,GACjD,SAAS,+BAA+B,KACtC,IAqCF,CAAC"}
@@ -33,7 +33,8 @@ export const describe_standard_cross_process_tests = (options) => {
33
33
  });
34
34
  describe_data_exposure_tests({
35
35
  setup_test: options.setup_test,
36
- surface_source: options.surface_source
36
+ surface_source: options.surface_source,
37
+ skip_routes: options.data_exposure_skip_routes
37
38
  });
38
39
  if (options.roles) {
39
40
  describe_standard_admin_integration_tests({
@@ -427,21 +427,21 @@ export declare const testing_action_manifest_action_spec: {
427
427
  method: z.ZodString;
428
428
  side_effects: z.ZodBoolean;
429
429
  account: z.ZodEnum<{
430
- required: "required";
431
- none: "none";
432
430
  optional: "optional";
431
+ none: "none";
432
+ required: "required";
433
433
  }>;
434
434
  actor: z.ZodEnum<{
435
- required: "required";
436
- none: "none";
437
435
  optional: "optional";
436
+ none: "none";
437
+ required: "required";
438
438
  }>;
439
439
  roles: z.ZodArray<z.ZodString>;
440
440
  credential_types: z.ZodArray<z.ZodString>;
441
441
  rate_limit: z.ZodNullable<z.ZodEnum<{
442
- both: "both";
443
442
  account: "account";
444
443
  ip: "ip";
444
+ both: "both";
445
445
  }>>;
446
446
  }, z.core.$strict>>;
447
447
  }, z.core.$strict>;
@@ -1 +1 @@
1
- {"version":3,"file":"data_exposure.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/data_exposure.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAqB7B,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAYrE,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,0BAA0B,CAAC;AAIvE;;;;;GAKG;AACH,eAAO,MAAM,kCAAkC,GAAI,QAAQ,OAAO,KAAG,GAAG,CAAC,MAAM,CAuB9E,CAAC;AAIF;;GAEG;AACH,eAAO,MAAM,yCAAyC,GACrD,SAAS,UAAU,EACnB,mBAAkB,aAAa,CAAC,MAAM,CAA6B,KACjE,IAWF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wCAAwC,GACpD,SAAS,UAAU,EACnB,oBAAmB,aAAa,CAAC,MAAM,CAA8B,KACnE,IAgBF,CAAC;AAIF,kDAAkD;AAClD,MAAM,WAAW,uBAAuB;IACvC,kEAAkE;IAClE,UAAU,EAAE,SAAS,CAAC;IACtB;;;OAGG;IACH,cAAc,EAAE,cAAc,CAAC;IAC/B,2FAA2F;IAC3F,gBAAgB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACzC,iGAAiG;IACjG,iBAAiB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC1C,kDAAkD;IAClD,WAAW,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,4BAA4B,GAAI,SAAS,uBAAuB,KAAG,IA0L/E,CAAC"}
1
+ {"version":3,"file":"data_exposure.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/data_exposure.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAqB7B,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAgBrE,OAAO,KAAK,EAAE,SAAS,EAAe,MAAM,0BAA0B,CAAC;AAIvE;;;;;GAKG;AACH,eAAO,MAAM,kCAAkC,GAAI,QAAQ,OAAO,KAAG,GAAG,CAAC,MAAM,CAuB9E,CAAC;AAIF;;GAEG;AACH,eAAO,MAAM,yCAAyC,GACrD,SAAS,UAAU,EACnB,mBAAkB,aAAa,CAAC,MAAM,CAA6B,KACjE,IAWF,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,wCAAwC,GACpD,SAAS,UAAU,EACnB,oBAAmB,aAAa,CAAC,MAAM,CAA8B,KACnE,IAgBF,CAAC;AAIF,kDAAkD;AAClD,MAAM,WAAW,uBAAuB;IACvC,kEAAkE;IAClE,UAAU,EAAE,SAAS,CAAC;IACtB;;;OAGG;IACH,cAAc,EAAE,cAAc,CAAC;IAC/B,2FAA2F;IAC3F,gBAAgB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IACzC,iGAAiG;IACjG,iBAAiB,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAC1C,kDAAkD;IAClD,WAAW,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CAC5B;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,4BAA4B,GAAI,SAAS,uBAAuB,KAAG,IA4L/E,CAAC"}
@@ -17,7 +17,7 @@ import './assert_dev_env.js';
17
17
  */
18
18
  import { describe, test, beforeAll, assert } from 'vitest';
19
19
  import { ROLE_ADMIN } from '../auth/role_schema.js';
20
- import { resolve_valid_path, generate_valid_body } from './schema_generators.js';
20
+ import { resolve_valid_path, generate_valid_body, to_route_content_type } from './schema_generators.js';
21
21
  import { is_null_schema, is_strict_object_schema } from '../http/schema_helpers.js';
22
22
  import { is_keeper_auth, is_public_auth } from '../http/auth_shape.js';
23
23
  import { sensitive_field_blocklist, admin_only_field_blocklist, assert_no_sensitive_fields_in_json, pick_auth_headers } from './integration_helpers.js';
@@ -142,7 +142,11 @@ export const describe_data_exposure_tests = (options) => {
142
142
  const url = resolve_valid_path(spec.path, spec.params);
143
143
  const res = await fixture.transport(url, {
144
144
  method: spec.method,
145
- headers: { host: 'localhost', origin: 'http://localhost:5173' }
145
+ headers: {
146
+ host: 'localhost',
147
+ origin: 'http://localhost:5173',
148
+ 'content-type': to_route_content_type(spec)
149
+ }
146
150
  });
147
151
  if (res.headers.get('Content-Type')?.includes('text/event-stream')) {
148
152
  await res.body?.cancel();
@@ -167,10 +171,12 @@ export const describe_data_exposure_tests = (options) => {
167
171
  if (skip_set.has(route_key))
168
172
  continue;
169
173
  const url = resolve_valid_path(spec.path, spec.params);
170
- const headers = authed_account.create_session_headers();
171
174
  const res = await fixture.transport(url, {
172
175
  method: spec.method,
173
- headers
176
+ headers: {
177
+ ...authed_account.create_session_headers(),
178
+ 'content-type': to_route_content_type(spec)
179
+ }
174
180
  });
175
181
  assert.strictEqual(res.status, 403, `${route_key} should return 403 for non-admin user`);
176
182
  let error_body;
@@ -207,10 +213,7 @@ export const describe_data_exposure_tests = (options) => {
207
213
  const headers = pick_auth_headers(spec, fixture, authed_account, admin_account);
208
214
  const request_init = {
209
215
  method: spec.method,
210
- headers: {
211
- ...headers,
212
- ...(body ? { 'content-type': 'application/json' } : {})
213
- },
216
+ headers: { ...headers, 'content-type': to_route_content_type(spec) },
214
217
  ...(body ? { body: JSON.stringify(body) } : {})
215
218
  };
216
219
  const res = await fixture.transport(url, request_init);
@@ -1 +1 @@
1
- {"version":3,"file":"round_trip.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/round_trip.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AA2B7B,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGzD,oDAAoD;AACpD,MAAM,WAAW,oBAAoB;IACpC;;;;;OAKG;IACH,UAAU,EAAE,SAAS,CAAC;IACtB;;;OAGG;IACH,cAAc,EAAE,cAAc,CAAC;IAC/B,kDAAkD;IAClD,WAAW,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5B,+EAA+E;IAC/E,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACvD;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CAAC,EAAE,GAAG,CACrB,MAAM,EACN,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CACnF,CAAC;CACF;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,8BAA8B,GAAI,SAAS,oBAAoB,KAAG,IAyI9E,CAAC"}
1
+ {"version":3,"file":"round_trip.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/round_trip.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AA+B7B,OAAO,KAAK,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAGzD,oDAAoD;AACpD,MAAM,WAAW,oBAAoB;IACpC;;;;;OAKG;IACH,UAAU,EAAE,SAAS,CAAC;IACtB;;;OAGG;IACH,cAAc,EAAE,cAAc,CAAC;IAC/B,kDAAkD;IAClD,WAAW,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAC5B,+EAA+E;IAC/E,eAAe,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;IACvD;;;;;;;;;;;;;OAaG;IACH,gBAAgB,CAAC,EAAE,GAAG,CACrB,MAAM,EACN,CAAC,OAAO,EAAE,WAAW,KAAK,OAAO,CAAC;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CACnF,CAAC;CACF;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,8BAA8B,GAAI,SAAS,oBAAoB,KAAG,IAmI9E,CAAC"}
@@ -20,7 +20,7 @@ import { describe, test, beforeAll, assert } from 'vitest';
20
20
  import { ROLE_ADMIN } from '../auth/role_schema.js';
21
21
  import { is_public_auth, needs_actor, input_schema_declares_acting } from '../http/auth_shape.js';
22
22
  import { assert_response_matches_spec, pick_auth_headers } from './integration_helpers.js';
23
- import { resolve_valid_path, generate_valid_body } from './schema_generators.js';
23
+ import { resolve_valid_path, generate_valid_body, to_route_content_type } from './schema_generators.js';
24
24
  /**
25
25
  * Run schema-driven round-trip validation tests.
26
26
  *
@@ -98,10 +98,7 @@ export const describe_round_trip_validation = (options) => {
98
98
  }
99
99
  const request_init = {
100
100
  method: spec.method,
101
- headers: {
102
- ...headers,
103
- ...(body ? { 'content-type': 'application/json' } : {})
104
- },
101
+ headers: { ...headers, 'content-type': to_route_content_type(spec) },
105
102
  ...(body ? { body: JSON.stringify(body) } : {})
106
103
  };
107
104
  const res = await fixture.transport(request_url, request_init);
@@ -132,10 +129,7 @@ export const describe_round_trip_validation = (options) => {
132
129
  const headers = pick_auth_headers(spec, fixture, authed_account, admin_account);
133
130
  const res = await fixture.transport(url, {
134
131
  method: spec.method,
135
- headers: {
136
- ...headers,
137
- ...(body ? { 'content-type': 'application/json' } : {})
138
- },
132
+ headers: { ...headers, 'content-type': to_route_content_type(spec) },
139
133
  ...(body ? { body: JSON.stringify(body) } : {})
140
134
  });
141
135
  try {
@@ -9,6 +9,7 @@ import './assert_dev_env.js';
9
9
  * @module
10
10
  */
11
11
  import { assert } from 'vitest';
12
+ import { z } from 'zod';
12
13
  import { JSONRPC_VERSION, JsonrpcErrorResponse, JsonrpcResponse } from '../http/jsonrpc.js';
13
14
  import { create_stub_app_server_context } from './stubs.js';
14
15
  /**
@@ -17,6 +17,18 @@ import { type ZodFieldInfo } from '@fuzdev/fuz_util/zod.ts';
17
17
  export declare const detect_format: (field_schema: z.ZodType) => string | null;
18
18
  /** Generate a valid-ish value for a field based on its base type. */
19
19
  export declare const generate_valid_value: (field: ZodFieldInfo, field_schema: z.ZodType) => unknown;
20
+ /**
21
+ * The `Content-Type` a well-formed request to a route sends: `application/json`,
22
+ * or `application/octet-stream` for a `raw_body` route. Every `POST` route
23
+ * refuses anything else with 415 before its other gates run (see
24
+ * `http/simple_request.ts`), so a probe of those gates must send it, body or
25
+ * not. Other methods don't check it, so sending it there is harmless.
26
+ *
27
+ * @param route - the route spec or surface route (reads `raw_body`)
28
+ */
29
+ export declare const to_route_content_type: (route: {
30
+ raw_body?: boolean;
31
+ }) => string;
20
32
  /**
21
33
  * Resolve a route path with valid-ish param values so params validation passes.
22
34
  * Used when testing input on routes that also have params.
@@ -1 +1 @@
1
- {"version":3,"file":"schema_generators.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/schema_generators.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAKN,KAAK,YAAY,EACjB,MAAM,yBAAyB,CAAC;AAIjC;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,cAAc,CAAC,CAAC,OAAO,KAAG,MAAM,GAAG,IAkBhE,CAAC;AAmHF,qEAAqE;AACrE,eAAO,MAAM,oBAAoB,GAAI,OAAO,YAAY,EAAE,cAAc,CAAC,CAAC,OAAO,KAAG,OAgGnF,CAAC;AAEF;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,EAAE,gBAAgB,CAAC,CAAC,SAAS,KAAG,MAiB9E,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,GAC/B,cAAc,CAAC,CAAC,OAAO,KACrB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SA+B5B,CAAC"}
1
+ {"version":3,"file":"schema_generators.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/schema_generators.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B;;;;;;;;GAQG;AAEH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAKN,KAAK,YAAY,EACjB,MAAM,yBAAyB,CAAC;AAIjC;;;GAGG;AACH,eAAO,MAAM,aAAa,GAAI,cAAc,CAAC,CAAC,OAAO,KAAG,MAAM,GAAG,IAkBhE,CAAC;AAmHF,qEAAqE;AACrE,eAAO,MAAM,oBAAoB,GAAI,OAAO,YAAY,EAAE,cAAc,CAAC,CAAC,OAAO,KAAG,OAgGnF,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,qBAAqB,GAAI,OAAO;IAAE,QAAQ,CAAC,EAAE,OAAO,CAAA;CAAE,KAAG,MACL,CAAC;AAElE;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,EAAE,gBAAgB,CAAC,CAAC,SAAS,KAAG,MAiB9E,CAAC;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,mBAAmB,GAC/B,cAAc,CAAC,CAAC,OAAO,KACrB,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SA+B5B,CAAC"}
@@ -264,6 +264,16 @@ export const generate_valid_value = (field, field_schema) => {
264
264
  return 'test_value';
265
265
  }
266
266
  };
267
+ /**
268
+ * The `Content-Type` a well-formed request to a route sends: `application/json`,
269
+ * or `application/octet-stream` for a `raw_body` route. Every `POST` route
270
+ * refuses anything else with 415 before its other gates run (see
271
+ * `http/simple_request.ts`), so a probe of those gates must send it, body or
272
+ * not. Other methods don't check it, so sending it there is harmless.
273
+ *
274
+ * @param route - the route spec or surface route (reads `raw_body`)
275
+ */
276
+ export const to_route_content_type = (route) => route.raw_body ? 'application/octet-stream' : 'application/json';
267
277
  /**
268
278
  * Resolve a route path with valid-ish param values so params validation passes.
269
279
  * Used when testing input on routes that also have params.
@@ -19,6 +19,7 @@ import '../assert_dev_env.js';
19
19
  * @module
20
20
  */
21
21
  import { create_jsonrpc_error_response, create_jsonrpc_response, is_jsonrpc_error_response, is_jsonrpc_notification, is_jsonrpc_request, is_jsonrpc_response } from '../../http/jsonrpc_helpers.js';
22
+ import { JSONRPC_VERSION } from '../../http/jsonrpc.js';
22
23
  // ---------------------------------------------------------------------
23
24
  // Predicates — compose with `WsClient.wait_for` and
24
25
  // `messages.filter(...)`. Both in-process and cross-process tests use
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fuzdev/fuz_app",
3
- "version": "0.132.0",
3
+ "version": "0.132.1",
4
4
  "description": "fullstack app library",
5
5
  "glyph": "🗝",
6
6
  "logo": "logo.svg",
@@ -90,7 +90,7 @@
90
90
  "@fuzdev/fuz_css": "^0.66.1",
91
91
  "@fuzdev/fuz_ui": "^0.213.0",
92
92
  "@fuzdev/fuz_util": "^0.72.0",
93
- "@fuzdev/gro": "^0.214.0",
93
+ "@fuzdev/gro": "^0.216.0",
94
94
  "@fuzdev/mdz": "^0.4.0",
95
95
  "@hono/bun": "^1.0.1",
96
96
  "@hono/deno": "^1.0.3",