# permission-middleware _(no submodules)_ ## Purpose Provides framework-agnostic permission checking middleware for `@suaveplan/permissions`. The `createPermissionMiddleware` factory returns a `(req, res, next)` function that reads the authenticated user from `req.user`, checks the configured permission via the adapter, and calls `next(PermissionsError)` on denial. The `checkPermission` function provides a one-off convenience check without creating a full engine instance, useful for route handlers that need a single inline permission assertion. ## Features - `createPermissionMiddleware(options)` — factory returning `MiddlewareFn` - `checkPermission(userId, resource, action, adapter)` — one-off policy evaluation - User extraction from `req.user.userId` or `req.user.sub` (JWT-compatible) - `ResourceExtractor` and `UserExtractor` type exports ## Usage: Basic Example ```ts import { createPermissionMiddleware, MemoryAdapter } from "@suaveplan/permissions"; const adapter = new MemoryAdapter(); const mw = createPermissionMiddleware({ resource: "posts", action: "delete", adapter, }); // Attach to route: app.delete("/posts/:id", verifyJwt, mw, handler) ``` ## Usage: Advanced Example ```ts import { checkPermission } from "@suaveplan/permissions"; import { MemoryAdapter } from "@suaveplan/permissions"; const adapter = new MemoryAdapter(); // Route handler inline check async function deletePost(userId: string, postId: string) { const result = await checkPermission(userId, "posts", "delete", adapter); if (!result.allowed) throw new Error(result.reason); // ... proceed with deletion } ``` ## API Reference ### `createPermissionMiddleware(options): MiddlewareFn` Options: `resource`, `action`, `adapter?`. Reads user from `req.user.userId` or `req.user.sub`. Calls `next(PermissionsError)` if no user, no adapter, or permission denied. ### `checkPermission(userId, resource, action, adapter): Promise` Creates a transient `PolicyEngine` and evaluates one permission check. ### `ResourceExtractor` `(req: unknown) => string` — type alias. ### `UserExtractor` `(req: unknown) => string | null` — type alias. ## Implementation Notes The middleware user extraction checks both `userId` (from a `UserContext`) and `sub` (from a `JWTPayload`) to support both `@suaveplan/auth`'s `verifyTokenMiddleware` (which attaches `req.user` as `JWTPayload`) and custom middleware that attaches `req.user` as `UserContext`. No adapter means the middleware fails closed with a `PERM_CODES.ADAPTER_ERROR`, preventing accidental open access when misconfigured.