skills/nocobase-acl-manage/SKILL.md
Task-driven ACL governance through nb CLI for role lifecycle, global role mode, permission policy, user-role membership, and risk assessment. Use when users describe business permission outcomes instead of raw command arguments.
npx skillsauth add nocobase/skills nocobase-acl-manageInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Turn ACL and permission governance into a task-driven workflow so users can ask for business outcomes while the skill handles:
plan -> confirm -> apply -> readback.global role mode is treated as a global system policy, not a per-role field.nb commands in this skill.| Task | User Outcome | Required Inputs | Optional Inputs |
|---|---|---|---|
| role.audit-all | list all roles with comparable policy summary | none | data_source_key, output |
| role.create-blank | create a role with default read-only baseline (single creation mode) | role_name | role_title, description, hidden, allow_configure, allow_new_menu |
| role.compare | explain differences between roles | role_names[] | data_source_key, output |
| Task | User Outcome | Required Inputs | Optional Inputs |
|---|---|---|---|
| global.role-mode.get | read current global role mode | none | output |
| global.role-mode.set | switch global role mode | role_mode | strict_mode |
role_mode enum mapping:
default: independent role usage (no union mode)allow-use-union: union mode available, role switching still allowedonly-use-union: force union mode for multi-role users| Task | User Outcome | Required Inputs | Optional Inputs |
|---|---|---|---|
| permission.system-snippets.set | set role-level system snippets | role_name, (snippet_preset or snippets) | none |
| permission.route.desktop.set | set desktop route permissions for a role | role_name, route_ids[] | set_mode (set or add or remove) |
| permission.data-source.global.set | set global strategy actions for all tables in one data source | role_name, global_actions[] | data_source_key |
| permission.data-source.resource.set | set independent actions for one or more collections | role_name, (collection_hint or collection_hints[]), actions[] | data_source_key, fields_map, scope_map, resource_scope (all by default) |
| permission.scope.manage | create/update/list reusable scopes | scope_task | data_source_key, scope_id, scope_payload |
| Task | User Outcome | Required Inputs | Optional Inputs |
|---|---|---|---|
| user.assign-role | assign one role to one or many users | role_name, (user_ids[] or user_filter) | allow_generic_association_write |
| user.unassign-role | remove one role from one or many users | role_name, (user_ids[] or user_filter) | allow_generic_association_write |
| user.audit-role-membership | inspect users bound to roles | (role_name or user_id) | output |
| Task | User Outcome | Required Inputs | Optional Inputs |
|---|---|---|---|
| risk.assess-role | risk score and rationale for one role | role_name | data_source_key, output |
| risk.assess-user | risk score based on user-role-permission relationship | user_id | data_source_key, output |
| risk.assess-system | system-level ACL governance risk summary | none | data_source_key, output |
Role creation interaction policy:
role.create-blank)role_name must use NocoBase role uid format with r_ prefixr_ prefix, normalize to r_<normalized_name> and show normalized value in confirmation/readbackrole_name is provided, execute creation directlyResource permission interaction policy:
permission.data-source.resource.set, always confirm:main by default unless user specifies another)all by default when user does not specify)add table permission / configure permission describe the operation, not ACL action createcreate as selected action when user clearly asks for data-creation capability (can create records / can add data)collection_hint(s)allall -> built-in scope key=all id in target data sourceown -> built-in scope key=own id in target data sourcecustom -> user-specified scope id (or resolved scope key)null when final scope is all or ownpermission.data-source.resource.set, execute one complete write payload per target collectionusingActionsConfig: trueactions[] set, with explicit scope binding (scopeId or scopeKey) for all|own and explicit non-empty fields arrays for field-configurable actionsscope=all (default) and allow user overridefields=[] as a full-field default markercreate, view, update, export, importXlsx)sort, createdBy, createdById, updatedBy, updatedById) unless user explicitly asks to exclude themfield.name) for writes, never display titlesview action must default to all fields for that collectionall permissions on a collection, resolve runtime available actions and confirm expanded action set before write| Input | Required | Default | Validation | Clarification Question |
|---|---|---|---|---|
| task | yes | none | one of canonical tasks or alias | "Which ACL governance task should run?" |
| role_name | conditional | none | role exists for update/audit tasks; write tasks normalize to r_* uid | "Which role should be targeted?" |
| role_mode | conditional | none | one of default/allow-use-union/only-use-union | "Which global role mode should be set?" |
| collection_hint / collection_hints[] | conditional | none | required for permission.data-source.resource.set; business name/keyword input is allowed | "Which business table(s) should be configured?" |
| resolved_collection_names[] | conditional | runtime resolved | required before write for permission.data-source.resource.set; each collection must exist in selected data source | "I found these matching collections. Which should be used?" |
| actions[] | conditional | none | required for permission.data-source.resource.set | "Which actions should be granted on these collections?" |
| resource_scope | no | all | one of all / own / custom(scope_id or scope_filter) | "Which data scope should be used? Default is all; choose own/custom only when needed." |
| data_source_key | no | main | must exist at runtime | "Which data source key should be used? (default: main)" |
| strict_mode | no | safe | safe or fast | "Use safe mode with full readback?" |
| allow_generic_association_write | no | false | boolean | "Allow guarded generic association writes for user-role assignment?" |
| output | no | text+matrix | text, text+matrix, text+evidence | "How detailed should the result be?" |
Default behavior when user says you decide:
role.create-blank firstdata_source_key=mainstrict_mode=safe23role.create-blank, ask only for role_name when missing; do not ask role-type questionsrole_name, normalize to r_* uid and echo normalized value in confirmationpermission.data-source.resource.set, default data_source_key=main when omitted unless user explicitly provides another data sourcepermission.data-source.resource.set, if collection hint cannot be resolved or is ambiguous, ask follow-up questions before writepermission.data-source.resource.set, if actions are incomplete, ask follow-up questions before writepermission.data-source.resource.set, if scope is omitted, apply default all and require confirmation before writepermission.data-source.resource.set, if custom scope is requested but scope id/key is unresolved, ask follow-up questions before writepermission.data-source.resource.set, if user has not confirmed the final write plan, do not write401, 403, Auth required), stop and instruct the agent to hand off environment/auth recovery to nocobase-env-managedefault/allow-use-union/only-use-unionrole.create-blank baseline first, then permission assignmentnb CLI is available in PATHnb <command> [subcommand ...] [flags ...]nb must be a command (for example env or api), not a flag such as -e/-t/-jnb -e localnb api resource list --resource users -e local -j--resources, --actions) over inline --body when possible--body-file over inline --body--body-file content must be valid JSON encoded as UTF-8 without BOM--body fails JSON parsing in PowerShell, regenerate payload as --body-file and retry once{\"k\":\"v\"}), it may be parsed as invalid JSONapi acl roles data-source-resources create|update and api acl roles apply-data-permissions when payload is missing or invalid (--body-file preferred, --body compatible)usingActionsConfig: true and non-empty actions[]create/view/update/export/importXlsx, each action must carry non-empty fields[]scopeId (for explicit id binding)scopeKey (for key-based resolution, such as all/own)scope.{id|key} (compatibility readback payload)all or own, readback must show resolved non-null scopeIdroles data-source-resources only has create|get|update; do not call listroles data-source-resources get|update, locator must be one of:--filter-by-tk <resource_config_id>--data-source-key <data_source_key> --name <collection_name>roles data-source-resources get ... --appends actionsroles apply-data-permissions --filter-by-tk <role_name> --body-file <path>roles data-sources-collections list, use --data-source-key <data_source_key> as the default locator; use --filter only for compatibilitynb api resource list --resource collections --filter '{}' --appends fields -j as primary metadata sourceroles desktop-routes add, request body must be JSON array of numeric route idsnb env listnb env update <current_env_name>nb api acl --helpnb api acl roles --helpnb api acl --help or nb api acl roles --help fails, stop and return capability-boundary message; do not switch to ad-hoc script execution.nb env list and resolve current env from the row marked with *nocobase-env-manage, then rerun the ACL task after env recoverynb env update <current_env_name>nocobase-env-manage for env/auth/runtime recovery, or nocobase-plugin-manage only if the CLI error explicitly says a plugin must be enablednocobase-env-manageall when omitted)scopeId / scope key)all fields by default unless user provided restrictions)permission.data-source.resource.set, prefer unified write via nb api acl roles apply-data-permissions with complete resources[] payload; use roles data-source-resources create|update only as compatibility pathnb api acl roles data-source-resources get ... --appends actions when verifying action-level scope/fieldsPrimary write path:
nb api acl roles users add/remove)Guarded fallback path (user-role membership only):
allow_generic_association_write=truenb api resource update/list only for users.roles association operationsHard restrictions:
nb api acl --help and nb api acl roles --help in the same locked base-dir before concluding capability status.js/.ps1/.sh executor scripts to bypass runtime command discoveryHigh-impact ACL actions:
ui.*, pm, pm.*, app)destroy, broad export/import grants)Safety rules:
When a scenario is not supported by current CLI/runtime/tool policy:
This scenario is currently blocked by capability or governance policy in this skill.Please complete the operation in NocoBase admin UI, or enable the guarded fallback option if available.If you want, I can provide exact UI navigation steps and field suggestions.nb env list, runtime commands resolvable)base-dir plus nb env list, nb env update <current_env_name>, nb api acl --help, and nb api acl roles --helppermission.data-source.resource.set, data source + resolved collections + actions + scope were confirmed before writeall as the applied default scopepermission.data-source.resource.set, readback confirms usingActionsConfig=true and action-level scope/fields in the same write cycle--appends actionsall|own, readback shows non-null scopeId and matching scope keyusingActionsConfig, actions, scope binding scopeId|scopeKey, fields)roles data-source-resources get|update locator is explicit (filterByTk or data-source-key + name) before executionresource collections read path; roles data-sources-collections list is compatibility-only for role-facing viewroles desktop-routes add uses JSON array body with numeric route idsrole_nameglobal.role-mode.get and global.role-mode.set with readback.role.create-blank then verify role exists and has conservative defaults.permission.data-source.global.set and verify strategy actions.permission.data-source.resource.set with business collection name should auto-resolve real collection name(s) from target data source.permission.data-source.resource.set with ambiguous collection match should ask for disambiguation before write.permission.data-source.resource.set with missing actions should ask for clarification before write.permission.data-source.resource.set with missing scope should default to all, show this in confirmation, and allow user override before write.permission.data-source.resource.set with view and no field restrictions should apply full-field permission by default via explicit non-empty field lists.permission.data-source.resource.set with scope=all should write explicit built-in scope binding (non-null scopeId for key=all).permission.data-source.resource.set should require pre-write confirmation including data source + resolved collections + actions + scope.permission.data-source.resource.set should write independent policy in one complete payload (usingActionsConfig + actions + scope + fields), not multi-step patching.user.assign-role in strict mode should use dedicated membership command when available; if unavailable, block with boundary guidance.user.assign-role guarded fallback should run only when dedicated command is unavailable and guarded mode is explicitly enabled.risk.assess-role should return score + evidence + recommendations.| Reference | Use When | Notes |
|---|---|---|
| references/intent-presets-v1.md | intent normalization and defaults | includes global role-mode wording |
| references/intent-to-tool-map-v1.md | runtime command resolution | maps logical tasks to CLI command patterns |
| references/execution-guard-template.md | every ACL write task | fixed preflight command template for base-dir lock and fail-closed checks |
| references/result-format-v1.md | output rendering | includes risk cards and capability path |
| references/configuration.md | ACL policy details | detailed data-source and scope guidance |
| references/independent-permissions.md | resource-level permission writes | usingActionsConfig + actions + fields + scope complete-write policy |
| tests/capability-test-plan.md | capability matrix | aligned with v2 domains |
| tests/test-playbook.md | acceptance regression | prompt-first TC01, TC02, TC04-TC20 with runtime evidence commands |
| references/refactor-plan-v2.md | capability gaps and rollout plan | includes CLI migration notes |
| tests/README.md | runtime verification | playbook execution flow and reporting notes |
tools
Use when a NocoBase task requires AI employee lifecycle work such as discovering existing employees, judging fit, creating a dedicated employee, or configuring profile, prompt, model, skills, tools, or knowledge base before another skill binds it to a UI surface.
tools
Use when users need to inspect, create, revise, enable, or diagnose NocoBase workflows through the `nb` CLI, including trigger selection, node-chain changes, version safety checks, and execution troubleshooting.
tools
DEFAULT entry point for NocoBase Modern UI authoring or tweaks: new pages, blocks, menu items, and localized edits to blocks, fields, actions, layouts, or reactions on an already-running app via backend flow-surfaces through nb api. Also handles AI employee / AI assistant action placement on UI surfaces. Hand off employee lifecycle work such as discovering, judging, creating, or configuring profile, prompt, model, skills, tools, or knowledge base to nocobase-ai-employee, then return for the UI write. Only hand off to nocobase-dsl-reconciler when the user explicitly asks for DSL, YAML, git, or cli push workflow. Does not handle ACL, data modeling, workflow orchestration, browser reproduction, page error postmortems, or non-Modern page navigation.
data-ai
Create and manage NocoBase data models through the available data-modeling surface. Use when users want to inspect or change collections, fields, relations, or view-backed schemas in a NocoBase app.