Skip to content

feat(auth): role-based access control (roles, permissions, guards) - #40

Merged
abdelkabirouadoukou merged 2 commits into
mainfrom
feat/rbac
Aug 9, 2026
Merged

feat(auth): role-based access control (roles, permissions, guards)#40
abdelkabirouadoukou merged 2 commits into
mainfrom
feat/rbac

Conversation

@abdelkabirouadoukou

@abdelkabirouadoukou abdelkabirouadoukou commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Part B — Authorization (RBAC)

What was verified before building

  • Confirmed @thexjs/auth already had sessions + a session store but no
    roles/permissions concept, and that the framework's route middleware
    (MiddlewareFn via export const middleware) is the idiomatic enforcement
    point — so guards are built as middleware, not as a parallel auth mechanism.
  • Confirmed @thexjs/auth already depends on @thexjs/core (for checkCsrf),
    so importing MiddlewareFn adds no new dependency.

What was added

  • Roles/permissions on the sessionAuthUser gains optional roles and
    permissions; they're snapshotted into the session at creation time.
  • resolveRoles hook on defineAuth — apps can derive roles from a DB or
    service at sign-in. Without it, roles come from the provider's user object.
  • Pure helpershasRole, hasAnyRole, hasPermission,
    hasAllPermissions (fail-closed on null sessions).
  • GuardsrequireRole(...), requirePermission(...), requireAuth()
    returning SessionGuards that fail closed: signed out → 401, authenticated
    but missing role/permission → 403.
  • Middleware adapterstoMiddleware(getSession, guard, opts) and
    auth.requireRole(roles, opts) / auth.requirePermission(...) /
    auth.requireAuth() / auth.guard(...) returning core MiddlewareFns for
    export const middleware, with optional redirectTo for signed-out users.
  • Exported all of it from @thexjs/auth; changeset: minor.

Tests added

  • packages/auth/src/rbac.test.ts (17 tests): role/permission helpers,
    guard fail-closed semantics, multi-role any-match, no-roles
    authenticate-only, middleware 401/redirect/pass-through via a real session,
    and resolveRoles snapshotting.

Verification

  • bun run lint — clean (340 files)
  • bunx tsc --noEmit -p packages/auth — clean
  • bun test packages/auth/ — 38 pass / 0 fail (92 expects)
  • Full suite: 243+ pass / 6 skip / 0 fail — the only intermittent failure is a
    pre-existing buildVercelOutput EISDIR race in the adapter test
    (bundles React from Bun's module cache concurrently; reproduces on clean
    main 2/15 runs, unrelated to this change).

Summary by CodeRabbit

  • New Features

    • Added role- and permission-based access control.
    • Sessions can include resolved roles and permissions.
    • Added authentication, role, permission, and custom authorization guards.
    • Unauthorized requests return clear 401 or 403 responses, with optional redirects for signed-out users.
    • Added reusable role and permission checks for applications and routes.
  • Documentation

    • Updated the enterprise readiness roadmap to reflect authorization support.

@vercel

vercel Bot commented Aug 8, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
thexjs-basic Ready Ready Preview Aug 8, 2026 8:42pm
x Ready Ready Preview Aug 8, 2026 8:42pm

@coderabbitai

coderabbitai Bot commented Aug 8, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@abdelkabirouadoukou, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 17 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: a0022e1e-d3ce-4697-931b-50ddd130408b

📥 Commits

Reviewing files that changed from the base of the PR and between f22aaae and e9ef00f.

📒 Files selected for processing (3)
  • packages/auth/src/auth.ts
  • packages/auth/src/rbac.test.ts
  • packages/auth/src/rbac.ts
📝 Walkthrough

Walkthrough

Changes

The auth package now snapshots roles and permissions when it creates sessions. It adds RBAC helpers, fail-closed guards, middleware adapters, public exports, tests, and release documentation.

RBAC authorization

Layer / File(s) Summary
Authorization contracts and guards
packages/auth/src/types.ts, packages/auth/src/rbac.ts
AuthUser supports roles and permissions. Predicates and guards handle authenticated, unauthenticated, and unauthorized sessions.
Session role resolution
packages/auth/src/auth.ts
Sessions resolve roles and permissions through resolveRoles or provider data. Auth exposes authentication, role, permission, and custom guard middleware.
Middleware integration and validation
packages/auth/src/index.ts, packages/auth/src/rbac.ts, packages/auth/src/rbac.test.ts, .changeset/rbac.md, ROADMAP.md
Middleware returns 401 or 403 responses, supports signed-out redirects, and continues authorized requests. Tests cover helper, guard, middleware, and session resolution behavior.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Request
  participant toMiddleware
  participant SessionGuard
  participant Next
  Request->>toMiddleware: invoke protected route middleware
  toMiddleware->>SessionGuard: resolve session and evaluate access
  alt authorized
    SessionGuard->>Next: continue request
  else signed out or unauthorized
    SessionGuard-->>toMiddleware: return 401 or 403 result
    toMiddleware-->>Request: return response or redirect
  end
Loading

Possibly related PRs

Suggested labels: enhancement, javascript

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the main change: adding role-based access control with roles, permissions, and guards.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/rbac

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@packages/auth/src/auth.ts`:
- Around line 175-181: Clone the roles and permissions arrays before assigning
them to snapshot in the authorization snapshot flow, covering both
config.resolveRoles results and user fallback values. Update the assignments in
the surrounding session snapshot logic so later mutations of the source objects
cannot alter stored session authorization state.

In `@packages/auth/src/rbac.test.ts`:
- Line 171: Update the cookie extraction in the RBAC tests at all three
locations to validate the optional result of getSetCookie()[0] before calling
split, removing the unsafe cast and handling an absent session cookie
explicitly.

In `@packages/auth/src/rbac.ts`:
- Around line 36-38: Update hasAllPermissions to explicitly return false when
session is null, before evaluating permissions.every; preserve the existing
all-permissions check for present sessions, including empty permission lists.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 873484c5-4069-4bf6-bf43-0f791a623c1a

📥 Commits

Reviewing files that changed from the base of the PR and between fb37498 and f22aaae.

📒 Files selected for processing (7)
  • .changeset/rbac.md
  • ROADMAP.md
  • packages/auth/src/auth.ts
  • packages/auth/src/index.ts
  • packages/auth/src/rbac.test.ts
  • packages/auth/src/rbac.ts
  • packages/auth/src/types.ts

Comment thread packages/auth/src/auth.ts Outdated
Comment thread packages/auth/src/rbac.test.ts Outdated
Comment thread packages/auth/src/rbac.ts
…ull session

Addresses CodeRabbit review findings on the RBAC PR:
- snapshotUser now shallow-copies roles/permissions from both the
  resolveRoles result and the AuthUser fallback, so mutating the source
  can no longer change an issued session's authorization (major)
- hasAllPermissions returns false for a null session even with an empty
  list, fixing the vacuous .every() success; hasAnyRole gets the same
  guard (major)
- tests use the existing extractCookie helper with an explicit
  requireSessionCookie that fails on an absent cookie instead of an
  unchecked getSetCookie()[0] cast (minor)
- adds regression tests: null session + empty lists, and snapshot
  immunity to source-array and resolver-result mutation
@abdelkabirouadoukou
abdelkabirouadoukou merged commit 17644fd into main Aug 9, 2026
9 checks passed
@abdelkabirouadoukou
abdelkabirouadoukou deleted the feat/rbac branch August 9, 2026 03:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant