@fuzdev/fuz_app 0.5.0 → 0.7.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.
- package/dist/actions/action_bridge.d.ts +3 -3
- package/dist/actions/action_bridge.d.ts.map +1 -1
- package/dist/actions/action_bridge.js +4 -3
- package/dist/actions/action_rpc.d.ts +89 -0
- package/dist/actions/action_rpc.d.ts.map +1 -0
- package/dist/actions/action_rpc.js +248 -0
- package/dist/http/jsonrpc.d.ts +62 -0
- package/dist/http/jsonrpc.d.ts.map +1 -0
- package/dist/http/jsonrpc.js +49 -0
- package/dist/http/jsonrpc_errors.d.ts +132 -0
- package/dist/http/jsonrpc_errors.d.ts.map +1 -0
- package/dist/http/jsonrpc_errors.js +197 -0
- package/dist/http/route_spec.d.ts +2 -1
- package/dist/http/route_spec.d.ts.map +1 -1
- package/dist/http/route_spec.js +43 -7
- package/dist/http/surface.d.ts +25 -0
- package/dist/http/surface.d.ts.map +1 -1
- package/dist/http/surface.js +16 -1
- package/dist/server/app_server.d.ts +3 -1
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +2 -1
- package/dist/testing/adversarial_input.d.ts.map +1 -1
- package/dist/testing/adversarial_input.js +22 -7
- package/dist/testing/app_server.d.ts +2 -1
- package/dist/testing/app_server.d.ts.map +1 -1
- package/dist/testing/app_server.js +1 -0
- package/dist/testing/rpc_attack_surface.d.ts +23 -0
- package/dist/testing/rpc_attack_surface.d.ts.map +1 -0
- package/dist/testing/rpc_attack_surface.js +376 -0
- package/dist/testing/rpc_helpers.d.ts +44 -0
- package/dist/testing/rpc_helpers.d.ts.map +1 -0
- package/dist/testing/rpc_helpers.js +74 -0
- package/dist/testing/rpc_round_trip.d.ts +41 -0
- package/dist/testing/rpc_round_trip.d.ts.map +1 -0
- package/dist/testing/rpc_round_trip.js +163 -0
- package/dist/testing/stubs.d.ts +3 -1
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +2 -1
- package/dist/testing/surface_invariants.d.ts +4 -0
- package/dist/testing/surface_invariants.d.ts.map +1 -1
- package/dist/testing/surface_invariants.js +4 -0
- package/package.json +1 -1
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON-RPC error infrastructure for fuz_app routes.
|
|
3
|
+
*
|
|
4
|
+
* Provides error types, named constructors, and HTTP status mapping
|
|
5
|
+
* for the throw/catch error pattern used by `apply_route_specs`.
|
|
6
|
+
* Extracted from zzz's `jsonrpc_errors.ts` — only core error codes
|
|
7
|
+
* (5 standard + 8 general application). Domain-specific codes stay
|
|
8
|
+
* in consumers. `JSONRPC_ERROR_CODES` is extensible — consumers
|
|
9
|
+
* add their own codes by casting `as JsonrpcErrorCode`.
|
|
10
|
+
*
|
|
11
|
+
* Complementary to `error_schemas.ts`: that module is declarative
|
|
12
|
+
* (Zod schemas for surface introspection), this one is runtime
|
|
13
|
+
* (throw + catch + map).
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Standard JSON-RPC error codes (5) plus general application codes (8).
|
|
19
|
+
*
|
|
20
|
+
* Extensible — consumers add domain-specific codes to their own objects
|
|
21
|
+
* by casting `as JsonrpcErrorCode`. Application codes use the -32000 to
|
|
22
|
+
* -32099 range reserved by the JSON-RPC spec.
|
|
23
|
+
*/
|
|
24
|
+
export const JSONRPC_ERROR_CODES = {
|
|
25
|
+
// Standard JSON-RPC errors — https://www.jsonrpc.org/specification
|
|
26
|
+
/** -32700 */
|
|
27
|
+
parse_error: -32700,
|
|
28
|
+
/** -32600 */
|
|
29
|
+
invalid_request: -32600,
|
|
30
|
+
/** -32601 */
|
|
31
|
+
method_not_found: -32601,
|
|
32
|
+
/** -32602 */
|
|
33
|
+
invalid_params: -32602,
|
|
34
|
+
/** -32603 */
|
|
35
|
+
internal_error: -32603,
|
|
36
|
+
// General application errors (-32000 to -32099)
|
|
37
|
+
/**
|
|
38
|
+
* Same as HTTP 401 "unauthorized", but correctly named.
|
|
39
|
+
*
|
|
40
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status#client_error_responses
|
|
41
|
+
*/
|
|
42
|
+
unauthenticated: -32001,
|
|
43
|
+
/**
|
|
44
|
+
* Named to match HTTP 403 — avoids confusion with 401 which
|
|
45
|
+
* is incorrectly named "unauthorized" in HTTP.
|
|
46
|
+
*/
|
|
47
|
+
forbidden: -32002,
|
|
48
|
+
not_found: -32003,
|
|
49
|
+
conflict: -32004,
|
|
50
|
+
/**
|
|
51
|
+
* Application-level validation failures (business logic).
|
|
52
|
+
* Use `invalid_params` (-32602) for schema/parsing failures.
|
|
53
|
+
*/
|
|
54
|
+
validation_error: -32005,
|
|
55
|
+
rate_limited: -32006,
|
|
56
|
+
service_unavailable: -32007,
|
|
57
|
+
timeout: -32008,
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Named constructors for `JsonrpcErrorJson` objects.
|
|
61
|
+
*
|
|
62
|
+
* Each function creates a JSON-RPC error response object with the correct
|
|
63
|
+
* code and a sensible default message. Used by the catch layer in
|
|
64
|
+
* `apply_route_specs` to build response bodies.
|
|
65
|
+
*/
|
|
66
|
+
export const jsonrpc_error_messages = {
|
|
67
|
+
parse_error: (data) => ({
|
|
68
|
+
code: JSONRPC_ERROR_CODES.parse_error,
|
|
69
|
+
message: 'parse error',
|
|
70
|
+
data,
|
|
71
|
+
}),
|
|
72
|
+
invalid_request: (data) => ({
|
|
73
|
+
code: JSONRPC_ERROR_CODES.invalid_request,
|
|
74
|
+
message: 'invalid request',
|
|
75
|
+
data,
|
|
76
|
+
}),
|
|
77
|
+
method_not_found: (method, data) => ({
|
|
78
|
+
code: JSONRPC_ERROR_CODES.method_not_found,
|
|
79
|
+
message: method ? `method not found: ${method}` : 'method not found',
|
|
80
|
+
data,
|
|
81
|
+
}),
|
|
82
|
+
invalid_params: (message, data) => ({
|
|
83
|
+
code: JSONRPC_ERROR_CODES.invalid_params,
|
|
84
|
+
message: message ?? 'invalid params',
|
|
85
|
+
data,
|
|
86
|
+
}),
|
|
87
|
+
internal_error: (message = 'internal server error', data) => ({
|
|
88
|
+
code: JSONRPC_ERROR_CODES.internal_error,
|
|
89
|
+
message,
|
|
90
|
+
data,
|
|
91
|
+
}),
|
|
92
|
+
unauthenticated: (message = 'unauthenticated', data) => ({
|
|
93
|
+
code: JSONRPC_ERROR_CODES.unauthenticated,
|
|
94
|
+
message,
|
|
95
|
+
data,
|
|
96
|
+
}),
|
|
97
|
+
forbidden: (message = 'forbidden', data) => ({
|
|
98
|
+
code: JSONRPC_ERROR_CODES.forbidden,
|
|
99
|
+
message,
|
|
100
|
+
data,
|
|
101
|
+
}),
|
|
102
|
+
not_found: (resource, data) => ({
|
|
103
|
+
code: JSONRPC_ERROR_CODES.not_found,
|
|
104
|
+
message: resource ? `${resource} not found` : 'not found',
|
|
105
|
+
data,
|
|
106
|
+
}),
|
|
107
|
+
conflict: (message = 'conflict', data) => ({
|
|
108
|
+
code: JSONRPC_ERROR_CODES.conflict,
|
|
109
|
+
message,
|
|
110
|
+
data,
|
|
111
|
+
}),
|
|
112
|
+
validation_error: (message = 'validation error', data) => ({
|
|
113
|
+
code: JSONRPC_ERROR_CODES.validation_error,
|
|
114
|
+
message,
|
|
115
|
+
data,
|
|
116
|
+
}),
|
|
117
|
+
rate_limited: (message = 'rate limited', data) => ({
|
|
118
|
+
code: JSONRPC_ERROR_CODES.rate_limited,
|
|
119
|
+
message,
|
|
120
|
+
data,
|
|
121
|
+
}),
|
|
122
|
+
service_unavailable: (message = 'service unavailable', data) => ({
|
|
123
|
+
code: JSONRPC_ERROR_CODES.service_unavailable,
|
|
124
|
+
message,
|
|
125
|
+
data,
|
|
126
|
+
}),
|
|
127
|
+
timeout: (message = 'timeout', data) => ({
|
|
128
|
+
code: JSONRPC_ERROR_CODES.timeout,
|
|
129
|
+
message,
|
|
130
|
+
data,
|
|
131
|
+
}),
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Error class carrying a JSON-RPC error code — thrown by handlers,
|
|
135
|
+
* caught by `apply_route_specs` and mapped to HTTP status + JSON-RPC error response.
|
|
136
|
+
*
|
|
137
|
+
* Named for what it is: an error with a JSON-RPC error code that gets thrown.
|
|
138
|
+
*/
|
|
139
|
+
export class ThrownJsonrpcError extends Error {
|
|
140
|
+
code;
|
|
141
|
+
data;
|
|
142
|
+
constructor(code, message, data, options) {
|
|
143
|
+
super(message, options);
|
|
144
|
+
this.code = code;
|
|
145
|
+
this.data = data;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const create_error_thrower = (error_fn) => (...args) => {
|
|
149
|
+
const m = error_fn(...args);
|
|
150
|
+
return new ThrownJsonrpcError(m.code, m.message, m.data);
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* Named constructors for `ThrownJsonrpcError`.
|
|
154
|
+
*
|
|
155
|
+
* Usage: `throw jsonrpc_errors.not_found('user')` or `throw jsonrpc_errors.forbidden()`.
|
|
156
|
+
*/
|
|
157
|
+
export const jsonrpc_errors = {
|
|
158
|
+
parse_error: create_error_thrower(jsonrpc_error_messages.parse_error),
|
|
159
|
+
invalid_request: create_error_thrower(jsonrpc_error_messages.invalid_request),
|
|
160
|
+
method_not_found: create_error_thrower(jsonrpc_error_messages.method_not_found),
|
|
161
|
+
invalid_params: create_error_thrower(jsonrpc_error_messages.invalid_params),
|
|
162
|
+
internal_error: create_error_thrower(jsonrpc_error_messages.internal_error),
|
|
163
|
+
unauthenticated: create_error_thrower(jsonrpc_error_messages.unauthenticated),
|
|
164
|
+
forbidden: create_error_thrower(jsonrpc_error_messages.forbidden),
|
|
165
|
+
not_found: create_error_thrower(jsonrpc_error_messages.not_found),
|
|
166
|
+
conflict: create_error_thrower(jsonrpc_error_messages.conflict),
|
|
167
|
+
validation_error: create_error_thrower(jsonrpc_error_messages.validation_error),
|
|
168
|
+
rate_limited: create_error_thrower(jsonrpc_error_messages.rate_limited),
|
|
169
|
+
service_unavailable: create_error_thrower(jsonrpc_error_messages.service_unavailable),
|
|
170
|
+
timeout: create_error_thrower(jsonrpc_error_messages.timeout),
|
|
171
|
+
};
|
|
172
|
+
// --- HTTP status mapping ---
|
|
173
|
+
const JSONRPC_ERROR_CODE_HTTP_STATUS = new Map([
|
|
174
|
+
[-32700, 400], // parse_error
|
|
175
|
+
[-32600, 400], // invalid_request
|
|
176
|
+
[-32601, 404], // method_not_found
|
|
177
|
+
[-32602, 400], // invalid_params
|
|
178
|
+
[-32603, 500], // internal_error
|
|
179
|
+
[-32001, 401], // unauthenticated
|
|
180
|
+
[-32002, 403], // forbidden
|
|
181
|
+
[-32003, 404], // not_found
|
|
182
|
+
[-32004, 409], // conflict
|
|
183
|
+
[-32005, 422], // validation_error
|
|
184
|
+
[-32006, 429], // rate_limited
|
|
185
|
+
[-32007, 503], // service_unavailable
|
|
186
|
+
[-32008, 504], // timeout
|
|
187
|
+
]);
|
|
188
|
+
/**
|
|
189
|
+
* Map a JSON-RPC error code to an HTTP status code.
|
|
190
|
+
*
|
|
191
|
+
* Returns 500 for unrecognized codes (consumer-defined codes
|
|
192
|
+
* without a mapping default to internal server error).
|
|
193
|
+
*
|
|
194
|
+
* @param code - the JSON-RPC error code
|
|
195
|
+
* @returns the corresponding HTTP status code
|
|
196
|
+
*/
|
|
197
|
+
export const jsonrpc_error_code_to_http_status = (code) => JSONRPC_ERROR_CODE_HTTP_STATUS.get(code) ?? 500;
|
|
@@ -171,7 +171,8 @@ export declare const apply_middleware_specs: (app: Hono, specs: Array<Middleware
|
|
|
171
171
|
*
|
|
172
172
|
* For each spec: resolves auth to guards via the provided resolver,
|
|
173
173
|
* adds input validation middleware (for routes with non-null input schemas),
|
|
174
|
-
* wraps handler with DEV-only output and error validation,
|
|
174
|
+
* wraps handler with DEV-only output and error validation, wraps with error
|
|
175
|
+
* catch layer (catches `ThrownJsonrpcError` and generic errors), and registers the route.
|
|
175
176
|
*
|
|
176
177
|
* Each handler receives a `RouteContext` with:
|
|
177
178
|
* - `db`: transaction-scoped (for non-GET) or pool-level (for GET)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route_spec.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/route_spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAC,OAAO,EAAW,IAAI,EAAE,iBAAiB,EAAC,MAAM,MAAM,CAAC;AACpE,OAAO,KAAK,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAE3B,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AACpC,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAKjB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"route_spec.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/route_spec.ts"],"names":[],"mappings":"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"}
|
package/dist/http/route_spec.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { DEV } from 'esm-env';
|
|
16
16
|
import { ERROR_INVALID_JSON_BODY, ERROR_INVALID_REQUEST_BODY, ERROR_INVALID_ROUTE_PARAMS, ERROR_INVALID_QUERY_PARAMS, } from './error_schemas.js';
|
|
17
|
+
import { ThrownJsonrpcError, JSONRPC_ERROR_CODES, jsonrpc_error_code_to_http_status, } from './jsonrpc_errors.js';
|
|
17
18
|
import { is_null_schema, merge_error_schemas } from './schema_helpers.js';
|
|
18
19
|
/**
|
|
19
20
|
* Get validated input from the Hono context.
|
|
@@ -54,11 +55,15 @@ export const get_route_query = (c) => {
|
|
|
54
55
|
/**
|
|
55
56
|
* Create input validation middleware for a route spec.
|
|
56
57
|
*
|
|
57
|
-
* Returns an empty array for
|
|
58
|
-
*
|
|
59
|
-
*
|
|
58
|
+
* Returns an empty array for GET routes (no body to parse — GET input is
|
|
59
|
+
* validated elsewhere, e.g. from `?params=` query string in RPC handlers)
|
|
60
|
+
* and for null-input routes (no body expected). For other routes with input
|
|
61
|
+
* schemas, returns a middleware that parses and validates the JSON body,
|
|
62
|
+
* storing the result on the context as `validated_input`.
|
|
60
63
|
*/
|
|
61
|
-
const create_input_validation = (input_schema) => {
|
|
64
|
+
const create_input_validation = (input_schema, method) => {
|
|
65
|
+
if (method === 'GET')
|
|
66
|
+
return [];
|
|
62
67
|
if (is_null_schema(input_schema))
|
|
63
68
|
return [];
|
|
64
69
|
const validate = async (c, next) => {
|
|
@@ -185,12 +190,41 @@ export const apply_middleware_specs = (app, specs) => {
|
|
|
185
190
|
app.use(spec.path, spec.handler);
|
|
186
191
|
}
|
|
187
192
|
};
|
|
193
|
+
/**
|
|
194
|
+
* Wrap a handler with error catch logic.
|
|
195
|
+
*
|
|
196
|
+
* Catches `ThrownJsonrpcError` and maps to HTTP status + JSON-RPC error response.
|
|
197
|
+
* Catches generic `Error` and maps to `internal_error` (-32603 → 500), including
|
|
198
|
+
* the error message in DEV only. Existing handlers that return `c.json()` directly
|
|
199
|
+
* are unaffected — the catch layer only activates when something is thrown.
|
|
200
|
+
*/
|
|
201
|
+
const wrap_error_catch = (handler, log) => {
|
|
202
|
+
return async (c, next) => {
|
|
203
|
+
try {
|
|
204
|
+
return await handler(c, next);
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
if (err instanceof ThrownJsonrpcError) {
|
|
208
|
+
const status = jsonrpc_error_code_to_http_status(err.code);
|
|
209
|
+
const error = { code: err.code, message: err.message };
|
|
210
|
+
if (err.data !== undefined)
|
|
211
|
+
error.data = err.data;
|
|
212
|
+
return c.json({ error }, status);
|
|
213
|
+
}
|
|
214
|
+
// generic error — internal_error
|
|
215
|
+
log.error('Unhandled handler error', err);
|
|
216
|
+
const message = DEV && err instanceof Error ? err.message : 'internal server error';
|
|
217
|
+
return c.json({ error: { code: JSONRPC_ERROR_CODES.internal_error, message } }, 500);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
};
|
|
188
221
|
/**
|
|
189
222
|
* Apply route specs to a Hono app.
|
|
190
223
|
*
|
|
191
224
|
* For each spec: resolves auth to guards via the provided resolver,
|
|
192
225
|
* adds input validation middleware (for routes with non-null input schemas),
|
|
193
|
-
* wraps handler with DEV-only output and error validation,
|
|
226
|
+
* wraps handler with DEV-only output and error validation, wraps with error
|
|
227
|
+
* catch layer (catches `ThrownJsonrpcError` and generic errors), and registers the route.
|
|
194
228
|
*
|
|
195
229
|
* Each handler receives a `RouteContext` with:
|
|
196
230
|
* - `db`: transaction-scoped (for non-GET) or pool-level (for GET)
|
|
@@ -215,7 +249,7 @@ export const apply_route_specs = (app, specs, resolve_auth_guards, log, db) => {
|
|
|
215
249
|
const guards = resolve_auth_guards(spec.auth);
|
|
216
250
|
const params_validation = create_params_validation(spec.params);
|
|
217
251
|
const query_validation = create_query_validation(spec.query);
|
|
218
|
-
const
|
|
252
|
+
const input_validation = create_input_validation(spec.input, spec.method);
|
|
219
253
|
const merged_errors = merge_error_schemas(spec);
|
|
220
254
|
// Step 1: adapt RouteHandler → Handler (construct RouteContext, call spec.handler)
|
|
221
255
|
const use_transaction = spec.transaction ?? spec.method !== 'GET';
|
|
@@ -225,7 +259,9 @@ export const apply_route_specs = (app, specs, resolve_auth_guards, log, db) => {
|
|
|
225
259
|
: (c) => inner(c, { db, background_db: db, pending_effects: c.var.pending_effects });
|
|
226
260
|
// Step 2: output validation
|
|
227
261
|
handler = wrap_output_validation(handler, spec.output, merged_errors, log);
|
|
228
|
-
|
|
262
|
+
// Step 3: error catch layer
|
|
263
|
+
handler = wrap_error_catch(handler, log);
|
|
264
|
+
app.on(spec.method, [spec.path], ...guards, ...params_validation, ...query_validation, ...input_validation, handler);
|
|
229
265
|
}
|
|
230
266
|
};
|
|
231
267
|
/**
|
package/dist/http/surface.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import type { SseEventSpec } from '../realtime/sse.js';
|
|
|
11
11
|
import type { MiddlewareSpec } from './middleware_spec.js';
|
|
12
12
|
import type { RouteAuth, RouteSpec } from './route_spec.js';
|
|
13
13
|
import type { RateLimitKey, RouteErrorSchemas } from './error_schemas.js';
|
|
14
|
+
import type { RpcAction } from '../actions/action_rpc.js';
|
|
14
15
|
import type { Sensitivity } from '../sensitivity.js';
|
|
15
16
|
/** A route in the generated attack surface (JSON-serializable). */
|
|
16
17
|
export interface AppSurfaceRoute {
|
|
@@ -59,6 +60,22 @@ export interface AppSurfaceEvent {
|
|
|
59
60
|
channel: string | null;
|
|
60
61
|
params_schema: unknown;
|
|
61
62
|
}
|
|
63
|
+
/** A method within an RPC endpoint in the generated attack surface (JSON-serializable). */
|
|
64
|
+
export interface AppSurfaceRpcMethod {
|
|
65
|
+
name: string;
|
|
66
|
+
auth: RouteAuth;
|
|
67
|
+
/** JSON Schema representation of the input schema. `null` for null-input methods. */
|
|
68
|
+
input_schema: unknown;
|
|
69
|
+
/** JSON Schema representation of the output schema. */
|
|
70
|
+
output_schema: unknown;
|
|
71
|
+
side_effects: boolean;
|
|
72
|
+
description: string;
|
|
73
|
+
}
|
|
74
|
+
/** An RPC endpoint in the generated attack surface (JSON-serializable). */
|
|
75
|
+
export interface AppSurfaceRpcEndpoint {
|
|
76
|
+
path: string;
|
|
77
|
+
methods: Array<AppSurfaceRpcMethod>;
|
|
78
|
+
}
|
|
62
79
|
/** Assembly-time diagnostic collected during surface generation or server assembly. */
|
|
63
80
|
export interface AppSurfaceDiagnostic {
|
|
64
81
|
level: 'warning' | 'info';
|
|
@@ -70,6 +87,7 @@ export interface AppSurfaceDiagnostic {
|
|
|
70
87
|
export interface AppSurface {
|
|
71
88
|
middleware: Array<AppSurfaceMiddleware>;
|
|
72
89
|
routes: Array<AppSurfaceRoute>;
|
|
90
|
+
rpc_endpoints: Array<AppSurfaceRpcEndpoint>;
|
|
73
91
|
env: Array<AppSurfaceEnv>;
|
|
74
92
|
events: Array<AppSurfaceEvent>;
|
|
75
93
|
diagnostics: Array<AppSurfaceDiagnostic>;
|
|
@@ -84,6 +102,12 @@ export interface AppSurfaceSpec {
|
|
|
84
102
|
surface: AppSurface;
|
|
85
103
|
route_specs: Array<RouteSpec>;
|
|
86
104
|
middleware_specs: Array<MiddlewareSpec>;
|
|
105
|
+
rpc_endpoints: Array<RpcEndpointSpec>;
|
|
106
|
+
}
|
|
107
|
+
/** An RPC endpoint definition for surface generation. */
|
|
108
|
+
export interface RpcEndpointSpec {
|
|
109
|
+
path: string;
|
|
110
|
+
actions: Array<RpcAction>;
|
|
87
111
|
}
|
|
88
112
|
/** Options for `generate_app_surface`. */
|
|
89
113
|
export interface GenerateAppSurfaceOptions {
|
|
@@ -91,6 +115,7 @@ export interface GenerateAppSurfaceOptions {
|
|
|
91
115
|
middleware_specs: Array<MiddlewareSpec>;
|
|
92
116
|
env_schema?: z.ZodObject;
|
|
93
117
|
event_specs?: Array<SseEventSpec>;
|
|
118
|
+
rpc_endpoints?: Array<RpcEndpointSpec>;
|
|
94
119
|
}
|
|
95
120
|
/**
|
|
96
121
|
* Collect error schemas from all middleware that applies to a route path.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"surface.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/surface.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAC,SAAS,EAAE,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAC1D,OAAO,KAAK,EAAC,YAAY,EAAE,iBAAiB,EAAC,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"surface.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/surface.ts"],"names":[],"mappings":"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"}
|
package/dist/http/surface.js
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* @module
|
|
8
8
|
*/
|
|
9
9
|
import { z } from 'zod';
|
|
10
|
+
import { map_action_auth } from '../actions/action_bridge.js';
|
|
10
11
|
import { schema_to_surface, middleware_applies, merge_error_schemas, is_null_schema, is_strict_object_schema, } from './schema_helpers.js';
|
|
11
12
|
// --- Surface generation ---
|
|
12
13
|
/**
|
|
@@ -69,7 +70,7 @@ export const events_to_surface = (event_specs) => {
|
|
|
69
70
|
* @returns the attack surface
|
|
70
71
|
*/
|
|
71
72
|
export const generate_app_surface = (options) => {
|
|
72
|
-
const { route_specs, middleware_specs, env_schema, event_specs } = options;
|
|
73
|
+
const { route_specs, middleware_specs, env_schema, event_specs, rpc_endpoints } = options;
|
|
73
74
|
const diagnostics = [];
|
|
74
75
|
// Spec-level diagnostics: check for non-strict input schemas
|
|
75
76
|
for (const r of route_specs) {
|
|
@@ -136,6 +137,19 @@ export const generate_app_surface = (options) => {
|
|
|
136
137
|
error_schemas,
|
|
137
138
|
};
|
|
138
139
|
}),
|
|
140
|
+
rpc_endpoints: rpc_endpoints?.length
|
|
141
|
+
? rpc_endpoints.map((ep) => ({
|
|
142
|
+
path: ep.path,
|
|
143
|
+
methods: ep.actions.map((a) => ({
|
|
144
|
+
name: a.spec.method,
|
|
145
|
+
auth: map_action_auth(a.spec.auth),
|
|
146
|
+
input_schema: schema_to_surface(a.spec.input),
|
|
147
|
+
output_schema: schema_to_surface(a.spec.output),
|
|
148
|
+
side_effects: a.spec.side_effects,
|
|
149
|
+
description: a.spec.description,
|
|
150
|
+
})),
|
|
151
|
+
}))
|
|
152
|
+
: [],
|
|
139
153
|
env: env_schema ? env_schema_to_surface(env_schema) : [],
|
|
140
154
|
events: event_specs?.length ? events_to_surface(event_specs) : [],
|
|
141
155
|
};
|
|
@@ -152,5 +166,6 @@ export const create_app_surface_spec = (options) => {
|
|
|
152
166
|
surface,
|
|
153
167
|
route_specs: options.route_specs,
|
|
154
168
|
middleware_specs: options.middleware_specs,
|
|
169
|
+
rpc_endpoints: options.rpc_endpoints ?? [],
|
|
155
170
|
};
|
|
156
171
|
};
|
|
@@ -22,7 +22,7 @@ import type { AppDeps } from '../auth/deps.js';
|
|
|
22
22
|
import type { AppBackend } from './app_backend.js';
|
|
23
23
|
import '../hono_context.js';
|
|
24
24
|
import { type ServeStaticFactory } from './static.js';
|
|
25
|
-
import { type AppSurfaceSpec } from '../http/surface.js';
|
|
25
|
+
import { type AppSurfaceSpec, type RpcEndpointSpec } from '../http/surface.js';
|
|
26
26
|
import { type RouteSpec } from '../http/route_spec.js';
|
|
27
27
|
import type { MiddlewareSpec } from '../http/middleware_spec.js';
|
|
28
28
|
import { type BootstrapStatus } from '../auth/bootstrap_routes.js';
|
|
@@ -129,6 +129,8 @@ export interface AppServerOptions {
|
|
|
129
129
|
};
|
|
130
130
|
/** SSE event specs for surface generation. Defaults to `[]` (no SSE events). */
|
|
131
131
|
event_specs?: Array<SseEventSpec>;
|
|
132
|
+
/** RPC endpoint specs for surface generation. */
|
|
133
|
+
rpc_endpoints?: Array<RpcEndpointSpec>;
|
|
132
134
|
/** Env schema for surface generation. Pass `z.object({})` when there are no env vars beyond `BaseServerEnv`. */
|
|
133
135
|
env_schema: z.ZodObject;
|
|
134
136
|
/** Middleware applied after routes, before static serving. Included in surface. */
|
|
@@ -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":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAC,IAAI,EAAE,KAAK,OAAO,EAAC,MAAM,MAAM,CAAC;AAGxC,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,EAEN,KAAK,cAAc,EAEnB,MAAM,2BAA2B,CAAC;AACnC,OAAO,KAAK,EAAC,uBAAuB,EAAC,MAAM,8BAA8B,CAAC;AAC1E,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AACrD,OAAO,EAGN,KAAK,WAAW,EAChB,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EAAC,WAAW,EAAC,MAAM,gCAAgC,CAAC;AAEhE,OAAO,EAGN,KAAK,WAAW,EAChB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAC9D,OAAO,EAAiB,KAAK,kBAAkB,EAAE,KAAK,eAAe,EAAC,MAAM,kBAAkB,CAAC;AAE/F,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,kBAAkB,CAAC;AAGjD,OAAO,oBAAoB,CAAC;AAE5B,OAAO,EAA2B,KAAK,kBAAkB,EAAC,MAAM,aAAa,CAAC;AAE9E,OAAO,EAEN,KAAK,cAAc,EAEnB,KAAK,eAAe,EACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAIN,KAAK,SAAS,EACd,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAGN,KAAK,eAAe,EACpB,MAAM,6BAA6B,CAAC;AAMrC;;GAEG;AACH,MAAM,WAAW,kBAAkB;IAClC,0DAA0D;IAC1D,MAAM,EAAE,MAAM,CAAC;IACf,uDAAuD;IACvD,IAAI,EAAE,MAAM,CAAC;CACb;AAED;;;;;GAKG;AACH,MAAM,WAAW,gBAAgB;IAChC,2DAA2D;IAC3D,OAAO,EAAE,UAAU,CAAC;IACpB,6CAA6C;IAC7C,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,sCAAsC;IACtC,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;IAE/B,6BAA6B;IAC7B,KAAK,EAAE;QACN,eAAe,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;QAC/B,iBAAiB,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,MAAM,GAAG,SAAS,CAAC;KACtD,CAAC;IAEF;;;;;OAKG;IACH,eAAe,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACrC;;;;;OAKG;IACH,0BAA0B,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD;;;;;OAKG;IACH,2BAA2B,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IACjD;;;;OAIG;IACH,sBAAsB,CAAC,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5C;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,2DAA2D;IAC3D,kBAAkB,CAAC,EAAE,gBAAgB,CAAC;IAEtC,yEAAyE;IACzE,SAAS,CAAC,EAAE;QACX,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;QAC1B,mEAAmE;QACnE,YAAY,CAAC,EAAE,MAAM,CAAC;QACtB;;;WAGG;QACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,uBAAuB,EAAE,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;KAC9E,CAAC;IAEF;;;OAGG;IACH,aAAa,CAAC,EAAE,KAAK,CAAC;IAEtB,6EAA6E;IAC7E,oBAAoB,CAAC,EAAE,KAAK,CAAC,kBAAkB,CAAC,CAAC;IAEjD;;;OAGG;IACH,kBAAkB,EAAE,CAAC,OAAO,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAEpE,4DAA4D;IAC5D,oBAAoB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,cAAc,CAAC,KAAK,KAAK,CAAC,cAAc,CAAC,CAAC;IAE/E;;;;;;;;;;OAUG;IACH,aAAa,CAAC,EAAE,IAAI,GAAG;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAC,CAAC;IAEvC,gFAAgF;IAChF,WAAW,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC,CAAC;IAElC,iDAAiD;IACjD,aAAa,CAAC,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC;IAEvC,gHAAgH;IAChH,UAAU,EAAE,CAAC,CAAC,SAAS,CAAC;IAExB,mFAAmF;IACnF,qBAAqB,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IAE9C,6DAA6D;IAC7D,cAAc,CAAC,EAAE;QAChB,YAAY,EAAE,kBAAkB,CAAC;QACjC,YAAY,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC;IAEF;;;;OAIG;IACH,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAEhC;;;;OAIG;IACH,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAExE,8CAA8C;IAC9C,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACrC;AAED,8CAA8C;AAC9C,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,UAAU,CAAC;IACpB,gBAAgB,EAAE,eAAe,CAAC;IAClC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,yEAAyE;IACzE,eAAe,EAAE,WAAW,GAAG,IAAI,CAAC;IACpC,iFAAiF;IACjF,0BAA0B,EAAE,WAAW,GAAG,IAAI,CAAC;IAC/C,kFAAkF;IAClF,2BAA2B,EAAE,WAAW,GAAG,IAAI,CAAC;IAChD,2EAA2E;IAC3E,YAAY,EAAE,WAAW,CAAC;IAC1B,oFAAoF;IACpF,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;CAC9B;AAED,uCAAuC;AACvC,MAAM,WAAW,SAAS;IACzB,GAAG,EAAE,IAAI,CAAC;IACV,wEAAwE;IACxE,YAAY,EAAE,cAAc,CAAC;IAC7B,gBAAgB,EAAE,eAAe,CAAC;IAClC,2EAA2E;IAC3E,YAAY,EAAE,WAAW,CAAC;IAC1B,uGAAuG;IACvG,iBAAiB,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IAClD,oFAAoF;IACpF,SAAS,EAAE,WAAW,GAAG,IAAI,CAAC;IAC9B,mEAAmE;IACnE,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,gDAAgD;AAChD,eAAO,MAAM,qBAAqB,QAAc,CAAC;AAEjD;;;;;;;;;GASG;AACH,eAAO,MAAM,iBAAiB,GAAU,SAAS,gBAAgB,KAAG,OAAO,CAAC,SAAS,CA6PpF,CAAC"}
|
|
@@ -105,7 +105,7 @@ export const create_app_server = async (options) => {
|
|
|
105
105
|
const app_settings = await query_app_settings_load({ db: deps.db });
|
|
106
106
|
// 7. Surface route ref — factory manages the circular ref
|
|
107
107
|
const surface_ref = {
|
|
108
|
-
surface: { middleware: [], routes: [], env: [], events: [], diagnostics: [] },
|
|
108
|
+
surface: { middleware: [], routes: [], rpc_endpoints: [], env: [], events: [], diagnostics: [] },
|
|
109
109
|
};
|
|
110
110
|
// 8. Route specs (consumer routes + factory-managed routes)
|
|
111
111
|
const context = {
|
|
@@ -151,6 +151,7 @@ export const create_app_server = async (options) => {
|
|
|
151
151
|
route_specs,
|
|
152
152
|
env_schema: options.env_schema,
|
|
153
153
|
event_specs: all_event_specs,
|
|
154
|
+
rpc_endpoints: options.rpc_endpoints,
|
|
154
155
|
});
|
|
155
156
|
// Config-level diagnostics (concatenated after spec-level from generate_app_surface)
|
|
156
157
|
const config_diagnostics = [];
|
|
@@ -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,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAUtB,OAAO,EAEN,0BAA0B,EAC1B,uBAAuB,EAGvB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,qBAAqB,CAAC;AA8ChE,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;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB,GAAI,cAAc,CAAC,CAAC,OAAO,KAAG,KAAK,CAAC,aAAa,CAyLtF,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;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,GAAI,SAAS,sBAAsB,KAAG,
|
|
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,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAUtB,OAAO,EAEN,0BAA0B,EAC1B,uBAAuB,EAGvB,MAAM,0BAA0B,CAAC;AAElC,OAAO,KAAK,EAAC,sBAAsB,EAAC,MAAM,qBAAqB,CAAC;AA8ChE,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;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB,GAAI,cAAc,CAAC,CAAC,OAAO,KAAG,KAAK,CAAC,aAAa,CAyLtF,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;;;;;;;;GAQG;AACH,eAAO,MAAM,0BAA0B,GAAI,SAAS,sBAAsB,KAAG,IA4M5E,CAAC"}
|
|
@@ -390,18 +390,33 @@ export const describe_adversarial_input = (options) => {
|
|
|
390
390
|
continue;
|
|
391
391
|
input_test_count += test_cases.length;
|
|
392
392
|
const app = select_auth_app(apps, route.auth);
|
|
393
|
-
const
|
|
393
|
+
const base_url = resolve_valid_path(route.path, spec.params);
|
|
394
|
+
const is_get = route.method === 'GET';
|
|
394
395
|
describe(key, () => {
|
|
395
396
|
for (const tc of test_cases) {
|
|
396
397
|
test(tc.label, async () => {
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
398
|
+
let res;
|
|
399
|
+
if (is_get) {
|
|
400
|
+
// GET routes with non-null input use ?params= query string (RPC convention)
|
|
401
|
+
const params_json = JSON.stringify(tc.body);
|
|
402
|
+
const url = `${base_url}?params=${encodeURIComponent(params_json)}`;
|
|
403
|
+
res = await app.request(url, { method: 'GET' });
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
res = await app.request(base_url, {
|
|
407
|
+
method: route.method,
|
|
408
|
+
headers: { 'Content-Type': 'application/json' },
|
|
409
|
+
body: JSON.stringify(tc.body),
|
|
410
|
+
});
|
|
411
|
+
}
|
|
402
412
|
assert.strictEqual(res.status, 400, `Expected 400 for ${key} [${tc.label}], got ${res.status}`);
|
|
403
413
|
const body = await res.json();
|
|
404
|
-
|
|
414
|
+
// GET RPC: valid-but-wrong-shape JSON (e.g. array) fails schema validation
|
|
415
|
+
// (ERROR_INVALID_REQUEST_BODY), not JSON parsing (ERROR_INVALID_JSON_BODY)
|
|
416
|
+
const expected_error = is_get && tc.expected_error === ERROR_INVALID_JSON_BODY
|
|
417
|
+
? ERROR_INVALID_REQUEST_BODY
|
|
418
|
+
: tc.expected_error;
|
|
419
|
+
assert.strictEqual(body.error, expected_error, `Expected ${expected_error} for ${key} [${tc.label}], got: ${body.error}`);
|
|
405
420
|
// validate response body structure matches error schema
|
|
406
421
|
if (tc.expected_error === 'invalid_request_body') {
|
|
407
422
|
ValidationError.parse(body);
|
|
@@ -19,7 +19,7 @@ import type { PasswordHashDeps } from '../auth/password.js';
|
|
|
19
19
|
import { type SessionOptions } from '../auth/session_cookie.js';
|
|
20
20
|
import type { AppBackend } from '../server/app_backend.js';
|
|
21
21
|
import { type AppServerOptions, type AppServerContext } from '../server/app_server.js';
|
|
22
|
-
import type { AppSurface } from '../http/surface.js';
|
|
22
|
+
import type { AppSurface, AppSurfaceSpec } from '../http/surface.js';
|
|
23
23
|
import type { RouteSpec } from '../http/route_spec.js';
|
|
24
24
|
/**
|
|
25
25
|
* Fast password stub for tests that don't exercise login/password flows.
|
|
@@ -137,6 +137,7 @@ export interface TestAccount {
|
|
|
137
137
|
export interface TestApp {
|
|
138
138
|
app: Hono;
|
|
139
139
|
backend: TestAppServer;
|
|
140
|
+
surface_spec: AppSurfaceSpec;
|
|
140
141
|
surface: AppSurface;
|
|
141
142
|
route_specs: Array<RouteSpec>;
|
|
142
143
|
/** Build request headers with the bootstrapped session cookie. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/app_server.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAE7B;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,IAAI,EAAC,MAAM,MAAM,CAAC;AAK/B,OAAO,EAA2B,KAAK,OAAO,EAAC,MAAM,oBAAoB,CAAC;AAE1E,OAAO,KAAK,EAAC,EAAE,EAAE,MAAM,EAAC,MAAM,aAAa,CAAC;AAC5C,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,qBAAqB,CAAC;AAU1D,OAAO,EAA8B,KAAK,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAG3F,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAEN,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/app_server.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import './assert_dev_env.js';
|
|
2
|
+
import type { AppSurfaceSpec } from '../http/surface.js';
|
|
3
|
+
/** Options for `describe_rpc_attack_surface_tests`. */
|
|
4
|
+
export interface RpcAttackSurfaceOptions {
|
|
5
|
+
/** Build the app surface bundle (surface + route specs + middleware specs + rpc_endpoints). */
|
|
6
|
+
build: () => AppSurfaceSpec;
|
|
7
|
+
/** All roles in the app (e.g. `['admin', 'keeper']`). */
|
|
8
|
+
roles: Array<string>;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Run the standard RPC attack surface test suite.
|
|
12
|
+
*
|
|
13
|
+
* Generates 3 test groups:
|
|
14
|
+
* 1. Auth enforcement — per-method auth checks via JSON-RPC envelopes
|
|
15
|
+
* 2. Adversarial envelopes — malformed JSON-RPC requests
|
|
16
|
+
* 3. Adversarial params — schema-invalid params per method
|
|
17
|
+
*
|
|
18
|
+
* Skips silently when `surface.rpc_endpoints` is empty.
|
|
19
|
+
*
|
|
20
|
+
* @param options - the test configuration
|
|
21
|
+
*/
|
|
22
|
+
export declare const describe_rpc_attack_surface_tests: (options: RpcAttackSurfaceOptions) => void;
|
|
23
|
+
//# sourceMappingURL=rpc_attack_surface.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rpc_attack_surface.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/rpc_attack_surface.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAkB7B,OAAO,KAAK,EAA6C,cAAc,EAAC,MAAM,oBAAoB,CAAC;AAenG,uDAAuD;AACvD,MAAM,WAAW,uBAAuB;IACvC,+FAA+F;IAC/F,KAAK,EAAE,MAAM,cAAc,CAAC;IAC5B,yDAAyD;IACzD,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC;CACrB;AAkaD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iCAAiC,GAAI,SAAS,uBAAuB,KAAG,IAOpF,CAAC"}
|