test(authz): end-to-end integration coverage, worked example, and docs
Task 15 of the authz permissions plan: proves db store + cache + catalog + middleware + audit compose correctly, wires a real (non-dangling) example into auth-showcase, and documents the declaration/registration/precedence surface in the package README.
This commit is contained in:
@@ -0,0 +1,30 @@
|
||||
import { defineAuthz } from "@wrnexus/authz";
|
||||
|
||||
/**
|
||||
* `app/authz/<name>.ts` declarations are discovered automatically and merged
|
||||
* into the process-wide catalog at boot (see `app/middleware/authz.ts`, which
|
||||
* registers the middleware that resolves against it).
|
||||
*/
|
||||
export default defineAuthz({
|
||||
permissions: {
|
||||
"post:read": { title: "View posts", public: true },
|
||||
"post:write": { title: "Create and edit posts" },
|
||||
"post:delete": { title: "Delete posts", risk: "high" },
|
||||
"admin:access": { title: "Reach the admin area", risk: "high" },
|
||||
},
|
||||
roles: {
|
||||
viewer: ["post:read"],
|
||||
editor: ["role:viewer", "post:write"],
|
||||
admin: ["role:editor", "post:delete", "admin:access"],
|
||||
},
|
||||
policies: {
|
||||
ownsPost: async (
|
||||
subject: { id?: string },
|
||||
resource?: { authorId?: string },
|
||||
): Promise<{ allowed: boolean; reason?: string }> =>
|
||||
resource?.authorId === subject?.id
|
||||
? { allowed: true }
|
||||
: { allowed: false, reason: "You are not the author" },
|
||||
},
|
||||
bindings: { "post:delete": ["ownsPost"] },
|
||||
});
|
||||
Reference in New Issue
Block a user