Skip to content
Back to skills

Tag

ASecurity

Resource tags on Control Plane — labels that organize resources, trigger built-in cpln/ behaviors, and drive targeting. Use when the user asks about tags, labels, tagging, naming conventions, or resource protection.

  • 10 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added August 31, 2026
devopsgobashterraformapifrontendbackendsecurity

Works with

  • cli
  • api
  • mcp

Security analysis

A100/100

Scanned October 1, 2026

npx -y skills add controlplane-com/ai-plugin --skill tag --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Tag?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Tag
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/controlplane-com-tag/badge)](https://www.skillsdirectory.com/skills/controlplane-com-tag)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: tag
description: "Resource tags on Control Plane — labels that organize resources, trigger built-in cpln/ behaviors, and drive targeting. Use when the user asks about tags, labels, tagging, naming conventions, or resource protection."
---

# Tags — Labeling, Built-in Behaviors & Targeting

Tags are **key-value labels** on almost every Control Plane resource (workload, GVC, identity, secret, policy, group, domain, image, volumeset, agent, ipset, org, mk8s, user, service account). They live in a top-level `tags:` map. A tag is three things at once: **metadata** for humans, a **selector** that policies/groups/GVCs/queries target, and — under the reserved `cpln/` namespace — a **switch** that turns on platform behavior the spec doesn't yet expose as a field.

## Why tags pay off

| Capability | What a tag unlocks | Mechanism |
|:---|:---|:---|
| Dynamic RBAC | A policy `targetQuery` on `environment=production` grants on every match — **including resources created later** | **access-control** |
| Dynamic group membership | A group `memberQuery` auto-enrolls users by tag (e.g. SSO provider) | **access-control** |
| Dynamic placement | A GVC `locationQuery` picks locations by tag (e.g. `cpln/country`) instead of a fixed list | **query-spec** |
| Fleet inventory & bulk ops | `cpln KIND query --tag tier=frontend` finds every matching resource to act on | **cpln** |
| Built-in behaviors | Reserved `cpln/*` tags switch on features (protection, sticky sessions, mTLS, …) | see below |
| Console organization | List columns, custom logos, saved groups, and the Query filter all read tags | see below |

The payoff is **retroactive and self-maintaining**: tag a new workload `environment=production` and every prod policy, group, and dashboard that queries that tag covers it automatically — no rule edits.

## Setting tags

| Where | How |
|:---|:---|
| CLI, dedicated | `cpln KIND tag NAME --tag key=value` (repeatable); `--remove-tag key` drops one |
| CLI, on create | `cpln KIND create ... --tag key=value` |
| CLI, generic update | `cpln KIND update NAME --set tags.key=value` (kinds with no `tag` subcommand, e.g. `user`) |
| MCP | The `mcp__cpln__create_*` / `update_*` tool for the kind accepts a `tags` object |
| Manifest | A top-level `tags:` map, then `cpln apply -f FILE` |

```bash
cpln workload tag my-api --tag environment=production --tag team=payments
cpln workload tag my-api --remove-tag team
```

**`=` guesses the type, `:` forces a string.** `--tag replicas=3` stores the number `3`; `--tag replicas:3` stores the string `"3"`; an empty value (`--tag key=`) stores `null`. This matters because queries are type-sensitive (see Gotchas).

## A taxonomy that earns its keep

Tags become leverage only when keys and values are **uniform** — a query for `environment=production` silently misses anything tagged `env=prod` or `Environment=Production`. Agree on a small, lowercase vocabulary up front:

| Key | Example values | Drives |
|:---|:---|:---|
| `environment` | `production`, `staging`, `dev` | RBAC scope, dashboards, promotion |
| `team` / `owner` | `payments`, `platform` | ownership, on-call routing, group queries |
| `tier` | `frontend`, `backend`, `data` | fleet ops, firewall / policy scope |
| `app` | `checkout`, `billing-api` | grouping multi-workload apps |
| `managed-by` | `terraform`, `console` | drift detection, IaC ownership |

Tag for the keys you will actually query; a tag nobody selects on is just decoration. Stay out of the `cpln/`, `syncer.cpln.io/`, and `firebase/` prefixes — those are platform-defined (below).

## Built-in tags that change behavior

The `cpln/` namespace is reserved: don't invent your own keys under it, but **do** set the documented tags below to switch on behavior. They are the escape hatch for options not yet first-class fields.

**Any resource — deletion guard.** `cpln/protected=true` makes the platform refuse to delete the resource (any kind); remove the tag to delete. The MCP `delete_resource` and `cpln KIND delete` both fail until it's cleared. In the Console it's the lock switch next to **Actions**.

```bash
cpln workload tag WORKLOAD --tag cpln/protected=true     # block delete
cpln workload tag WORKLOAD --remove-tag cpln/protected   # allow delete
```

**Workload behavior:**

| Tag | Value | Effect |
|:---|:---|:---|
| `cpln/timeoutSecondsOverride` | seconds (≤3600) | Raise the request timeout past the 600s ceiling |
| `cpln/largeDisk` | `true` | Allocate a large ephemeral disk |
| `cpln/tracingDisabled` | `true` | Turn off distributed tracing for this workload |
| `cpln/publishNotReadyAddresses` | `true` | Route internal traffic to replicas before they pass readiness |
| `cpln/discoverCrossGvcReplicas` | `true` | Discover replicas in other GVCs over mTLS |
| `cpln/bypassProxyOutbound` | `true` | Skip the service-mesh proxy on outbound traffic |
| `cpln/disableServiceMeshInboundPort` / `...OutboundPort` | port | Exclude one port from the service mesh |
| `cpln/externalAuth*` | family | Route every request through an external authorization service (`...Address` required; see **workload-security**) |
| `cpln/rateLimit*` | family | Enforce limits via an external rate-limit service (`...Address` required; see **cdn-rate-limiting**) |

BYOK / Direct-LB workloads add `cpln/disableServiceMesh`, `cpln/disableServiceMeshOutboundCIDR`, and `cpln/k8sClusterRole`.

**GVC — sticky sessions** (apply to every workload in the GVC): `cpln/sessionCookie` (cookie name) plus `cpln/sessionDuration` (a Go duration, e.g. `30m`).

**Domain:** `cpln/clientCertificateValidation=enabled` requires a valid client cert, i.e. mTLS (**domain**); `cpln/skipDNSCheck=true` skips DNS validation; `cpln/wildcard=true` enables a wildcard certificate.

## Auto-populated tags you can target

Some tags are set *by the platform* and are read-only — their value is that you can **query** them:

| Tag | On | Use |
|:---|:---|:---|
| `cpln/city` / `cpln/country` / `cpln/continent` | location | Select locations by geography in a GVC `locationQuery` |
| `firebase/sign_in_provider` | user | Auto-enroll users by SSO provider in a group `memberQuery` |
| `syncer.cpln.io/source` / `syncer.cpln.io/lastError` | secret | Trace External-Secret-Syncer ownership and its last sync error |
| `cpln/release` | helm-managed resources | Identify what `cpln helm` created |

## In the Console

| Tag | UI behavior |
|:---|:---|
| `cpln/protected` | Toggled by the lock switch; blocks the Delete action |
| Any tag whose value is a URL (`https://`, `http://`, `ws://`, `wss://`) | Rendered as a clickable link in the resource's Tag Links |
| `cpln/console.tagColumns` (org) | Surfaces chosen tags as list columns, e.g. `workload=env,team;gvc=region` |
| `cpln/custom-logo` / `cpln/custom-logo-dark` (org) | Custom org logo in the sidebar |
| `resourceGroup::KEY[::VALUE]` (org) | Saved, pinnable resource groups in the sidebar nav |

The **Query** button on any list maps directly to the query spec (match All / Any / None) — see **query-spec**.

## Worked examples

**Production RBAC by tag (retroactive).** Tag the workloads, then grant once:

```bash
cpln workload tag checkout payments-api --tag environment=production
cpln policy create --name prod-operators --target-kind workload \
  --query-tag environment=production          # then add a binding — see access-control
```

New workloads tagged `environment=production` fall under the policy automatically.

**Fleet query.** Find every frontend workload to audit or roll: `cpln workload query --tag tier=frontend`.

## Gotchas

| Trap | Detail |
|:---|:---|
| Booleans match as strings | A tag stored `true` is the string `"true"` — query `value: "true"`, not `true`, or it matches nothing |
| Set-time type matters | `--tag n=5` stores a number, `--tag n:5` a string; query the same type you stored |
| No inheritance | A GVC's tags do **not** flow to its workloads — tag each resource you want matched |
| Mutable on immutable resources | Name and type are fixed, but tags are always editable — even on the org |
| Protected blocks delete | `cpln/protected=true` makes deletes fail until you remove the tag |
| Removal | `--remove-tag key` (or set the value `null`); an empty value is kept as a marker, not deleted |
| Case-sensitive | Keys and values are exact-match; `Prod` is not `prod` |

## Verify

- `cpln KIND get NAME -o yaml` — confirm the `tags:` block.
- `cpln KIND query --tag key=value` — confirm the resource is selected by the tag a policy or group will use.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.