From cpln
Manages access control, RBAC policies, and permissions on Control Plane. Handles policy creation, binding management, and troubleshooting common failures like policies that exist but grant nothing.
How this skill is triggered — by the user, by Claude, or both
Slash command
/cpln:access-controlThe summary Claude sees in its skill listing — used to decide when to auto-load this skill
> **Tool availability:** some MCP tools named here live in the `full` toolset profile — if one is not advertised on this connection, tell the user to reconnect the MCP server with `?toolsets=full` (or use the `cpln` CLI fallback). Reads and deletes work on every profile via the generic `list_resources` / `get_resource` / `delete_resource` tools.
Tool availability: some MCP tools named here live in the
fulltoolset profile — if one is not advertised on this connection, tell the user to reconnect the MCP server with?toolsets=full(or use thecplnCLI fallback). Reads and deletes work on every profile via the genericlist_resources/get_resource/delete_resourcetools.
A policy targets one resource kind and binds permissions to principals (users, groups, service accounts, workload identities). The common failure is a policy that exists but grants nothing — a wrong targetKind, permission name, or principal link fails with no error — so read the policy back after writing.
| Layer | Scope | Controls |
|---|---|---|
| Billing-account roles | account-wide (set on the billing account, separate from org policies) | billing_admin, billing_viewer, org_creator — none grant org-resource access |
| Org policies | per resource kind | all day-to-day access |
A caller is allowed an action when some policy on the resource's kind has a binding that lists that action (or a permission implying it) and names the caller — or a group the caller is in.
A policy = one targetKind + a target scope + bindings.
kind: policy
name: app-secret-access
targetKind: secret # exactly one resource kind
targetLinks: # OR `target: all` OR `targetQuery:` (pick one)
- //secret/database-url
bindings: # ≤ 50
- permissions: [reveal, use]
principalLinks: # 1–200
- //gvc/production/identity/app-identity
Limits: bindings ≤ 50; principalLinks 1–200 per binding; targetLinks ≤ 200. origin is read-only — default (yours) or builtin (locked; see Built-ins).
Target scope (pick one): target: all (org-wide roles) · targetLinks (specific resources) · targetQuery (tag query — see query-spec).
Valid target kinds: the targetKind enum accepts all 33 resource kinds, but only the 20 kinds with permission schemas (the ones get_permissions accepts) are meaningful targets: workload, secret, gvc, identity, image, org, policy, group, serviceaccount, user, volumeset, domain, location, ipset, mk8s, cloudaccount, agent, auditctx, quota, task.
Create vs update:
create_policy builds one binding from addPermissions × (addUsers/addGroups/addServiceAccounts/addIdentities) — providing only one side is an error (a binding needs both). It also requires exactly one target scope (targetAll / targetLinks / targetQuery). For several distinct bindings, use update_policy addBindings.update_policy merges bindings (matched by exact permission set — you can't extend a set) but replaces targets (targetLinks wholesale, removeTargetLinks incremental, targetAll — mutually exclusive).get_permissions (kind) is the source of truth — it returns the kind's exact permission list and its implication map. Confirm names with it before writing a policy; never hand-write them, and don't assume a kind only has create / delete / edit / view / manage.
Two traps that don't need a lookup:
manage implies every permission for a kind — grant it only to true admins.reveal, not read — the most common mistake.Many kinds add non-obvious permissions beyond CRUD — e.g. secret reveal/use, image pull, workload connect/exec.*, serviceaccount addKey, user invite/impersonate, mk8s clusterAdmin — so pull the real set with get_permissions.
| Type | Link |
|---|---|
| User | //user/EMAIL |
| Group (preferred) | //group/NAME |
| Service account | //serviceaccount/NAME |
| Workload identity | //gvc/GVC/identity/NAME (GVC-scoped — never //identity/NAME) |
An identity never belongs to a group, so authorize it only with a binding that names its exact link. At runtime the attached identity is the workload's API credential: calls from inside the workload with the injected CPLN_TOKEN against CPLN_ENDPOINT carry exactly the permissions policies grant that identity — nothing more.
Members are users and service accounts only (≤ 200). Bind policies to groups, not individuals.
create_group (name, memberLinks, memberQuery, identityMatcher); edit_group (addMemberLinks / removeMemberLinks — read first with get_resource (kind="group")).memberQuery matches users by tag query; identityMatcher matches identities by a jmespath/javascript expression.add_key_to_service_account (serviceAccountName, keyDescription required, optional groupName) — auto-creates the SA if missing and returns the key once (save it; lost = revoke + remint). create_service_account makes one with no key.update_service_account removeKeys: [NAME] (immediate). delete_resource (kind="service_account") revokes all keys.CPLN_TOKEN secret/env var — the CLI uses it ahead of any profile (and works without one); don't pass --token on the command line (it leaks into logs). Full setup: gitops-cicd.invite_user_to_org (email, optional groupName).get_resource (kind="user") / delete_resource (kind="user") take identifier (id or email); list_resources (kind="user") has an email filter. No create_user/update_user.| Resource | Name | Grants |
|---|---|---|
| Group | superusers | manage on every kind (creator auto-added) |
| Group | viewers | view on every kind |
| Service account | controlplane | platform-internal — off-limits |
| Policies | superusers-KIND / viewers-KIND | origin: builtin, target: all |
superusers (or viewers for read-only) — don't recreate admin policies.superusers).cpln/protected=true can't be deleted until untagged.create_policy builds these; the cpln apply -f manifest is the policy-as-code equivalent for CI/CD.
superusers. Scoped admin — one policy per targetKind with [manage].workload [connect, create, delete, edit, exec, view] + secret [create, delete, edit, reveal, use, view] on a developers group.viewers.workload [create, delete, edit, view] + image [create, pull, view] + secret [use, view] on //serviceaccount/cicd-deployer.spec.identityLink).policy [view] + auditctx [view] on an auditors group.get_cpln_rules (once per mutating session) and read this skill.get_permissions for the kind — confirm permission names.list_resources (kind="policy") / get_resource (kind="policy") (+ get_resource kind="group" / kind="service_account").create_policy / update_policy (+ group / SA / user tools).| Tool | Purpose | Key params |
|---|---|---|
mcp__cpln__get_permissions | Permissions + implications for a kind | kind |
mcp__cpln__list_resources (kind="policy") / get_resource (kind="policy") | List / read policies | name |
mcp__cpln__create_policy | Create a policy | name, targetKind, targetAll/targetLinks/targetQuery, addPermissions, addUsers/addGroups/addServiceAccounts/addIdentities |
mcp__cpln__update_policy | Update metadata, targets, bindings | name, addBindings/removeBindings, targetLinks/removeTargetLinks/targetAll, targetQuery |
mcp__cpln__delete_resource (kind="policy") | Delete a policy (destructive) | name |
mcp__cpln__list_resources (kind="group") / get_resource (kind="group") | List / read groups | name |
mcp__cpln__create_group | Create a group | name, memberLinks, memberQuery, identityMatcher |
mcp__cpln__edit_group | Add/remove members, update meta | name, addMemberLinks, removeMemberLinks |
mcp__cpln__delete_resource (kind="group") | Delete a group (destructive) | name |
mcp__cpln__list_resources (kind="service_account") / get_resource (kind="service_account") | List / read SAs (key metadata only) | name |
mcp__cpln__create_service_account | Create an SA (no key) | name, description |
mcp__cpln__add_key_to_service_account | Mint a key (auto-creates SA) | serviceAccountName, keyDescription, groupName |
mcp__cpln__update_service_account | Update meta / revoke keys | name, removeKeys |
mcp__cpln__delete_resource (kind="service_account") | Delete an SA (revokes all keys) | name |
mcp__cpln__list_resources (kind="user") / get_resource (kind="user") | List / read users | email / identifier |
mcp__cpln__invite_user_to_org | Invite a user by email | email, groupName |
mcp__cpln__delete_resource (kind="user") | Remove a user (destructive) | identifier |
CLI fallback (read the cpln skill first; verify with cpln <resource> --help): policy-as-code in CI/CD (CPLN_TOKEN + cpln apply -f), cpln RESOURCE permissions to list a kind's permissions, cpln policy access-report NAME to audit a policy.
| Need | Skill |
|---|---|
Query language for targetQuery / memberQuery | query-spec |
| Org creation, billing, profiles, SSO | org-management |
| Audit trail of policy / access changes | audit-compliance |
| Full workload secret-access flow | setup-secret |
| Credential-free cloud access (AWS / GCP / Azure / NGS) | setup-cloud-access |
| Workload identities, private-network connectivity | native-networking |
npx claudepluginhub controlplane-com/ai-plugin --plugin cplnBuilds accessible UIs with shadcn/ui components on Radix UI + Tailwind CSS, plus canvas visuals. For React apps (Next.js, Vite, Remix, Astro), design systems, responsive layouts, themes, dark mode, prototypes.