ld-permissions
npx skills add https://github.com/lightdash/lightdash --skill ld-permissions
Agent 安装分布
Skill 文档
Permissions & Authorization Guide
This skill helps you work with Lightdash’s CASL-based permissions system, including scopes, custom roles, and authorization enforcement.
What do you need help with?
- Add a new scope/permission – Step-by-step guide to add a new permission
- Debug a permission issue – Troubleshoot why a user can’t access something
- Understand the permission flow – Learn how permissions work end-to-end
- Work with custom roles – Create or modify custom roles with specific scopes
Quick Reference
Key Files
| Purpose | Location |
|---|---|
| Scope definitions | packages/common/src/authorization/scopes.ts |
| CASL types | packages/common/src/authorization/types.ts |
| Ability builder | packages/common/src/authorization/index.ts |
| System role abilities | packages/common/src/authorization/projectMemberAbility.ts |
| Role-to-scope mapping | packages/common/src/authorization/roleToScopeMapping.ts |
| Scope-to-CASL conversion | packages/common/src/authorization/scopeAbilityBuilder.ts |
Common Patterns
Backend permission check:
import { subject } from '@casl/ability';
import { ForbiddenError } from '@lightdash/common';
if (user.ability.cannot('manage', subject('Dashboard', { projectUuid }))) {
throw new ForbiddenError('You do not have permission');
}
Frontend permission check:
const { user } = useUser();
if (user?.ability.can('manage', 'Dashboard')) {
return <EditButton />;
}
or wrap in a CASL component:
import { Can } from '../../providers/Ability';
<Can I="manage" a="Dashboard">
<EditButton />
</Can>
Full Documentation
For comprehensive documentation, read: .context/PERMISSIONS.md
This includes:
- Architecture diagram showing the complete permission flow
- All scope groups and modifiers (@self, @public, @space, etc.)
- Database schema for custom roles
- Step-by-step guide to add new scopes
- Troubleshooting guide
Adding a New Scope (Quick Guide)
- Define scope in
packages/common/src/authorization/scopes.ts:
{
name: 'manage:NewFeature',
description: 'Description for custom role UI',
isEnterprise: false,
group: ScopeGroup.PROJECT_MANAGEMENT,
getConditions: (context) => [addUuidCondition(context)],
}
-
Add subject (if new) in
packages/common/src/authorization/types.ts -
Add to system role in
packages/common/src/authorization/roleToScopeMapping.ts -
Update ability builder in
packages/common/src/authorization/projectMemberAbility.ts -
Enforce in service with
user.ability.cannot()check -
Add frontend check with
user?.ability.can()
Debugging Permission Issues
When a user gets “ForbiddenError”:
- Check scope exists – Is the scope defined in
scopes.ts? - Check role assignment – Does the user’s role include this scope?
- Check conditions – Do the CASL conditions match the resource?
- Check enterprise flag – Is
isEnterprise: truebut deployment isn’t enterprise? - Check subject name – Case-sensitive match in
CaslSubjectNames?
Use grep to find where the permission is checked:
grep -r "ability.cannot.*'manage'.*'YourSubject'" packages/backend/src/services/
Please describe what you’re trying to accomplish, or ask me to explain any aspect of the permissions system.