import { x as IamEngine } from "../../index-DiOdpz0c.js"; import { t as IamRequest } from "../../request-BouexCSW.js"; import { IamAdminAudit } from "../generic/index.js"; //#region src/server/express/index.d.ts /** Minimal IamExpress request shape. */ interface Req { method?: string; path?: string; url?: string; ip?: string; params?: Record; headers?: Record; body?: unknown; user?: { id: string; [k: string]: unknown; }; [k: string]: unknown; } /** Minimal IamExpress response shape. */ interface Res { status(code: number): Res; json(body: unknown): void; } /** IamExpress next function. */ type Next = (err?: unknown) => void; /** IamExpress middleware function. */ type Middleware = (req: Req, res: Res, next: Next) => void; /** Minimal IamExpress Router interface for admin routes. */ interface ExpressRouterLike { get(path: string, handler: (req: Req, res: Res) => void | Promise): void; put(path: string, handler: (req: Req, res: Res) => void | Promise): void; post(path: string, handler: (req: Req, res: Res) => void | Promise): void; delete(path: string, handler: (req: Req, res: Res) => void | Promise): void; } /** IamExpress server integration types. Type-only namespace - zero bundle cost. */ declare namespace IamExpress { /** * Describes options for {@link iamAccessMiddleware} and {@link iamGuard}. * * Every extractor has a sensible default; override only what your app needs. * * @template TScope - Constrains valid scope strings. */ interface IOptions { /** Extracts the current user ID from the request. */ getUserId?: (req: Req) => string | null; /** Derives the target resource from the request. */ getResource?: (req: Req) => IamRequest.IResource; /** Derives the action being performed from the request. */ getAction?: (req: Req) => string; /** Extracts environment context (IP, user-agent, etc.) from the request. */ getEnvironment?: (req: Req) => IamRequest.IEnvironment; /** Determines the scope used for the access check. */ getScope?: (req: Req) => TScope | undefined; /** Handles a denied request (defaults to 403 JSON). */ onDenied?: (req: Req, res: Res) => void; /** Handles thrown errors during evaluation (defaults to 500 JSON). */ onError?: (err: Error, req: Req, res: Res, next: Next) => void; } /** * Required iamGuard callback for admin endpoints. * * Returning `false` (or throwing) blocks the mutation; returning `true` lets it * proceed. The admin router writes policies, roles, and assignments directly * to the adapter; mounting it without auth has historically been the most * common foot-gun in authorization systems, so this hook is mandatory. */ type IAdminAuthorize = (req: Req) => boolean | Promise; /** Describes options for {@link iamAdminRouter}. `authorize` is required. */ interface IAdminRouterOptions extends IamAdminAudit.IOptions { /** Required. Runs before every admin handler (read or write). */ authorize: IAdminAuthorize; /** Overrides the 401 unauthorized response. */ onUnauthorized?: (req: Req, res: Res) => void; /** Overrides the 500 internal error response. */ onError?: (err: Error, req: Req, res: Res) => void; /** * Optional audit hook fired AFTER every mutation handler (PUT/POST/ * DELETE/PATCH) completes - success or failure. The hook is * fire-and-forget: a slow or throwing implementation never blocks the * request and can never alter the response. GET handlers do not fire it. * * See {@link IamAdminAudit.IOptions} for additional hardening knobs: * `redactPath`, `onAuditHookError`, and `includeErrorMessage`. */ onAdminMutation?: IamAdminAudit.Hook; } } /** * Builds global IamExpress middleware that runs `engine.can(...)` on every request. * * Replies 401 when no user is present and 403 when denied. * * @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 opts - Configures extractors and error hooks. * @returns An IamExpress middleware function. * @example * ```ts * app.use(iamAccessMiddleware(engine, { * getUserId: (req) => req.user?.id ?? null, * })) * ``` */ declare function iamAccessMiddleware(engine: IamEngine, opts?: IamExpress.IOptions): Middleware; /** * Builds per-route middleware that checks `(action, resourceType)` for the * current user, pulling the resource ID from `req.params.id`. * * @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 action - Specifies the action being performed. * @param resourceType - Specifies the resource type required for the check. * @param opts - Configures optional extractors and `scope` override. * @returns An IamExpress middleware function. * @example * ```ts * app.delete('/posts/:id', iamGuard(engine, 'delete', 'post'), handler) * app.post('/admin/users', iamGuard(engine, 'manage', 'user', { scope: 'admin' }), handler) * ``` */ declare function iamGuard(engine: IamEngine, action: TAction, resourceType: TResource, opts?: Pick, 'getUserId' | 'getEnvironment' | 'onDenied'> & { scope?: TScope; }): Middleware; /** * Builds an IamExpress router for the duck-iam admin API. * * Returns a factory that accepts the IamExpress `Router` constructor so we never * import express at runtime. Throws when `opts.authorize` is missing. * * @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 whose `admin` operations are exposed. * @param opts - Must include `authorize`; mounting unauthenticated is rejected. * @returns A factory `(Router) => router` that wires admin endpoints. * @throws Error when `opts.authorize` is not a function. * @example * ```ts * import { Router } from 'express' * app.use('/api/access-admin', iamAdminRouter(engine, { * authorize: (req) => req.user?.role === 'admin', * onAdminMutation: (e) => auditLog.write(e), * })(Router)) * ``` * @example * Rate limiting is out of scope; compose at the mount point with the * caller's library of choice - `express-rate-limit` is the canonical pick: * ```ts * import rateLimit from 'express-rate-limit' * const adminLimiter = rateLimit({ windowMs: 60_000, max: 30 }) * app.use('/api/access-admin', adminLimiter, iamAdminRouter(engine, { authorize })(Router)) * ``` */ declare function iamAdminRouter(engine: IamEngine, opts: IamExpress.IAdminRouterOptions): (Router: () => ExpressRouterLike) => ExpressRouterLike; //#endregion export { IamExpress, iamAccessMiddleware, iamAdminRouter, iamGuard }; //# sourceMappingURL=index.d.ts.map