@fuzdev/fuz_app 0.61.0 → 0.62.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/CLAUDE.md
CHANGED
|
@@ -225,6 +225,24 @@ and `FrontendActionHandlers`.
|
|
|
225
225
|
- `compose_gen_file({origin_path, imports, blocks})` — encapsulates the per-`*.gen.ts` boilerplate (banner + `imports.build()` + blocks join + template literal). Returns the full file body. Each consumer producer collapses to one `compose_gen_file` call wrapping the helper invocations.
|
|
226
226
|
- `create_namespace_qualifier(sources, imports)` — multi-source consumer helper. Takes `ReadonlyArray<{ns, module, specs}>`, registers `import * as ns from module` for each on `imports`, builds the `method_to_ns` lookup with duplicate-method detection, returns `{qualify_spec, all_specs}` ready to thread through the high-level helpers. Closes the per-file boilerplate gap that kept zap + visiones on hand-rolled template strings even after the `qualify_spec?` callback landed (the per-call callback wasn't enough — the import dance + dup-check was the real boilerplate).
|
|
227
227
|
|
|
228
|
+
## Registry compile (`compile_action_registry.ts`)
|
|
229
|
+
|
|
230
|
+
Shared registration loop called by both `create_rpc_endpoint` and
|
|
231
|
+
`register_action_ws`. Validates four invariants and returns the
|
|
232
|
+
`Map<method, RpcAction>` the dispatchers use:
|
|
233
|
+
|
|
234
|
+
1. Auth-shape biconditional (`assert_route_auth_acting_biconditional` —
|
|
235
|
+
`auth.actor !== 'none' ⟺ input declares acting?: ActingActor`).
|
|
236
|
+
2. Rate-limit / account axis — `rate_limit: 'account' | 'both'` requires
|
|
237
|
+
`auth.account === 'required'`.
|
|
238
|
+
3. JSON-RPC §4.2 wire validity — `request_response` specs with a handler
|
|
239
|
+
may not use `z.null()` for input (use `z.void()` for nullary).
|
|
240
|
+
4. Unique `method` across the array.
|
|
241
|
+
|
|
242
|
+
Only `request_response` specs with a handler reach the dispatch map;
|
|
243
|
+
`remote_notification` / handler-less specs (e.g. WS `cancel`) stay
|
|
244
|
+
registry-only.
|
|
245
|
+
|
|
228
246
|
## HTTP bridge (`action_bridge.ts`)
|
|
229
247
|
|
|
230
248
|
Derives transport-specific specs from action specs. HTTP-specific concerns
|
|
@@ -256,7 +274,7 @@ surface is published in `library.json` codegen anyway.
|
|
|
256
274
|
Shim responsibilities:
|
|
257
275
|
|
|
258
276
|
1. **Parse envelope** — POST body as `JsonrpcRequest` (parse errors → JSON-RPC `parse_error` 400). GET reads `method`, `id`, `params` from query string; missing `method`/`id` → 400 `invalid_request`. Integer `id` normalization: `?id=42` matches `{id: 42}`.
|
|
259
|
-
2. **Lookup method** — `Map<method, RpcAction
|
|
277
|
+
2. **Lookup method** — `Map<method, RpcAction>` built via `compile_action_registry` (which runs the registry-time invariants — see §Registry compile above). Unknown method → `method_not_found`.
|
|
260
278
|
3. **GET read restriction** — GET is rejected for `side_effects: true` actions (`invalid_request` with "must use POST"). HTTP-only.
|
|
261
279
|
4. **Build PerformActionInput** — read `account_id` / `credential_type` from `c.var`, resolve `client_ip` via `get_client_ip`, pass `c.req.raw.signal` as `signal`, build a DEV-warn-and-drop `notify`. Test-preset escape hatch reads `TEST_CONTEXT_PRESET_KEY` + `REQUEST_CONTEXT_KEY` and forwards as `preset.request_context`.
|
|
262
280
|
5. **Call `perform_action`** — runs steps 1–6 of the shared pipeline (see §Shared dispatch core below).
|
|
@@ -358,19 +376,8 @@ narrowing — ideal when handlers are stateless free functions. fuz_app's
|
|
|
358
376
|
handlers close over factory-captured deps (`log`, `audit`,
|
|
359
377
|
`options.app_settings`, `options.max_tokens`), so per-pair typing via
|
|
360
378
|
`rpc_action()` is the right shape here: the binding happens at
|
|
361
|
-
construction time and the handler keeps its closure.
|
|
362
|
-
|
|
363
|
-
`role_grant_offer_actions.ts`, `self_service_role_actions.ts` (every
|
|
364
|
-
spec there is actor-implying), and `account_actions.ts` (account-grain).
|
|
365
|
-
The conditional auto-selects the right tier per spec; consumers don't
|
|
366
|
-
pick a binder.
|
|
367
|
-
|
|
368
|
-
The earlier two-binder split (`rpc_action` + `rpc_actor_action`) was
|
|
369
|
-
collapsed once the symmetric account-grain narrowing landed. Same
|
|
370
|
-
runtime; the second symbol no longer added information the spec
|
|
371
|
-
literal didn't already carry. Uniform binding keeps a future handler
|
|
372
|
-
that gains `ctx.auth.actor` reads from accidentally landing on a
|
|
373
|
-
looser narrow — the spec literal drives the type either way.
|
|
379
|
+
construction time and the handler keeps its closure. The conditional
|
|
380
|
+
auto-selects the right tier per spec; consumers don't pick a binder.
|
|
374
381
|
|
|
375
382
|
## Transports (`transports.ts`, `transports_http.ts`, `transports_ws.ts`, `transports_ws_backend.ts`)
|
|
376
383
|
|
|
@@ -529,11 +536,11 @@ dispatcher without the origin/auth front-stack.
|
|
|
529
536
|
|
|
530
537
|
Actions are passed as `ReadonlyArray<Action>` — the composable
|
|
531
538
|
`{spec, handler?}` tuple shared with `create_rpc_client`. The dispatcher
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
539
|
+
builds its `action_map: Map<string, RpcAction>` via `compile_action_registry`
|
|
540
|
+
(see §Registry compile above) — only `request_response` specs with a
|
|
541
|
+
handler land in the map. Specs without a handler (client-only /
|
|
542
|
+
dispatcher-handled like `cancel`) surface as `method_not_found` if the
|
|
543
|
+
wire targets them.
|
|
537
544
|
|
|
538
545
|
Required deps: `db: Db` (pool-level, used by `perform_action` for both the
|
|
539
546
|
per-message authorization phase and the transactional dispatch wrap when
|
|
@@ -988,9 +995,8 @@ transport; `ActionHandler` is the single handler signature.
|
|
|
988
995
|
|
|
989
996
|
`RpcAction = Action<RequestResponseActionSpec> & {handler: ActionHandler}`
|
|
990
997
|
is the narrowing the HTTP RPC dispatcher accepts (`create_rpc_endpoint`)
|
|
991
|
-
and the `rpc_action` binder produces (the actor-axis narrowing
|
|
992
|
-
in `HandlerForSpec<TSpec>`
|
|
993
|
-
`rpc_actor_action`).
|
|
998
|
+
and the `rpc_action` binder produces (the actor-axis narrowing lives
|
|
999
|
+
in `HandlerForSpec<TSpec>`).
|
|
994
1000
|
|
|
995
1001
|
## Shared dispatch core (`perform_action.ts`)
|
|
996
1002
|
|
package/dist/auth/CLAUDE.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
> Auth domain: identity, crypto primitives, schema + DDL, queries, middleware, routes, RPC actions, cleanup.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Grouped below by theme. For design rationale and threat
|
|
6
6
|
model, see `../../../docs/identity.md` and `../../../docs/security.md`. For the
|
|
7
7
|
subsystem's place in server assembly and middleware ordering, see
|
|
8
8
|
`../../../docs/architecture.md` and the root `../../../CLAUDE.md`.
|
|
@@ -1530,9 +1530,9 @@ spread `all_self_service_role_action_specs` separately when needed.
|
|
|
1530
1530
|
|
|
1531
1531
|
`all_fuz_auth_action_spec_registries` — walker/codegen entry for every
|
|
1532
1532
|
fuz-auth action-spec bundle (`admin`, `role_grant_offer`, `account`,
|
|
1533
|
-
`self_service_role`, `actor_lookup`). Not a mounting
|
|
1534
|
-
specs are excluded. Iterated by
|
|
1535
|
-
|
|
1533
|
+
`self_service_role`, `actor_lookup`, `actor_search`). Not a mounting
|
|
1534
|
+
surface; protocol specs are excluded. Iterated by registry-wide
|
|
1535
|
+
invariant tests in `../../test/auth/`.
|
|
1536
1536
|
|
|
1537
1537
|
### `account_action_specs.ts` + `account_actions.ts` — seven self-service RPC actions
|
|
1538
1538
|
|
|
@@ -137,7 +137,10 @@ export interface AppServerOptions {
|
|
|
137
137
|
* listener to `backend.deps.audit.on_event_chain` (composing with the
|
|
138
138
|
* consumer's `on_audit_event` callback rather than rebuilding `AppDeps`), and
|
|
139
139
|
* auto-includes `audit_log_event_specs` in the surface. The result is exposed
|
|
140
|
-
* on `AppServerContext` (for route factories) and `AppServer` (for the caller)
|
|
140
|
+
* on `AppServerContext` (for route factories) and `AppServer` (for the caller),
|
|
141
|
+
* always typed as `AuditLogSse | null` — when this option is set, the field
|
|
142
|
+
* is non-null. Use `require_audit_sse(ctx)` to assert the invariant in
|
|
143
|
+
* route factories that depend on it.
|
|
141
144
|
*
|
|
142
145
|
* Pass `true` for defaults (admin role), or `{role: 'custom'}` for a custom role.
|
|
143
146
|
* Omit to wire audit SSE manually.
|
|
@@ -160,14 +163,27 @@ export interface AppServerOptions {
|
|
|
160
163
|
* `create_standard_rpc_actions(ctx.deps, {app_settings: ctx.app_settings})`.
|
|
161
164
|
*/
|
|
162
165
|
rpc_endpoints?: Array<RpcEndpointSpec> | ((context: AppServerContext) => Array<RpcEndpointSpec>);
|
|
163
|
-
/**
|
|
164
|
-
|
|
166
|
+
/**
|
|
167
|
+
* Env schema for surface generation. Defaults to `BaseServerEnv` —
|
|
168
|
+
* pass an extended schema (typically `BaseServerEnv.extend({...})`)
|
|
169
|
+
* when the consumer adds app-specific env vars.
|
|
170
|
+
*/
|
|
171
|
+
env_schema?: z.ZodObject;
|
|
165
172
|
/** Middleware applied after routes, before static serving. Included in surface. */
|
|
166
173
|
post_route_middleware?: Array<MiddlewareSpec>;
|
|
167
174
|
/** Static file serving. Omit if not serving static files. */
|
|
168
175
|
static_serving?: {
|
|
169
176
|
serve_static: ServeStaticFactory;
|
|
177
|
+
/** Root directory for static files. Default `'./build'`. */
|
|
178
|
+
root?: string;
|
|
179
|
+
/** Optional SPA fallback path served for client-side routes. */
|
|
170
180
|
spa_fallback?: string;
|
|
181
|
+
/**
|
|
182
|
+
* Predicate deciding which paths receive the SPA fallback.
|
|
183
|
+
* Default: every path that is not under `/api/`. Only consulted
|
|
184
|
+
* when `spa_fallback` is set.
|
|
185
|
+
*/
|
|
186
|
+
is_spa_route?: (path: string) => boolean;
|
|
171
187
|
};
|
|
172
188
|
/**
|
|
173
189
|
* Await all pending fire-and-forget effects before returning the response.
|
|
@@ -202,7 +218,11 @@ export interface AppServerContext {
|
|
|
202
218
|
action_account_rate_limiter: RateLimiter | null;
|
|
203
219
|
/** Global app settings (mutable ref — mutated by settings admin route). */
|
|
204
220
|
app_settings: AppSettings;
|
|
205
|
-
/**
|
|
221
|
+
/**
|
|
222
|
+
* Factory-managed audit log SSE. Non-null when the `audit_log_sse`
|
|
223
|
+
* option was passed to `create_app_server`, `null` when omitted.
|
|
224
|
+
* Use `require_audit_sse(ctx)` to assert the invariant.
|
|
225
|
+
*/
|
|
206
226
|
audit_sse: AuditLogSse | null;
|
|
207
227
|
}
|
|
208
228
|
/** Result of `create_app_server()`. */
|
|
@@ -215,11 +235,35 @@ export interface AppServer {
|
|
|
215
235
|
app_settings: AppSettings;
|
|
216
236
|
/** Migration results from `create_app_backend` (auth + any `migration_namespaces` passed there). */
|
|
217
237
|
migration_results: ReadonlyArray<MigrationResult>;
|
|
218
|
-
/**
|
|
238
|
+
/**
|
|
239
|
+
* Factory-managed audit log SSE. Non-null when the `audit_log_sse`
|
|
240
|
+
* option was passed to `create_app_server`, `null` when omitted.
|
|
241
|
+
* Use `require_audit_sse(server)` to assert the invariant.
|
|
242
|
+
*/
|
|
219
243
|
audit_sse: AuditLogSse | null;
|
|
220
244
|
/** Close the database connection. Propagated from `AppBackend`. */
|
|
221
245
|
close: () => Promise<void>;
|
|
222
246
|
}
|
|
247
|
+
/**
|
|
248
|
+
* Assert that `audit_sse` was wired by `create_app_server` and return it
|
|
249
|
+
* as a non-null `AuditLogSse`. Throws a labelled error when the
|
|
250
|
+
* `audit_log_sse` option was not passed to `create_app_server`.
|
|
251
|
+
*
|
|
252
|
+
* Use in route factories that depend on factory-managed audit SSE:
|
|
253
|
+
*
|
|
254
|
+
* ```ts
|
|
255
|
+
* create_route_specs: (ctx) => create_audit_log_route_specs({
|
|
256
|
+
* stream: require_audit_sse(ctx),
|
|
257
|
+
* }),
|
|
258
|
+
* ```
|
|
259
|
+
*
|
|
260
|
+
* Preferred over `ctx.audit_sse!` — `!` lies to the type system and
|
|
261
|
+
* produces a downstream cannot-read-property crash if a consumer wires
|
|
262
|
+
* the route without enabling the option.
|
|
263
|
+
*/
|
|
264
|
+
export declare const require_audit_sse: (source: {
|
|
265
|
+
audit_sse: AuditLogSse | null;
|
|
266
|
+
}) => AuditLogSse;
|
|
223
267
|
/** Default maximum request body size: 1 MiB. */
|
|
224
268
|
export declare const DEFAULT_MAX_BODY_SIZE: number;
|
|
225
269
|
/**
|
|
@@ -231,7 +275,11 @@ export declare const DEFAULT_MAX_BODY_SIZE: number;
|
|
|
231
275
|
* pass `migration_namespaces` to `create_app_backend`.
|
|
232
276
|
*
|
|
233
277
|
* When `audit_log_sse` is set, the SSE registry's listener is appended to
|
|
234
|
-
* `backend.deps.audit.on_event_chain` — no shallow-copy of `AppDeps`.
|
|
278
|
+
* `backend.deps.audit.on_event_chain` — no shallow-copy of `AppDeps`. The
|
|
279
|
+
* `audit_sse` field on the returned `AppServer` (and the
|
|
280
|
+
* `AppServerContext` passed to `create_route_specs`) is non-null in that
|
|
281
|
+
* case; consumers can call `require_audit_sse(ctx)` / `require_audit_sse(server)`
|
|
282
|
+
* to assert the invariant.
|
|
235
283
|
*
|
|
236
284
|
* @returns assembled Hono app, backend, surface build, and bootstrap status
|
|
237
285
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/app_server.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,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,SAAS,EAAC,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAGN,KAAK,WAAW,EAChB,MAAM,+BAA+B,CAAC;
|
|
1
|
+
{"version":3,"file":"app_server.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/server/app_server.ts"],"names":[],"mappings":"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"}
|
|
@@ -13,6 +13,7 @@ import { bodyLimit } from 'hono/body-limit';
|
|
|
13
13
|
import { z } from 'zod';
|
|
14
14
|
import { session_cookie_options, } from '../auth/session_cookie.js';
|
|
15
15
|
import { create_audit_log_sse, audit_log_event_specs, } from '../realtime/sse_auth_guard.js';
|
|
16
|
+
import { BaseServerEnv } from './env.js';
|
|
16
17
|
import { query_app_settings_load } from '../auth/app_settings_queries.js';
|
|
17
18
|
import { create_rate_limiter, default_login_account_rate_limit, default_action_account_rate_limit, default_action_ip_rate_limit, } from '../rate_limiter.js';
|
|
18
19
|
// Side-effect import: augments Hono's ContextVariableMap so consumers
|
|
@@ -31,6 +32,29 @@ import { fuz_auth_guard_resolver } from '../auth/auth_guard_resolver.js';
|
|
|
31
32
|
import { create_fuz_authorization_handler } from '../auth/request_context.js';
|
|
32
33
|
import { ERROR_PAYLOAD_TOO_LARGE } from '../http/error_schemas.js';
|
|
33
34
|
import { create_rpc_endpoint } from '../actions/action_rpc.js';
|
|
35
|
+
/**
|
|
36
|
+
* Assert that `audit_sse` was wired by `create_app_server` and return it
|
|
37
|
+
* as a non-null `AuditLogSse`. Throws a labelled error when the
|
|
38
|
+
* `audit_log_sse` option was not passed to `create_app_server`.
|
|
39
|
+
*
|
|
40
|
+
* Use in route factories that depend on factory-managed audit SSE:
|
|
41
|
+
*
|
|
42
|
+
* ```ts
|
|
43
|
+
* create_route_specs: (ctx) => create_audit_log_route_specs({
|
|
44
|
+
* stream: require_audit_sse(ctx),
|
|
45
|
+
* }),
|
|
46
|
+
* ```
|
|
47
|
+
*
|
|
48
|
+
* Preferred over `ctx.audit_sse!` — `!` lies to the type system and
|
|
49
|
+
* produces a downstream cannot-read-property crash if a consumer wires
|
|
50
|
+
* the route without enabling the option.
|
|
51
|
+
*/
|
|
52
|
+
export const require_audit_sse = (source) => {
|
|
53
|
+
if (!source.audit_sse) {
|
|
54
|
+
throw new Error('audit_sse is null — pass `audit_log_sse: true` (or `{role}`) in `AppServerOptions`');
|
|
55
|
+
}
|
|
56
|
+
return source.audit_sse;
|
|
57
|
+
};
|
|
34
58
|
/** Default maximum request body size: 1 MiB. */
|
|
35
59
|
export const DEFAULT_MAX_BODY_SIZE = 1024 * 1024;
|
|
36
60
|
/**
|
|
@@ -42,7 +66,11 @@ export const DEFAULT_MAX_BODY_SIZE = 1024 * 1024;
|
|
|
42
66
|
* pass `migration_namespaces` to `create_app_backend`.
|
|
43
67
|
*
|
|
44
68
|
* When `audit_log_sse` is set, the SSE registry's listener is appended to
|
|
45
|
-
* `backend.deps.audit.on_event_chain` — no shallow-copy of `AppDeps`.
|
|
69
|
+
* `backend.deps.audit.on_event_chain` — no shallow-copy of `AppDeps`. The
|
|
70
|
+
* `audit_sse` field on the returned `AppServer` (and the
|
|
71
|
+
* `AppServerContext` passed to `create_route_specs`) is non-null in that
|
|
72
|
+
* case; consumers can call `require_audit_sse(ctx)` / `require_audit_sse(server)`
|
|
73
|
+
* to assert the invariant.
|
|
46
74
|
*
|
|
47
75
|
* @returns assembled Hono app, backend, surface build, and bootstrap status
|
|
48
76
|
*/
|
|
@@ -161,7 +189,7 @@ export const create_app_server = async (options) => {
|
|
|
161
189
|
const surface_spec = create_app_surface_spec({
|
|
162
190
|
middleware_specs: surface_middleware,
|
|
163
191
|
route_specs,
|
|
164
|
-
env_schema: options.env_schema,
|
|
192
|
+
env_schema: options.env_schema ?? BaseServerEnv,
|
|
165
193
|
event_specs: all_event_specs,
|
|
166
194
|
rpc_endpoints: resolved_rpc_endpoints,
|
|
167
195
|
});
|
|
@@ -269,8 +297,8 @@ export const create_app_server = async (options) => {
|
|
|
269
297
|
}
|
|
270
298
|
// Static file serving
|
|
271
299
|
if (options.static_serving) {
|
|
272
|
-
const { serve_static, spa_fallback } = options.static_serving;
|
|
273
|
-
for (const mw of create_static_middleware(serve_static, { spa_fallback })) {
|
|
300
|
+
const { serve_static, root, spa_fallback, is_spa_route } = options.static_serving;
|
|
301
|
+
for (const mw of create_static_middleware(serve_static, { root, spa_fallback, is_spa_route })) {
|
|
274
302
|
app.use('/*', mw);
|
|
275
303
|
}
|
|
276
304
|
}
|
package/dist/testing/CLAUDE.md
CHANGED
|
@@ -700,14 +700,14 @@ deps — no DB needed.
|
|
|
700
700
|
Options: `{build: () => AppSurfaceSpec, roles: Array<string>}`.
|
|
701
701
|
|
|
702
702
|
**Opt-in bundles need their own per-bundle suite file.** Action bundles
|
|
703
|
-
not folded into `create_standard_rpc_actions` (today `self_service_role_actions
|
|
704
|
-
and `
|
|
705
|
-
from `describe_rpc_attack_surface_tests` +
|
|
706
|
-
unless the consumer ships a
|
|
707
|
-
opt-in factory on the RPC
|
|
708
|
-
`../../test/CLAUDE.md` §Composable
|
|
709
|
-
|
|
710
|
-
|
|
703
|
+
not folded into `create_standard_rpc_actions` (today `self_service_role_actions`,
|
|
704
|
+
`actor_lookup_actions`, and `actor_search_actions`) get zero adversarial
|
|
705
|
+
/ round-trip coverage from `describe_rpc_attack_surface_tests` +
|
|
706
|
+
`describe_rpc_round_trip_tests` unless the consumer ships a
|
|
707
|
+
`<module>.rpc_suites.db.test.ts` mounting the opt-in factory on the RPC
|
|
708
|
+
endpoint and calling both suites. See `../../test/CLAUDE.md` §Composable
|
|
709
|
+
Test Suites for the obligation note; existing
|
|
710
|
+
`../../test/auth/*.rpc_suites.db.test.ts` files are templates.
|
|
711
711
|
|
|
712
712
|
## Cross-cutting conventions
|
|
713
713
|
|