@fuzdev/fuz_app 0.59.0 → 0.60.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 (95) hide show
  1. package/dist/actions/CLAUDE.md +5 -5
  2. package/dist/actions/action_codegen.d.ts +1 -1
  3. package/dist/actions/action_codegen.js +2 -2
  4. package/dist/actions/action_event_helpers.d.ts +3 -3
  5. package/dist/actions/action_event_helpers.js +8 -8
  6. package/dist/actions/action_event_types.d.ts +3 -3
  7. package/dist/actions/action_event_types.js +3 -3
  8. package/dist/actions/transports_ws_auth_guard.d.ts +2 -2
  9. package/dist/actions/transports_ws_auth_guard.js +3 -3
  10. package/dist/auth/CLAUDE.md +157 -15
  11. package/dist/auth/actor_lookup_action_specs.d.ts +127 -0
  12. package/dist/auth/actor_lookup_action_specs.d.ts.map +1 -0
  13. package/dist/auth/actor_lookup_action_specs.js +93 -0
  14. package/dist/auth/actor_lookup_actions.d.ts +19 -0
  15. package/dist/auth/actor_lookup_actions.d.ts.map +1 -0
  16. package/dist/auth/actor_lookup_actions.js +32 -0
  17. package/dist/auth/actor_lookup_queries.d.ts +44 -0
  18. package/dist/auth/actor_lookup_queries.d.ts.map +1 -0
  19. package/dist/auth/actor_lookup_queries.js +42 -0
  20. package/dist/auth/actor_search_action_specs.d.ts +166 -0
  21. package/dist/auth/actor_search_action_specs.d.ts.map +1 -0
  22. package/dist/auth/actor_search_action_specs.js +139 -0
  23. package/dist/auth/actor_search_actions.d.ts +31 -0
  24. package/dist/auth/actor_search_actions.d.ts.map +1 -0
  25. package/dist/auth/actor_search_actions.js +61 -0
  26. package/dist/auth/actor_search_queries.d.ts +75 -0
  27. package/dist/auth/actor_search_queries.d.ts.map +1 -0
  28. package/dist/auth/actor_search_queries.js +91 -0
  29. package/dist/auth/admin_actions.js +2 -2
  30. package/dist/auth/all_action_spec_registries.d.ts +55 -0
  31. package/dist/auth/all_action_spec_registries.d.ts.map +1 -0
  32. package/dist/auth/all_action_spec_registries.js +59 -0
  33. package/dist/auth/audit_emitter.d.ts +1 -1
  34. package/dist/auth/audit_emitter.js +2 -2
  35. package/dist/auth/audit_log_queries.d.ts +1 -1
  36. package/dist/auth/audit_log_queries.js +3 -3
  37. package/dist/auth/audit_log_routes.d.ts +1 -1
  38. package/dist/auth/audit_log_routes.js +1 -1
  39. package/dist/auth/audit_log_schema.d.ts +5 -5
  40. package/dist/auth/audit_log_schema.js +7 -7
  41. package/dist/auth/auth_ddl.d.ts +7 -0
  42. package/dist/auth/auth_ddl.d.ts.map +1 -1
  43. package/dist/auth/auth_ddl.js +8 -0
  44. package/dist/auth/credential_type_schema.d.ts +1 -1
  45. package/dist/auth/credential_type_schema.js +3 -3
  46. package/dist/auth/grant_path_schema.d.ts +1 -1
  47. package/dist/auth/grant_path_schema.js +3 -3
  48. package/dist/auth/migrations.d.ts +4 -4
  49. package/dist/auth/migrations.d.ts.map +1 -1
  50. package/dist/auth/migrations.js +7 -6
  51. package/dist/auth/role_grant_offer_actions.js +2 -2
  52. package/dist/auth/role_grant_offer_notifications.d.ts +2 -2
  53. package/dist/auth/role_grant_offer_notifications.js +2 -2
  54. package/dist/auth/role_grant_queries.d.ts +21 -0
  55. package/dist/auth/role_grant_queries.d.ts.map +1 -1
  56. package/dist/auth/role_grant_queries.js +31 -0
  57. package/dist/auth/role_schema.d.ts +2 -2
  58. package/dist/auth/role_schema.js +3 -3
  59. package/dist/auth/self_service_role_actions.d.ts +1 -1
  60. package/dist/auth/self_service_role_actions.js +2 -2
  61. package/dist/auth/session_cookie.d.ts +1 -1
  62. package/dist/auth/session_cookie.js +1 -1
  63. package/dist/auth/session_middleware.d.ts +1 -1
  64. package/dist/auth/session_middleware.js +5 -5
  65. package/dist/rate_limiter.d.ts +5 -5
  66. package/dist/rate_limiter.js +6 -6
  67. package/dist/realtime/sse_auth_guard.d.ts +3 -3
  68. package/dist/realtime/sse_auth_guard.js +4 -4
  69. package/dist/server/app_backend.d.ts +3 -3
  70. package/dist/server/app_backend.js +4 -4
  71. package/dist/server/app_server.d.ts +1 -1
  72. package/dist/server/app_server.js +10 -10
  73. package/dist/testing/CLAUDE.md +22 -12
  74. package/dist/testing/admin_integration.js +4 -4
  75. package/dist/testing/app_server.d.ts +1 -1
  76. package/dist/testing/app_server.js +2 -2
  77. package/dist/testing/attack_surface.d.ts +4 -4
  78. package/dist/testing/attack_surface.js +6 -6
  79. package/dist/testing/audit_completeness.js +4 -4
  80. package/dist/testing/data_exposure.d.ts +2 -2
  81. package/dist/testing/data_exposure.js +7 -7
  82. package/dist/testing/db.d.ts +8 -8
  83. package/dist/testing/db.js +11 -11
  84. package/dist/testing/integration.js +4 -4
  85. package/dist/testing/integration_helpers.d.ts +6 -6
  86. package/dist/testing/integration_helpers.js +7 -7
  87. package/dist/testing/rate_limiting.js +4 -4
  88. package/dist/testing/round_trip.js +2 -2
  89. package/dist/testing/rpc_round_trip.js +2 -2
  90. package/dist/testing/schema_generators.d.ts.map +1 -1
  91. package/dist/testing/schema_generators.js +23 -2
  92. package/dist/testing/sse_round_trip.js +2 -2
  93. package/dist/testing/surface_invariants.d.ts +4 -4
  94. package/dist/testing/surface_invariants.js +5 -5
  95. package/package.json +1 -1
@@ -17,7 +17,7 @@
17
17
  *
18
18
  * To add a migration in the pre-stable phase, prefer extending an existing
19
19
  * entry's body (consumers will re-bootstrap on upgrade). If you do append
20
- * a new entry to `AUTH_MIGRATIONS`, the runner will apply it on existing
20
+ * a new entry to `auth_migrations`, the runner will apply it on existing
21
21
  * tracker rows — the same shape that will become mandatory once the
22
22
  * schema stabilizes:
23
23
  *
@@ -36,7 +36,7 @@
36
36
  *
37
37
  * @module
38
38
  */
39
- import { ACCOUNT_SCHEMA, ACCOUNT_EMAIL_INDEX, ACCOUNT_USERNAME_CI_INDEX, ACTOR_SCHEMA, ACTOR_INDEX, ROLE_GRANT_SCHEMA, ROLE_GRANT_INDEXES, AUTH_SESSION_SCHEMA, AUTH_SESSION_INDEXES, API_TOKEN_SCHEMA, API_TOKEN_INDEX, BOOTSTRAP_LOCK_SCHEMA, BOOTSTRAP_LOCK_SEED, INVITE_SCHEMA, INVITE_INDEXES, APP_SETTINGS_SCHEMA, APP_SETTINGS_SEED, } from './auth_ddl.js';
39
+ import { ACCOUNT_SCHEMA, ACCOUNT_EMAIL_INDEX, ACCOUNT_USERNAME_CI_INDEX, ACTOR_SCHEMA, ACTOR_INDEX, ACTOR_NAME_LOWER_INDEX, ROLE_GRANT_SCHEMA, ROLE_GRANT_INDEXES, AUTH_SESSION_SCHEMA, AUTH_SESSION_INDEXES, API_TOKEN_SCHEMA, API_TOKEN_INDEX, BOOTSTRAP_LOCK_SCHEMA, BOOTSTRAP_LOCK_SEED, INVITE_SCHEMA, INVITE_INDEXES, APP_SETTINGS_SCHEMA, APP_SETTINGS_SEED, } from './auth_ddl.js';
40
40
  import { AUDIT_LOG_SCHEMA, AUDIT_LOG_INDEXES } from './audit_log_ddl.js';
41
41
  import { ROLE_GRANT_OFFER_SCHEMA, ROLE_GRANT_OFFER_PENDING_UNIQUE_INDEX, ROLE_GRANT_OFFER_INBOX_INDEX, ROLE_GRANT_OFFER_SCOPE_SENTINEL_UUID, ROLE_GRANT_OFFER_SCOPE_KIND_GLOBAL_TOKEN, } from './role_grant_offer_ddl.js';
42
42
  /** Namespace identifier for fuz_app auth migrations. */
@@ -48,7 +48,7 @@ export const AUTH_MIGRATION_NAMESPACE = 'fuz_auth';
48
48
  * as `ReadonlyArray<string>` (not a literal tuple) so `.includes()` accepts
49
49
  * any consumer-supplied namespace string without a cast.
50
50
  */
51
- export const RESERVED_MIGRATION_NAMESPACES = [AUTH_MIGRATION_NAMESPACE];
51
+ export const reserved_migration_namespaces = [AUTH_MIGRATION_NAMESPACE];
52
52
  /**
53
53
  * Auth schema migrations in order.
54
54
  *
@@ -69,7 +69,7 @@ export const RESERVED_MIGRATION_NAMESPACES = [AUTH_MIGRATION_NAMESPACE];
69
69
  * (registry-membership validation against `create_scope_kind_schema`);
70
70
  * v2 may add INSERT-time `(role, scope_kind)` enforcement.
71
71
  */
72
- export const AUTH_MIGRATIONS = [
72
+ export const auth_migrations = [
73
73
  // v0: full auth schema — all IF NOT EXISTS, safe for existing databases
74
74
  {
75
75
  name: 'full_auth_schema',
@@ -79,6 +79,7 @@ export const AUTH_MIGRATIONS = [
79
79
  await db.query(ACCOUNT_USERNAME_CI_INDEX);
80
80
  await db.query(ACTOR_SCHEMA);
81
81
  await db.query(ACTOR_INDEX);
82
+ await db.query(ACTOR_NAME_LOWER_INDEX);
82
83
  await db.query(ROLE_GRANT_SCHEMA);
83
84
  for (const sql of ROLE_GRANT_INDEXES) {
84
85
  await db.query(sql);
@@ -150,7 +151,7 @@ export const AUTH_MIGRATIONS = [
150
151
  },
151
152
  ];
152
153
  /** Pre-composed migration namespace for auth tables. */
153
- export const AUTH_MIGRATION_NS = {
154
+ export const auth_migration_ns = {
154
155
  namespace: AUTH_MIGRATION_NAMESPACE,
155
- migrations: AUTH_MIGRATIONS,
156
+ migrations: auth_migrations,
156
157
  };
@@ -40,7 +40,7 @@
40
40
  import { rpc_action, } from '../actions/action_rpc.js';
41
41
  import { jsonrpc_errors } from '../http/jsonrpc_errors.js';
42
42
  import { emit_after_commit } from '../http/pending_effects.js';
43
- import { BUILTIN_ROLE_SPECS_BY_NAME, ROLE_ADMIN, role_has_grant_path, } from './role_schema.js';
43
+ import { builtin_role_specs_by_name, ROLE_ADMIN, role_has_grant_path, } from './role_schema.js';
44
44
  import { GRANT_PATH_ADMIN } from './grant_path_schema.js';
45
45
  import { ROLE_GRANT_OFFER_DEFAULT_TTL_MS, to_role_grant_offer_json, } from './role_grant_offer_schema.js';
46
46
  import { query_role_grant_offer_create, query_role_grant_offer_decline, query_role_grant_offer_retract, query_role_grant_offer_list, query_role_grant_offer_history_for_account, query_accept_offer, RoleGrantOfferActorAccountMismatchError, RoleGrantOfferActorMismatchError, RoleGrantOfferAlreadyTerminalError, RoleGrantOfferExpiredError, RoleGrantOfferNotFoundError, RoleGrantOfferSelfTargetError, } from './role_grant_offer_queries.js';
@@ -108,7 +108,7 @@ export const authorize_admin_or_holder = async (auth, input, _deps, _ctx) => {
108
108
  */
109
109
  export const create_role_grant_offer_actions = (deps, options = {}) => {
110
110
  const { log, audit, notification_sender = null } = deps;
111
- const role_specs = options.roles?.role_specs ?? BUILTIN_ROLE_SPECS_BY_NAME;
111
+ const role_specs = options.roles?.role_specs ?? builtin_role_specs_by_name;
112
112
  const default_ttl_ms = options.default_ttl_ms ?? ROLE_GRANT_OFFER_DEFAULT_TTL_MS;
113
113
  const authorize = options.authorize ?? default_authorize;
114
114
  // Four denial paths (admin-grant-path gate, authorize, self-target,
@@ -23,7 +23,7 @@
23
23
  * `NotificationSender.send_to_account` argument), not in the payload.
24
24
  *
25
25
  * The specs surface as `EventSpec`s via `create_action_event_spec` — callers
26
- * append `ROLE_GRANT_OFFER_NOTIFICATION_SPECS` to their `event_specs` on
26
+ * append `role_grant_offer_notification_specs` to their `event_specs` on
27
27
  * `create_app_server` so the surface reflects them and DEV-mode broadcast
28
28
  * validation catches payload drift.
29
29
  *
@@ -376,7 +376,7 @@ export declare const role_grant_revoke_notification_spec: {
376
376
  * Pass to `create_app_server`'s `event_specs` so the attack surface reflects
377
377
  * them and DEV-mode `create_validated_broadcaster` catches payload drift.
378
378
  */
379
- export declare const ROLE_GRANT_OFFER_NOTIFICATION_SPECS: Array<EventSpec>;
379
+ export declare const role_grant_offer_notification_specs: Array<EventSpec>;
380
380
  export declare const build_role_grant_offer_received_notification: (params: RoleGrantOfferReceivedParams) => JsonrpcNotification;
381
381
  export declare const build_role_grant_offer_retracted_notification: (params: RoleGrantOfferRetractedParams) => JsonrpcNotification;
382
382
  export declare const build_role_grant_offer_accepted_notification: (params: RoleGrantOfferAcceptedParams) => JsonrpcNotification;
@@ -23,7 +23,7 @@
23
23
  * `NotificationSender.send_to_account` argument), not in the payload.
24
24
  *
25
25
  * The specs surface as `EventSpec`s via `create_action_event_spec` — callers
26
- * append `ROLE_GRANT_OFFER_NOTIFICATION_SPECS` to their `event_specs` on
26
+ * append `role_grant_offer_notification_specs` to their `event_specs` on
27
27
  * `create_app_server` so the surface reflects them and DEV-mode broadcast
28
28
  * validation catches payload drift.
29
29
  *
@@ -165,7 +165,7 @@ export const role_grant_revoke_notification_spec = {
165
165
  * Pass to `create_app_server`'s `event_specs` so the attack surface reflects
166
166
  * them and DEV-mode `create_validated_broadcaster` catches payload drift.
167
167
  */
168
- export const ROLE_GRANT_OFFER_NOTIFICATION_SPECS = [
168
+ export const role_grant_offer_notification_specs = [
169
169
  create_action_event_spec(role_grant_offer_received_notification_spec),
170
170
  create_action_event_spec(role_grant_offer_retracted_notification_spec),
171
171
  create_action_event_spec(role_grant_offer_accepted_notification_spec),
@@ -113,6 +113,27 @@ export declare const query_role_grant_find_active_for_actor: (deps: QueryDeps, a
113
113
  * The `IS NOT DISTINCT FROM` comparison handles the NULL case uniformly.
114
114
  */
115
115
  export declare const query_role_grant_has_role: (deps: QueryDeps, actor_id: string, role: string, scope_id?: string | null) => Promise<boolean>;
116
+ /**
117
+ * Account-grain check: does any actor on `account_id` hold an active
118
+ * global role_grant for `role`?
119
+ *
120
+ * Symmetric with `query_role_grant_has_role` but keyed on the account
121
+ * instead of a single actor — for surfaces with `auth: actor: 'none'`
122
+ * that don't load `auth.role_grants` and can't use the in-memory
123
+ * `has_scoped_role` predicate. Joins `role_grant` → `actor`; matches
124
+ * only global role_grants (`scope_id IS NULL`) since the use case is
125
+ * "is the caller's account broadly admin", not scope-aware.
126
+ *
127
+ * Fast under the existing `idx_role_grant_actor` index — the inner
128
+ * `actor_id IN (...)` subquery is index-scan, and the outer EXISTS
129
+ * stops at the first match.
130
+ *
131
+ * @param deps - query dependencies
132
+ * @param account_id - the account to check
133
+ * @param role - the role to check for (e.g. `ROLE_ADMIN`)
134
+ * @returns `true` if any actor on the account has an active global role_grant for `role`
135
+ */
136
+ export declare const query_account_has_global_role: (deps: QueryDeps, account_id: string, role: string) => Promise<boolean>;
116
137
  /**
117
138
  * List all role_grants for an actor (including revoked/expired).
118
139
  */
@@ -1 +1 @@
1
- {"version":3,"file":"role_grant_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/role_grant_queries.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"role_grant_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/role_grant_queries.ts"],"names":[],"mappings":"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"}
@@ -180,6 +180,37 @@ export const query_role_grant_has_role = async (deps, actor_id, role, scope_id)
180
180
  ) AS exists`, [actor_id, role, scope_id ?? null]);
181
181
  return row?.exists ?? false;
182
182
  };
183
+ /**
184
+ * Account-grain check: does any actor on `account_id` hold an active
185
+ * global role_grant for `role`?
186
+ *
187
+ * Symmetric with `query_role_grant_has_role` but keyed on the account
188
+ * instead of a single actor — for surfaces with `auth: actor: 'none'`
189
+ * that don't load `auth.role_grants` and can't use the in-memory
190
+ * `has_scoped_role` predicate. Joins `role_grant` → `actor`; matches
191
+ * only global role_grants (`scope_id IS NULL`) since the use case is
192
+ * "is the caller's account broadly admin", not scope-aware.
193
+ *
194
+ * Fast under the existing `idx_role_grant_actor` index — the inner
195
+ * `actor_id IN (...)` subquery is index-scan, and the outer EXISTS
196
+ * stops at the first match.
197
+ *
198
+ * @param deps - query dependencies
199
+ * @param account_id - the account to check
200
+ * @param role - the role to check for (e.g. `ROLE_ADMIN`)
201
+ * @returns `true` if any actor on the account has an active global role_grant for `role`
202
+ */
203
+ export const query_account_has_global_role = async (deps, account_id, role) => {
204
+ const row = await deps.db.query_one(`SELECT EXISTS(
205
+ SELECT 1 FROM role_grant
206
+ WHERE actor_id IN (SELECT id FROM actor WHERE account_id = $1)
207
+ AND role = $2
208
+ AND scope_id IS NULL
209
+ AND revoked_at IS NULL
210
+ AND (expires_at IS NULL OR expires_at > NOW())
211
+ ) AS exists`, [account_id, role]);
212
+ return row?.exists ?? false;
213
+ };
183
214
  /**
184
215
  * List all role_grants for an actor (including revoked/expired).
185
216
  */
@@ -63,7 +63,7 @@ export type BuiltinRole = z.infer<typeof BuiltinRole>;
63
63
  * flows. Only useful for diagnostic snapshotting.
64
64
  *
65
65
  * Builtins (`keeper`, `admin`) ship preconfigured in
66
- * `BUILTIN_ROLE_SPECS_BY_NAME`.
66
+ * `builtin_role_specs_by_name`.
67
67
  */
68
68
  export interface RoleSpec {
69
69
  /** Unique role name. Must match `RoleName` regex; collisions with builtins throw. */
@@ -105,7 +105,7 @@ export interface RoleSpec {
105
105
  * no effect on already-built role schemas (the factory copies entries
106
106
  * into a fresh `Map`).
107
107
  */
108
- export declare const BUILTIN_ROLE_SPECS_BY_NAME: ReadonlyMap<string, RoleSpec>;
108
+ export declare const builtin_role_specs_by_name: ReadonlyMap<string, RoleSpec>;
109
109
  /** Optional registries to validate `RoleSpec` cross-axis fields against at construction time. */
110
110
  export interface CreateRoleSchemaOptions {
111
111
  /** Pass `create_credential_type_schema()` to validate `RoleSpec.required_credential_types` entries. */
@@ -44,7 +44,7 @@ export const BuiltinRole = z.enum(BUILTIN_ROLES);
44
44
  * no effect on already-built role schemas (the factory copies entries
45
45
  * into a fresh `Map`).
46
46
  */
47
- export const BUILTIN_ROLE_SPECS_BY_NAME = new Map([
47
+ export const builtin_role_specs_by_name = new Map([
48
48
  [
49
49
  ROLE_KEEPER,
50
50
  {
@@ -139,7 +139,7 @@ export const create_role_schema = (consumer_roles, options = {}) => {
139
139
  if (!parsed.success) {
140
140
  throw new Error(`Invalid role name "${spec.name}": ${parsed.error.issues[0].message}`);
141
141
  }
142
- if (BUILTIN_ROLE_SPECS_BY_NAME.has(spec.name)) {
142
+ if (builtin_role_specs_by_name.has(spec.name)) {
143
143
  throw new Error(`App role "${spec.name}" collides with builtin role`);
144
144
  }
145
145
  if (seen.has(spec.name)) {
@@ -150,7 +150,7 @@ export const create_role_schema = (consumer_roles, options = {}) => {
150
150
  validate_registry_membership(spec.name, 'applicable_scope_kinds', spec.applicable_scope_kinds, scope_kinds_registry);
151
151
  validate_registry_membership(spec.name, 'grant_paths', spec.grant_paths, grant_paths_registry);
152
152
  }
153
- const role_specs = new Map(BUILTIN_ROLE_SPECS_BY_NAME);
153
+ const role_specs = new Map(builtin_role_specs_by_name);
154
154
  for (const spec of consumer_roles) {
155
155
  role_specs.set(spec.name, spec);
156
156
  }
@@ -44,7 +44,7 @@ export interface SelfServiceRoleActionsOptions {
44
44
  /**
45
45
  * Optional override allowlist of role strings eligible for
46
46
  * self-service. When omitted, eligibility is derived from
47
- * `roles.role_specs` (or `BUILTIN_ROLE_SPECS_BY_NAME` when `roles`
47
+ * `roles.role_specs` (or `builtin_role_specs_by_name` when `roles`
48
48
  * is also omitted) by selecting every role whose
49
49
  * `RoleSpec.grant_paths` includes `'self_service'`. Pass an empty
50
50
  * array to lock the surface down (every call comes back as
@@ -38,7 +38,7 @@
38
38
  */
39
39
  import { rpc_action } from '../actions/action_rpc.js';
40
40
  import { jsonrpc_errors } from '../http/jsonrpc_errors.js';
41
- import { BUILTIN_ROLE_SPECS_BY_NAME, list_roles_with_grant_path, } from './role_schema.js';
41
+ import { builtin_role_specs_by_name, list_roles_with_grant_path, } from './role_schema.js';
42
42
  import { GRANT_PATH_SELF_SERVICE } from './grant_path_schema.js';
43
43
  import { query_create_role_grant, query_revoke_role_grant } from './role_grant_queries.js';
44
44
  import { is_role_grant_active } from './account_schema.js';
@@ -55,7 +55,7 @@ import { ERROR_ROLE_NOT_SELF_SERVICE_ELIGIBLE, self_service_role_set_action_spec
55
55
  * @throws Error at factory time if any `eligible_roles` entry is missing from `options.roles.role_specs`
56
56
  */
57
57
  export const create_self_service_role_actions = (deps, options = {}) => {
58
- const role_specs = options.roles?.role_specs ?? BUILTIN_ROLE_SPECS_BY_NAME;
58
+ const role_specs = options.roles?.role_specs ?? builtin_role_specs_by_name;
59
59
  const eligible = options.eligible_roles
60
60
  ? new Set(options.eligible_roles)
61
61
  : new Set(list_roles_with_grant_path(role_specs, GRANT_PATH_SELF_SERVICE));
@@ -38,7 +38,7 @@ export interface SessionCookieOptions {
38
38
  * - `sameSite: 'strict'` - Prevents CSRF
39
39
  * - `httpOnly: true` - Prevents XSS access to cookie
40
40
  */
41
- export declare const SESSION_COOKIE_OPTIONS: SessionCookieOptions;
41
+ export declare const session_cookie_options: SessionCookieOptions;
42
42
  /**
43
43
  * Configuration for a session cookie format.
44
44
  *
@@ -31,7 +31,7 @@ const EXPIRES_AT_INTEGER_RE = /^\d+$/;
31
31
  * - `sameSite: 'strict'` - Prevents CSRF
32
32
  * - `httpOnly: true` - Prevents XSS access to cookie
33
33
  */
34
- export const SESSION_COOKIE_OPTIONS = {
34
+ export const session_cookie_options = {
35
35
  path: '/',
36
36
  httpOnly: true,
37
37
  secure: true,
@@ -18,7 +18,7 @@ export declare const get_session_cookie: <T>(c: Context, options: SessionOptions
18
18
  * `options.max_age` is the single source of truth for cookie lifetime: it
19
19
  * drives both the embedded `expires_at` (via `create_session_cookie_value`)
20
20
  * and the cookie's HTTP `Max-Age` attribute set here. Falls back to
21
- * `SESSION_COOKIE_OPTIONS.maxAge` (= `SESSION_AGE_MAX`) when unset.
21
+ * `session_cookie_options.maxAge` (= `SESSION_AGE_MAX`) when unset.
22
22
  * `options.cookie_options` cannot carry `maxAge` (omitted in the type) so
23
23
  * the two values can't drift.
24
24
  */
@@ -5,7 +5,7 @@
5
5
  * @module
6
6
  */
7
7
  import { getCookie, setCookie, deleteCookie } from 'hono/cookie';
8
- import { SESSION_COOKIE_OPTIONS, process_session_cookie, create_session_cookie_value, } from './session_cookie.js';
8
+ import { session_cookie_options, process_session_cookie, create_session_cookie_value, } from './session_cookie.js';
9
9
  import { generate_session_token, hash_session_token, AUTH_SESSION_LIFETIME_MS, query_create_session, query_session_enforce_limit, } from './session_queries.js';
10
10
  /**
11
11
  * Read the session cookie value from a request.
@@ -19,15 +19,15 @@ export const get_session_cookie = (c, options) => {
19
19
  * `options.max_age` is the single source of truth for cookie lifetime: it
20
20
  * drives both the embedded `expires_at` (via `create_session_cookie_value`)
21
21
  * and the cookie's HTTP `Max-Age` attribute set here. Falls back to
22
- * `SESSION_COOKIE_OPTIONS.maxAge` (= `SESSION_AGE_MAX`) when unset.
22
+ * `session_cookie_options.maxAge` (= `SESSION_AGE_MAX`) when unset.
23
23
  * `options.cookie_options` cannot carry `maxAge` (omitted in the type) so
24
24
  * the two values can't drift.
25
25
  */
26
26
  export const set_session_cookie = (c, value, options) => {
27
27
  const cookie_options = {
28
- ...SESSION_COOKIE_OPTIONS,
28
+ ...session_cookie_options,
29
29
  ...options.cookie_options,
30
- maxAge: options.max_age ?? SESSION_COOKIE_OPTIONS.maxAge,
30
+ maxAge: options.max_age ?? session_cookie_options.maxAge,
31
31
  };
32
32
  setCookie(c, options.cookie_name, value, cookie_options);
33
33
  };
@@ -36,7 +36,7 @@ export const set_session_cookie = (c, value, options) => {
36
36
  */
37
37
  export const clear_session_cookie = (c, options) => {
38
38
  const cookie_options = {
39
- ...SESSION_COOKIE_OPTIONS,
39
+ ...session_cookie_options,
40
40
  ...options.cookie_options,
41
41
  };
42
42
  deleteCookie(c, options.cookie_name, cookie_options);
@@ -43,9 +43,9 @@ export interface RateLimiterOptions {
43
43
  max_keys?: number | null;
44
44
  }
45
45
  /** Default options for per-IP login rate limiting: 5 attempts per 15 minutes. */
46
- export declare const DEFAULT_LOGIN_IP_RATE_LIMIT: RateLimiterOptions;
46
+ export declare const default_login_ip_rate_limit: RateLimiterOptions;
47
47
  /** Default options for per-account login rate limiting: 10 attempts per 30 minutes. */
48
- export declare const DEFAULT_LOGIN_ACCOUNT_RATE_LIMIT: RateLimiterOptions;
48
+ export declare const default_login_account_rate_limit: RateLimiterOptions;
49
49
  /**
50
50
  * Default options for per-IP action-dispatcher rate limiting: 600 attempts
51
51
  * per 15 minutes. Shared by the HTTP RPC and WebSocket action dispatchers
@@ -53,7 +53,7 @@ export declare const DEFAULT_LOGIN_ACCOUNT_RATE_LIMIT: RateLimiterOptions;
53
53
  * scripts and egregious oracle probes, but well above human or normal
54
54
  * automation pace. Tighten downstream for stricter deployments.
55
55
  */
56
- export declare const DEFAULT_ACTION_IP_RATE_LIMIT: RateLimiterOptions;
56
+ export declare const default_action_ip_rate_limit: RateLimiterOptions;
57
57
  /**
58
58
  * Default options for per-actor action-dispatcher rate limiting: 1200
59
59
  * attempts per 15 minutes. Shared by the HTTP RPC and WebSocket action
@@ -61,7 +61,7 @@ export declare const DEFAULT_ACTION_IP_RATE_LIMIT: RateLimiterOptions;
61
61
  * admin workflow; an oracle probing 10k addresses still finishes in
62
62
  * ~2 hours, slow enough to surface in audit. Tighten downstream.
63
63
  */
64
- export declare const DEFAULT_ACTION_ACCOUNT_RATE_LIMIT: RateLimiterOptions;
64
+ export declare const default_action_account_rate_limit: RateLimiterOptions;
65
65
  /**
66
66
  * Result of a rate limit check or record operation.
67
67
  */
@@ -139,7 +139,7 @@ export declare class RateLimiter {
139
139
  /**
140
140
  * Create a `RateLimiter` with sensible defaults for per-IP login protection.
141
141
  *
142
- * @param options - override individual options; unset fields use `DEFAULT_LOGIN_IP_RATE_LIMIT`
142
+ * @param options - override individual options; unset fields use `default_login_ip_rate_limit`
143
143
  */
144
144
  export declare const create_rate_limiter: (options?: Partial<RateLimiterOptions>) => RateLimiter;
145
145
  /**
@@ -17,14 +17,14 @@ import { ERROR_RATE_LIMIT_EXCEEDED } from './http/error_schemas.js';
17
17
  */
18
18
  export const DEFAULT_RATE_LIMITER_MAX_KEYS = 100_000;
19
19
  /** Default options for per-IP login rate limiting: 5 attempts per 15 minutes. */
20
- export const DEFAULT_LOGIN_IP_RATE_LIMIT = {
20
+ export const default_login_ip_rate_limit = {
21
21
  max_attempts: 5,
22
22
  window_ms: 15 * 60_000,
23
23
  cleanup_interval_ms: 5 * 60_000,
24
24
  max_keys: DEFAULT_RATE_LIMITER_MAX_KEYS,
25
25
  };
26
26
  /** Default options for per-account login rate limiting: 10 attempts per 30 minutes. */
27
- export const DEFAULT_LOGIN_ACCOUNT_RATE_LIMIT = {
27
+ export const default_login_account_rate_limit = {
28
28
  max_attempts: 10,
29
29
  window_ms: 30 * 60_000,
30
30
  cleanup_interval_ms: 5 * 60_000,
@@ -37,7 +37,7 @@ export const DEFAULT_LOGIN_ACCOUNT_RATE_LIMIT = {
37
37
  * scripts and egregious oracle probes, but well above human or normal
38
38
  * automation pace. Tighten downstream for stricter deployments.
39
39
  */
40
- export const DEFAULT_ACTION_IP_RATE_LIMIT = {
40
+ export const default_action_ip_rate_limit = {
41
41
  max_attempts: 600,
42
42
  window_ms: 15 * 60_000,
43
43
  cleanup_interval_ms: 5 * 60_000,
@@ -50,7 +50,7 @@ export const DEFAULT_ACTION_IP_RATE_LIMIT = {
50
50
  * admin workflow; an oracle probing 10k addresses still finishes in
51
51
  * ~2 hours, slow enough to surface in audit. Tighten downstream.
52
52
  */
53
- export const DEFAULT_ACTION_ACCOUNT_RATE_LIMIT = {
53
+ export const default_action_account_rate_limit = {
54
54
  max_attempts: 1200,
55
55
  window_ms: 15 * 60_000,
56
56
  cleanup_interval_ms: 5 * 60_000,
@@ -203,10 +203,10 @@ export class RateLimiter {
203
203
  /**
204
204
  * Create a `RateLimiter` with sensible defaults for per-IP login protection.
205
205
  *
206
- * @param options - override individual options; unset fields use `DEFAULT_LOGIN_IP_RATE_LIMIT`
206
+ * @param options - override individual options; unset fields use `default_login_ip_rate_limit`
207
207
  */
208
208
  export const create_rate_limiter = (options) => {
209
- return new RateLimiter({ ...DEFAULT_LOGIN_IP_RATE_LIMIT, ...options });
209
+ return new RateLimiter({ ...default_login_ip_rate_limit, ...options });
210
210
  };
211
211
  /**
212
212
  * Build a 429 rate-limit-exceeded JSON response with `Retry-After` header.
@@ -27,7 +27,7 @@ export declare const AUDIT_LOG_CHANNEL = "audit_log";
27
27
  * (matched by the blake3 session hash in `event.metadata.session_id`) — closing
28
28
  * all of a user's streams for a single-session revoke would be over-aggressive.
29
29
  */
30
- export declare const DISCONNECT_EVENT_TYPES: ReadonlySet<string>;
30
+ export declare const disconnect_event_types: ReadonlySet<string>;
31
31
  /**
32
32
  * Create an audit event handler that closes SSE streams on auth changes.
33
33
  *
@@ -69,7 +69,7 @@ export interface AuditLogSse {
69
69
  * One spec per `AUDIT_EVENT_TYPES` entry, all sharing the `AuditLogEventJson` params schema.
70
70
  * Pass to `create_app_server`'s `event_specs` for surface generation and DEV validation.
71
71
  */
72
- export declare const AUDIT_LOG_EVENT_SPECS: Array<EventSpec>;
72
+ export declare const audit_log_event_specs: Array<EventSpec>;
73
73
  /**
74
74
  * Default max concurrent SSE subscribers per session scope for the audit log.
75
75
  *
@@ -102,7 +102,7 @@ export declare const AUDIT_LOG_SSE_MAX_PER_SCOPE = 10;
102
102
  * create_audit_log_route_specs({stream: audit_sse});
103
103
  *
104
104
  * // In create_app_server options:
105
- * event_specs: AUDIT_LOG_EVENT_SPECS,
105
+ * event_specs: audit_log_event_specs,
106
106
  * ```
107
107
  */
108
108
  export declare const create_audit_log_sse: (options: {
@@ -25,7 +25,7 @@ export const AUDIT_LOG_CHANNEL = 'audit_log';
25
25
  * (matched by the blake3 session hash in `event.metadata.session_id`) — closing
26
26
  * all of a user's streams for a single-session revoke would be over-aggressive.
27
27
  */
28
- export const DISCONNECT_EVENT_TYPES = new Set([
28
+ export const disconnect_event_types = new Set([
29
29
  'role_grant_revoke', // role revoked — user lost access
30
30
  'session_revoke', // single session revoked — close only that stream
31
31
  'session_revoke_all', // all sessions invalidated — user should be kicked
@@ -51,7 +51,7 @@ export const DISCONNECT_EVENT_TYPES = new Set([
51
51
  */
52
52
  export const create_sse_auth_guard = (registry, required_role, log) => {
53
53
  return (event) => {
54
- if (!DISCONNECT_EVENT_TYPES.has(event.event_type))
54
+ if (!disconnect_event_types.has(event.event_type))
55
55
  return;
56
56
  // Only act on successful revocations. Failed attempts carry
57
57
  // attacker-controlled identifiers (e.g., session_revoke with outcome=failure
@@ -98,7 +98,7 @@ export const create_sse_auth_guard = (registry, required_role, log) => {
98
98
  * One spec per `AUDIT_EVENT_TYPES` entry, all sharing the `AuditLogEventJson` params schema.
99
99
  * Pass to `create_app_server`'s `event_specs` for surface generation and DEV validation.
100
100
  */
101
- export const AUDIT_LOG_EVENT_SPECS = AUDIT_EVENT_TYPES.map((event_type) => ({
101
+ export const audit_log_event_specs = AUDIT_EVENT_TYPES.map((event_type) => ({
102
102
  method: event_type,
103
103
  params: AuditLogEventJson,
104
104
  description: `Audit log: ${event_type.replaceAll('_', ' ')}`,
@@ -136,7 +136,7 @@ export const AUDIT_LOG_SSE_MAX_PER_SCOPE = 10;
136
136
  * create_audit_log_route_specs({stream: audit_sse});
137
137
  *
138
138
  * // In create_app_server options:
139
- * event_specs: AUDIT_LOG_EVENT_SPECS,
139
+ * event_specs: audit_log_event_specs,
140
140
  * ```
141
141
  */
142
142
  export const create_audit_log_sse = (options) => {
@@ -66,7 +66,7 @@ export interface CreateAppBackendOptions {
66
66
  * Audit-log config for consumer event-type extensions. Built once at
67
67
  * startup via `create_audit_log_config({extra_events})` and captured
68
68
  * inside `AppDeps.audit` so consumer handlers cannot silently fall
69
- * back to the builtin config. Omit to use `BUILTIN_AUDIT_LOG_CONFIG`
69
+ * back to the builtin config. Omit to use `builtin_audit_log_config`
70
70
  * (no extra events).
71
71
  */
72
72
  audit_log_config?: AuditLogConfig;
@@ -76,7 +76,7 @@ export interface CreateAppBackendOptions {
76
76
  * (`namespace`, `name`, `sequence`); order is append-only so forward-only
77
77
  * guarantees hold per-namespace.
78
78
  *
79
- * Names in `RESERVED_MIGRATION_NAMESPACES` (currently `['fuz_auth']`) are
79
+ * Names in `reserved_migration_namespaces` (currently `['fuz_auth']`) are
80
80
  * rejected at startup. Omit for no extra namespaces. This is the only
81
81
  * place to splice consumer migrations — DB init belongs to the backend
82
82
  * lifecycle, not server assembly.
@@ -92,7 +92,7 @@ export interface CreateAppBackendOptions {
92
92
  *
93
93
  * @param options - keyring, password deps, optional database URL, and optional `migration_namespaces`
94
94
  * @returns app backend with deps, database metadata, and combined migration results
95
- * @throws Error if `migration_namespaces` contains a namespace in `RESERVED_MIGRATION_NAMESPACES`
95
+ * @throws Error if `migration_namespaces` contains a namespace in `reserved_migration_namespaces`
96
96
  */
97
97
  export declare const create_app_backend: (options: CreateAppBackendOptions) => Promise<AppBackend>;
98
98
  //# sourceMappingURL=app_backend.d.ts.map
@@ -13,7 +13,7 @@
13
13
  import { Logger } from '@fuzdev/fuz_util/log.js';
14
14
  import { create_audit_emitter } from '../auth/audit_emitter.js';
15
15
  import { run_migrations } from '../db/migrate.js';
16
- import { AUTH_MIGRATION_NS, RESERVED_MIGRATION_NAMESPACES } from '../auth/migrations.js';
16
+ import { auth_migration_ns, reserved_migration_namespaces } from '../auth/migrations.js';
17
17
  import { create_db } from '../db/create_db.js';
18
18
  /**
19
19
  * Initialize the backend: database + auth migrations + deps.
@@ -24,7 +24,7 @@ import { create_db } from '../db/create_db.js';
24
24
  *
25
25
  * @param options - keyring, password deps, optional database URL, and optional `migration_namespaces`
26
26
  * @returns app backend with deps, database metadata, and combined migration results
27
- * @throws Error if `migration_namespaces` contains a namespace in `RESERVED_MIGRATION_NAMESPACES`
27
+ * @throws Error if `migration_namespaces` contains a namespace in `reserved_migration_namespaces`
28
28
  */
29
29
  export const create_app_backend = async (options) => {
30
30
  const { database_url, keyring, password, stat, read_text_file, delete_file } = options;
@@ -32,13 +32,13 @@ export const create_app_backend = async (options) => {
32
32
  const { db, close, db_type, db_name } = await create_db(database_url);
33
33
  if (options.migration_namespaces?.length) {
34
34
  for (const ns of options.migration_namespaces) {
35
- if (RESERVED_MIGRATION_NAMESPACES.includes(ns.namespace)) {
35
+ if (reserved_migration_namespaces.includes(ns.namespace)) {
36
36
  throw new Error(`Migration namespace "${ns.namespace}" is reserved by fuz_app — choose a different namespace`);
37
37
  }
38
38
  }
39
39
  }
40
40
  const migration_results = await run_migrations(db, [
41
- AUTH_MIGRATION_NS,
41
+ auth_migration_ns,
42
42
  ...(options.migration_namespaces ?? []),
43
43
  ]);
44
44
  const audit = create_audit_emitter({
@@ -136,7 +136,7 @@ export interface AppServerOptions {
136
136
  * When truthy, creates an `AuditLogSse` instance internally, appends the SSE
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
- * auto-includes `AUDIT_LOG_EVENT_SPECS` in the surface. The result is exposed
139
+ * auto-includes `audit_log_event_specs` in the surface. The result is exposed
140
140
  * on `AppServerContext` (for route factories) and `AppServer` (for the caller).
141
141
  *
142
142
  * Pass `true` for defaults (admin role), or `{role: 'custom'}` for a custom role.
@@ -11,10 +11,10 @@ import { Hono } from 'hono';
11
11
  import { logger } from 'hono/logger';
12
12
  import { bodyLimit } from 'hono/body-limit';
13
13
  import { z } from 'zod';
14
- import { SESSION_COOKIE_OPTIONS, } from '../auth/session_cookie.js';
15
- import { create_audit_log_sse, AUDIT_LOG_EVENT_SPECS, } from '../realtime/sse_auth_guard.js';
14
+ import { session_cookie_options, } from '../auth/session_cookie.js';
15
+ import { create_audit_log_sse, audit_log_event_specs, } from '../realtime/sse_auth_guard.js';
16
16
  import { query_app_settings_load } from '../auth/app_settings_queries.js';
17
- import { create_rate_limiter, DEFAULT_LOGIN_ACCOUNT_RATE_LIMIT, DEFAULT_ACTION_ACCOUNT_RATE_LIMIT, DEFAULT_ACTION_IP_RATE_LIMIT, } from '../rate_limiter.js';
17
+ import { create_rate_limiter, default_login_account_rate_limit, default_action_account_rate_limit, default_action_ip_rate_limit, } from '../rate_limiter.js';
18
18
  // Side-effect import: augments Hono's ContextVariableMap so consumers
19
19
  // that import app_server get type-safe c.get('auth_session_id') etc.
20
20
  import '../hono_context.js';
@@ -53,19 +53,19 @@ export const create_app_server = async (options) => {
53
53
  // Rate limiter defaults (undefined = default, null = disable)
54
54
  const ip_rate_limiter = options.ip_rate_limiter === undefined ? create_rate_limiter() : options.ip_rate_limiter;
55
55
  const login_account_rate_limiter = options.login_account_rate_limiter === undefined
56
- ? create_rate_limiter(DEFAULT_LOGIN_ACCOUNT_RATE_LIMIT)
56
+ ? create_rate_limiter(default_login_account_rate_limit)
57
57
  : options.login_account_rate_limiter;
58
58
  const signup_account_rate_limiter = options.signup_account_rate_limiter === undefined
59
- ? create_rate_limiter(DEFAULT_LOGIN_ACCOUNT_RATE_LIMIT)
59
+ ? create_rate_limiter(default_login_account_rate_limit)
60
60
  : options.signup_account_rate_limiter;
61
61
  const bearer_ip_rate_limiter = options.bearer_ip_rate_limiter === undefined
62
62
  ? create_rate_limiter()
63
63
  : options.bearer_ip_rate_limiter;
64
64
  const action_ip_rate_limiter = options.action_ip_rate_limiter === undefined
65
- ? create_rate_limiter(DEFAULT_ACTION_IP_RATE_LIMIT)
65
+ ? create_rate_limiter(default_action_ip_rate_limit)
66
66
  : options.action_ip_rate_limiter;
67
67
  const action_account_rate_limiter = options.action_account_rate_limiter === undefined
68
- ? create_rate_limiter(DEFAULT_ACTION_ACCOUNT_RATE_LIMIT)
68
+ ? create_rate_limiter(default_action_account_rate_limit)
69
69
  : options.action_account_rate_limiter;
70
70
  // Factory-managed audit SSE — appends a listener to the bound emitter's
71
71
  // chain so SSE fan-out runs alongside the consumer's `on_audit_event`
@@ -156,7 +156,7 @@ export const create_app_server = async (options) => {
156
156
  : middleware_specs;
157
157
  const all_event_specs = [
158
158
  ...(options.event_specs ?? []),
159
- ...(audit_sse ? AUDIT_LOG_EVENT_SPECS : []),
159
+ ...(audit_sse ? audit_log_event_specs : []),
160
160
  ];
161
161
  const surface_spec = create_app_surface_spec({
162
162
  middleware_specs: surface_middleware,
@@ -176,11 +176,11 @@ export const create_app_server = async (options) => {
176
176
  message: 'Session cookie secure=false — cookies sent over HTTP',
177
177
  });
178
178
  }
179
- if (cookie_opts.sameSite && cookie_opts.sameSite !== SESSION_COOKIE_OPTIONS.sameSite) {
179
+ if (cookie_opts.sameSite && cookie_opts.sameSite !== session_cookie_options.sameSite) {
180
180
  config_diagnostics.push({
181
181
  level: 'warning',
182
182
  category: 'security',
183
- message: `Session cookie sameSite='${cookie_opts.sameSite}' — weakened from default '${SESSION_COOKIE_OPTIONS.sameSite}'`,
183
+ message: `Session cookie sameSite='${cookie_opts.sameSite}' — weakened from default '${session_cookie_options.sameSite}'`,
184
184
  });
185
185
  }
186
186
  if (cookie_opts.httpOnly === false) {