authhero 8.18.0 → 8.19.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 (37) hide show
  1. package/dist/authhero.cjs +112 -112
  2. package/dist/authhero.d.ts +316 -238
  3. package/dist/authhero.mjs +10529 -10428
  4. package/dist/tsconfig.types.tsbuildinfo +1 -1
  5. package/dist/types/authentication-flows/passwordless.d.ts +4 -4
  6. package/dist/types/helpers/audit-target-types.d.ts +6 -0
  7. package/dist/types/helpers/default-destinations.d.ts +14 -4
  8. package/dist/types/helpers/outbox-destinations/code-hooks.d.ts +56 -0
  9. package/dist/types/helpers/password-connection.d.ts +16 -0
  10. package/dist/types/helpers/run-outbox-relay.d.ts +8 -1
  11. package/dist/types/hooks/codehooks.d.ts +78 -9
  12. package/dist/types/index.d.ts +235 -234
  13. package/dist/types/routes/auth-api/index.d.ts +22 -22
  14. package/dist/types/routes/auth-api/passwordless.d.ts +12 -12
  15. package/dist/types/routes/auth-api/register/index.d.ts +2 -2
  16. package/dist/types/routes/auth-api/token.d.ts +10 -10
  17. package/dist/types/routes/management-api/authentication-methods.d.ts +1 -1
  18. package/dist/types/routes/management-api/clients.d.ts +9 -9
  19. package/dist/types/routes/management-api/connections.d.ts +6 -6
  20. package/dist/types/routes/management-api/custom-domains.d.ts +6 -6
  21. package/dist/types/routes/management-api/email-templates.d.ts +18 -18
  22. package/dist/types/routes/management-api/forms.d.ts +126 -126
  23. package/dist/types/routes/management-api/guardian.d.ts +5 -5
  24. package/dist/types/routes/management-api/hooks.d.ts +24 -24
  25. package/dist/types/routes/management-api/index.d.ts +211 -211
  26. package/dist/types/routes/management-api/migration-sources.d.ts +6 -6
  27. package/dist/types/routes/management-api/organizations.d.ts +2 -2
  28. package/dist/types/routes/management-api/prompts.d.ts +4 -4
  29. package/dist/types/routes/management-api/roles.d.ts +6 -6
  30. package/dist/types/routes/management-api/tenant-export-import.d.ts +5 -5
  31. package/dist/types/routes/management-api/tenants.d.ts +1 -1
  32. package/dist/types/routes/management-api/users.d.ts +2 -2
  33. package/dist/types/routes/universal-login/common.d.ts +4 -4
  34. package/dist/types/routes/universal-login/flow-api.d.ts +8 -8
  35. package/dist/types/routes/universal-login/u2-index.d.ts +5 -5
  36. package/dist/types/routes/universal-login/u2-routes.d.ts +5 -5
  37. package/package.json +5 -5
@@ -414,7 +414,7 @@ export declare function passwordlessGrantUser(ctx: Context<{
414
414
  } | undefined;
415
415
  } | undefined;
416
416
  passkey_options?: {
417
- challenge_ui?: "button" | "both" | "autofill" | undefined;
417
+ challenge_ui?: "both" | "autofill" | "button" | undefined;
418
418
  local_enrollment_enabled?: boolean | undefined;
419
419
  progressive_enrollment_enabled?: boolean | undefined;
420
420
  } | undefined;
@@ -458,7 +458,7 @@ export declare function passwordlessGrantUser(ctx: Context<{
458
458
  custom_login_page_preview?: string | undefined;
459
459
  form_template?: string | undefined;
460
460
  addons?: Record<string, any> | undefined;
461
- token_endpoint_auth_method?: "none" | "private_key_jwt" | "client_secret_post" | "client_secret_basic" | "client_secret_jwt" | undefined;
461
+ token_endpoint_auth_method?: "none" | "client_secret_post" | "client_secret_basic" | "client_secret_jwt" | "private_key_jwt" | undefined;
462
462
  client_metadata?: Record<string, string> | undefined;
463
463
  hide_sign_up_disabled_error?: boolean | undefined;
464
464
  mobile?: Record<string, any> | undefined;
@@ -541,8 +541,8 @@ export declare function passwordlessGrantUser(ctx: Context<{
541
541
  } | undefined;
542
542
  authenticated_at?: string | undefined;
543
543
  };
544
- connectionType: "username" | "sms" | "email";
545
- authConnection: "username" | "sms" | "email";
544
+ connectionType: "username" | "email" | "sms";
545
+ authConnection: "username" | "email" | "sms";
546
546
  session_id: string | undefined;
547
547
  authParams: {
548
548
  client_id: string;
@@ -0,0 +1,6 @@
1
+ /** Target entity types whose id identifies an affected user. For these, the
2
+ * flat log's `user_id` is the target (the user the operation acted on) rather
3
+ * than the actor — matching Auth0, e.g. "Delete a User" logs the deleted user.
4
+ * Shared by `helpers/logging.ts` (write path) and
5
+ * `outbox-destinations/logs.ts` (outbox transform) so the two never drift. */
6
+ export declare const USER_TARGET_TYPES: Set<string>;
@@ -1,13 +1,15 @@
1
- import { DataAdapters } from "@authhero/adapter-interfaces";
1
+ import { CodeExecutor, DataAdapters } from "@authhero/adapter-interfaces";
2
2
  import { EventDestination } from "./outbox-relay";
3
3
  import { type GetServiceToken } from "./outbox-destinations/webhooks";
4
4
  import type { WebhookInvoker } from "../types/AuthHeroConfig";
5
5
  export interface CreateDefaultDestinationsConfig {
6
6
  /**
7
- * Data adapter — only the `logs`, `hooks`, `users`, and `logStreams`
8
- * adapters are used by the built-in destinations.
7
+ * Data adapter — the `logs`, `hooks`, `users`, and `logStreams` adapters are
8
+ * used by the built-in destinations. When `codeExecutor` is set, the
9
+ * `actions`, `hookCode`, and `actionExecutions` adapters are also required so
10
+ * `CodeHookDestination` can resolve and run tenant code hooks.
9
11
  */
10
- dataAdapter: Pick<DataAdapters, "logs" | "hooks" | "users" | "logStreams">;
12
+ dataAdapter: Pick<DataAdapters, "logs" | "hooks" | "users" | "logStreams"> & Partial<Pick<DataAdapters, "actions" | "hookCode" | "actionExecutions" | "multiTenancyConfig">>;
11
13
  /**
12
14
  * Produces a Bearer access token for the given tenant, used when POSTing
13
15
  * `hook.*` events to the configured webhook URLs.
@@ -37,6 +39,14 @@ export interface CreateDefaultDestinationsConfig {
37
39
  * deliveries don't diverge from inline per-request ones.
38
40
  */
39
41
  webhookInvoker?: WebhookInvoker;
42
+ /**
43
+ * Code executor — same instance passed to `init({ codeExecutor })`. When
44
+ * provided (and `dataAdapter` carries `actions`, `hookCode`, and
45
+ * `actionExecutions`), a `CodeHookDestination` is added so cron-drained
46
+ * `hook.*` events also run tenant code hooks. Without it, code hooks that
47
+ * failed per-request delivery would be silently skipped on retry.
48
+ */
49
+ codeExecutor?: CodeExecutor;
40
50
  }
41
51
  /**
42
52
  * Build the same array of outbox destinations that authhero's per-request
@@ -0,0 +1,56 @@
1
+ import { AuditEvent, CodeExecutor } from "@authhero/adapter-interfaces";
2
+ import { EventDestination } from "../outbox-relay";
3
+ import { CodeHookData } from "../../hooks/codehooks";
4
+ interface CodeHookInvocation {
5
+ eventId: string;
6
+ tenantId: string;
7
+ triggerId: string;
8
+ /** Serialized user snapshot from the audit event (`target.after`). */
9
+ user?: unknown;
10
+ /** Serialized request context from the audit event. */
11
+ request?: unknown;
12
+ }
13
+ /**
14
+ * Delivers `hook.*` outbox events to tenant-authored **code hooks** (actions)
15
+ * for the matching `trigger_id`. Runs alongside `WebhookDestination` — both
16
+ * accept the same `hook.*` events — so a single registration/deletion event
17
+ * fans out to webhooks *and* code hooks. The fan-out is not retried
18
+ * independently: the relay retries the whole outbox event, running its
19
+ * destinations in order and stopping at the first failure, so a code-hook
20
+ * failure here causes earlier destinations (e.g. webhooks) to run again on the
21
+ * retry. Every destination on the event must therefore be idempotent.
22
+ *
23
+ * Reliability model: unlike the previous inline execution (best-effort,
24
+ * at-most-once, failures logged and dropped), code hooks delivered here are
25
+ * **at-least-once**. If any code hook for the trigger fails, `deliver` throws
26
+ * so the relay retries the whole event with backoff and, after `maxRetries`,
27
+ * dead-letters it. A retry re-runs every code hook for the trigger, so the
28
+ * event id is passed to user code as `event.idempotency_key` for dedupe.
29
+ *
30
+ * Must be listed AFTER `WebhookDestination` and BEFORE
31
+ * `RegistrationFinalizerDestination` so `registration_completed_at` is only
32
+ * flipped on a pass where every webhook *and* code hook succeeded.
33
+ *
34
+ * Constructed per-request (via `getDestinations(ctx)`) so it can close over
35
+ * `ctx.env.codeExecutor`. The same class is used by the cron `drainOutbox`
36
+ * safety net when a `codeExecutor` is supplied to `createDefaultDestinations`.
37
+ * When no executor is configured, code hooks cannot run (nor be deployed), so
38
+ * `deliver` is a no-op success — matching the inline `handleCodeHook` which
39
+ * returns `null` without an executor.
40
+ */
41
+ export declare class CodeHookDestination implements EventDestination {
42
+ name: string;
43
+ private data;
44
+ private codeExecutor?;
45
+ constructor(data: CodeHookData, codeExecutor?: CodeExecutor);
46
+ accepts(event: AuditEvent): boolean;
47
+ transform(event: AuditEvent): CodeHookInvocation;
48
+ deliver(invocations: CodeHookInvocation[]): Promise<void>;
49
+ /**
50
+ * Fetch every hook for the tenant, paging past the adapter's default page
51
+ * size. `hooks.list` returns only the first page by default, so a tenant with
52
+ * more enabled code hooks than one page would silently skip the rest.
53
+ */
54
+ private listAllHooks;
55
+ }
56
+ export {};
@@ -0,0 +1,16 @@
1
+ import type { EnrichedClient } from "./client";
2
+ /**
3
+ * Resolve the tenant's database (username/password) connection for a client.
4
+ *
5
+ * The reset-password flows need the real connection name/id because a user's
6
+ * stored `user.connection` may be the hardcoded "Username-Password-Authentication"
7
+ * fallback rather than the tenant's actual connection. Centralised here so the
8
+ * HTML route and the screen handler resolve it identically.
9
+ *
10
+ * @param fallbackConnection connection name to use when the client has no
11
+ * database connection (typically `user.connection`).
12
+ */
13
+ export declare function resolvePasswordConnection(client: EnrichedClient, fallbackConnection: string): {
14
+ connection: string;
15
+ connectionId?: string;
16
+ };
@@ -1,4 +1,4 @@
1
- import { DataAdapters } from "@authhero/adapter-interfaces";
1
+ import { CodeExecutor, DataAdapters } from "@authhero/adapter-interfaces";
2
2
  import type { WebhookInvoker } from "../types/AuthHeroConfig";
3
3
  export interface RunOutboxRelayConfig {
4
4
  /** Same `DataAdapters` passed to `init()`. Must include `outbox` to drain. */
@@ -24,6 +24,13 @@ export interface RunOutboxRelayConfig {
24
24
  maxRetries?: number;
25
25
  /** Webhook HTTP timeout (ms), when the default invoker is used. */
26
26
  webhookTimeoutMs?: number;
27
+ /**
28
+ * Optional code executor — same instance passed to `init({ codeExecutor })`.
29
+ * When provided, cron-drained `hook.*` events also run tenant code hooks, so
30
+ * a code hook that failed per-request delivery is retried rather than
31
+ * silently skipped.
32
+ */
33
+ codeExecutor?: CodeExecutor;
27
34
  }
28
35
  /**
29
36
  * One-call outbox relay for cron / scheduled handlers.
@@ -1,22 +1,62 @@
1
1
  import { Context } from "hono";
2
- import { ActionExecutionResult, CodeExecutionLog, DataAdapters, Hook } from "@authhero/adapter-interfaces";
2
+ import { ActionExecutionResult, CodeExecutionLog, CodeExecutor, DataAdapters, Hook } from "@authhero/adapter-interfaces";
3
3
  import { Bindings, Variables } from "../types";
4
4
  import { HookEvent, OnExecuteCredentialsExchangeAPI } from "../types/Hooks";
5
+ import { EnrichedClient } from "../helpers/client";
5
6
  /**
6
7
  * Auth0 uses `post-login` for what we internally call `post-user-login`.
7
8
  * Normalize when writing execution records so the public API matches Auth0.
8
9
  */
9
10
  export declare function toAuth0TriggerId(internal: string): string;
11
+ /**
12
+ * The subset of `DataAdapters` needed to resolve and run a code hook and to
13
+ * persist its execution record. Narrowed so `CodeHookDestination` and the cron
14
+ * `createDefaultDestinations` helper can construct it without depending on the
15
+ * full adapter surface.
16
+ */
17
+ export type CodeHookData = Pick<DataAdapters, "hooks" | "actions" | "hookCode" | "actionExecutions" | "multiTenancyConfig">;
10
18
  type CodeHook = Extract<Hook, {
11
19
  code_id: string;
12
20
  }>;
13
21
  export declare function isCodeHook(hook: Hook): hook is CodeHook;
22
+ /**
23
+ * Loosened event shape accepted by `buildSerializableEvent` / `executeCodeHook`.
24
+ *
25
+ * The inline hook call sites pass a full `HookEvent`. The `CodeHookDestination`
26
+ * (which runs from the outbox relay, after the request has closed) has no live
27
+ * `ctx` and reconstructs the event from the persisted audit event, so `user`
28
+ * and `request` arrive as already-serialized `unknown` values. Both are
29
+ * assignable to this type.
30
+ */
31
+ export type CodeHookEventInput = {
32
+ ctx?: unknown;
33
+ client?: Pick<EnrichedClient, "client_id" | "name" | "client_metadata"> | null;
34
+ } & Record<string, unknown>;
14
35
  /**
15
36
  * Build a serializable event object from a HookEvent.
16
37
  * Strips the `ctx` property (Hono context) which cannot be serialized,
17
38
  * and returns a plain JSON-compatible object.
18
39
  */
19
- export declare function buildSerializableEvent(event: HookEvent, secrets?: Record<string, string>): Record<string, unknown>;
40
+ export declare function buildSerializableEvent(event: CodeHookEventInput, secrets?: Record<string, string>): Record<string, unknown>;
41
+ /**
42
+ * The namespaced API surface exposed to code hooks. User code records calls of
43
+ * the form `<namespace>.<method>(...)` (e.g. `accessToken.setCustomClaim`,
44
+ * `access.deny`), which {@link replayApiCalls} replays against the real
45
+ * namespace objects. Each top-level key is a namespace whose members are the
46
+ * callable methods for that namespace — so the shape is nested (namespace →
47
+ * method → function) rather than a flat `any` surface. Concrete per-trigger API
48
+ * types (`OnExecute*API`) structurally satisfy this.
49
+ *
50
+ * The method args stay permissive (`any[]`): this surface is a dynamic
51
+ * dispatcher — {@link replayApiCalls} looks methods up by string and applies
52
+ * the recorded `unknown[]` args, while call sites register concretely-typed
53
+ * methods (`(key: string, value: unknown) => void`, …). A stricter `unknown[]`
54
+ * args tuple would reject those concrete registrations (parameter
55
+ * contravariance). The return type is still narrowed to `unknown`.
56
+ */
57
+ export type CodeHookApiMethod = (...args: any[]) => unknown;
58
+ export type CodeHookApiNamespace = Record<string, CodeHookApiMethod>;
59
+ export type CodeHookApi = Record<string, CodeHookApiNamespace>;
20
60
  /**
21
61
  * Replay recorded API calls from code hook execution against real API objects.
22
62
  * Handles calls like "accessToken.setCustomClaim" by navigating the api object.
@@ -24,22 +64,51 @@ export declare function buildSerializableEvent(event: HookEvent, secrets?: Recor
24
64
  export declare function replayApiCalls(apiCalls: Array<{
25
65
  method: string;
26
66
  args: unknown[];
27
- }>, api: Record<string, any>): void;
67
+ }>, api: CodeHookApi): void;
28
68
  export type HandleCodeHookOutcome = {
29
69
  result: ActionExecutionResult;
30
70
  logs: CodeExecutionLog[];
31
71
  /** True if api.access.deny was recorded by the executor. */
32
72
  denied: boolean;
33
73
  };
74
+ /**
75
+ * Core code-hook execution, decoupled from the Hono request `ctx`.
76
+ *
77
+ * Given an explicit executor, data adapter, and tenant, fetches the code,
78
+ * runs it, and replays the recorded API calls against `api`. Shared by the
79
+ * inline `handleCodeHook` wrapper (request-time) and by `CodeHookDestination`
80
+ * (outbox relay, after the request has closed).
81
+ *
82
+ * Always returns an outcome — including a `code_not_found` / `execution_failed`
83
+ * outcome — so the caller can persist an `action_executions` record. It only
84
+ * throws for `api.access.deny`, which surfaces as a thrown `HTTPException` from
85
+ * the replayed API call; callers that must abort the flow catch it.
86
+ *
87
+ * `idempotencyKey`, when set, is exposed to user code as `event.idempotency_key`.
88
+ * The outbox is at-least-once, so a retried hook event re-runs the code; authors
89
+ * performing non-idempotent side effects can dedupe on this key.
90
+ */
91
+ export declare function executeCodeHook(params: {
92
+ codeExecutor: CodeExecutor;
93
+ data: CodeHookData;
94
+ tenantId: string;
95
+ hook: {
96
+ code_id: string;
97
+ hook_id?: string;
98
+ };
99
+ event: CodeHookEventInput;
100
+ triggerId: string;
101
+ api: CodeHookApi;
102
+ idempotencyKey?: string;
103
+ }): Promise<HandleCodeHookOutcome>;
34
104
  /**
35
105
  * Execute a code hook by fetching the code from the database, running it
36
106
  * through the code executor, and replaying API calls against the real api
37
107
  * object.
38
108
  *
39
- * Returns the per-action result (Auth0 shape) so the caller can aggregate
40
- * results across all actions on a trigger into a single `action_executions`
41
- * record. Returns `null` when the code cannot be located or the executor is
42
- * unavailable — the caller decides whether to surface that.
109
+ * Thin request-time wrapper over `executeCodeHook` that resolves the executor
110
+ * and tenant from `ctx`. Returns `null` when the code executor is unavailable
111
+ * or the tenant can't be resolved the caller decides whether to surface that.
43
112
  */
44
113
  export declare function handleCodeHook(ctx: Context<{
45
114
  Bindings: Bindings;
@@ -47,13 +116,13 @@ export declare function handleCodeHook(ctx: Context<{
47
116
  }>, data: DataAdapters, hook: {
48
117
  code_id: string;
49
118
  hook_id: string;
50
- }, event: HookEvent, triggerId: string, api: Record<string, any>): Promise<HandleCodeHookOutcome | null>;
119
+ }, event: HookEvent, triggerId: string, api: CodeHookApi): Promise<HandleCodeHookOutcome | null>;
51
120
  /**
52
121
  * Aggregate per-action outcomes into an Auth0-shape execution record and
53
122
  * persist it via the adapter. Returns the generated execution_id (uuid)
54
123
  * so the caller can embed it in the surrounding tenant log.
55
124
  */
56
- export declare function persistActionExecution(data: DataAdapters, tenant_id: string, triggerId: string, outcomes: HandleCodeHookOutcome[]): Promise<string | null>;
125
+ export declare function persistActionExecution(data: Pick<DataAdapters, "actionExecutions">, tenant_id: string, triggerId: string, outcomes: HandleCodeHookOutcome[]): Promise<string | null>;
57
126
  /**
58
127
  * Execute code hooks for the credentials-exchange trigger.
59
128
  * Filters enabled code hooks from the provided hooks list and executes them.