@fuzdev/fuz_app 0.59.0 → 0.61.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 (151) 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/dist/ui/AccountSessions.svelte +21 -6
  96. package/dist/ui/AccountSessions.svelte.d.ts.map +1 -1
  97. package/dist/ui/AdminAccounts.svelte +32 -25
  98. package/dist/ui/AdminAccounts.svelte.d.ts.map +1 -1
  99. package/dist/ui/AdminAuditLog.svelte +3 -3
  100. package/dist/ui/AdminInvites.svelte +20 -15
  101. package/dist/ui/AdminOverview.svelte +19 -21
  102. package/dist/ui/AdminOverview.svelte.d.ts.map +1 -1
  103. package/dist/ui/AdminRoleGrantHistory.svelte +3 -3
  104. package/dist/ui/AdminSessions.svelte +19 -21
  105. package/dist/ui/AdminSessions.svelte.d.ts.map +1 -1
  106. package/dist/ui/AdminSettings.svelte +1 -3
  107. package/dist/ui/AdminSettings.svelte.d.ts.map +1 -1
  108. package/dist/ui/CLAUDE.md +123 -69
  109. package/dist/ui/ConfirmButton.svelte +82 -24
  110. package/dist/ui/ConfirmButton.svelte.d.ts +8 -34
  111. package/dist/ui/ConfirmButton.svelte.d.ts.map +1 -1
  112. package/dist/ui/OpenSignupToggle.svelte +6 -4
  113. package/dist/ui/OpenSignupToggle.svelte.d.ts.map +1 -1
  114. package/dist/ui/RoleGrantOfferForm.svelte +4 -4
  115. package/dist/ui/RoleGrantOfferHistory.svelte +3 -3
  116. package/dist/ui/RoleGrantOfferInbox.svelte +10 -6
  117. package/dist/ui/RoleGrantOfferInbox.svelte.d.ts.map +1 -1
  118. package/dist/ui/account_sessions_state.svelte.d.ts +17 -7
  119. package/dist/ui/account_sessions_state.svelte.d.ts.map +1 -1
  120. package/dist/ui/account_sessions_state.svelte.js +32 -33
  121. package/dist/ui/admin_accounts_state.svelte.d.ts +48 -17
  122. package/dist/ui/admin_accounts_state.svelte.d.ts.map +1 -1
  123. package/dist/ui/admin_accounts_state.svelte.js +58 -76
  124. package/dist/ui/admin_invites_state.svelte.d.ts +14 -7
  125. package/dist/ui/admin_invites_state.svelte.d.ts.map +1 -1
  126. package/dist/ui/admin_invites_state.svelte.js +32 -48
  127. package/dist/ui/admin_sessions_state.svelte.d.ts +15 -8
  128. package/dist/ui/admin_sessions_state.svelte.d.ts.map +1 -1
  129. package/dist/ui/admin_sessions_state.svelte.js +30 -47
  130. package/dist/ui/app_settings_state.svelte.d.ts +8 -3
  131. package/dist/ui/app_settings_state.svelte.d.ts.map +1 -1
  132. package/dist/ui/app_settings_state.svelte.js +19 -27
  133. package/dist/ui/async_slot.svelte.d.ts +173 -0
  134. package/dist/ui/async_slot.svelte.d.ts.map +1 -0
  135. package/dist/ui/async_slot.svelte.js +241 -0
  136. package/dist/ui/audit_log_state.svelte.d.ts +8 -2
  137. package/dist/ui/audit_log_state.svelte.d.ts.map +1 -1
  138. package/dist/ui/audit_log_state.svelte.js +19 -18
  139. package/dist/ui/keyed_async_slot.svelte.d.ts +139 -0
  140. package/dist/ui/keyed_async_slot.svelte.d.ts.map +1 -0
  141. package/dist/ui/keyed_async_slot.svelte.js +177 -0
  142. package/dist/ui/role_grant_offers_state.svelte.d.ts +39 -7
  143. package/dist/ui/role_grant_offers_state.svelte.d.ts.map +1 -1
  144. package/dist/ui/role_grant_offers_state.svelte.js +34 -15
  145. package/dist/ui/table_state.svelte.d.ts +10 -7
  146. package/dist/ui/table_state.svelte.d.ts.map +1 -1
  147. package/dist/ui/table_state.svelte.js +11 -8
  148. package/package.json +1 -1
  149. package/dist/ui/loadable.svelte.d.ts +0 -60
  150. package/dist/ui/loadable.svelte.d.ts.map +0 -1
  151. package/dist/ui/loadable.svelte.js +0 -80
@@ -464,7 +464,7 @@ persistence + rehydration by the consumer.
464
464
  wireable via `CreateAppBackendOptions.on_audit_event`. Mirrors the SSE
465
465
  guard in `realtime/sse_auth_guard.ts` but targets the WS transport.
466
466
 
467
- `WS_DISCONNECT_EVENT_TYPES` (ReadonlySet): `session_revoke`,
467
+ `ws_disconnect_event_types` (ReadonlySet): `session_revoke`,
468
468
  `token_revoke`, `session_revoke_all`, `token_revoke_all`, `password_change`.
469
469
  `role_grant_revoke` is intentionally **omitted** — the WS transport does not
470
470
  track per-connection role requirements, so role-scoped disconnection would
@@ -484,7 +484,7 @@ caller close another user's socket by guessing a session hash or token id.
484
484
 
485
485
  `create_ws_logout_closer(transport, log)` is the sibling helper for
486
486
  user-initiated `logout` events — kept separate because
487
- `WS_DISCONNECT_EVENT_TYPES` deliberately omits `logout` (admin-initiated
487
+ `ws_disconnect_event_types` deliberately omits `logout` (admin-initiated
488
488
  revocations use `session_revoke`, while `logout` is the user-initiated
489
489
  case). Compose the two on `on_audit_event`:
490
490
 
@@ -600,9 +600,9 @@ an action through its lifecycle.
600
600
 
601
601
  - `ActionExecutor` — `'frontend' | 'backend'`
602
602
  - `ActionEventStep` — `'initial' | 'parsed' | 'handling' | 'handled' | 'failed'`
603
- - `ACTION_EVENT_STEP_TRANSITIONS` — valid next-steps: `initial → parsed | failed`, `parsed → handling | failed`, `handling → handled | failed`, `handled`/`failed` terminal.
604
- - `ACTION_EVENT_PHASE_BY_KIND` — valid phases per kind (`request_response` has 6, `remote_notification` has 2, `local_call` has 1).
605
- - `ACTION_EVENT_PHASE_TRANSITIONS` — chained phases: `send_request → receive_response`; `receive_request → send_response`; everything else terminal.
603
+ - `action_event_step_transitions` — valid next-steps: `initial → parsed | failed`, `parsed → handling | failed`, `handling → handled | failed`, `handled`/`failed` terminal.
604
+ - `action_event_phase_by_kind` — valid phases per kind (`request_response` has 6, `remote_notification` has 2, `local_call` has 1).
605
+ - `action_event_phase_transitions` — chained phases: `send_request → receive_response`; `receive_request → send_response`; everything else terminal.
606
606
  - `ActionEventEnvironment` — `{executor, lookup_action_handler, lookup_action_spec, log?}`. The ambient registry + handler resolver for an `ActionEvent`.
607
607
 
608
608
  ### `action_event_data.ts`
@@ -182,7 +182,7 @@ export declare const generate_actions_api_method_signature: (spec: ActionSpecUni
182
182
  /** Discriminator for `generate_action_method_enums` — which method-set enums to emit. */
183
183
  export type ActionMethodEnumKind = 'all' | 'request_response' | 'remote_notification' | 'local_call' | 'frontend' | 'backend' | 'frontend_handled' | 'backend_handled' | 'broadcast';
184
184
  /** Default emit set — every enum kind. */
185
- export declare const ACTION_METHOD_ENUM_KINDS_ALL: ReadonlySet<ActionMethodEnumKind>;
185
+ export declare const action_method_enum_kinds_all: ReadonlySet<ActionMethodEnumKind>;
186
186
  /**
187
187
  * Resolve a per-spec identifier qualifier with the standard default-vs-callback
188
188
  * dance. When `qualify_spec` is set, returns the caller's callback verbatim
@@ -416,7 +416,7 @@ ${lines}
416
416
  export type ${name} = z.infer<typeof ${name}>;`;
417
417
  };
418
418
  /** Default emit set — every enum kind. */
419
- export const ACTION_METHOD_ENUM_KINDS_ALL = new Set([
419
+ export const action_method_enum_kinds_all = new Set([
420
420
  'all',
421
421
  'request_response',
422
422
  'remote_notification',
@@ -483,7 +483,7 @@ export const resolve_spec_qualifier = (imports, options) => {
483
483
  * `cancel` in the emitted enums. Default `false`.
484
484
  */
485
485
  export const generate_action_method_enums = (specs, imports, options) => {
486
- const emit = options?.emit ?? ACTION_METHOD_ENUM_KINDS_ALL;
486
+ const emit = options?.emit ?? action_method_enum_kinds_all;
487
487
  const filtered = filter_protocol_actions(specs, options?.include_protocol_actions);
488
488
  const registry = new ActionRegistry([...filtered]);
489
489
  const blocks = [];
@@ -59,20 +59,20 @@ export declare const is_notification_send_with_parsed_input: <TMethod extends st
59
59
  input: unknown;
60
60
  };
61
61
  /**
62
- * Validate that a step transition is legal per `ACTION_EVENT_STEP_TRANSITIONS`.
62
+ * Validate that a step transition is legal per `action_event_step_transitions`.
63
63
  *
64
64
  * @throws Error if `from → to` is not a permitted transition
65
65
  */
66
66
  export declare const validate_step_transition: (from: ActionEventStep, to: ActionEventStep) => void;
67
67
  /**
68
68
  * Validate that `phase` is one of the phases allowed for `kind` per
69
- * `ACTION_EVENT_PHASE_BY_KIND`.
69
+ * `action_event_phase_by_kind`.
70
70
  *
71
71
  * @throws Error if `phase` is not valid for `kind`
72
72
  */
73
73
  export declare const validate_phase_for_kind: (kind: ActionKind, phase: ActionEventPhase) => void;
74
74
  /**
75
- * Validate that a phase chain is legal per `ACTION_EVENT_PHASE_TRANSITIONS`.
75
+ * Validate that a phase chain is legal per `action_event_phase_transitions`.
76
76
  *
77
77
  * @throws Error if `from → to` is not the permitted next phase (or `from` is terminal)
78
78
  */
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * @module
5
5
  */
6
- import { ACTION_EVENT_STEP_TRANSITIONS, ACTION_EVENT_PHASE_BY_KIND, ACTION_EVENT_PHASE_TRANSITIONS, } from './action_event_types.js';
6
+ import { action_event_step_transitions, action_event_phase_by_kind, action_event_phase_transitions, } from './action_event_types.js';
7
7
  // Type guards for action kinds
8
8
  export const is_request_response = (data) => data.kind === 'request_response';
9
9
  export const is_remote_notification = (data) => data.kind === 'remote_notification';
@@ -28,33 +28,33 @@ export const is_failed = (data) => data.step === 'failed';
28
28
  export const is_send_request_with_parsed_input = (data) => is_send_request(data) && (data.step === 'parsed' || data.step === 'handling');
29
29
  export const is_notification_send_with_parsed_input = (data) => is_notification_send(data) && (data.step === 'parsed' || data.step === 'handling');
30
30
  /**
31
- * Validate that a step transition is legal per `ACTION_EVENT_STEP_TRANSITIONS`.
31
+ * Validate that a step transition is legal per `action_event_step_transitions`.
32
32
  *
33
33
  * @throws Error if `from → to` is not a permitted transition
34
34
  */
35
35
  export const validate_step_transition = (from, to) => {
36
- if (!ACTION_EVENT_STEP_TRANSITIONS[from].includes(to)) {
36
+ if (!action_event_step_transitions[from].includes(to)) {
37
37
  throw new Error(`Invalid step transition from '${from}' to '${to}'`);
38
38
  }
39
39
  };
40
40
  /**
41
41
  * Validate that `phase` is one of the phases allowed for `kind` per
42
- * `ACTION_EVENT_PHASE_BY_KIND`.
42
+ * `action_event_phase_by_kind`.
43
43
  *
44
44
  * @throws Error if `phase` is not valid for `kind`
45
45
  */
46
46
  export const validate_phase_for_kind = (kind, phase) => {
47
- if (!ACTION_EVENT_PHASE_BY_KIND[kind].includes(phase)) {
47
+ if (!action_event_phase_by_kind[kind].includes(phase)) {
48
48
  throw new Error(`Invalid phase '${phase}' for ${kind} action`);
49
49
  }
50
50
  };
51
51
  /**
52
- * Validate that a phase chain is legal per `ACTION_EVENT_PHASE_TRANSITIONS`.
52
+ * Validate that a phase chain is legal per `action_event_phase_transitions`.
53
53
  *
54
54
  * @throws Error if `from → to` is not the permitted next phase (or `from` is terminal)
55
55
  */
56
56
  export const validate_phase_transition = (from, to) => {
57
- const expected = ACTION_EVENT_PHASE_TRANSITIONS[from];
57
+ const expected = action_event_phase_transitions[from];
58
58
  if (expected !== to) {
59
59
  throw new Error(`Invalid phase transition from '${from}' to '${to}'`);
60
60
  }
@@ -79,7 +79,7 @@ export const is_action_complete = (data) => {
79
79
  if (data.step !== 'handled')
80
80
  return false;
81
81
  // Check if in terminal phase
82
- const next_phase = ACTION_EVENT_PHASE_TRANSITIONS[data.phase];
82
+ const next_phase = action_event_phase_transitions[data.phase];
83
83
  return next_phase === null;
84
84
  };
85
85
  export const create_initial_data = (kind, phase, method, executor, input) => ({
@@ -19,9 +19,9 @@ export declare const ActionEventStep: z.ZodEnum<{
19
19
  failed: "failed";
20
20
  }>;
21
21
  export type ActionEventStep = z.infer<typeof ActionEventStep>;
22
- export declare const ACTION_EVENT_STEP_TRANSITIONS: Record<ActionEventStep, ReadonlyArray<ActionEventStep>>;
23
- export declare const ACTION_EVENT_PHASE_BY_KIND: Record<ActionKind, ReadonlyArray<ActionEventPhase>>;
24
- export declare const ACTION_EVENT_PHASE_TRANSITIONS: Record<ActionEventPhase, ActionEventPhase | null>;
22
+ export declare const action_event_step_transitions: Record<ActionEventStep, ReadonlyArray<ActionEventStep>>;
23
+ export declare const action_event_phase_by_kind: Record<ActionKind, ReadonlyArray<ActionEventPhase>>;
24
+ export declare const action_event_phase_transitions: Record<ActionEventPhase, ActionEventPhase | null>;
25
25
  export interface ActionEventEnvironment {
26
26
  readonly executor: ActionExecutor;
27
27
  lookup_action_handler: (method: string, phase: ActionEventPhase) => ((event: any) => any) | undefined;
@@ -12,14 +12,14 @@ export const ActionEventStep = z.enum(['initial', 'parsed', 'handling', 'handled
12
12
  // value types on the object literal) without narrowing lookups to literal
13
13
  // tuple types — a `satisfies` shape forces every `X[k]` reader to widen
14
14
  // back to `ReadonlyArray<V>` themselves to call `.includes(...)`.
15
- export const ACTION_EVENT_STEP_TRANSITIONS = {
15
+ export const action_event_step_transitions = {
16
16
  initial: ['parsed', 'failed'],
17
17
  parsed: ['handling', 'failed'],
18
18
  handling: ['handled', 'failed'],
19
19
  handled: [],
20
20
  failed: [],
21
21
  };
22
- export const ACTION_EVENT_PHASE_BY_KIND = {
22
+ export const action_event_phase_by_kind = {
23
23
  request_response: [
24
24
  'send_request',
25
25
  'receive_request',
@@ -31,7 +31,7 @@ export const ACTION_EVENT_PHASE_BY_KIND = {
31
31
  remote_notification: ['send', 'receive'],
32
32
  local_call: ['execute'],
33
33
  };
34
- export const ACTION_EVENT_PHASE_TRANSITIONS = {
34
+ export const action_event_phase_transitions = {
35
35
  send_request: 'receive_response',
36
36
  receive_request: 'send_response',
37
37
  send_response: null,
@@ -36,7 +36,7 @@ export type AuditEventHandler = (event: AuditLogEvent) => void;
36
36
  * require either closing all sockets (too aggressive) or new tracking
37
37
  * (out of scope). Consumers that need it compose their own callback.
38
38
  */
39
- export declare const WS_DISCONNECT_EVENT_TYPES: ReadonlySet<string>;
39
+ export declare const ws_disconnect_event_types: ReadonlySet<string>;
40
40
  /**
41
41
  * Create an audit event handler that closes WebSocket connections on auth changes.
42
42
  *
@@ -56,7 +56,7 @@ export declare const create_ws_auth_guard: (transport: BackendWebsocketTransport
56
56
  * user-initiated logout.
57
57
  *
58
58
  * Sibling helper to `create_ws_auth_guard` — kept separate because
59
- * `WS_DISCONNECT_EVENT_TYPES` deliberately omits `logout` (admin-initiated
59
+ * `ws_disconnect_event_types` deliberately omits `logout` (admin-initiated
60
60
  * revocations use `session_revoke`, while `logout` is the user-initiated
61
61
  * case). Three consumers (tx, undying, zzz) hand-rolled this same branch
62
62
  * before extraction.
@@ -23,7 +23,7 @@
23
23
  * require either closing all sockets (too aggressive) or new tracking
24
24
  * (out of scope). Consumers that need it compose their own callback.
25
25
  */
26
- export const WS_DISCONNECT_EVENT_TYPES = new Set([
26
+ export const ws_disconnect_event_types = new Set([
27
27
  'session_revoke',
28
28
  'token_revoke',
29
29
  'session_revoke_all',
@@ -45,7 +45,7 @@ export const WS_DISCONNECT_EVENT_TYPES = new Set([
45
45
  */
46
46
  export const create_ws_auth_guard = (transport, log) => {
47
47
  return (event) => {
48
- if (!WS_DISCONNECT_EVENT_TYPES.has(event.event_type))
48
+ if (!ws_disconnect_event_types.has(event.event_type))
49
49
  return;
50
50
  // Failed mutations carry attacker-controlled metadata — never act on them.
51
51
  if (event.outcome === 'failure')
@@ -90,7 +90,7 @@ export const create_ws_auth_guard = (transport, log) => {
90
90
  * user-initiated logout.
91
91
  *
92
92
  * Sibling helper to `create_ws_auth_guard` — kept separate because
93
- * `WS_DISCONNECT_EVENT_TYPES` deliberately omits `logout` (admin-initiated
93
+ * `ws_disconnect_event_types` deliberately omits `logout` (admin-initiated
94
94
  * revocations use `session_revoke`, while `logout` is the user-initiated
95
95
  * case). Three consumers (tx, undying, zzz) hand-rolled this same branch
96
96
  * before extraction.
@@ -21,7 +21,7 @@ sections.
21
21
  | Module | Exports |
22
22
  | ---------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
23
23
  | `keyring.ts` | `Keyring`, `create_keyring`, `validate_keyring`, `create_validated_keyring`, `ValidatedKeyringResult` |
24
- | `session_cookie.ts` | `SessionOptions<T>`, `SessionCookieOptions`, `SESSION_COOKIE_OPTIONS`, `SESSION_AGE_MAX`, `SESSION_REFRESH_THRESHOLD_S`, `ParsedSession`, `ProcessSessionResult`, `parse_session`, `create_session_cookie_value`, `process_session_cookie`, `create_session_config`, `fuz_session_config` |
24
+ | `session_cookie.ts` | `SessionOptions<T>`, `SessionCookieOptions`, `session_cookie_options`, `SESSION_AGE_MAX`, `SESSION_REFRESH_THRESHOLD_S`, `ParsedSession`, `ProcessSessionResult`, `parse_session`, `create_session_cookie_value`, `process_session_cookie`, `create_session_config`, `fuz_session_config` |
25
25
  | `password.ts` | `Password`, `PasswordProvided`, `PasswordHashDeps`, `PASSWORD_LENGTH_MIN` (12, OWASP), `PASSWORD_LENGTH_MAX` (300) |
26
26
  | `password_argon2.ts` | `hash_password`, `verify_password`, `verify_dummy`, `argon2_password_deps` |
27
27
  | `api_token.ts` | `API_TOKEN_PREFIX` (`secret_fuz_token_`), `hash_api_token`, `generate_api_token` |
@@ -179,7 +179,7 @@ those three. Mirrors the open-registry pattern used for `RoleName` /
179
179
  constant is named `_API_TOKEN` (not `_BEARER`) so wire literal and
180
180
  the `api_token` storage table stay in lockstep.
181
181
  - `BUILTIN_CREDENTIAL_TYPES` const tuple, `BuiltinCredentialType` Zod
182
- enum, `BUILTIN_CREDENTIAL_TYPE_META` admin-UI-facing descriptions.
182
+ enum, `builtin_credential_type_meta` admin-UI-facing descriptions.
183
183
  - `create_credential_type_schema(consumer_types?)`
184
184
  → `{CredentialType, credential_types: ReadonlyMap}`. Builtins always
185
185
  present; consumer collisions / regex failures / duplicates throw at
@@ -197,7 +197,7 @@ granted. Four builtins (`admin`, `self_service`, `system`, `bootstrap`).
197
197
  - `GRANT_PATH_ADMIN` / `_SELF_SERVICE` / `_SYSTEM` / `_BOOTSTRAP` —
198
198
  builtin literal constants.
199
199
  - `BUILTIN_GRANT_PATHS` const tuple, `BuiltinGrantPath` Zod enum,
200
- `BUILTIN_GRANT_PATH_META` descriptions.
200
+ `builtin_grant_path_meta` descriptions.
201
201
  - `create_grant_path_schema(consumer_paths?)`
202
202
  → `{GrantPath, grant_paths: ReadonlyMap}`. Same construction-time
203
203
  guards as the credential-type schema. Pass the result into
@@ -224,7 +224,7 @@ against the corresponding open registries at construction time.
224
224
  - `ROLE_KEEPER = 'keeper'` — bootstrap-only via daemon token; `grant_paths: ['bootstrap']`,
225
225
  `required_credential_types: ['daemon_token']`.
226
226
  - `ROLE_ADMIN = 'admin'` — admin-grantable; `grant_paths: ['admin']`.
227
- - `BUILTIN_ROLES`, `BuiltinRole` (Zod enum), `BUILTIN_ROLE_SPECS_BY_NAME`
227
+ - `BUILTIN_ROLES`, `BuiltinRole` (Zod enum), `builtin_role_specs_by_name`
228
228
  (`ReadonlyMap<string, RoleSpec>`) — not overridable by consumers.
229
229
  - `RoleSpec`: `{name, description?, required_credential_types?, applicable_scope_kinds?, grant_paths?}`
230
230
  — every cross-axis field is an open-registry string array. Empty
@@ -302,7 +302,7 @@ Zod enum; `AuditOutcome` is `'success' | 'failure'`.
302
302
 
303
303
  #### Metadata schemas
304
304
 
305
- - `AUDIT_METADATA_SCHEMAS` — per-type `z.looseObject`. Notable shapes:
305
+ - `audit_metadata_schemas` — per-type `z.looseObject`. Notable shapes:
306
306
  - `role_grant_create` — `scope_id`, optional `role_grant_id` (failed grants
307
307
  omit — admin-grant-path denial never produces a row), optional
308
308
  `source_offer_id`, optional `self_service` (set by
@@ -376,7 +376,7 @@ Zod enum; `AuditOutcome` is `'success' | 'failure'`.
376
376
  without validation). Pass the result to `create_app_backend({audit_log_config})`
377
377
  — it gets captured inside the bound `AppDeps.audit` emitter, and every
378
378
  call to `audit.emit` validates against it (defaults to
379
- `BUILTIN_AUDIT_LOG_CONFIG` when absent). `query_audit_log` still accepts
379
+ `builtin_audit_log_config` when absent). `query_audit_log` still accepts
380
380
  the trailing `config` positional arg for in-transaction emit sites that
381
381
  hold a transaction-scoped DB only. Builtin collisions and
382
382
  `AuditEventTypeName` format failures throw at construction. The DB
@@ -396,7 +396,7 @@ Zod enum; `AuditOutcome` is `'success' | 'failure'`.
396
396
  factory they track the same config, but a hand-rolled `AuditLogConfig`
397
397
  (or a cast escape) can fire both on a single emission. Sample via
398
398
  `get_*` getters; `reset_*` are test-only. `AUDIT_EVENT_TYPES`,
399
- `AUDIT_METADATA_SCHEMAS`, `BUILTIN_AUDIT_LOG_CONFIG`, and the configs
399
+ `audit_metadata_schemas`, `builtin_audit_log_config`, and the configs
400
400
  returned by `create_audit_log_config` are `Object.freeze`'d to convert
401
401
  accidental mutation (bugs, test cross-contamination, cast escapes)
402
402
  into loud TypeErrors — not a security boundary.
@@ -470,7 +470,7 @@ exports: `RoleGrantOfferReceivedParams`, `_RetractedParams`, `_AcceptedParams`,
470
470
  `_DeclinedParams`, `_SupersedeParams`, `RoleGrantRevokeParams`. Notification
471
471
  builders: `build_role_grant_offer_received_notification(params)` etc.
472
472
 
473
- `ROLE_GRANT_OFFER_NOTIFICATION_SPECS: Array<EventSpec>` — pass to
473
+ `role_grant_offer_notification_specs: Array<EventSpec>` — pass to
474
474
  `create_app_server`'s `event_specs` so the attack surface reflects them
475
475
  and DEV-mode `create_validated_broadcaster` catches payload drift.
476
476
 
@@ -521,6 +521,31 @@ account_id = ANY(...))` so `actor.id`s never round-trip back to the
521
521
  visibility). Returns `Array<AdminAccountEntryJson>`, sorted by
522
522
  `created_at`.
523
523
 
524
+ ### `actor_lookup_queries.ts`
525
+
526
+ - `query_actors_by_ids(deps, ids) → Array<ActorLookupRow>` — batched
527
+ `actor` ⨝ `account` INNER JOIN, returns
528
+ `{id, username, display_name}` per resolved actor. Empty input
529
+ fast-paths to `[]`; hard-deleted (or cascade-orphaned) rows silently
530
+ drop. Row shape omits `account_id` — the join is control-plane, not
531
+ wire-visible. Caller bounds `ids.length` (the action spec enforces
532
+ `ACTOR_LOOKUP_IDS_MAX`); SQL does not.
533
+
534
+ ### `actor_search_queries.ts`
535
+
536
+ - `query_actor_search(deps, {query, scope_ids?, limit}) → Array<ActorLookupRow>` —
537
+ case-insensitive LIKE-prefix on `actor.name`, backed by the
538
+ `idx_actor_name_lower` functional index in `auth_ddl.ts`. Returns the
539
+ same `{id, username, display_name}` row shape as `query_actors_by_ids`
540
+ so the labels arc stays uniform. LIKE wildcards (`%`, `_`, `\`) in
541
+ the user-supplied `query` are escaped before substitution so the
542
+ prefix-only contract is enforceable. When `scope_ids` is non-empty,
543
+ the result is filtered to actors holding an **active** role_grant
544
+ (`revoked_at IS NULL AND (expires_at IS NULL OR expires_at > NOW())`)
545
+ on one of the supplied scopes; `DISTINCT` collapses multi-grant
546
+ duplicates. When `scope_ids` is empty, no role_grant join — the handler
547
+ enforces admin for that path.
548
+
524
549
  ### `role_grant_queries.ts`
525
550
 
526
551
  - `query_create_role_grant` — idempotent; `ON CONFLICT` target and fallback
@@ -551,6 +576,12 @@ account_id = ANY(...))` so `actor.id`s never round-trip back to the
551
576
  that isn't the request actor (e.g., post-mutation verification, scripts,
552
577
  audit-time checks). For the request actor, prefer `has_scoped_role` /
553
578
  `has_any_scoped_role` on the in-memory `auth.role_grants` snapshot.
579
+ - `query_account_has_global_role(deps, account_id, role)` — account-grain
580
+ sibling: does any actor on `account_id` hold an active **global**
581
+ (`scope_id IS NULL`) role_grant for `role`? For surfaces with
582
+ `auth: actor: 'none'` that don't load `auth.role_grants` and can't use
583
+ `has_scoped_role`. EXISTS over the `idx_role_grant_actor`-backed
584
+ subquery, stops at the first match.
554
585
  - `query_role_grant_find_account_id_for_role(deps, role)` — joins
555
586
  role_grant → actor → account, returns first match. Used by daemon token
556
587
  middleware to resolve the keeper account.
@@ -701,7 +732,7 @@ run'` if the seed somehow missed (defensive — migrations always seed).
701
732
  ### `audit_log_queries.ts`
702
733
 
703
734
  - `query_audit_log<T>(deps, input, config?)` — `config` defaults to
704
- `BUILTIN_AUDIT_LOG_CONFIG`. Membership check runs against
735
+ `builtin_audit_log_config`. Membership check runs against
705
736
  `config.event_types`; metadata validation runs independently against
706
737
  `config.metadata_schemas[event_type]` when present. Mismatches and
707
738
  unknown types log + bump their counters (see schema section);
@@ -769,8 +800,8 @@ without rebuilding `AppDeps`.
769
800
 
770
801
  ### `migrations.ts`
771
802
 
772
- - `AUTH_MIGRATION_NAMESPACE = 'fuz_auth'`, `AUTH_MIGRATION_NS` (pre-composed), `RESERVED_MIGRATION_NAMESPACES: ReadonlyArray<string>` (membership list `create_app_backend` rejects on; consumer-discoverable instead of probing the runtime throw).
773
- - `AUTH_MIGRATIONS`:
803
+ - `AUTH_MIGRATION_NAMESPACE = 'fuz_auth'`, `auth_migration_ns` (pre-composed), `reserved_migration_namespaces: ReadonlyArray<string>` (membership list `create_app_backend` rejects on; consumer-discoverable instead of probing the runtime throw).
804
+ - `auth_migrations`:
774
805
  - **v0 `full_auth_schema`** — every table + index + seed for the v1
775
806
  identity system (account, actor, role_grant, auth_session, api_token,
776
807
  audit_log, bootstrap_lock, invite, app_settings). All
@@ -1253,7 +1284,7 @@ of paginated cross-account listings (`admin_account_list`,
1253
1284
  cross-account reads (`admin_session_list`, `invite_list`). The
1254
1285
  dispatcher's per-action hook (shared by HTTP RPC + WS) records every
1255
1286
  invocation regardless of outcome so successful probes consume budget.
1256
- Default `DEFAULT_ACTION_ACCOUNT_RATE_LIMIT` is 1200/15min per actor —
1287
+ Default `default_action_account_rate_limit` is 1200/15min per actor —
1257
1288
  permissive enough for any human admin workflow, slow enough that
1258
1289
  scripted oracles surface in audit. Tighten downstream via
1259
1290
  `AppServerOptions.action_account_rate_limiter`.
@@ -1286,7 +1317,7 @@ self-service `account_actions.ts` surface):
1286
1317
 
1287
1318
  Closure state:
1288
1319
 
1289
- - `grantable_roles` is derived once from `options.roles?.role_specs ?? BUILTIN_ROLE_SPECS_BY_NAME`
1320
+ - `grantable_roles` is derived once from `options.roles?.role_specs ?? builtin_role_specs_by_name`
1290
1321
  via `list_roles_with_grant_path(_, GRANT_PATH_ADMIN)` and closed over
1291
1322
  by the `admin_account_list` handler.
1292
1323
  - `options.app_settings` — when provided, captured by the
@@ -1430,7 +1461,7 @@ Options:
1430
1461
 
1431
1462
  - `roles?: RoleSchemaResult` — drives the admin-grant-path lookup
1432
1463
  (`role_has_grant_path(_, role, GRANT_PATH_ADMIN)`); defaults to
1433
- `BUILTIN_ROLE_SPECS_BY_NAME`.
1464
+ `builtin_role_specs_by_name`.
1434
1465
  - `default_ttl_ms?: number` — applied to new offers (defaults to
1435
1466
  `ROLE_GRANT_OFFER_DEFAULT_TTL_MS`).
1436
1467
  - `authorize?: RoleGrantOfferCreateAuthorize` — custom policy for
@@ -1495,6 +1526,14 @@ and `create_frontend_rpc_client({specs})` wiring. Self-service role
1495
1526
  specs are not included (opt-in, app-specific `eligible_roles`) —
1496
1527
  spread `all_self_service_role_action_specs` separately when needed.
1497
1528
 
1529
+ ### `all_action_spec_registries.ts` — walker-only registry-of-registries
1530
+
1531
+ `all_fuz_auth_action_spec_registries` — walker/codegen entry for every
1532
+ fuz-auth action-spec bundle (`admin`, `role_grant_offer`, `account`,
1533
+ `self_service_role`, `actor_lookup`). Not a mounting surface; protocol
1534
+ specs are excluded. Iterated by `../../test/auth/action_spec_input_invariants.test.ts`
1535
+ and `../../test/auth/all_action_spec_registries.acting_biconditional.test.ts`.
1536
+
1498
1537
  ### `account_action_specs.ts` + `account_actions.ts` — seven self-service RPC actions
1499
1538
 
1500
1539
  Counterpart to `account_routes.ts`. Cookie-lifecycle flows (`login`,
@@ -1583,7 +1622,7 @@ codegen invariant and grow the surface linearly per role.
1583
1622
 
1584
1623
  - `eligible_roles?: ReadonlyArray<string>` — optional override
1585
1624
  allowlist. When omitted, eligibility is derived from
1586
- `roles.role_specs` (or `BUILTIN_ROLE_SPECS_BY_NAME` when `roles` is
1625
+ `roles.role_specs` (or `builtin_role_specs_by_name` when `roles` is
1587
1626
  also omitted) by selecting every role whose `RoleSpec.grant_paths`
1588
1627
  includes `'self_service'` (`GRANT_PATH_SELF_SERVICE`). Roles outside
1589
1628
  the eligible set are rejected with `forbidden` + reason
@@ -1610,6 +1649,109 @@ Deps: `Pick<RouteFactoryDeps, 'log' | 'audit'>`.
1610
1649
  `all_self_service_role_action_specs: ReadonlyArray<RequestResponseActionSpec>` —
1611
1650
  codegen-ready registry of the single unified spec.
1612
1651
 
1652
+ ### `actor_lookup_action_specs.ts` + `actor_lookup_actions.ts` — opt-in batched actor → label resolver
1653
+
1654
+ One static `request_response` action — `actor_lookup({ids}) → {actors:
1655
+ [{id, username, display_name?}]}` — powers the labels arc for surfaces
1656
+ that stamp an actor id (bylines, owner columns, grantor labels, audit
1657
+ "by" cells). One round trip resolves a batch to display strings;
1658
+ `ACTOR_LOOKUP_IDS_MAX = 50` cap per call.
1659
+
1660
+ **Auth + rate-limit posture.** `{account: 'required', actor: 'none'}` +
1661
+ `rate_limit: 'account'`. Account-grain — the caller need only be signed
1662
+ in; resolution skips the actor phase. The auth gate + per-account rate
1663
+ limit + per-call cap bound the batched username-enumeration surface that
1664
+ a `cell_list` ↔ `actor_lookup` pair would otherwise present. Don't loosen
1665
+ to public — a public-surface byline should resolve via SSR-stamped labels
1666
+ or per-cell embedded actor labels, not by widening this gate.
1667
+
1668
+ **Wire shape — info-leak audit.** Deliberately omitted from
1669
+ `ActorLookupEntryJson`:
1670
+
1671
+ - `account_id` — the actor↔account join is a control-plane detail.
1672
+ - `email`, password/credential fields — never queried.
1673
+ - `created_at` / `updated_at` — timing-oracle avoidance.
1674
+ - role / role_grants / session state — separation of concern.
1675
+
1676
+ `display_name` is omitted (not `null`) when `actor.name` is blank, so
1677
+ clients see `undefined` rather than a sentinel string. Unknown ids are
1678
+ silently absent — by construction this is an existence-oracle (caller
1679
+ diffs response ids against request ids), bounded by rate-limit, the
1680
+ 50-id cap, actor-uuid intractability (122-bit random), and the
1681
+ hard-delete-cascade indistinguishability from never-existed (no
1682
+ tombstone oracle). Response order is unspecified — callers index by
1683
+ `id` when needed.
1684
+
1685
+ `create_actor_lookup_actions(deps)` — `deps:
1686
+ Pick<RouteFactoryDeps, 'log'>`. Pure read; no audit, no side effects.
1687
+ Backed by `query_actors_by_ids` (see Queries §
1688
+ [`actor_lookup_queries.ts`](#actor_lookup_queriests)).
1689
+
1690
+ Bundle is **not** included in `create_standard_rpc_actions` — consumers
1691
+ without a byline surface can skip it. Spread
1692
+ `all_actor_lookup_action_specs` alongside the standard bundle when the
1693
+ labels arc is needed.
1694
+
1695
+ ### `actor_search_action_specs.ts` + `actor_search_actions.ts` — opt-in prefix-search picker
1696
+
1697
+ One static `request_response` action — `actor_search({query, scope_ids?, limit?}) → {actors: [{id, username, display_name?}]}` —
1698
+ powers person-target pickers. Sibling to `actor_lookup`: that resolves a
1699
+ batch of known ids to labels; this resolves a partial name to candidate
1700
+ actors. Reuses `ActorLookupEntryJson` from
1701
+ `./actor_lookup_action_specs.ts` so the labels arc on the consumer side
1702
+ stays uniform. Default limit `ACTOR_SEARCH_LIMIT_DEFAULT = 20`, hard cap
1703
+ `ACTOR_SEARCH_LIMIT_MAX = 50`. Query string capped at
1704
+ `ACTOR_SEARCH_QUERY_LENGTH_MAX = 50`.
1705
+
1706
+ **Auth + rate-limit posture.** `{account: 'required', actor: 'none'}` +
1707
+ `rate_limit: 'account'`. Same shape as `actor_lookup`. The handler
1708
+ additionally requires the caller to be admin when `scope_ids` is empty —
1709
+ unbounded global search is the admin-only arm; non-admin callers must
1710
+ always pass at least one scope_id and get filtered to actors with active
1711
+ role_grants on those scopes. The admin check is **account-grain** (any
1712
+ actor on the caller's account holds a global `admin` role_grant) via
1713
+ `query_account_has_global_role` — the `actor: 'none'` posture means
1714
+ `auth.role_grants` is empty and the in-memory `has_scoped_role` helper
1715
+ doesn't apply.
1716
+
1717
+ **Caller-passes-scope_ids design.** `scope_ids` is trusted as a filter,
1718
+ not as an authority claim — the SQL filters to actors with role_grants on
1719
+ those scopes regardless of whether the caller has authority over them.
1720
+ Consumers (e.g. visiones' `CellGrantsEditor.svelte`) pre-filter
1721
+ `scope_ids` against their own authority (the teacher-predicate stays in
1722
+ the consumer layer, not in fuz_app). This does **not** widen the
1723
+ scope-existence oracle: an attacker passing a random scope_id never
1724
+ learns the scope existed if no member happens to match the query, and
1725
+ even on a match the result row only carries the matching actor — never
1726
+ "which scope matched".
1727
+
1728
+ **Wire shape — additional info-leak posture beyond `actor_lookup`'s.**
1729
+
1730
+ - Prefix match (`LOWER(name) LIKE LOWER(query) || '%' ESCAPE '\\'`),
1731
+ **not** full `%query%`. LIKE wildcards in the user-supplied query are
1732
+ escaped at the JS layer so a `%xyz` input can't widen to full LIKE
1733
+ and defeat the per-call cap.
1734
+ - Empty result set on no-match — fail-soft like `cell_list`. No "no
1735
+ actor matches" error that would leak an existence boundary on the
1736
+ search-term axis.
1737
+ - Hard-deleted actors silently drop (same `account_id` cascade as
1738
+ `actor_lookup`).
1739
+
1740
+ Reason constant exported for failed-arm matching: `ERROR_ACTOR_SEARCH_SCOPE_REQUIRED`
1741
+ (`'actor_search_scope_required'`) — fired with `invalid_params` when a
1742
+ non-admin caller omits `scope_ids` or passes `[]`. Surfaced on
1743
+ `spec.error_reasons` so codegen + form-state matching can read it
1744
+ declaratively.
1745
+
1746
+ `create_actor_search_actions(deps)` — `deps:
1747
+ Pick<RouteFactoryDeps, 'log'>`. Pure read; no audit, no side effects.
1748
+ Backed by `query_actor_search` (see Queries §`actor_search_queries.ts`).
1749
+
1750
+ Bundle is **not** included in `create_standard_rpc_actions` — consumers
1751
+ without a person-target picker can skip it. Spread
1752
+ `all_actor_search_action_specs` alongside the standard bundle when the
1753
+ picker is needed.
1754
+
1613
1755
  ## Cleanup
1614
1756
 
1615
1757
  `cleanup.ts` — periodic auth maintenance:
@@ -0,0 +1,127 @@
1
+ /**
2
+ * `actor_lookup` RPC spec — authenticated batched id → username/display_name
3
+ * resolver, keyed by actor id.
4
+ *
5
+ * Powers the labels arc for surfaces that stamp an actor id (bylines,
6
+ * owner columns, grantor labels, audit-log "by" cells). One round trip
7
+ * resolves an array of ids to display strings.
8
+ *
9
+ * ## Auth + rate-limit posture
10
+ *
11
+ * `{account: 'required', actor: 'none'}` + `rate_limit: 'account'`.
12
+ * Account-grain — only that the caller is signed in matters, not which
13
+ * actor is calling, so resolution skips the actor phase. The auth gate
14
+ * + per-account rate limit (default 1200/15min) + the
15
+ * {@link ACTOR_LOOKUP_IDS_MAX | per-call cap} bound the batched
16
+ * username-enumeration surface that the `cell_list` ↔ `actor_lookup`
17
+ * pair would otherwise present.
18
+ *
19
+ * If a public-surface byline ever lands (e.g. an unauthenticated
20
+ * gallery), it should resolve via a separate public-safe mechanism
21
+ * (SSR-stamped labels or a per-cell embedded actor label), **not** by
22
+ * loosening this gate.
23
+ *
24
+ * ## Wire shape — info-leak audit
25
+ *
26
+ * Output: `{actors: [{id, username, display_name?}]}`. Deliberately
27
+ * omitted:
28
+ *
29
+ * - `account_id` — the actor↔account join is a control-plane detail
30
+ * - `email`, password/credential fields — never queried
31
+ * - `created_at` / `updated_at` — timing-oracle avoidance
32
+ * - role / role_grants / session state — separation of concern
33
+ *
34
+ * `display_name` is omitted (not `null`) when `actor.name` is blank, so
35
+ * clients see `undefined` rather than a sentinel string. Unknown ids are
36
+ * silently absent from the response — by construction this is an
37
+ * existence-oracle (the caller can diff response ids against request
38
+ * ids), bounded by:
39
+ *
40
+ * 1. rate-limit (per-account, see above),
41
+ * 2. {@link ACTOR_LOOKUP_IDS_MAX} cap per call,
42
+ * 3. actor-uuid intractability (122-bit random),
43
+ * 4. hard-deleted actors are indistinguishable from never-existed (no
44
+ * tombstone oracle — see `actor_lookup_queries.ts`).
45
+ *
46
+ * Response order is unspecified — callers index by `id` when needed.
47
+ *
48
+ * @module
49
+ */
50
+ import { z } from 'zod';
51
+ /**
52
+ * Hard cap on the number of ids resolvable in one call. Bounds the
53
+ * batched username-enumeration surface.
54
+ */
55
+ export declare const ACTOR_LOOKUP_IDS_MAX = 50;
56
+ /** One resolved actor row. `display_name` omitted when blank. */
57
+ export declare const ActorLookupEntryJson: z.ZodObject<{
58
+ id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
59
+ username: z.ZodString;
60
+ display_name: z.ZodOptional<z.ZodString>;
61
+ }, z.core.$strict>;
62
+ export type ActorLookupEntryJson = z.infer<typeof ActorLookupEntryJson>;
63
+ export declare const ActorLookupInput: z.ZodObject<{
64
+ ids: z.ZodArray<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
65
+ }, z.core.$strict>;
66
+ export type ActorLookupInput = z.infer<typeof ActorLookupInput>;
67
+ export declare const ActorLookupOutput: z.ZodObject<{
68
+ actors: z.ZodArray<z.ZodObject<{
69
+ id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
70
+ username: z.ZodString;
71
+ display_name: z.ZodOptional<z.ZodString>;
72
+ }, z.core.$strict>>;
73
+ }, z.core.$strict>;
74
+ export type ActorLookupOutput = z.infer<typeof ActorLookupOutput>;
75
+ export declare const actor_lookup_action_spec: {
76
+ method: string;
77
+ kind: "request_response";
78
+ initiator: "frontend";
79
+ auth: {
80
+ account: "required";
81
+ actor: "none";
82
+ };
83
+ side_effects: false;
84
+ input: z.ZodObject<{
85
+ ids: z.ZodArray<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
86
+ }, z.core.$strict>;
87
+ output: z.ZodObject<{
88
+ actors: z.ZodArray<z.ZodObject<{
89
+ id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
90
+ username: z.ZodString;
91
+ display_name: z.ZodOptional<z.ZodString>;
92
+ }, z.core.$strict>>;
93
+ }, z.core.$strict>;
94
+ async: true;
95
+ rate_limit: "account";
96
+ description: string;
97
+ };
98
+ /**
99
+ * All actor_lookup action specs — independent opt-in registry. Consumers
100
+ * spread alongside `all_standard_action_specs` if they want the labels
101
+ * arc; not folded into the standard bundle because consumers without a
102
+ * byline surface can skip it.
103
+ */
104
+ export declare const all_actor_lookup_action_specs: readonly [{
105
+ method: string;
106
+ kind: "request_response";
107
+ initiator: "frontend";
108
+ auth: {
109
+ account: "required";
110
+ actor: "none";
111
+ };
112
+ side_effects: false;
113
+ input: z.ZodObject<{
114
+ ids: z.ZodArray<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
115
+ }, z.core.$strict>;
116
+ output: z.ZodObject<{
117
+ actors: z.ZodArray<z.ZodObject<{
118
+ id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
119
+ username: z.ZodString;
120
+ display_name: z.ZodOptional<z.ZodString>;
121
+ }, z.core.$strict>>;
122
+ }, z.core.$strict>;
123
+ async: true;
124
+ rate_limit: "account";
125
+ description: string;
126
+ }];
127
+ //# sourceMappingURL=actor_lookup_action_specs.d.ts.map