@fuzdev/fuz_app 0.62.0 → 0.63.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/dist/actions/CLAUDE.md +15 -13
  2. package/dist/actions/action_rpc.d.ts +10 -0
  3. package/dist/actions/action_rpc.d.ts.map +1 -1
  4. package/dist/actions/action_rpc.js +1 -1
  5. package/dist/actions/action_spec.d.ts +1 -1
  6. package/dist/actions/action_spec.js +1 -1
  7. package/dist/actions/perform_action.d.ts.map +1 -1
  8. package/dist/actions/perform_action.js +1 -0
  9. package/dist/auth/CLAUDE.md +45 -24
  10. package/dist/auth/account_action_specs.d.ts +6 -0
  11. package/dist/auth/account_action_specs.d.ts.map +1 -1
  12. package/dist/auth/account_action_specs.js +11 -4
  13. package/dist/auth/account_actions.d.ts.map +1 -1
  14. package/dist/auth/account_actions.js +9 -4
  15. package/dist/auth/account_routes.d.ts.map +1 -1
  16. package/dist/auth/account_routes.js +8 -4
  17. package/dist/auth/account_schema.d.ts +2 -2
  18. package/dist/auth/account_schema.js +2 -2
  19. package/dist/auth/actor_lookup_actions.d.ts +1 -1
  20. package/dist/auth/actor_lookup_actions.js +1 -1
  21. package/dist/auth/actor_lookup_queries.d.ts +1 -1
  22. package/dist/auth/actor_lookup_queries.js +1 -1
  23. package/dist/auth/actor_search_action_specs.d.ts +1 -1
  24. package/dist/auth/actor_search_action_specs.js +1 -1
  25. package/dist/auth/actor_search_actions.d.ts +1 -1
  26. package/dist/auth/actor_search_actions.js +1 -1
  27. package/dist/auth/actor_search_queries.d.ts +1 -1
  28. package/dist/auth/actor_search_queries.js +1 -1
  29. package/dist/auth/all_action_spec_registries.d.ts +2 -2
  30. package/dist/auth/all_action_spec_registries.js +2 -2
  31. package/dist/auth/audit_log_routes.d.ts +1 -1
  32. package/dist/auth/audit_log_routes.js +1 -1
  33. package/dist/auth/audit_log_schema.d.ts +25 -0
  34. package/dist/auth/audit_log_schema.d.ts.map +1 -1
  35. package/dist/auth/audit_log_schema.js +16 -0
  36. package/dist/auth/request_context.d.ts +1 -1
  37. package/dist/env/update_env_variable.js +1 -1
  38. package/dist/http/CLAUDE.md +15 -15
  39. package/dist/testing/CLAUDE.md +28 -44
  40. package/dist/testing/audit_completeness.d.ts.map +1 -1
  41. package/dist/testing/audit_completeness.js +17 -1
  42. package/dist/ui/CLAUDE.md +13 -18
  43. package/dist/ui/keyed_async_slot.svelte.d.ts +1 -1
  44. package/dist/ui/keyed_async_slot.svelte.js +1 -1
  45. package/package.json +1 -1
@@ -5,9 +5,9 @@
5
5
  * `Account`, `Actor`, `RoleGrant`, `AuthSession`, and `ApiToken`.
6
6
  *
7
7
  * Identifier primitives (`Username`, `UsernameProvided`, `Email`) live
8
- * in `../primitive_schemas.ts` — they're general validator shapes that
8
+ * in `primitive_schemas.ts` — they're general validator shapes that
9
9
  * don't depend on the auth domain. The auth-shape request-contract
10
- * primitive `ActingActor` lives in `../http/auth_shape.ts` next to
10
+ * primitive `ActingActor` lives in `http/auth_shape.ts` next to
11
11
  * `RouteAuth` (the two pair: `auth.actor !== 'none'` ⟺ input declares
12
12
  * `acting?: ActingActor`).
13
13
  *
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Pure read — no audit, no side effects. Auth (`account: 'required'`) +
5
5
  * rate-limit (`account`-grain) enforced at the spec layer; see
6
- * `./actor_lookup_action_specs.ts` for the info-leak audit.
6
+ * `auth/actor_lookup_action_specs.ts` for the info-leak audit.
7
7
  *
8
8
  * `display_name` is omitted (not `null`) when `actor.name` is blank,
9
9
  * matching the wire shape `display_name?` so the typed client sees an
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Pure read — no audit, no side effects. Auth (`account: 'required'`) +
5
5
  * rate-limit (`account`-grain) enforced at the spec layer; see
6
- * `./actor_lookup_action_specs.ts` for the info-leak audit.
6
+ * `auth/actor_lookup_action_specs.ts` for the info-leak audit.
7
7
  *
8
8
  * `display_name` is omitted (not `null`) when `actor.name` is blank,
9
9
  * matching the wire shape `display_name?` so the typed client sees an
@@ -10,7 +10,7 @@
10
10
  * The inner join still resolves one row per actor — `actor.account_id`
11
11
  * is `NOT NULL` so every actor has exactly one account.
12
12
  *
13
- * Info-leak posture (see `actor_lookup_action_specs.ts` § audit):
13
+ * Info-leak posture (see `actor_lookup_action_specs.ts` §audit):
14
14
  *
15
15
  * - Row shape **omits** `account_id` — the join is control-plane,
16
16
  * not wire-visible.
@@ -10,7 +10,7 @@
10
10
  * The inner join still resolves one row per actor — `actor.account_id`
11
11
  * is `NOT NULL` so every actor has exactly one account.
12
12
  *
13
- * Info-leak posture (see `actor_lookup_action_specs.ts` § audit):
13
+ * Info-leak posture (see `actor_lookup_action_specs.ts` §audit):
14
14
  *
15
15
  * - Row shape **omits** `account_id` — the join is control-plane,
16
16
  * not wire-visible.
@@ -45,7 +45,7 @@
45
45
  * ## Wire shape — info-leak audit
46
46
  *
47
47
  * Output `{actors: [{id, username, display_name?}]}` is identical to
48
- * `actor_lookup`'s — see `./actor_lookup_action_specs.ts` for the full
48
+ * `actor_lookup`'s — see `auth/actor_lookup_action_specs.ts` for the full
49
49
  * field-by-field audit. Same omissions (`account_id`, email,
50
50
  * timestamps, role / role_grants / session state), same `display_name`
51
51
  * omitted-not-null contract, same response-order-unspecified rule.
@@ -45,7 +45,7 @@
45
45
  * ## Wire shape — info-leak audit
46
46
  *
47
47
  * Output `{actors: [{id, username, display_name?}]}` is identical to
48
- * `actor_lookup`'s — see `./actor_lookup_action_specs.ts` for the full
48
+ * `actor_lookup`'s — see `auth/actor_lookup_action_specs.ts` for the full
49
49
  * field-by-field audit. Same omissions (`account_id`, email,
50
50
  * timestamps, role / role_grants / session state), same `display_name`
51
51
  * omitted-not-null contract, same response-order-unspecified rule.
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Pure read — no audit, no side effects. Auth (`account: 'required'`,
5
5
  * `actor: 'none'`) + rate-limit (`account`-grain) enforced at the spec
6
- * layer; see `./actor_search_action_specs.ts` for the info-leak audit
6
+ * layer; see `auth/actor_search_action_specs.ts` for the info-leak audit
7
7
  * and threat model.
8
8
  *
9
9
  * The handler adds two checks the spec layer can't express:
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Pure read — no audit, no side effects. Auth (`account: 'required'`,
5
5
  * `actor: 'none'`) + rate-limit (`account`-grain) enforced at the spec
6
- * layer; see `./actor_search_action_specs.ts` for the info-leak audit
6
+ * layer; see `auth/actor_search_action_specs.ts` for the info-leak audit
7
7
  * and threat model.
8
8
  *
9
9
  * The handler adds two checks the spec layer can't express:
@@ -29,7 +29,7 @@
29
29
  * gates), no role_grant join — every actor with a matching prefix is
30
30
  * returned.
31
31
  *
32
- * ## Info-leak posture (see `actor_search_action_specs.ts` § audit)
32
+ * ## Info-leak posture (see `actor_search_action_specs.ts` §audit)
33
33
  *
34
34
  * - Row shape **omits** `account_id` — the join is control-plane, not
35
35
  * wire-visible. Identical to `actor_lookup_queries.ts`.
@@ -29,7 +29,7 @@
29
29
  * gates), no role_grant join — every actor with a matching prefix is
30
30
  * returned.
31
31
  *
32
- * ## Info-leak posture (see `actor_search_action_specs.ts` § audit)
32
+ * ## Info-leak posture (see `actor_search_action_specs.ts` §audit)
33
33
  *
34
34
  * - Row shape **omits** `account_id` — the join is control-plane, not
35
35
  * wire-visible. Identical to `actor_lookup_queries.ts`.
@@ -22,14 +22,14 @@
22
22
  * - Codegen that needs to see every fuz_auth surface at once
23
23
  * (typed-client filters, attack-surface reports). For typed-client
24
24
  * wiring of the standard surface, prefer `all_standard_action_specs`
25
- * in `./standard_action_specs.ts` — it mirrors the
25
+ * in `auth/standard_action_specs.ts` — it mirrors the
26
26
  * `create_standard_rpc_actions` mount and stays narrower than this
27
27
  * registry-of-registries (no opt-in bundles).
28
28
  *
29
29
  * `protocol_action_specs` (heartbeat / cancel) is **not** included —
30
30
  * those are transport-level wire-protocol concerns shipped by fuz_app
31
31
  * and spread by every consumer at registration via `protocol_actions`
32
- * from `../actions/protocol.ts`. Walker tests that need protocol
32
+ * from `actions/protocol.ts`. Walker tests that need protocol
33
33
  * coverage spread `protocol_action_specs` separately.
34
34
  *
35
35
  * @module
@@ -22,14 +22,14 @@
22
22
  * - Codegen that needs to see every fuz_auth surface at once
23
23
  * (typed-client filters, attack-surface reports). For typed-client
24
24
  * wiring of the standard surface, prefer `all_standard_action_specs`
25
- * in `./standard_action_specs.ts` — it mirrors the
25
+ * in `auth/standard_action_specs.ts` — it mirrors the
26
26
  * `create_standard_rpc_actions` mount and stays narrower than this
27
27
  * registry-of-registries (no opt-in bundles).
28
28
  *
29
29
  * `protocol_action_specs` (heartbeat / cancel) is **not** included —
30
30
  * those are transport-level wire-protocol concerns shipped by fuz_app
31
31
  * and spread by every consumer at registration via `protocol_actions`
32
- * from `../actions/protocol.ts`. Walker tests that need protocol
32
+ * from `actions/protocol.ts`. Walker tests that need protocol
33
33
  * coverage spread `protocol_action_specs` separately.
34
34
  *
35
35
  * @module
@@ -7,7 +7,7 @@
7
7
  * `GET /audit/stream` SSE route — streams aren't an action-kind, so they
8
8
  * stay on REST. The event payload broadcast on the stream surfaces via
9
9
  * `audit_log_event_specs` (one `EventSpec` per audit event type) declared
10
- * alongside the broadcaster in `../realtime/sse_auth_guard.ts`.
10
+ * alongside the broadcaster in `realtime/sse_auth_guard.ts`.
11
11
  *
12
12
  * @module
13
13
  */
@@ -7,7 +7,7 @@
7
7
  * `GET /audit/stream` SSE route — streams aren't an action-kind, so they
8
8
  * stay on REST. The event payload broadcast on the stream surfaces via
9
9
  * `audit_log_event_specs` (one `EventSpec` per audit event type) declared
10
- * alongside the broadcaster in `../realtime/sse_auth_guard.ts`.
10
+ * alongside the broadcaster in `realtime/sse_auth_guard.ts`.
11
11
  *
12
12
  * @module
13
13
  */
@@ -85,21 +85,46 @@ export declare const audit_metadata_schemas: Readonly<{
85
85
  reason: z.ZodOptional<z.ZodEnum<{
86
86
  concurrent_change: "concurrent_change";
87
87
  }>>;
88
+ credential_type: z.ZodOptional<z.ZodEnum<{
89
+ daemon_token: "daemon_token";
90
+ session: "session";
91
+ api_token: "api_token";
92
+ }>>;
88
93
  }, z.core.$loose>>;
89
94
  session_revoke: z.ZodObject<{
90
95
  session_id: z.ZodString;
96
+ credential_type: z.ZodOptional<z.ZodEnum<{
97
+ daemon_token: "daemon_token";
98
+ session: "session";
99
+ api_token: "api_token";
100
+ }>>;
91
101
  }, z.core.$loose>;
92
102
  session_revoke_all: z.ZodObject<{
93
103
  count: z.ZodOptional<z.ZodNumber>;
94
104
  reason: z.ZodOptional<z.ZodString>;
95
105
  attempted_account_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
106
+ credential_type: z.ZodOptional<z.ZodEnum<{
107
+ daemon_token: "daemon_token";
108
+ session: "session";
109
+ api_token: "api_token";
110
+ }>>;
96
111
  }, z.core.$loose>;
97
112
  token_create: z.ZodObject<{
98
113
  token_id: z.ZodString;
99
114
  name: z.ZodString;
115
+ credential_type: z.ZodOptional<z.ZodEnum<{
116
+ daemon_token: "daemon_token";
117
+ session: "session";
118
+ api_token: "api_token";
119
+ }>>;
100
120
  }, z.core.$loose>;
101
121
  token_revoke: z.ZodObject<{
102
122
  token_id: z.ZodString;
123
+ credential_type: z.ZodOptional<z.ZodEnum<{
124
+ daemon_token: "daemon_token";
125
+ session: "session";
126
+ api_token: "api_token";
127
+ }>>;
103
128
  }, z.core.$loose>;
104
129
  token_revoke_all: z.ZodObject<{
105
130
  count: z.ZodOptional<z.ZodNumber>;
@@ -1 +1 @@
1
- {"version":3,"file":"audit_log_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_log_schema.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"audit_log_schema.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_log_schema.ts"],"names":[],"mappings":"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"}
@@ -14,6 +14,17 @@ import { Blake3Hash } from '@fuzdev/fuz_util/hash_blake3.js';
14
14
  import { AuthSessionJson } from './account_schema.js';
15
15
  import { Email } from '../primitive_schemas.js';
16
16
  import { ApiTokenId } from './api_token.js';
17
+ import { BuiltinCredentialType } from './credential_type_schema.js';
18
+ /**
19
+ * Defense-in-depth audit field — records the credential channel
20
+ * (`session` / `api_token` / `daemon_token`) the request arrived on.
21
+ * Present on events whose specs declare `credential_types: ['session']`
22
+ * so forensics survive a future loosening or bypass of the spec gate.
23
+ * See `docs/security.md` §Credential-channel gating.
24
+ */
25
+ const credential_type_meta = BuiltinCredentialType.optional().meta({
26
+ description: 'Credential channel the request arrived on. Defense in depth — the spec gate restricts to `session`, but the row preserves what actually authenticated the request in case the gate is loosened or bypassed in a future refactor.',
27
+ });
17
28
  /**
18
29
  * All tracked auth event types. Frozen to convert accidental in-process
19
30
  * mutation (test cross-contamination, cast escapes) into loud TypeErrors.
@@ -102,10 +113,12 @@ export const audit_metadata_schemas = Object.freeze({
102
113
  reason: z.enum(['concurrent_change']).optional().meta({
103
114
  description: 'Failure category. `concurrent_change` indicates another password change committed first against the same starting hash (verify-write race loser). Absent for typed-wrong-password failures.',
104
115
  }),
116
+ credential_type: credential_type_meta,
105
117
  })
106
118
  .nullable(),
107
119
  session_revoke: z.looseObject({
108
120
  session_id: Blake3Hash.meta({ description: 'Blake3 hash identifying the revoked session row.' }),
121
+ credential_type: credential_type_meta,
109
122
  }),
110
123
  session_revoke_all: z.looseObject({
111
124
  // Omitted on `outcome='failure'` (no revocation attempted — e.g. target
@@ -122,13 +135,16 @@ export const audit_metadata_schemas = Object.freeze({
122
135
  attempted_account_id: Uuid.optional().meta({
123
136
  description: 'Probed account id when the target lookup missed (FK constraint forces `target_account_id` to null).',
124
137
  }),
138
+ credential_type: credential_type_meta,
125
139
  }),
126
140
  token_create: z.looseObject({
127
141
  token_id: ApiTokenId.meta({ description: 'Public id of the created API token (`tok_…`).' }),
128
142
  name: z.string().meta({ description: 'Operator-supplied label for the token.' }),
143
+ credential_type: credential_type_meta,
129
144
  }),
130
145
  token_revoke: z.looseObject({
131
146
  token_id: ApiTokenId.meta({ description: 'Public id of the revoked API token (`tok_…`).' }),
147
+ credential_type: credential_type_meta,
132
148
  }),
133
149
  token_revoke_all: z.looseObject({
134
150
  // Same shape as `session_revoke_all` for failures.
@@ -340,7 +340,7 @@ export declare const build_account_context: (deps: QueryDeps, account_id: string
340
340
  *
341
341
  * The auth phase deliberately stops short of constructing a `Response` so
342
342
  * the same failure flows through every transport without the auth-domain
343
- * code knowing about JSON-RPC. See `fuz_app/CLAUDE.md` § Cleanest
343
+ * code knowing about JSON-RPC. See `../../../CLAUDE.md` §Cleanest
344
344
  * architecture takes priority for the rationale.
345
345
  */
346
346
  export type AuthorizationFailureBody = {
@@ -70,7 +70,7 @@ export const update_env_variable = async (key, value, options) => {
70
70
  const updated_content = updated_lines.join('\n') + (has_trailing_newline ? '\n' : '');
71
71
  await write_file(file_path, updated_content, 'utf-8');
72
72
  };
73
- // Keep this tokenization aligned with `parse_dotenv` in `./dotenv.ts`:
73
+ // Keep this tokenization aligned with `parse_dotenv` in `env/dotenv.ts`:
74
74
  // trim, skip empties/comments, split on the first `=`.
75
75
  const find_last_key_line_index = (lines, key) => {
76
76
  if (!key)
@@ -5,12 +5,12 @@ surface introspection, JSON-RPC envelope + error taxonomy, proxy/origin
5
5
  middleware primitives, post-commit effect helper, generic admin route specs.
6
6
 
7
7
  **Nothing in this directory is auth-specific.** Auth middleware, routes, and
8
- guards live in `../auth/` and consume these primitives. Routes and actions in
8
+ guards live in `auth/` and consume these primitives. Routes and actions in
9
9
  other domains should do the same — extend, don't special-case.
10
10
 
11
11
  For the design rationale behind declarative routes, DEV-only output
12
12
  validation, the three-layer error-schema merge, and fire-and-forget effects,
13
- see `../../docs/architecture.md`.
13
+ see ../../docs/architecture.md.
14
14
 
15
15
  ## Module Map
16
16
 
@@ -42,7 +42,7 @@ by `generate_app_surface`. Same-shaped data, different consumers.
42
42
 
43
43
  - `method` — `'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'`
44
44
  - `path` — Hono path (supports `:param` segments)
45
- - `auth: RouteAuth` — flat record `{account, actor, roles?, credential_types?}` from `auth_shape.ts`. Each axis is `'none' | 'optional' | 'required'`. Same shape governs `ActionSpec.auth` (see `../actions/CLAUDE.md`).
45
+ - `auth: RouteAuth` — flat record `{account, actor, roles?, credential_types?}` from `auth_shape.ts`. Each axis is `'none' | 'optional' | 'required'`. Same shape governs `ActionSpec.auth` (see `actions/CLAUDE.md`).
46
46
  - `handler: RouteHandler` — `(c: Context, route: RouteContext) => Response | Promise<Response>`
47
47
  - `description` — free-text, surfaced in `AppSurface`
48
48
  - `params?: z.ZodObject` — strict-object schema for URL path params
@@ -84,7 +84,7 @@ interface RouteContext {
84
84
  `db.transaction`.
85
85
 
86
86
  Pool-level fire-and-forget writes (audit logs, etc.) run through the bound
87
- `AppDeps.audit` capability — see `../auth/CLAUDE.md` §Deps. Handlers that
87
+ `AppDeps.audit` capability — see `auth/CLAUDE.md` §Deps. Handlers that
88
88
  need rollback-resilient writes call `deps.audit.emit(route, input)`, which
89
89
  captures the pool inside the bound emitter so the row lands even when
90
90
  the handler's transaction rolls back.
@@ -98,7 +98,7 @@ the handler's transaction rolls back.
98
98
 
99
99
  Override explicitly when a mutation route must manage its own transactions
100
100
  (e.g. signup, which does a multi-step flow that can't live inside a single
101
- wrapper). See `../auth/signup_routes.ts`.
101
+ wrapper). See `auth/signup_routes.ts`.
102
102
 
103
103
  ### Validation pipeline (per-route middleware order)
104
104
 
@@ -114,7 +114,7 @@ wrapper). See `../auth/signup_routes.ts`.
114
114
  or `auth.actor === 'required'`. Fires before any body parsing so
115
115
  unauthenticated callers never see route-shape information from
116
116
  input parse failures. The `AuthGuardResolver` (e.g.
117
- `fuz_auth_guard_resolver` from `../auth/auth_guard_resolver.ts`) returns
117
+ `fuz_auth_guard_resolver` from `auth/auth_guard_resolver.ts`) returns
118
118
  this set as `pre_validation: Array<MiddlewareHandler>`.
119
119
  4. **Input validation** — JSON body parsed + validated; mismatch returns
120
120
  400 `ERROR_INVALID_JSON_BODY` (not JSON) or `ERROR_INVALID_REQUEST_BODY`
@@ -191,7 +191,7 @@ are the contract with external callers.
191
191
 
192
192
  The production behavior short-circuits to the unwrapped handler — no
193
193
  parse work on the hot path. Uniform across all three action-handler
194
- surfaces (REST, RPC, WS); see `../../docs/architecture.md` §DEV-only
194
+ surfaces (REST, RPC, WS); see ../../docs/architecture.md §DEV-only
195
195
  Output Validation.
196
196
 
197
197
  ### Helpers
@@ -205,8 +205,8 @@ Output Validation.
205
205
 
206
206
  `error_schemas.ts` is the **declarative** error surface:
207
207
 
208
- - `ERROR_*` snake*case string constants — single source of truth; use
209
- `.literal(ERROR*\*)` in Zod schemas and inline checks in handlers
208
+ - `ERROR_*` `snake_case` string constants — single source of truth; use
209
+ `.literal(ERROR_*)` in Zod schemas and inline checks in handlers
210
210
  - `ApiError`, `ValidationError`, `PermissionError`,
211
211
  `CredentialTypeRequiredError`, `RateLimitError`, `PayloadTooLargeError`,
212
212
  `ForeignKeyError` — standard shapes
@@ -413,7 +413,7 @@ connection is from a configured trusted proxy. Without this middleware,
413
413
  `get_client_ip(c)` returns `'unknown'`.
414
414
 
415
415
  Must run **before** auth and rate-limiting middleware. See the root
416
- `../../CLAUDE.md` §Middleware Ordering.
416
+ ../../CLAUDE.md §Middleware Ordering.
417
417
 
418
418
  - `normalize_ip(ip)` — idempotent: lowercase + strip `::ffff:` prefix on
419
419
  IPv4-mapped IPv6 addresses; safe on non-IP strings (`'unknown'` → `'unknown'`).
@@ -465,7 +465,7 @@ don't include ports — bounded by operator configuration in practice.
465
465
 
466
466
  Origin allowlisting for locally-running services — **not** the CSRF
467
467
  layer. CSRF is handled by `SameSite: strict` on session cookies (see
468
- `../auth/session_middleware.ts`).
468
+ `auth/session_middleware.ts`).
469
469
 
470
470
  - `parse_allowed_origins(env_value)` — comma-separated patterns → `Array<RegExp>`
471
471
  - `should_allow_origin(origin, patterns)` — case-insensitive match
@@ -664,7 +664,7 @@ emit_after_commit(ctx, () => notification_sender.send_to_account(account_id, msg
664
664
  ```
665
665
 
666
666
  Used for WS sends (`NotificationSender.send_to_account` for
667
- role-grant-offer notifications — see `../auth/CLAUDE.md` §WS notifications)
667
+ role-grant-offer notifications — see `auth/CLAUDE.md` §WS notifications)
668
668
  and any side effect that must run only after the transaction commits.
669
669
 
670
670
  ### Key properties
@@ -712,7 +712,7 @@ auth-domain dependencies:
712
712
  surface data reveals API structure (schemas, auth, routes)
713
713
 
714
714
  Auth-aware variants (account status, bootstrap status) live in
715
- `../auth/` — `common_routes.ts` stays generic.
715
+ `auth/` — `common_routes.ts` stays generic.
716
716
 
717
717
  ## DB Routes (Generic Browser)
718
718
 
@@ -743,7 +743,7 @@ Interfaces exported for consumer use: `TableInfo`, `TableWithCount`,
743
743
  ## Cross-Module Notes
744
744
 
745
745
  - **Middleware ordering** is assembled by `create_app_server` — see the
746
- root `../../CLAUDE.md` §Middleware Ordering. The invariants `http/`
746
+ root ../../CLAUDE.md §Middleware Ordering. The invariants `http/`
747
747
  needs consumers to uphold: trusted-proxy runs before auth/rate-limit;
748
748
  origin verification runs before session parsing; `client_ip` must be
749
749
  set before any handler or rate limiter reads it
@@ -753,7 +753,7 @@ Interfaces exported for consumer use: `TableInfo`, `TableWithCount`,
753
753
  - **Input/output schemas align with SAES.** When wiring RPC via
754
754
  `actions/action_rpc.ts` or bridging to `RouteSpec` via
755
755
  `actions/action_bridge.ts`, the same Zod types flow through unchanged
756
- (see `../actions/CLAUDE.md` §Single JSON-RPC 2.0 endpoint and §HTTP bridge)
756
+ (see `actions/CLAUDE.md` §Single JSON-RPC 2.0 endpoint and §HTTP bridge)
757
757
  - **Error modules are complementary, not redundant.** `error_schemas.ts`
758
758
  is Zod-first (for routes and surface); `jsonrpc_errors.ts` is
759
759
  throw-first (for handlers and the catch layer). A single `ERROR_*`
@@ -6,23 +6,17 @@ round-trip harnesses. Consumers import these to assemble their own test suites
6
6
  against a fuz_app-derived server.
7
7
 
8
8
  For narrative wiring examples (how to call these from a consumer's vitest
9
- setup), see `../../../docs/testing.md`. For fuz_app's own test suite
10
- conventions (`.db.test.ts` suffix, the `db` vitest project, `assert_rejects`),
11
- see `../../test/CLAUDE.md`. This file is a reference index for the helpers
12
- themselves.
9
+ setup), see ../../../docs/testing.md. For fuz_app's own test suite
10
+ conventions, see ../../test/CLAUDE.md. For shared testing conventions
11
+ (`.db.test.ts`, `assert` from vitest, `assert_rejects`, `vi.mock` caveats),
12
+ see Skill(fuz-stack) testing-patterns. This file is a reference index for
13
+ the helpers themselves.
13
14
 
14
15
  ## Production guard — always the first import
15
16
 
16
- Every module in this directory starts with `import './assert_dev_env.js';`
17
- as its first line. The side-effect import reads `DEV` from `esm-env` and
18
- throws if it is false preventing accidental inclusion in production
19
- bundles. SvelteKit and Vite set `DEV` correctly for dev + tests; the
20
- production code path explodes at the first testing-module import.
21
-
22
- When adding a new module to this directory, make this import the first
23
- line. The convention is enforced by grep, not by a linter — break it and
24
- the production bundle still builds, then crashes at runtime on first
25
- module load.
17
+ Every module here starts with `import './assert_dev_env.js';` — reads `DEV`
18
+ from `esm-env` and throws if false, preventing production-bundle inclusion.
19
+ Enforced by grep, not a linter; make this the first line in new modules.
26
20
 
27
21
  ## Stubs, factories, mocks
28
22
 
@@ -40,7 +34,7 @@ module load.
40
34
  | `create_stub_app_deps()` | Factory returning fresh `AppDeps` with no-op FS/keyring/password, a `create_noop_stub` DB, silent `Logger`, no-op `audit`. |
41
35
  | `create_test_audit_emitter()` | No-op `AuditEmitter` for tests that don't assert on audit fan-out. `emit` / `emit_role_grant_target` are no-ops; `emit_pool` resolves immediately; `notify` is a no-op; `on_event_chain` is empty. |
42
36
  | `create_stub_audit_sse()` | No-op `AuditLogSse` for surface-test wiring without booting real SSE. `subscribe` returns a no-op cleanup; `on_audit_event` is a no-op; the `registry` is a fresh `SubscriberRegistry` (live `.size` / `.close_*` for tests touching registry state, isolated per call). For real SSE plumbing, build via `create_audit_log_sse` against `create_test_app`. |
43
- | `create_stub_api_middleware({include_daemon_token?})` | Stub `MiddlewareSpec[]` matching `create_auth_middleware_specs`'s output (origin/session/request_context/bearer_auth, optional daemon_token) for surface generation without booting real auth. See `../auth/CLAUDE.md` §Middleware for the real stack. |
37
+ | `create_stub_api_middleware({include_daemon_token?})` | Stub `MiddlewareSpec[]` matching `create_auth_middleware_specs`'s output (origin/session/request_context/bearer_auth, optional daemon_token) for surface generation without booting real auth. See `auth/CLAUDE.md` §Middleware for the real stack. |
44
38
  | `create_stub_app_server_context(session_options)` | Stub `AppServerContext` — rate limiters null, `bootstrap_status.available: false`, `app_settings.open_signup: false`. |
45
39
  | `create_test_app_surface_spec(options)` | Builds an `AppSurfaceSpec` that mirrors `create_app_server`'s route assembly: consumer routes + factory-managed bootstrap routes (prefixed via `bootstrap_route_prefix`, default `'/api/account'`) + stub middleware + surface generation. `CreateTestAppSurfaceSpecOptions` accepts `session_options`, `create_route_specs`, `env_schema?`, `event_specs?`, `rpc_endpoints?`, `transform_middleware?`, `bootstrap_route_prefix?`. Single source of truth for attack-surface tests — track `create_app_server` wiring changes here. |
46
40
 
@@ -572,7 +566,7 @@ Options: `{session_options, create_route_specs, app_options?, db_factories?}`.
572
566
 
573
567
  7 test groups covering admin surface: account listing, role_grant grant
574
568
  lifecycle (via `role_grant_offer_create` + `role_grant_revoke` RPC flows —
575
- **not** REST; see `../auth/CLAUDE.md` for `role_grant_offer_action_specs.ts` + `role_grant_offer_actions.ts`), session / token management, audit log reads (RPC),
569
+ **not** REST; see `auth/CLAUDE.md` for `role_grant_offer_action_specs.ts` + `role_grant_offer_actions.ts`), session / token management, audit log reads (RPC),
576
570
  admin-to-admin isolation, error coverage, response schema validation.
577
571
 
578
572
  Required options: `{session_options, create_route_specs, roles: RoleSchemaResult, rpc_endpoints: RpcEndpointsSuiteOption, admin_prefix?, app_options?, db_factories?}`.
@@ -688,7 +682,7 @@ Registry lookups:
688
682
  - unauthenticated → `unauthenticated` (code -32001)
689
683
  - wrong role → `forbidden` (-32002)
690
684
  - authenticated without role → `forbidden`
691
- - **keeper rejects non-daemon credentials** — session and api_token credentials are rejected even when the account has the keeper role (only `daemon_token` passes). The credential-type gate fires before the role gate (see `../auth/CLAUDE.md` §`request_context.ts` for `require_credential_types`).
685
+ - **keeper rejects non-daemon credentials** — session and api_token credentials are rejected even when the account has the keeper role (only `daemon_token` passes). The credential-type gate fires before the role gate (see `auth/CLAUDE.md` §`request_context.ts` for `require_credential_types`).
692
686
  - correct auth passes (not 401/403)
693
687
  - GET unauthenticated for `side_effects: false` reads
694
688
  2. **RPC adversarial envelopes** — fixed set exercising dispatcher steps 1–2: non-JSON body, wrong `jsonrpc` version, missing `jsonrpc` / `method` / `id`, batch array, unknown method, GET missing `method`/`id`, GET invalid JSON params, GET non-object params, GET mutation method → `invalid_request`.
@@ -705,42 +699,32 @@ not folded into `create_standard_rpc_actions` (today `self_service_role_actions`
705
699
  / round-trip coverage from `describe_rpc_attack_surface_tests` +
706
700
  `describe_rpc_round_trip_tests` unless the consumer ships a
707
701
  `<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
702
+ endpoint and calling both suites. See ../../test/CLAUDE.md §Composable
709
703
  Test Suites for the obligation note; existing
710
- `../../test/auth/*.rpc_suites.db.test.ts` files are templates.
704
+ ../../test/auth/\*.rpc_suites.db.test.ts files are templates.
711
705
 
712
706
  ## Cross-cutting conventions
713
707
 
714
- - **`assert` from vitest, not `expect`.** Project-wide convention
715
- (mirrored in `src/test/CLAUDE.md`). Use `assert_rejects` from
716
- `@fuzdev/fuz_util/testing.js` for async rejection assertions.
717
- - **`.db.test.ts` suffix** for any test file that instantiates a `Db`
718
- (directly or via `create_test_app`, `create_describe_db`,
719
- `create_pglite_factory`). The suffix opts the file into the `db`
720
- vitest project (`isolate: false`, `fileParallelism: false`) so the
721
- PGlite WASM cache is shared across every DB test file.
708
+ Shared conventions (`.db.test.ts` suffix, `isolate: false` semantics,
709
+ `assert` from vitest, `assert_rejects`, `vi.mock` avoidance under
710
+ `isolate: false`) live in Skill(fuz-stack) testing-patterns.
711
+ fuz_app-specific points:
712
+
722
713
  - **`await_pending_effects: true`** is set by `create_test_app`.
723
714
  Fire-and-forget effects (audit logs, session touches, WS fan-out via
724
715
  `emit_after_commit`) resolve before the response returns, so tests
725
716
  can assert on side effects inline without manual flushing.
726
- - **Avoid `vi.mock()` inside `.db.test.ts`.** With `isolate: false`,
727
- module-level mocks leak across files. When a mock is unavoidable
728
- (e.g. `middleware.ts` uses them module-level for bearer auth tests),
729
- always pair with `vi.restoreAllMocks()` in `afterEach` to contain
730
- the blast radius.
731
- - **Deep-path imports only.** `testing/` follows the package
732
- convention import from the canonical module (`./db.js`,
733
- `./rpc_helpers.js`, etc.), never a barrel. fuz_app's `dist/` doesn't
734
- ship one.
735
- - **DI via small `*Deps` interfaces.** Stub factories here accept the
736
- same narrow `*Deps` contracts production code uses — never
737
- `Pick<GodType, ...>`. New helpers that need env/fs/logger access
738
- should take `EnvDeps` / `FsReadDeps` / `Logger` from
739
- `runtime/deps.ts` or `@fuzdev/fuz_util/log.js`.
717
+ - **Deep-path imports only.** Import from the canonical module
718
+ (`testing/db.js`, `testing/rpc_helpers.js`, etc.); fuz_app's `dist/` ships no
719
+ barrel.
720
+ - **DI via small `*Deps` interfaces.** Stub factories accept the same
721
+ narrow `*Deps` contracts production code uses — never
722
+ `Pick<GodType, ...>`. New helpers needing env/fs/logger take
723
+ `EnvDeps` / `FsReadDeps` / `Logger` from `runtime/deps.ts` or
724
+ `@fuzdev/fuz_util/log.js`.
740
725
  - **Keep the shared echo routes in sync with public surface.** When
741
726
  middleware or public API gains a new context variable, header, or
742
727
  field, update the echo in `middleware.ts`
743
728
  (`create_bearer_auth_test_app`, `create_test_middleware_stack_app`)
744
- alongside the assertions in `src/test/auth/*.test.ts`. The two move
745
- together — drift between them shows up as a missed assertion, not a
746
- test failure.
729
+ alongside the assertions in `src/test/auth/*.test.ts`. Drift surfaces
730
+ as a missed assertion, not a test failure.
@@ -1 +1 @@
1
- {"version":3,"file":"audit_completeness.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/audit_completeness.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAkB7B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAIrD,OAAO,EAGN,KAAK,eAAe,EAEpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAIN,KAAK,SAAS,EACd,MAAM,SAAS,CAAC;AAKjB,OAAO,EAIN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAqB1B;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC5C,4CAA4C;IAC5C,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,wDAAwD;IACxD,kBAAkB,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAChE;;;;;;;;;;;OAWG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC,iDAAiD;IACjD,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,qEAAqE;IACrE,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;CAChC;AAoDD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iCAAiC,GAAI,SAAS,4BAA4B,KAAG,IAkgBzF,CAAC"}
1
+ {"version":3,"file":"audit_completeness.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/testing/audit_completeness.ts"],"names":[],"mappings":"AAAA,OAAO,qBAAqB,CAAC;AAkB7B,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAIrD,OAAO,EAGN,KAAK,eAAe,EAEpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAIN,KAAK,SAAS,EACd,MAAM,SAAS,CAAC;AAKjB,OAAO,EAIN,KAAK,uBAAuB,EAC5B,MAAM,kBAAkB,CAAC;AAqB1B;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC5C,4CAA4C;IAC5C,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,wDAAwD;IACxD,kBAAkB,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,KAAK,CAAC,SAAS,CAAC,CAAC;IAChE;;;;;;;;;;;OAWG;IACH,aAAa,EAAE,uBAAuB,CAAC;IACvC,iDAAiD;IACjD,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,qEAAqE;IACrE,YAAY,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;CAChC;AA2ED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,iCAAiC,GAAI,SAAS,4BAA4B,KAAG,IAihBzF,CAAC"}