Skip to content

Comments

feat: dogfood pbac internally on IS_CALCOM instances #23537

Merged
sean-brydon merged 4 commits intomainfrom
feat/dogfood-pbac-internally
Sep 3, 2025
Merged

feat: dogfood pbac internally on IS_CALCOM instances #23537
sean-brydon merged 4 commits intomainfrom
feat/dogfood-pbac-internally

Conversation

@sean-brydon
Copy link
Member

What does this PR do?

This PR enabled the PBAC check for pretty much everywhere if the feature flag is enabled for a org.

However, If PBAC fails for whatever reason - we fall back to our old role checks (current way of checking permissions in prod) and log heavily so we can setup alerts in axiom and figure out where this is happening.

We will be testing this internally on the Cal.com org while we roll this out slowly with/without a feature flag.

How should this be tested?

Use yarn seed-pbac and just explore the app. If you see logs console of PBAC INTERNAL there is places where the default role permissions do not match the current implementation without a feature flag

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Sep 3, 2025

Walkthrough

Added an internal DOGFOOD_PBAC_INTERNALLY toggle and dogfoodFallback logic in PermissionCheckService: after awaiting PBAC checks in checkPermission and checkPermissions, if PBAC denies access and the toggle is enabled the code routes to a new private dogfoodFallback which logs a JSON warning payload and evaluates role-based fallback via checkFallbackRoles using membershipRole and fallbackRoles. Tests were expanded to cover PBAC-failure fallback paths for single and multiple permissions and an empty-permissions case. Note: dogfoodFallback is defined twice in the class (duplicate private method definitions).

Possibly related PRs


📜 Recent review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between bf19acb and 4a3f019.

📒 Files selected for processing (2)
  • packages/features/pbac/services/__tests__/permission-check.service.test.ts (3 hunks)
  • packages/features/pbac/services/permission-check.service.ts (4 hunks)
🚧 Files skipped from review as they are similar to previous changes (2)
  • packages/features/pbac/services/permission-check.service.ts
  • packages/features/pbac/services/tests/permission-check.service.test.ts
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install dependencies / Yarn install & cache
✨ Finishing Touches
  • 📝 Generate Docstrings
🧪 Generate unit tests
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/dogfood-pbac-internally

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
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

CodeRabbit Commands (Invoked using PR/Issue comments)

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

Other keywords and placeholders

  • Add @coderabbitai ignore or @coderabbit ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Status, Documentation and Community

  • Visit our Status Page to check the current availability of CodeRabbit.
  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

@graphite-app graphite-app bot requested a review from a team September 3, 2025 07:24
@keithwillcode keithwillcode added consumer core area: core, team members only labels Sep 3, 2025
@dosubot dosubot bot added the ✨ feature New feature or request label Sep 3, 2025
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
packages/features/pbac/services/permission-check.service.ts (1)

275-277: Fix unsafe optional chaining that can throw at runtime.

membership?.team.parentId will throw if team is undefined.

-    if (membership?.team.parentId) {
+    if (membership?.team?.parentId) {
🧹 Nitpick comments (7)
packages/features/pbac/services/__tests__/permission-check.service.test.ts (4)

17-23: Mocking IS_CALCOM for dogfood path is fine; consider adding a non-Cal.com check.

Looks good to force the internal path. Optionally add one test where IS_CALCOM=false (e.g., with vi.resetModules and a different mock) to confirm no RBAC fallback occurs when PBAC denies.


157-193: Dogfood fallback happy-path covered; assert no org fetch to tighten scope.

Test is solid. You can also assert that getOrgMembership wasn’t called to make the fallback signal unambiguous in this scenario.

-      expect(mockRepository.checkRolePermission).toHaveBeenCalled();
+      expect(mockRepository.checkRolePermission).toHaveBeenCalled();
+      expect(mockRepository.getOrgMembership).toHaveBeenCalledTimes(1);

299-335: Multi-permission dogfood fallback covered; mirror single-permission assertion.

Similarly, consider asserting org lookup was attempted exactly once to document intended flow.

-      expect(mockRepository.checkRolePermissions).toHaveBeenCalled();
+      expect(mockRepository.checkRolePermissions).toHaveBeenCalled();
+      expect(mockRepository.getOrgMembership).toHaveBeenCalledTimes(1);

336-370: Nit: Align test data naming to reduce cognitive load.

Role is MEMBER but customRoleId is "admin_role". Rename to "member_role" and update the expectation to avoid confusion.

-        role: "MEMBER" as MembershipRole, // Change to MEMBER so fallback also fails
-        customRoleId: "admin_role",
+        role: "MEMBER" as MembershipRole, // MEMBER so fallback also fails
+        customRoleId: "member_role",
...
-      expect(mockRepository.checkRolePermissions).toHaveBeenCalledWith("admin_role", []);
+      expect(mockRepository.checkRolePermissions).toHaveBeenCalledWith("member_role", []);
packages/features/pbac/services/permission-check.service.ts (3)

20-21: Make dogfood flag runtime-togglable.

Hard-tying to IS_CALCOM is fine, but add an env/feature override to disable quickly if needed.

-const DOGFOOD_PBAC_INTERNALLY = IS_CALCOM;
+const DOGFOOD_PBAC_INTERNALLY =
+  (process.env.DOGFOOD_PBAC_INTERNALLY ?? "").toLowerCase() === "true" || IS_CALCOM;

286-331: Improve log grammar and use structured logging; include membershipRole.

Message is awkward (“doesnt”) and current stringified JSON reduces queryability in Axiom. Prefer structured fields.

-    const debugInfo = {
+    const debugInfo = {
       userId,
       teamId,
       membershipId,
       permissions,
       hasPbacPermission,
       fallbackRoles,
+      membershipRole,
     };
-
-    this.logger.warn(
-      `PBAC INTERNAL - Failed but user doesnt have permission string to carry out this action. Falling back to fallback roles. \n JSON${JSON.stringify(
-        debugInfo,
-        null,
-        2
-      )}`
-    );
+    this.logger.warn(
+      { pbacDogfoodFallback: debugInfo },
+      "PBAC INTERNAL - PBAC check failed; falling back to RBAC (dogfood)"
+    );

222-240: Optional: Avoid redundant membership fetches in hasPermission(s).

checkPermission(s) already fetched membership; passing membership/orgMembership into hasPermission(s) would save a DB roundtrip.

📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

💡 Knowledge Base configuration:

  • MCP integration is disabled by default for public repositories
  • Jira integration is disabled by default for public repositories
  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 2d9c1b3 and b7d028f.

📒 Files selected for processing (2)
  • packages/features/pbac/services/__tests__/permission-check.service.test.ts (4 hunks)
  • packages/features/pbac/services/permission-check.service.ts (5 hunks)
🧰 Additional context used
📓 Path-based instructions (4)
**/*.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

**/*.ts: For Prisma queries, only select data you need; never use include, always use select
Ensure the credential.key field is never returned from tRPC endpoints or APIs

Files:

  • packages/features/pbac/services/__tests__/permission-check.service.test.ts
  • packages/features/pbac/services/permission-check.service.ts
**/*.{ts,tsx}

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Flag excessive Day.js use in performance-critical code; prefer native Date or Day.js .utc() in hot paths like loops

Files:

  • packages/features/pbac/services/__tests__/permission-check.service.test.ts
  • packages/features/pbac/services/permission-check.service.ts
**/*.{ts,tsx,js,jsx}

⚙️ CodeRabbit configuration file

Flag default exports and encourage named exports. Named exports provide better tree-shaking, easier refactoring, and clearer imports. Exempt main components like pages, layouts, and components that serve as the primary export of a module.

Files:

  • packages/features/pbac/services/__tests__/permission-check.service.test.ts
  • packages/features/pbac/services/permission-check.service.ts
**/*.{service,repository}.ts

📄 CodeRabbit inference engine (.cursor/rules/review.mdc)

Avoid dot-suffixes like .service.ts or .repository.ts for new files; reserve .test.ts, .spec.ts, .types.ts for their specific purposes

Files:

  • packages/features/pbac/services/permission-check.service.ts
🧬 Code graph analysis (1)
packages/features/pbac/services/permission-check.service.ts (3)
packages/lib/constants.ts (1)
  • IS_CALCOM (43-49)
packages/features/pbac/domain/types/permission-registry.ts (1)
  • PermissionString (60-60)
packages/platform/libraries/index.ts (1)
  • MembershipRole (98-98)
⏰ Context from checks skipped due to timeout of 180000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: Install dependencies / Yarn install & cache
🔇 Additional comments (3)
packages/features/pbac/services/permission-check.service.ts (3)

2-2: Importing IS_CALCOM is appropriate; confirm build-time value.

Ensure the bundling/runtime environment doesn’t tree-shake/inline a stale value across deployments. If needed, expose this via config to allow runtime toggling.


132-147: LGTM: PBAC-first with dogfood fallback is correctly gated.

The flow validates, checks PBAC, then optionally falls back via roles only on internal dogfooding.


195-210: LGTM: Multi-permission path mirrors single-permission behavior.

Consistent gating and return semantics.

@vercel
Copy link

vercel bot commented Sep 3, 2025

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

2 Skipped Deployments
Project Deployment Preview Comments Updated (UTC)
cal Ignored Ignored Sep 3, 2025 9:41am
cal-eu Ignored Ignored Sep 3, 2025 9:41am

@sean-brydon sean-brydon merged commit afb54ca into main Sep 3, 2025
80 of 86 checks passed
@sean-brydon sean-brydon deleted the feat/dogfood-pbac-internally branch September 3, 2025 12:48
@github-actions
Copy link
Contributor

github-actions bot commented Sep 3, 2025

E2E results are ready!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

consumer core area: core, team members only ✨ feature New feature or request ready-for-e2e size/L

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants