@fuzdev/fuz_app 0.39.0 → 0.40.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 (42) hide show
  1. package/dist/auth/CLAUDE.md +89 -17
  2. package/dist/auth/account_actions.d.ts +5 -3
  3. package/dist/auth/account_actions.d.ts.map +1 -1
  4. package/dist/auth/account_actions.js +5 -6
  5. package/dist/auth/account_routes.d.ts.map +1 -1
  6. package/dist/auth/account_routes.js +7 -7
  7. package/dist/auth/admin_action_specs.d.ts +6 -138
  8. package/dist/auth/admin_action_specs.d.ts.map +1 -1
  9. package/dist/auth/admin_action_specs.js +4 -2
  10. package/dist/auth/admin_actions.d.ts +4 -3
  11. package/dist/auth/admin_actions.d.ts.map +1 -1
  12. package/dist/auth/admin_actions.js +8 -9
  13. package/dist/auth/audit_log_queries.d.ts +16 -6
  14. package/dist/auth/audit_log_queries.d.ts.map +1 -1
  15. package/dist/auth/audit_log_queries.js +7 -8
  16. package/dist/auth/audit_log_schema.d.ts +24 -74
  17. package/dist/auth/audit_log_schema.d.ts.map +1 -1
  18. package/dist/auth/audit_log_schema.js +17 -2
  19. package/dist/auth/bootstrap_routes.d.ts.map +1 -1
  20. package/dist/auth/bootstrap_routes.js +3 -3
  21. package/dist/auth/cleanup.d.ts +9 -1
  22. package/dist/auth/cleanup.d.ts.map +1 -1
  23. package/dist/auth/cleanup.js +2 -2
  24. package/dist/auth/deps.d.ts +13 -1
  25. package/dist/auth/deps.d.ts.map +1 -1
  26. package/dist/auth/permit_offer_actions.d.ts +16 -2
  27. package/dist/auth/permit_offer_actions.d.ts.map +1 -1
  28. package/dist/auth/permit_offer_actions.js +26 -8
  29. package/dist/auth/self_service_role_actions.d.ts +136 -0
  30. package/dist/auth/self_service_role_actions.d.ts.map +1 -0
  31. package/dist/auth/self_service_role_actions.js +198 -0
  32. package/dist/auth/signup_routes.d.ts.map +1 -1
  33. package/dist/auth/signup_routes.js +2 -2
  34. package/dist/auth/standard_rpc_actions.d.ts +1 -1
  35. package/dist/auth/standard_rpc_actions.js +1 -1
  36. package/dist/server/app_backend.d.ts +9 -1
  37. package/dist/server/app_backend.d.ts.map +1 -1
  38. package/dist/server/app_backend.js +12 -1
  39. package/dist/ui/ui_format.d.ts +2 -3
  40. package/dist/ui/ui_format.d.ts.map +1 -1
  41. package/dist/ui/ui_format.js +1 -1
  42. package/package.json +1 -1
@@ -43,12 +43,11 @@ import { admin_account_list_action_spec, admin_session_list_action_spec, admin_s
43
43
  /**
44
44
  * Create the admin-only RPC actions.
45
45
  *
46
- * @param deps - stateless capabilities (log, on_audit_event)
46
+ * @param deps - `AdminActionDeps` slice of `AppDeps` (`log`, `on_audit_event`, optional `audit_log_config`)
47
47
  * @param options - role schema for `grantable_roles` derivation
48
48
  * @returns the `RpcAction` array to spread into a `create_rpc_endpoint` call
49
49
  */
50
50
  export const create_admin_actions = (deps, options = {}) => {
51
- const { log, on_audit_event } = deps;
52
51
  const role_options = options.roles?.role_options ?? BUILTIN_ROLE_OPTIONS;
53
52
  const grantable_roles = [];
54
53
  for (const [name, rc] of role_options) {
@@ -81,7 +80,7 @@ export const create_admin_actions = (deps, options = {}) => {
81
80
  reason: ERROR_ACCOUNT_NOT_FOUND,
82
81
  attempted_account_id: input.account_id,
83
82
  },
84
- }, log, on_audit_event);
83
+ }, deps);
85
84
  throw jsonrpc_errors.not_found('account', { reason: ERROR_ACCOUNT_NOT_FOUND });
86
85
  }
87
86
  const count = await query_session_revoke_all_for_account(ctx, input.account_id);
@@ -92,7 +91,7 @@ export const create_admin_actions = (deps, options = {}) => {
92
91
  target_account_id: input.account_id,
93
92
  ip: ctx.client_ip,
94
93
  metadata: { count },
95
- }, log, on_audit_event);
94
+ }, deps);
96
95
  return { ok: true, count };
97
96
  };
98
97
  const token_revoke_all_handler = async (input, ctx) => {
@@ -112,7 +111,7 @@ export const create_admin_actions = (deps, options = {}) => {
112
111
  reason: ERROR_ACCOUNT_NOT_FOUND,
113
112
  attempted_account_id: input.account_id,
114
113
  },
115
- }, log, on_audit_event);
114
+ }, deps);
116
115
  throw jsonrpc_errors.not_found('account', { reason: ERROR_ACCOUNT_NOT_FOUND });
117
116
  }
118
117
  const count = await query_revoke_all_api_tokens_for_account(ctx, input.account_id);
@@ -123,7 +122,7 @@ export const create_admin_actions = (deps, options = {}) => {
123
122
  target_account_id: input.account_id,
124
123
  ip: ctx.client_ip,
125
124
  metadata: { count },
126
- }, log, on_audit_event);
125
+ }, deps);
127
126
  return { ok: true, count };
128
127
  };
129
128
  const audit_log_list_handler = async (input, ctx) => {
@@ -188,7 +187,7 @@ export const create_admin_actions = (deps, options = {}) => {
188
187
  account_id: auth.account.id,
189
188
  ip: ctx.client_ip,
190
189
  metadata: { invite_id: invite.id, email, username },
191
- }, log, on_audit_event);
190
+ }, deps);
192
191
  return { ok: true, invite };
193
192
  };
194
193
  const invite_list_handler = async (_input, ctx) => {
@@ -207,7 +206,7 @@ export const create_admin_actions = (deps, options = {}) => {
207
206
  account_id: auth.account.id,
208
207
  ip: ctx.client_ip,
209
208
  metadata: { invite_id: input.invite_id },
210
- }, log, on_audit_event);
209
+ }, deps);
211
210
  return { ok: true };
212
211
  };
213
212
  const actions = [
@@ -246,7 +245,7 @@ export const create_admin_actions = (deps, options = {}) => {
246
245
  old_value,
247
246
  new_value: input.open_signup,
248
247
  },
249
- }, log, on_audit_event);
248
+ }, deps);
250
249
  const settings = await query_app_settings_load_with_username(ctx);
251
250
  return { ok: true, settings };
252
251
  };
@@ -11,9 +11,9 @@
11
11
  *
12
12
  * @module
13
13
  */
14
- import type { Logger } from '@fuzdev/fuz_util/log.js';
15
14
  import type { QueryDeps } from '../db/query_deps.js';
16
15
  import type { RouteContext } from '../http/route_spec.js';
16
+ import type { AppDeps } from './deps.js';
17
17
  import { type AuditLogConfig, type AuditLogEvent, type AuditLogInput, type AuditLogListOptions, type AuditLogEventWithUsernamesJson, type PermitHistoryEventJson } from './audit_log_schema.js';
18
18
  /** Default limit for audit log listings. */
19
19
  export declare const AUDIT_LOG_DEFAULT_LIMIT = 50;
@@ -81,19 +81,29 @@ export declare const query_audit_log_list_permit_history: (deps: QueryDeps, limi
81
81
  * @returns the number of entries deleted
82
82
  */
83
83
  export declare const query_audit_log_cleanup_before: (deps: QueryDeps, before: Date) => Promise<number>;
84
+ /**
85
+ * Capabilities required by `audit_log_fire_and_forget`.
86
+ *
87
+ * Defined as a slice of `AppDeps` so call sites can pass the surrounding deps
88
+ * bundle directly without a structural-compatibility coincidence. The bundled
89
+ * shape replaces the prior `(log, on_audit_event, config?)` positional args
90
+ * — consumers that forgot the trailing `config` would silently fall back to
91
+ * `BUILTIN_AUDIT_LOG_CONFIG` and skip metadata validation for their own
92
+ * event types. `audit_log_config` is optional on `AppDeps` and defaults to
93
+ * `BUILTIN_AUDIT_LOG_CONFIG` inside `audit_log_fire_and_forget` when absent.
94
+ */
95
+ export type AuditLogFireAndForgetDeps = Pick<AppDeps, 'log' | 'on_audit_event' | 'audit_log_config'>;
84
96
  /**
85
97
  * Log an audit event without blocking the caller.
86
98
  *
87
99
  * Errors are logged — audit logging never breaks auth flows. Uses
88
100
  * `background_db` so entries persist even when the request transaction
89
- * rolls back. Write and `on_event` callback failures are logged separately.
101
+ * rolls back. Write and `on_audit_event` callback failures are logged separately.
90
102
  *
91
103
  * @param route - `background_db` and `pending_effects` from the route context
92
104
  * @param input - the audit event to record
93
- * @param log - the logger instance
94
- * @param on_event - callback invoked with the inserted row after a successful write
95
- * @param config - audit-log config. Defaults to `BUILTIN_AUDIT_LOG_CONFIG`.
105
+ * @param deps - logger, `on_audit_event` callback, and optional `audit_log_config`
96
106
  * @returns the settled promise (callers may ignore it)
97
107
  */
98
- export declare const audit_log_fire_and_forget: <T extends string>(route: Pick<RouteContext, "background_db" | "pending_effects">, input: AuditLogInput<T>, log: Logger, on_event: (event: AuditLogEvent) => void, config?: AuditLogConfig) => Promise<void>;
108
+ export declare const audit_log_fire_and_forget: <T extends string>(route: Pick<RouteContext, "background_db" | "pending_effects">, input: AuditLogInput<T>, deps: AuditLogFireAndForgetDeps) => Promise<void>;
99
109
  //# sourceMappingURL=audit_log_queries.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"audit_log_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_log_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAEnD,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAEN,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,8BAA8B,EACnC,KAAK,sBAAsB,EAC3B,MAAM,uBAAuB,CAAC;AAE/B,4CAA4C;AAC5C,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAa1C,iFAAiF;AACjF,eAAO,MAAM,sCAAsC,QAAO,MACvB,CAAC;AAEpC,0CAA0C;AAC1C,eAAO,MAAM,wCAAwC,QAAO,IAE3D,CAAC;AAYF,gFAAgF;AAChF,eAAO,MAAM,qCAAqC,QAAO,MACvB,CAAC;AAEnC,0CAA0C;AAC1C,eAAO,MAAM,uCAAuC,QAAO,IAE1D,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,eAAe,GAAU,CAAC,SAAS,MAAM,EACrD,MAAM,SAAS,EACf,OAAO,aAAa,CAAC,CAAC,CAAC,EACvB,SAAQ,cAAyC,KAC/C,OAAO,CAAC,aAAa,CAmCvB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAChC,MAAM,SAAS,EACf,UAAU,mBAAmB,KAC3B,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAwC9B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mCAAmC,GAC/C,MAAM,SAAS,EACf,UAAU,mBAAmB,KAC3B,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CA8C/C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gCAAgC,GAC5C,MAAM,SAAS,EACf,YAAY,MAAM,EAClB,cAA+B,KAC7B,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAO9B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,mCAAmC,GAC/C,MAAM,SAAS,EACf,cAA+B,EAC/B,eAAU,KACR,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAYvC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,8BAA8B,GAC1C,MAAM,SAAS,EACf,QAAQ,IAAI,KACV,OAAO,CAAC,MAAM,CAMhB,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yBAAyB,GAAI,CAAC,SAAS,MAAM,EACzD,OAAO,IAAI,CAAC,YAAY,EAAE,eAAe,GAAG,iBAAiB,CAAC,EAC9D,OAAO,aAAa,CAAC,CAAC,CAAC,EACvB,KAAK,MAAM,EACX,UAAU,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,EACxC,SAAQ,cAAyC,KAC/C,OAAO,CAAC,IAAI,CAcd,CAAC"}
1
+ {"version":3,"file":"audit_log_queries.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/audit_log_queries.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAEnD,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,uBAAuB,CAAC;AACxD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,WAAW,CAAC;AACvC,OAAO,EAEN,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,8BAA8B,EACnC,KAAK,sBAAsB,EAC3B,MAAM,uBAAuB,CAAC;AAE/B,4CAA4C;AAC5C,eAAO,MAAM,uBAAuB,KAAK,CAAC;AAa1C,iFAAiF;AACjF,eAAO,MAAM,sCAAsC,QAAO,MACvB,CAAC;AAEpC,0CAA0C;AAC1C,eAAO,MAAM,wCAAwC,QAAO,IAE3D,CAAC;AAYF,gFAAgF;AAChF,eAAO,MAAM,qCAAqC,QAAO,MACvB,CAAC;AAEnC,0CAA0C;AAC1C,eAAO,MAAM,uCAAuC,QAAO,IAE1D,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,eAAe,GAAU,CAAC,SAAS,MAAM,EACrD,MAAM,SAAS,EACf,OAAO,aAAa,CAAC,CAAC,CAAC,EACvB,SAAQ,cAAyC,KAC/C,OAAO,CAAC,aAAa,CAmCvB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,oBAAoB,GAChC,MAAM,SAAS,EACf,UAAU,mBAAmB,KAC3B,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAwC9B,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,mCAAmC,GAC/C,MAAM,SAAS,EACf,UAAU,mBAAmB,KAC3B,OAAO,CAAC,KAAK,CAAC,8BAA8B,CAAC,CA8C/C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,gCAAgC,GAC5C,MAAM,SAAS,EACf,YAAY,MAAM,EAClB,cAA+B,KAC7B,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC,CAO9B,CAAC;AAEF;;;;;;;GAOG;AACH,eAAO,MAAM,mCAAmC,GAC/C,MAAM,SAAS,EACf,cAA+B,EAC/B,eAAU,KACR,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAYvC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,8BAA8B,GAC1C,MAAM,SAAS,EACf,QAAQ,IAAI,KACV,OAAO,CAAC,MAAM,CAMhB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,MAAM,MAAM,yBAAyB,GAAG,IAAI,CAC3C,OAAO,EACP,KAAK,GAAG,gBAAgB,GAAG,kBAAkB,CAC7C,CAAC;AAEF;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,yBAAyB,GAAI,CAAC,SAAS,MAAM,EACzD,OAAO,IAAI,CAAC,YAAY,EAAE,eAAe,GAAG,iBAAiB,CAAC,EAC9D,OAAO,aAAa,CAAC,CAAC,CAAC,EACvB,MAAM,yBAAyB,KAC7B,OAAO,CAAC,IAAI,CAed,CAAC"}
@@ -216,23 +216,22 @@ export const query_audit_log_cleanup_before = async (deps, before) => {
216
216
  *
217
217
  * Errors are logged — audit logging never breaks auth flows. Uses
218
218
  * `background_db` so entries persist even when the request transaction
219
- * rolls back. Write and `on_event` callback failures are logged separately.
219
+ * rolls back. Write and `on_audit_event` callback failures are logged separately.
220
220
  *
221
221
  * @param route - `background_db` and `pending_effects` from the route context
222
222
  * @param input - the audit event to record
223
- * @param log - the logger instance
224
- * @param on_event - callback invoked with the inserted row after a successful write
225
- * @param config - audit-log config. Defaults to `BUILTIN_AUDIT_LOG_CONFIG`.
223
+ * @param deps - logger, `on_audit_event` callback, and optional `audit_log_config`
226
224
  * @returns the settled promise (callers may ignore it)
227
225
  */
228
- export const audit_log_fire_and_forget = (route, input, log, on_event, config = BUILTIN_AUDIT_LOG_CONFIG) => {
229
- const p = query_audit_log({ db: route.background_db }, input, config)
226
+ export const audit_log_fire_and_forget = (route, input, deps) => {
227
+ const { log, on_audit_event, audit_log_config = BUILTIN_AUDIT_LOG_CONFIG } = deps;
228
+ const p = query_audit_log({ db: route.background_db }, input, audit_log_config)
230
229
  .then((event) => {
231
230
  try {
232
- on_event(event);
231
+ on_audit_event(event);
233
232
  }
234
233
  catch (callback_err) {
235
- log.error('Audit log on_event callback failed:', callback_err);
234
+ log.error('Audit log on_audit_event callback failed:', callback_err);
236
235
  }
237
236
  })
238
237
  .catch((err) => {
@@ -103,12 +103,14 @@ export declare const AUDIT_METADATA_SCHEMAS: Readonly<{
103
103
  permit_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
104
104
  scope_id: z.ZodOptional<z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>>;
105
105
  source_offer_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
106
+ self_service: z.ZodOptional<z.ZodBoolean>;
106
107
  }, z.core.$loose>;
107
108
  permit_revoke: z.ZodObject<{
108
109
  role: z.ZodString;
109
110
  permit_id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
110
111
  scope_id: z.ZodOptional<z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>>;
111
112
  reason: z.ZodOptional<z.ZodString>;
113
+ self_service: z.ZodOptional<z.ZodBoolean>;
112
114
  }, z.core.$loose>;
113
115
  permit_offer_create: z.ZodObject<{
114
116
  offer_id: z.ZodOptional<z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">>;
@@ -166,11 +168,11 @@ export declare const AUDIT_METADATA_SCHEMAS: Readonly<{
166
168
  export type AuditMetadataMap = {
167
169
  [K in AuditEventType]: z.infer<(typeof AUDIT_METADATA_SCHEMAS)[K]>;
168
170
  };
169
- /** Audit log row from the database. */
171
+ /** Audit log row from the database. See `AuditLogEventJson` for `event_type` widening rationale. */
170
172
  export interface AuditLogEvent {
171
173
  id: Uuid;
172
174
  seq: number;
173
- event_type: AuditEventType;
175
+ event_type: AuditEventTypeName;
174
176
  outcome: AuditOutcome;
175
177
  actor_id: Uuid | null;
176
178
  account_id: Uuid | null;
@@ -258,40 +260,32 @@ export declare const create_audit_log_config: (options?: CreateAuditLogConfigOpt
258
260
  export interface AuditLogListOptions {
259
261
  limit?: number;
260
262
  offset?: number;
261
- event_type?: AuditEventType;
262
- event_type_in?: Array<AuditEventType>;
263
+ /**
264
+ * Event-type filter. Accepts any string — builtins or consumer-registered
265
+ * via `create_audit_log_config({extra_events})`. The DB column is
266
+ * `TEXT NOT NULL` with no CHECK, so unknown strings simply match nothing.
267
+ */
268
+ event_type?: string;
269
+ event_type_in?: Array<string>;
263
270
  account_id?: Uuid;
264
271
  outcome?: AuditOutcome;
265
272
  /** When set, only return events with `seq` greater than this value. Enables SSE reconnection gap fill. */
266
273
  since_seq?: number;
267
274
  }
268
- /** Zod schema for client-safe audit log event. */
275
+ /**
276
+ * Zod schema for client-safe audit log event.
277
+ *
278
+ * `event_type` is `AuditEventTypeName` (regex-validated string) — matches
279
+ * the `AuditLogEvent` row and the DB's `TEXT NOT NULL` column. Consumer
280
+ * types registered via `create_audit_log_config({extra_events})` round-trip
281
+ * through queries, `on_audit_event` callbacks, and JSON-RPC responses
282
+ * identically to builtins. `AuditLogInput<T>` stays parameterized on the
283
+ * write side so `AuditMetadataMap` narrowing via `get_audit_metadata` works.
284
+ */
269
285
  export declare const AuditLogEventJson: z.ZodObject<{
270
286
  id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
271
287
  seq: z.ZodNumber;
272
- event_type: z.ZodEnum<{
273
- login: "login";
274
- logout: "logout";
275
- bootstrap: "bootstrap";
276
- signup: "signup";
277
- password_change: "password_change";
278
- session_revoke: "session_revoke";
279
- session_revoke_all: "session_revoke_all";
280
- token_create: "token_create";
281
- token_revoke: "token_revoke";
282
- token_revoke_all: "token_revoke_all";
283
- permit_grant: "permit_grant";
284
- permit_revoke: "permit_revoke";
285
- permit_offer_create: "permit_offer_create";
286
- permit_offer_accept: "permit_offer_accept";
287
- permit_offer_decline: "permit_offer_decline";
288
- permit_offer_retract: "permit_offer_retract";
289
- permit_offer_expire: "permit_offer_expire";
290
- permit_offer_supersede: "permit_offer_supersede";
291
- invite_create: "invite_create";
292
- invite_delete: "invite_delete";
293
- app_settings_update: "app_settings_update";
294
- }>;
288
+ event_type: z.ZodString;
295
289
  outcome: z.ZodEnum<{
296
290
  success: "success";
297
291
  failure: "failure";
@@ -308,29 +302,7 @@ export type AuditLogEventJson = z.infer<typeof AuditLogEventJson>;
308
302
  export declare const AuditLogEventWithUsernamesJson: z.ZodObject<{
309
303
  id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
310
304
  seq: z.ZodNumber;
311
- event_type: z.ZodEnum<{
312
- login: "login";
313
- logout: "logout";
314
- bootstrap: "bootstrap";
315
- signup: "signup";
316
- password_change: "password_change";
317
- session_revoke: "session_revoke";
318
- session_revoke_all: "session_revoke_all";
319
- token_create: "token_create";
320
- token_revoke: "token_revoke";
321
- token_revoke_all: "token_revoke_all";
322
- permit_grant: "permit_grant";
323
- permit_revoke: "permit_revoke";
324
- permit_offer_create: "permit_offer_create";
325
- permit_offer_accept: "permit_offer_accept";
326
- permit_offer_decline: "permit_offer_decline";
327
- permit_offer_retract: "permit_offer_retract";
328
- permit_offer_expire: "permit_offer_expire";
329
- permit_offer_supersede: "permit_offer_supersede";
330
- invite_create: "invite_create";
331
- invite_delete: "invite_delete";
332
- app_settings_update: "app_settings_update";
333
- }>;
305
+ event_type: z.ZodString;
334
306
  outcome: z.ZodEnum<{
335
307
  success: "success";
336
308
  failure: "failure";
@@ -349,29 +321,7 @@ export type AuditLogEventWithUsernamesJson = z.infer<typeof AuditLogEventWithUse
349
321
  export declare const PermitHistoryEventJson: z.ZodObject<{
350
322
  id: z.core.$ZodBranded<z.ZodUUID, "Uuid", "out">;
351
323
  seq: z.ZodNumber;
352
- event_type: z.ZodEnum<{
353
- login: "login";
354
- logout: "logout";
355
- bootstrap: "bootstrap";
356
- signup: "signup";
357
- password_change: "password_change";
358
- session_revoke: "session_revoke";
359
- session_revoke_all: "session_revoke_all";
360
- token_create: "token_create";
361
- token_revoke: "token_revoke";
362
- token_revoke_all: "token_revoke_all";
363
- permit_grant: "permit_grant";
364
- permit_revoke: "permit_revoke";
365
- permit_offer_create: "permit_offer_create";
366
- permit_offer_accept: "permit_offer_accept";
367
- permit_offer_decline: "permit_offer_decline";
368
- permit_offer_retract: "permit_offer_retract";
369
- permit_offer_expire: "permit_offer_expire";
370
- permit_offer_supersede: "permit_offer_supersede";
371
- invite_create: "invite_create";
372
- invite_delete: "invite_delete";
373
- app_settings_update: "app_settings_update";
374
- }>;
324
+ event_type: z.ZodString;
375
325
  outcome: z.ZodEnum<{
376
326
  success: "success";
377
327
  failure: "failure";
@@ -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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"}
@@ -89,17 +89,23 @@ export const AUDIT_METADATA_SCHEMAS = Object.freeze({
89
89
  }),
90
90
  // `permit_id` is optional on `permit_grant` because failed grants
91
91
  // (e.g. `web_grantable` denied) never produce a permit row.
92
+ // `self_service: true` is set by the self-service role toggle in
93
+ // `self_service_role_actions.ts` — declared explicitly rather than
94
+ // riding on `z.looseObject` permissiveness so the field is part of
95
+ // the documented schema surface.
92
96
  permit_grant: z.looseObject({
93
97
  role: z.string(),
94
98
  permit_id: Uuid.optional(),
95
99
  scope_id: Uuid.nullish(),
96
100
  source_offer_id: Uuid.optional(),
101
+ self_service: z.boolean().optional(),
97
102
  }),
98
103
  permit_revoke: z.looseObject({
99
104
  role: z.string(),
100
105
  permit_id: Uuid,
101
106
  scope_id: Uuid.nullish(),
102
107
  reason: z.string().optional(),
108
+ self_service: z.boolean().optional(),
103
109
  }),
104
110
  // `offer_id` is optional because failed creates (e.g. `web_grantable`
105
111
  // denied, `authorize` callback denied) never produce an offer row.
@@ -205,11 +211,20 @@ export const create_audit_log_config = (options) => {
205
211
  metadata_schemas: Object.freeze(metadata_schemas),
206
212
  });
207
213
  };
208
- /** Zod schema for client-safe audit log event. */
214
+ /**
215
+ * Zod schema for client-safe audit log event.
216
+ *
217
+ * `event_type` is `AuditEventTypeName` (regex-validated string) — matches
218
+ * the `AuditLogEvent` row and the DB's `TEXT NOT NULL` column. Consumer
219
+ * types registered via `create_audit_log_config({extra_events})` round-trip
220
+ * through queries, `on_audit_event` callbacks, and JSON-RPC responses
221
+ * identically to builtins. `AuditLogInput<T>` stays parameterized on the
222
+ * write side so `AuditMetadataMap` narrowing via `get_audit_metadata` works.
223
+ */
209
224
  export const AuditLogEventJson = z.strictObject({
210
225
  id: Uuid,
211
226
  seq: z.number().int(),
212
- event_type: AuditEventType,
227
+ event_type: AuditEventTypeName,
213
228
  outcome: AuditOutcome,
214
229
  actor_id: Uuid.nullable(),
215
230
  account_id: Uuid.nullable(),
@@ -1 +1 @@
1
- {"version":3,"file":"bootstrap_routes.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/bootstrap_routes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,MAAM,CAAC;AAClC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAExD,OAAO,EAAoB,KAAK,uBAAuB,EAAC,MAAM,wBAAwB,CAAC;AAGvF,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AACpC,OAAO,EAAkB,KAAK,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAEtE,OAAO,EAA+B,KAAK,WAAW,EAAC,MAAM,oBAAoB,CAAC;AAClF,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,oBAAoB,CAAC;AAanD,gFAAgF;AAChF,eAAO,MAAM,cAAc;;;;kBAIzB,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D,iFAAiF;AACjF,eAAO,MAAM,eAAe;;;kBAG1B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACrC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,8EAA8E;IAC9E,gBAAgB,EAAE,eAAe,CAAC;IAClC;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,uBAAuB,EAAE,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,4EAA4E;IAC5E,eAAe,EAAE,WAAW,GAAG,IAAI,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACxC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACnD,EAAE,EAAE,EAAE,CAAC;IACP,GAAG,EAAE,MAAM,CAAC;CACZ;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,sBAAsB,GAClC,MAAM,wBAAwB,EAC9B,SAAS;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAC,KAClC,OAAO,CAAC,eAAe,CAwBzB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,GACxC,MAAM,gBAAgB,EACtB,SAAS,qBAAqB,KAC5B,KAAK,CAAC,SAAS,CAyHjB,CAAC"}
1
+ {"version":3,"file":"bootstrap_routes.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/bootstrap_routes.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AACtB,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,MAAM,CAAC;AAClC,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,qBAAqB,CAAC;AAExD,OAAO,EAAoB,KAAK,uBAAuB,EAAC,MAAM,wBAAwB,CAAC;AAGvF,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AACpC,OAAO,EAAkB,KAAK,SAAS,EAAC,MAAM,uBAAuB,CAAC;AAEtE,OAAO,EAA+B,KAAK,WAAW,EAAC,MAAM,oBAAoB,CAAC;AAClF,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,oBAAoB,CAAC;AAanD,gFAAgF;AAChF,eAAO,MAAM,cAAc;;;;kBAIzB,CAAC;AACH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC;AAE5D,iFAAiF;AACjF,eAAO,MAAM,eAAe;;;kBAG1B,CAAC;AACH,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,eAAe;IAC/B,SAAS,EAAE,OAAO,CAAC;IACnB,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;;GAKG;AACH,MAAM,WAAW,qBAAqB;IACrC,eAAe,EAAE,cAAc,CAAC,MAAM,CAAC,CAAC;IACxC,8EAA8E;IAC9E,gBAAgB,EAAE,eAAe,CAAC;IAClC;;;OAGG;IACH,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,uBAAuB,EAAE,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9E,4EAA4E;IAC5E,eAAe,EAAE,WAAW,GAAG,IAAI,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACxC,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACnD,EAAE,EAAE,EAAE,CAAC;IACP,GAAG,EAAE,MAAM,CAAC;CACZ;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,sBAAsB,GAClC,MAAM,wBAAwB,EAC9B,SAAS;IAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;CAAC,KAClC,OAAO,CAAC,eAAe,CAwBzB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,4BAA4B,GACxC,MAAM,gBAAgB,EACtB,SAAS,qBAAqB,KAC5B,KAAK,CAAC,SAAS,CAuHjB,CAAC"}
@@ -67,7 +67,7 @@ export const check_bootstrap_status = async (deps, options) => {
67
67
  * @returns route specs (not yet applied to Hono)
68
68
  */
69
69
  export const create_bootstrap_route_specs = (deps, options) => {
70
- const { keyring, on_audit_event } = deps;
70
+ const { keyring } = deps;
71
71
  const { session_options, bootstrap_status, on_bootstrap, ip_rate_limiter } = options;
72
72
  const { token_path } = bootstrap_status;
73
73
  return [
@@ -123,7 +123,7 @@ export const create_bootstrap_route_specs = (deps, options) => {
123
123
  outcome: 'failure',
124
124
  ip: get_client_ip(c),
125
125
  metadata: { error: result.error },
126
- }, deps.log, on_audit_event);
126
+ }, deps);
127
127
  return c.json({ error: result.error }, result.status);
128
128
  }
129
129
  // Successful bootstrap — update state immediately
@@ -150,7 +150,7 @@ export const create_bootstrap_route_specs = (deps, options) => {
150
150
  actor_id: result.actor.id,
151
151
  account_id: result.account.id,
152
152
  ip: get_client_ip(c),
153
- }, deps.log, on_audit_event);
153
+ }, deps);
154
154
  // CRITICAL: If token file deletion failed, throw to force operator attention.
155
155
  // All success work (session, on_bootstrap, audit) has completed above.
156
156
  // The error response alerts the operator to delete the token file manually.
@@ -20,7 +20,7 @@
20
20
  */
21
21
  import type { Logger } from '@fuzdev/fuz_util/log.js';
22
22
  import type { QueryDeps } from '../db/query_deps.js';
23
- import type { AuditLogEvent } from './audit_log_schema.js';
23
+ import type { AuditLogConfig, AuditLogEvent } from './audit_log_schema.js';
24
24
  /** Dependencies for the cleanup helpers. */
25
25
  export interface AuthCleanupDeps extends QueryDeps {
26
26
  log: Logger;
@@ -30,6 +30,14 @@ export interface AuthCleanupDeps extends QueryDeps {
30
30
  * to skip broadcast — the audit rows still land in the DB.
31
31
  */
32
32
  on_audit_event?: ((event: AuditLogEvent) => void) | null;
33
+ /**
34
+ * Audit-log config. Only the builtin `permit_offer_expire` event type is
35
+ * emitted here, so omitting this is safe — the field exists so consumers
36
+ * threading the same `AppDeps` bundle to scheduled cleanup keep using
37
+ * their registered config (and consumer extensions to the
38
+ * `permit_offer_expire` metadata schema get validated).
39
+ */
40
+ audit_log_config?: AuditLogConfig;
33
41
  }
34
42
  /** Result of `run_auth_cleanup`. */
35
43
  export interface AuthCleanupResult {
@@ -1 +1 @@
1
- {"version":3,"file":"cleanup.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/cleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAInD,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,uBAAuB,CAAC;AAEzD,4CAA4C;AAC5C,MAAM,WAAW,eAAgB,SAAQ,SAAS;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;CACzD;AAED,oCAAoC;AACpC,MAAM,WAAW,iBAAiB;IACjC,8CAA8C;IAC9C,gBAAgB,EAAE,MAAM,CAAC;IACzB,yDAAyD;IACzD,cAAc,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,6BAA6B,GAAU,MAAM,eAAe,KAAG,OAAO,CAAC,MAAM,CA6BzF,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,GAAU,MAAM,eAAe,KAAG,OAAO,CAAC,iBAAiB,CAIvF,CAAC"}
1
+ {"version":3,"file":"cleanup.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/cleanup.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,qBAAqB,CAAC;AAInD,OAAO,KAAK,EAAC,cAAc,EAAE,aAAa,EAAC,MAAM,uBAAuB,CAAC;AAEzE,4CAA4C;AAC5C,MAAM,WAAW,eAAgB,SAAQ,SAAS;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ;;;;OAIG;IACH,cAAc,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC;IACzD;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,cAAc,CAAC;CAClC;AAED,oCAAoC;AACpC,MAAM,WAAW,iBAAiB;IACjC,8CAA8C;IAC9C,gBAAgB,EAAE,MAAM,CAAC;IACzB,yDAAyD;IACzD,cAAc,EAAE,MAAM,CAAC;CACvB;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,6BAA6B,GAAU,MAAM,eAAe,KAAG,OAAO,CAAC,MAAM,CAiCzF,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,gBAAgB,GAAU,MAAM,eAAe,KAAG,OAAO,CAAC,iBAAiB,CAIvF,CAAC"}
@@ -33,7 +33,7 @@ import { query_audit_log } from './audit_log_queries.js';
33
33
  */
34
34
  export const cleanup_expired_permit_offers = async (deps) => {
35
35
  const expired = await query_permit_offer_sweep_expired(deps);
36
- const { on_audit_event } = deps;
36
+ const { on_audit_event, audit_log_config } = deps;
37
37
  for (const offer of expired) {
38
38
  try {
39
39
  const event = await query_audit_log(deps, {
@@ -46,7 +46,7 @@ export const cleanup_expired_permit_offers = async (deps) => {
46
46
  role: offer.role,
47
47
  scope_id: offer.scope_id,
48
48
  },
49
- });
49
+ }, audit_log_config);
50
50
  if (on_audit_event) {
51
51
  try {
52
52
  on_audit_event(event);
@@ -12,7 +12,7 @@ import type { Keyring } from './keyring.js';
12
12
  import type { PasswordHashDeps } from './password.js';
13
13
  import type { Db } from '../db/db.js';
14
14
  import type { StatResult } from '../runtime/deps.js';
15
- import type { AuditLogEvent } from './audit_log_schema.js';
15
+ import type { AuditLogConfig, AuditLogEvent } from './audit_log_schema.js';
16
16
  /**
17
17
  * Stateless capabilities bundle for fuz_app backends.
18
18
  *
@@ -41,6 +41,18 @@ export interface AppDeps {
41
41
  * Defaults to a noop when not wired to SSE.
42
42
  */
43
43
  on_audit_event: (event: AuditLogEvent) => void;
44
+ /**
45
+ * Audit-log config for `audit_log_fire_and_forget` and `query_audit_log`.
46
+ * Built once at startup via `create_audit_log_config({extra_events})` to
47
+ * register consumer event types. Optional — defaults to
48
+ * `BUILTIN_AUDIT_LOG_CONFIG` when absent.
49
+ *
50
+ * Threaded through `AppDeps` (instead of a per-call positional arg) so
51
+ * consumer handlers cannot silently fall back to the builtin config by
52
+ * forgetting to pass theirs — the deps bundle carries it everywhere
53
+ * fuz_app emits an audit event.
54
+ */
55
+ audit_log_config?: AuditLogConfig;
44
56
  }
45
57
  /**
46
58
  * Capabilities for route spec factories.
@@ -1 +1 @@
1
- {"version":3,"file":"deps.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/deps.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AACpC,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAC,aAAa,EAAC,MAAM,uBAAuB,CAAC;AAEzD;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACvB,+DAA+D;IAC/D,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACnD,2BAA2B;IAC3B,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,qBAAqB;IACrB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,0CAA0C;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,6EAA6E;IAC7E,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,yBAAyB;IACzB,EAAE,EAAE,EAAE,CAAC;IACP,kCAAkC;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;OAKG;IACH,cAAc,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;CAC/C;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC"}
1
+ {"version":3,"file":"deps.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/deps.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAC,OAAO,EAAC,MAAM,cAAc,CAAC;AAC1C,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,eAAe,CAAC;AACpD,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AACpC,OAAO,KAAK,EAAC,UAAU,EAAC,MAAM,oBAAoB,CAAC;AACnD,OAAO,KAAK,EAAC,cAAc,EAAE,aAAa,EAAC,MAAM,uBAAuB,CAAC;AAEzE;;;;;GAKG;AACH,MAAM,WAAW,OAAO;IACvB,+DAA+D;IAC/D,IAAI,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACnD,2BAA2B;IAC3B,cAAc,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAClD,qBAAqB;IACrB,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7C,0CAA0C;IAC1C,OAAO,EAAE,OAAO,CAAC;IACjB,6EAA6E;IAC7E,QAAQ,EAAE,gBAAgB,CAAC;IAC3B,yBAAyB;IACzB,EAAE,EAAE,EAAE,CAAC;IACP,kCAAkC;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;OAKG;IACH,cAAc,EAAE,CAAC,KAAK,EAAE,aAAa,KAAK,IAAI,CAAC;IAC/C;;;;;;;;;;OAUG;IACH,gBAAgB,CAAC,EAAE,cAAc,CAAC;CAClC;AAED;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC"}
@@ -72,6 +72,20 @@ export interface PermitOfferActionOptions {
72
72
  */
73
73
  authorize?: PermitOfferCreateAuthorize;
74
74
  }
75
+ /**
76
+ * Authorization callback that admits any admin and otherwise falls back to
77
+ * the symmetric default (caller must hold the offered role globally).
78
+ *
79
+ * The `web_grantable` filter in `create_handler` runs **before** the
80
+ * `authorize` callback, so this never sees non-web-grantable roles. Drop
81
+ * into `create_permit_offer_actions({authorize: authorize_admin_or_holder})`
82
+ * (or any factory that forwards `authorize`, e.g. `create_standard_rpc_actions`)
83
+ * for the common "admins offer anything; users offer what they hold"
84
+ * pattern. Scope-aware policies (e.g. classroom_teacher offering
85
+ * classroom_student in their own scope) wrap this and short-circuit `true`
86
+ * before delegating.
87
+ */
88
+ export declare const authorize_admin_or_holder: PermitOfferCreateAuthorize;
75
89
  /**
76
90
  * Dependencies for `create_permit_offer_actions`.
77
91
  *
@@ -80,7 +94,7 @@ export interface PermitOfferActionOptions {
80
94
  * directly (the transport's `send_to_account` signature accepts the broader
81
95
  * `JsonrpcMessageFromServerToClient`, which is contravariantly compatible).
82
96
  */
83
- export interface PermitOfferActionDeps extends Pick<RouteFactoryDeps, 'log' | 'on_audit_event'> {
97
+ export interface PermitOfferActionDeps extends Pick<RouteFactoryDeps, 'log' | 'on_audit_event' | 'audit_log_config'> {
84
98
  /** Optional WS fan-out primitive. `null` or absent → notifications skipped. */
85
99
  notification_sender?: NotificationSender | null;
86
100
  }
@@ -88,7 +102,7 @@ export interface PermitOfferActionDeps extends Pick<RouteFactoryDeps, 'log' | 'o
88
102
  * Create the seven permit-offer RPC actions (six offer-lifecycle methods
89
103
  * plus `permit_revoke`).
90
104
  *
91
- * @param deps - stateless capabilities; needs `log` and `on_audit_event`; optional `notification_sender` for WS fan-out
105
+ * @param deps - `PermitOfferActionDeps` `log`, `on_audit_event`, optional `audit_log_config` (slice of `AppDeps`); optional `notification_sender` for WS fan-out
92
106
  * @param options - role schema, default TTL, authorization override
93
107
  * @returns the `RpcAction` array to spread into a `create_rpc_endpoint` call
94
108
  */
@@ -1 +1 @@
1
- {"version":3,"file":"permit_offer_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/permit_offer_actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAa,KAAK,aAAa,EAAE,KAAK,SAAS,EAAC,MAAM,0BAA0B,CAAC;AAGxF,OAAO,EAAmC,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAsBzF,OAAO,EAAW,KAAK,cAAc,EAAC,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,WAAW,CAAC;AAChD,OAAO,EAON,KAAK,kBAAkB,EACvB,MAAM,iCAAiC,CAAC;AAmCzC;;;;;;;;GAQG;AACH,MAAM,MAAM,0BAA0B,GAAG,CACxC,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAC,EACrE,IAAI,EAAE,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,EACnC,GAAG,EAAE,aAAa,KACd,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEhC,iDAAiD;AACjD,MAAM,WAAW,wBAAwB;IACxC;;;OAGG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,sFAAsF;IACtF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,0BAA0B,CAAC;CACvC;AAqCD;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAAC,gBAAgB,EAAE,KAAK,GAAG,gBAAgB,CAAC;IAC9F,+EAA+E;IAC/E,mBAAmB,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;CAChD;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,GACvC,MAAM,qBAAqB,EAC3B,UAAS,wBAA6B,KACpC,KAAK,CAAC,SAAS,CA8djB,CAAC"}
1
+ {"version":3,"file":"permit_offer_actions.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/auth/permit_offer_actions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AAEH,OAAO,EAAa,KAAK,aAAa,EAAE,KAAK,SAAS,EAAC,MAAM,0BAA0B,CAAC;AAGxF,OAAO,EAAmC,KAAK,gBAAgB,EAAC,MAAM,kBAAkB,CAAC;AAsBzF,OAAO,EAAW,KAAK,cAAc,EAAC,MAAM,sBAAsB,CAAC;AACnE,OAAO,KAAK,EAAC,gBAAgB,EAAC,MAAM,WAAW,CAAC;AAChD,OAAO,EAON,KAAK,kBAAkB,EACvB,MAAM,iCAAiC,CAAC;AAmCzC;;;;;;;;GAQG;AACH,MAAM,MAAM,0BAA0B,GAAG,CACxC,IAAI,EAAE,cAAc,EACpB,KAAK,EAAE;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAC,EACrE,IAAI,EAAE,IAAI,CAAC,gBAAgB,EAAE,KAAK,CAAC,EACnC,GAAG,EAAE,aAAa,KACd,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAEhC,iDAAiD;AACjD,MAAM,WAAW,wBAAwB;IACxC;;;OAGG;IACH,KAAK,CAAC,EAAE,gBAAgB,CAAC;IACzB,sFAAsF;IACtF,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,0BAA0B,CAAC;CACvC;AAyBD;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,yBAAyB,EAAE,0BAQvC,CAAC;AAcF;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAsB,SAAQ,IAAI,CAClD,gBAAgB,EAChB,KAAK,GAAG,gBAAgB,GAAG,kBAAkB,CAC7C;IACA,+EAA+E;IAC/E,mBAAmB,CAAC,EAAE,kBAAkB,GAAG,IAAI,CAAC;CAChD;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,GACvC,MAAM,qBAAqB,EAC3B,UAAS,wBAA6B,KACpC,KAAK,CAAC,SAAS,CAudjB,CAAC"}