Skip to content

Conversation

SarahSoutoul
Copy link
Contributor

@SarahSoutoul SarahSoutoul commented Sep 29, 2025

🔎 Previews:

What does this solve?

Linear: https://linear.app/clerk/issue/DOCS-10913/permissions-info-in-docs-outdated

The Dashboard has changed significantly since many of the docs around permissions were first written.

  • Creating permissions now requires creating a feature first.
  • The Dashboard layout and navigation for roles and permissions has changed.
  • The Dashboard now hides the org: prefix, which is still used in code and docs. But also, org: gets added automatically now, so users don't need to enter the required format of org:<role> for e.g.

What changed?

  • Applied changes to reflect on the new layout and navigation.
  • Added a callout to explain the confusion with Dashboard hiding the org: prefix vs what's in the actual code when checking permissions.
  • Clarified steps on how to create permissions.
  • Refined the Permission-based authorization checks text to be more highlighted in the docs.

Note: One thing I'm unsure about is the docs mention "Custom permissions"; but on the Dashboard, it is now called "Feature permissions". I had originally changes all the "custom" for "feature", but I feel like custom permissions is so much more user friendlier to understand, especially compared to system permissions.

Checklist

  • I have clicked on "Files changed" and performed a thorough self-review
  • All existing checks pass

@SarahSoutoul SarahSoutoul self-assigned this Sep 29, 2025
Copy link

vercel bot commented Sep 29, 2025

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

Project Deployment Preview Updated (UTC)
clerk-docs Ready Ready Preview Oct 8, 2025 6:08pm

@SarahSoutoul SarahSoutoul changed the title Refinements Update permission creation steps and clarify org: prefix behavior Sep 29, 2025
@alexisintech
Copy link
Member

Note: One thing I'm unsure about is the docs mention "Custom permissions"; but on the Dashboard, it is now called "Feature permissions". I had originally changes all the "custom" for "feature", but I feel like custom permissions is so much more user friendlier to understand, especially compared to system permissions.

Are you comfortable mentioning this feedback to the team? Let them know we'd have to update all of the docs, so we want to be sure what terminology we're going with - but advocate that "Custom permissions" seem more user friendly/intuitive.

@SarahSoutoul
Copy link
Contributor Author

Are you comfortable mentioning this feedback to the team? Let them know we'd have to update all of the docs, so we want to be sure what terminology we're going with - but advocate that "Custom permissions" seem more user friendly/intuitive.

Yes, done: https://clerkinc.slack.com/archives/C06FGDX7MRD/p1759250794885609. Let's see!

@SarahSoutoul
Copy link
Contributor Author

SarahSoutoul commented Sep 30, 2025

@alexisintech Seems like the consensus is to keep it as custom permissions, but to make it a lowercase thing, aka it's not a feature name. just a descriptor. Here is the slack context: https://clerkinc.slack.com/archives/C06FGDX7MRD/p1759250794885609 . Changes here: Refine post dashboard convo

Permissions grant users privileged access to resources and operations, like creating and deleting. Clerk supports two types of permissions: **system permissions** and **custom permissions**.

> [!IMPORTANT]
> In the Clerk Dashboard, permissions appear in the format `<feature>:<permission>`. However, the `org:` prefix is automatically applied under the hood for all organization-scoped permissions. This means that when checking permissions in your code, always include the full key with the prefix (`org:<feature>:<permission>`).
Copy link
Member

Choose a reason for hiding this comment

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

you don't need to pass the org: prefix in code when checking perms! was there somewhere that you got this information from?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Discussed it with @royanger, but also, it's in our docs code examples too.

Screenshot 2025-10-02 at 2 18 19 pm

Copy link
Member

Choose a reason for hiding this comment

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

gotcha! its not required when checking perms, but it is required in other places, like when passing params to certain methods and what not. here's the relevant slack discussion: https://clerkinc.slack.com/archives/C07JG7SCWCD/p1759437155781849

the solution we settled on is to just go ahead and add the orgs: prefix everywhere (docs and dash) to minimize confusion


Permission-based authorization checks link with feature-based authorization checks. This means that if you are checking a custom permission, it will only work if the feature part of the permission key (`org:<feature>:<permission>`) **is a feature included in the organization's active plan**. For example, say you want to check if an organization member has the custom permission `org:teams:manage`, where `teams` is the feature. Before performing the authorization check, you need to ensure that the user's organization is subscribed to a plan that has the `teams` feature. If the user's organization is not subscribed to a plan that has the `teams` feature, the authorization check will always return `false`, even if the user has the custom permission.
> [!IMPORTANT]
> Permission-based authorization checks link with feature-based authorization checks. This means that a permission check will only work if the feature part of the permission key (`org:<feature>:<permission>`) **is a feature included in the organization's active plan**. For example, say you want to check if an organization member has the custom permission `org:teams:manage`, where `teams` is the feature. Before performing the authorization check, you need to ensure that the user's organization is subscribed to a plan that has the `teams` feature. If not, the authorization check will always return `false`, even if the user has the custom permission.
Copy link
Member

Choose a reason for hiding this comment

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

this isn't true, because you can assign a feature permission to a role, and give a user that role, and they will have that permission - regardless of if the organization pays for a subscription plan/feature or not.

i can try to help rewrite this - let me draft something

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This was a messaging that was already there - I just made it into a callout. But from my discussion with @royanger, I understood the above to be true?

Copy link
Member

Choose a reason for hiding this comment

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

naurrr, that may be only if billing is enabled?
i have a fresh app, enabled orgs, and then assigned a custom permission to a role, and that role to a user. then i did a has() check for it, and it worked.
no billing / plans required.

Copy link
Member

Choose a reason for hiding this comment

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

so i've played around with this - i have a custom permission invoices:create. i enabled billing, created an organization plan, added the invoices feature to it. i have one user whose active organization is subscribed to the plan, so they have that permission because their org plan has that feature. i have one user whose active organization is not subscribed to the plan, but they have the permission through their role. and i'm not getting any issues with authorization checks. so maybe this information doesn't ring true anymore? i see that @mzhong9723 added it in this PR: https://github.com/clerk/clerk-docs/pull/2263/files - maybe she can give us some insight on why she added it!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

naurrr, that may be only if billing is enabled?

Yes, this is in the billing guide, so I'm guessing this limitation only applies when billing is enabled. But yeah interested to hear your thoughts @mzhong9723 🙏

Copy link
Member

Choose a reason for hiding this comment

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

The correct behavior if billing is enabled should be that the features that an organization member receives should only come from the active organization plan.

i have one user whose active organization is not subscribed to the plan, but they have the permission through their role.

So this scenario seems like a bug 🤔

Copy link
Member

Choose a reason for hiding this comment

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

I just set up the following scenario:

  • user is an admin in two organizations: testorg and testorg2
  • billing is enabled, testorg has active plan expensive_org. testorg2 has plan expensive_org_copy
  • expensive_org doesn't have any features, expensive_org_copy has two features: teams and dashboard
  • role org:admin has permissions for the teams and dashboard features

Here's what I see from the user's org memberships:

testorg org memberships only has system permissions
Screenshot 2025-10-03 at 2 28 53 PM

testorg2 org membership permissions shows the teams and dashboard permissions
Screenshot 2025-10-03 at 2 28 45 PM

Copy link
Member

Choose a reason for hiding this comment

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

but the callout is talking about if you do a permission check, it will fail even if the user has the permission if the user's organization is not subscribed to the plan that has the feature

If not, the authorization check will always return false, even if the user has the custom permission.

but that's not true from what i tested o.O

@SarahSoutoul
Copy link
Contributor Author

Noticed the /docs/reference/nuxt/clerk-middleware page still contained the old linkage to authorization checks rather than the tooltip like the other changes?

Screenshot 2025-10-07 at 12 05 45 pm

Copy link
Member

@alexisintech alexisintech left a comment

Choose a reason for hiding this comment

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

I think this is good to go for now!

@alexisintech
Copy link
Member

alexisintech commented Oct 7, 2025

Noticed the /docs/reference/nuxt/clerk-middleware page still contained the old linkage to authorization checks rather than the tooltip like the other changes?

Screenshot 2025-10-07 at 12 05 45 pm

Because it says "Learn more about authorization checks" and links to the reference page. It wouldn't make sense if it said "Learn more about authorization checks" and then its just a hoverable tooltip instead of a visitable link. Experiment with it: put the tooltip there and see what I mean!

@SarahSoutoul
Copy link
Contributor Author

SarahSoutoul commented Oct 7, 2025

Noticed the /docs/reference/nuxt/clerk-middleware page still contained the old linkage to authorization checks rather than the tooltip like the other changes?
Screenshot 2025-10-07 at 12 05 45 pm

Because it says "Learn more about authorization checks" and links to the reference page. It wouldn't make sense if it said "Learn more about authorization checks" and then its just a hoverable tooltip instead of a visitable link. Experiment with it: put the tooltip there and see what I mean!

Totally fair! I think we're good to go then.

One thing is I can see see the callout is back? Could I get the context around this?

@alexisintech
Copy link
Member

Noticed the /docs/reference/nuxt/clerk-middleware page still contained the old linkage to authorization checks rather than the tooltip like the other changes?
Screenshot 2025-10-07 at 12 05 45 pm

Because it says "Learn more about authorization checks" and links to the reference page. It wouldn't make sense if it said "Learn more about authorization checks" and then its just a hoverable tooltip instead of a visitable link. Experiment with it: put the tooltip there and see what I mean!

Totally fair! I think we're good to go then.

One thing is I can see see the callout is back? Could I get the context around this?

the callout was always correct - I just didn't have billing enabled 😅 LOL

@alexisintech
Copy link
Member

feel free to merge 😸💖

@SarahSoutoul SarahSoutoul merged commit 2c037ed into main Oct 8, 2025
7 checks passed
@SarahSoutoul SarahSoutoul deleted the ss/DOCS-10913 branch October 8, 2025 18:11
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.

3 participants