import { t as IamClient } from "../../client-0N6XNM6z.cjs"; import { x as IamEngine } from "../../index-FAZKS-3M.cjs"; import { t as IamRequest } from "../../request-CuQVve_Q.cjs"; //#region src/server/generic/index.d.ts /** * Shared admin-mutation audit event shape. * * Every framework adapter (express, hono, next, nest) accepts an optional * `onAdminMutation` callback in its admin-router options. The callback fires * once per mutation (PUT/POST/DELETE/PATCH) after the handler completes, * regardless of success or failure. It is fire-and-forget - adapters never * `await` it inline - so a slow or throwing hook can never block, fail, or * leak timing information back to the caller. Errors inside the hook are * caught and one-line-logged via `console.error`. * * GET (read) handlers never fire the hook. * * Rate-limit throttling is out of scope; callers compose their own rate-limit * middleware around the admin router. See each adapter's JSDoc for a pattern. */ declare namespace IamAdminAudit { /** Categorical action describing what changed. */ type Action = 'create' | 'update' | 'delete' | 'replace'; /** Categorical target describing what kind of object was changed. */ type Target = 'policy' | 'role' | 'assignment' | 'role-assignment' | 'attributes'; /** * Describes a single admin mutation event. * * Field-level semantics worth calling out: * * - `path` - By default carries the request URL **including any expanded * route parameters** (e.g. `/admin/policies/policy-123/tenant-acme`). * That string therefore can contain tenant IDs, subject IDs, role IDs, * and other potentially sensitive identifiers. To redact, pass * {@link IOptions.redactPath} on the adapter's admin options. * - `error` - By default this is the **error class name only** (e.g. * `'TypeError'`, `'PolicyValidationError'`), NOT `err.message`. The * message can leak credentials, query fragments, or SQL when the * downstream throw originates in a DB driver. To restore the full * message, pass {@link IOptions.includeErrorMessage} `true` on the * adapter's admin options. */ interface IEvent { /** Whatever the adapter's `authorize` callback returned (often a user/JWT claims object). */ actor?: unknown; /** Semantic verb. */ action: Action; /** Semantic noun. */ target: Target; /** Optional identifier of the target object (e.g. policy id, subject id). */ targetId?: string; /** Event timestamp from `Date.now()`. */ ts: number; /** HTTP method that triggered the mutation. */ method: string; /** * HTTP path that triggered the mutation. By default this is the raw * request path with route parameters already expanded (so it may include * tenant IDs, subject IDs, etc.). Use {@link IOptions.redactPath} to * strip or rewrite identifiers before the hook sees the value. */ path: string; /** Whether the handler completed without throwing. */ success: boolean; /** * Stringified error indicator when `success === false`. Defaults to the * thrown value's class name (e.g. `'TypeError'`). Set * {@link IOptions.includeErrorMessage} `true` on the adapter options to * write `err.message` instead. */ error?: string; } /** Audit-hook signature. Sync or async; never awaited by the adapter. */ type Hook = (event: IEvent) => void | Promise; /** * Shared audit-hook hardening options. * * Every framework adapter's admin-router options interface composes this * shape, so the hardening surface is identical across express/hono/next/ * nest. All fields are optional and additive - the legacy hook behaviour * is preserved when none are supplied. */ interface IOptions { /** * Optional redactor applied to {@link IEvent.path} before the hook * receives the event. * * The default `event.path` carries the request URL including expanded * route parameters - e.g. `/admin/policies/policy-123/tenant-acme` - * which means tenant IDs, subject IDs and role IDs can flow into audit * sinks unredacted. Supply a redactor when your audit sink lives outside * your trust boundary. * * @example * ```ts * // Replace the last segment with `:id`. * redactPath: (p) => p.replace(/\/[^/]+$/, '/:id') * ``` */ redactPath?: (path: string) => string; /** * Invoked when the hook itself throws (sync or async). The default sink * is `console.error`; supply this to route hook failures into your * logger or metrics pipeline. Errors thrown by `onAuditHookError` itself * are caught and last-resort-logged via `console.error` - they never * propagate. */ onAuditHookError?: (err: unknown, event: IEvent) => void; /** * When `true`, populate {@link IEvent.error} with `err.message`. The * default is the error **class name** because downstream DB-driver * errors can carry credentials, query fragments, or SQL inside their * message. Only enable this if you control the throw sites and the * audit sink. */ includeErrorMessage?: boolean; /** * CSRF guard for state-changing admin mutations. * * Default (`undefined`): a built-in `Sec-Fetch-Site` check rejects * cross-site browser requests - browsers populate the header * automatically; its absence indicates a non-browser caller (curl, * server-to-server, native app) and is allowed. This default closes * the most common cookie-auth admin-CSRF vector without operator * action. * * Pass `false` to disable entirely (server-to-server with bearer * tokens / mTLS that intentionally posts cross-site). Pass a function * to supply a stricter check - e.g. an Origin allowlist: * * @example * ```ts * // Default - uses built-in Sec-Fetch-Site check * adminRouter(engine, { authorize }) * * // Disable (bearer-token API, no browser involved) * adminRouter(engine, { authorize, csrfCheck: false }) * * // Stricter: Origin allowlist * const ADMIN_ORIGINS = new Set(['https://admin.example.com']) * adminRouter(engine, { * authorize, * csrfCheck: (req) => ADMIN_ORIGINS.has(req.headers.origin), * }) * ``` */ csrfCheck?: ((req: unknown) => boolean) | false; } } /** * Log a one-time notice on first admin-router construction so operators * upgrading from 2.0.x are explicitly told the default changed. Suppressed * when the operator passed `csrfCheck` (any value including `false`). * * Called by every framework adapter exactly once at construction. */ declare function iamNoticeCsrfDefaultIfNeeded(csrfCheckPassed: boolean): void; /** * Default CSRF predicate: reject browser requests whose `Sec-Fetch-Site` * header is `'cross-site'` or `'cross-origin'`. Same-origin and same-site * requests pass; non-browser callers (no header set) pass. * * @param req - Any object the adapter can extract a header from. * @returns `true` to allow, `false` to reject (403). */ declare function iamDefaultCsrfCheck(req: unknown): boolean; /** * Composable admin-mutation audit wrapper. Runs `handler` inside * try/catch/finally, capturing success/failure for the audit event and * surfacing the operator-friendly error string. * * Re-throws the original error so the caller's catch can build the * framework-specific error response. The audit always fires (via finally). * * @template T - Handler return type. * @param ctx - Audit payload + hooks shared across framework adapters. * @param handler - The actual mutation function (e.g. `engine.admin.savePolicy`). */ declare function iamWithAdminAudit(ctx: { actor: unknown; action: IamAdminAudit.Action; target: IamAdminAudit.Target; targetId?: string; method: string; path: string; onAdminMutation?: IamAdminAudit.Hook; redactPath?: (path: string) => string; onAuditHookError?: (err: unknown, event: IamAdminAudit.IEvent) => void; includeErrorMessage?: boolean; }, handler: () => Promise): Promise; /** * Result of {@link iamRunAdminAuthz}. Discriminated union so the framework * adapter can branch on the phase and produce its own response. */ type IamIAdminAuthzResult = { phase: 'forbidden'; } | { phase: 'unauthorized'; } | { phase: 'error'; error: Error; } | { phase: 'ok'; actor: unknown; }; /** * Run the CSRF + authorize phases shared by every admin route. * Discriminated-union return lets each framework adapter map to its own * response shape (express writes to `res`, hono/next return `Response`, nest * throws). The catch arm wraps thrown values into a normal `Error`. */ declare function iamRunAdminAuthz(req: TReq, csrfCheck: ((req: TReq) => boolean) | null, authorize: (req: TReq) => unknown | Promise): Promise; /** * Derive an audit-friendly string from an unknown thrown value. * * By default returns the constructor name of the thrown value (e.g. * `'Error'`, `'TypeError'`, `'PolicyValidationError'`) so credential-bearing * `err.message` strings never leak into audit sinks. When * `includeMessage === true`, returns `err.message` for `Error` instances and * `String(err)` otherwise. Non-Error throws (`undefined`, strings, numbers) * are handled defensively. * * @param err - The thrown value; may not be an `Error` instance. * @param includeMessage - When `true`, return the full message instead of the class name. * @returns A stable string suitable for {@link IamAdminAudit.IEvent.error}. */ declare function iamErrorToAuditString(err: unknown, includeMessage?: boolean): string; /** * Fire-and-forget invoker for an {@link IamAdminAudit.Hook}. * * Resolves any returned promise off the request critical path. Applies * {@link IamAdminAudit.IOptions.redactPath} to `event.path` before invoking the * hook so route parameters never reach the sink. Routes thrown errors (sync * or async) to {@link IamAdminAudit.IOptions.onAuditHookError} when configured, * falling back to `console.error` with a one-line tag. The hook can never * block, fail, or destabilise the response. * * @param hook - Optional caller-supplied hook; no-op when absent. * @param event - Event payload describing the mutation. * @param opts - Optional hardening options (path redaction, hook-error sink). */ declare function iamFireAdminMutation(hook: IamAdminAudit.Hook | undefined, event: IamAdminAudit.IEvent, opts?: Pick): void; /** * Builds a server-side permission map for a subject and a list of checks. * * Call once per request and forward the map to the client. * * @template TAction - Constrains valid action strings. * @template TResource - Constrains valid resource strings. * @template TRole - Constrains valid role strings. * @template TScope - Constrains valid scope strings. * @param engine - Provides the access engine to consult. * @param subjectId - Identifies the subject whose permissions are computed. * @param checks - Lists the permission tuples to evaluate. * @param environment - Optional environment context shared across checks. * @returns A permission map keyed by `(action, resource, scope)` tuple. */ declare function generateIamPermissionMap(engine: IamEngine, subjectId: string, checks: readonly IamClient.IPermissionCheck[], environment?: IamRequest.IEnvironment): Promise>; /** * Builds a typed `can(action, resourceType, ...)` function bound to a subject. * * Useful inside request handlers for terse permission checks. * * @template TAction - Constrains valid action strings. * @template TResource - Constrains valid resource strings. * @template TRole - Constrains valid role strings. * @template TScope - Constrains valid scope strings. * @param engine - Provides the access engine to consult. * @param subjectId - Identifies the subject the returned function checks. * @param environment - Optional environment context applied to every check. * @returns A `(action, resourceType, resourceId?, scope?) => Promise` checker. * @example * ```ts * const can = createIamSubjectCan(engine, req.user.id) * if (await can('delete', 'post')) { ... } * ``` */ declare function createIamSubjectCan(engine: IamEngine, subjectId: string, environment?: IamRequest.IEnvironment): (action: TAction, resourceType: TResource, resourceId?: string, scope?: TScope) => Promise; /** * Extracts an environment object from common request shapes. * * Looks at `req.ip`, `x-forwarded-for`, `x-real-ip`, and `user-agent`, and * stamps the current timestamp. * * @param req - Provides any request-like object with `ip` and/or `headers`. * @returns The extracted {@link IamRequest.IEnvironment}. */ declare function iamExtractEnvironment(req: { ip?: string; headers?: Record | Headers; method?: string; url?: string; }): IamRequest.IEnvironment; /** Maps HTTP methods to default access actions used by the framework adapters. */ declare const IAM_METHOD_ACTION_MAP: Readonly>; //#endregion export { IAM_METHOD_ACTION_MAP, IamAdminAudit, IamIAdminAuthzResult, createIamSubjectCan, generateIamPermissionMap, iamDefaultCsrfCheck, iamErrorToAuditString, iamExtractEnvironment, iamFireAdminMutation, iamNoticeCsrfDefaultIfNeeded, iamRunAdminAuthz, iamWithAdminAudit }; //# sourceMappingURL=index.d.cts.map