app/lib/roles.ts
32 lines and 1 functions in DrDustinEdwards/carrel, at commit d5d5e82 on 2026-10-24. This file on GitHub.
Functions
| Function | Lines | Complexity | Covered | CRAP | Mutation |
|---|---|---|---|---|---|
| can | 34 to 36 | 2 | 100% | OkCRAP 2 | No data: mutation testing has not run on this repo yet |
Imports
It imports no other module of this repo. Imported by app/lib/ai.server.ts, app/lib/binder.server.ts, app/lib/book-history.server.ts, app/lib/books.server.ts, app/lib/bulk.server.ts, app/lib/content.server.ts, app/lib/google/drive.server.ts, app/lib/history.server.ts, app/lib/legal.server.ts, app/lib/mcp/tools.ts, app/lib/media.server.ts, app/lib/mentions.server.ts, app/lib/people-admin.server.ts, app/lib/people.server.ts, app/lib/projects.server.ts, app/lib/voice.server.ts, app/lib/waiting.server.ts, app/lib/writing.server.ts, app/routes/ai-draft.tsx, app/routes/book.chapter.tsx, app/routes/book.corkboard.tsx, app/routes/book.file.tsx, app/routes/book.outliner.tsx, app/routes/book.tsx, app/routes/editor.tsx, app/routes/legal.tsx, app/routes/media.tsx, app/routes/project.flags.tsx, app/routes/project.tsx, app/routes/project.voice.tsx.
Source
// Who may do what on a project. Pure, so every caller (UI loaders now, MCP tools later) asks the
// same question the same way.
export type Role = "reader" | "editor" | "owner";
/**
* `delete_media` removes a file from a site's storage (stage 3). It is the Owner's alone: a file can
* be in use on pages the site's reference check cannot see, such as another site linking it.
* `delete_content` removes a post from a site. Also the Owner's alone: unlike unpublish, it takes the
* post off the site's list altogether.
* `read_mentions` and `decide_mention` are the Owner's alone: Dustin ruled (2026-09-26) that the inbox belongs to
* Dustin alone (a mention is text a stranger sent, and the site reserves deleting one to its admin).
* They are two actions so the page can be opened to Editors and Readers by changing one line here.
*/
export type Action =
| "read"
| "comment"
| "edit"
| "publish"
| "send_external"
| "manage"
| "delete_media"
| "delete_content"
| "read_mentions"
| "decide_mention";
const ALLOWED: Record<Role, ReadonlySet<Action>> = {
reader: new Set(["read", "comment"]),
editor: new Set(["read", "comment", "edit"]),
owner: new Set(["read", "comment", "edit", "publish", "send_external", "manage", "delete_media", "delete_content", "read_mentions", "decide_mention"]),
};
/** A person with no role on a project may do nothing on it, including read it. */
export function can(role: Role | null, action: Action): boolean {
return role !== null && ALLOWED[role].has(action);
}