← Control PlaneCONTENT HISTORYWHAT CHANGED · RULE-BASED ANALYSIS
Update to Control Plane
Snapshot Sep 30, 2026 · 23:00 UTC · version 1.0.1
Collection source: not recorded for this historical snapshot.
First saved snapshot
No earlier snapshot is available to establish a change.
Compare saved observations
Download comparison JSONFull technical diff · 0 changed fields
Full snapshot data
{
"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.",
"included_files": [],
"skill_md_contents": "---\nname: tag\ndescription: \"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.\"\n---\n\n# Tags — Labeling, Built-in Behaviors & Targeting\n\nTags 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.\n\n## Why tags pay off\n\n| Capability | What a tag unlocks | Mechanism |\n|:---|:---|:---|\n| Dynamic RBAC | A policy `targetQuery` on `environment=production` grants on every match — **including resources created later** | **access-control** |\n| Dynamic group membership | A group `memberQuery` auto-enrolls users by tag (e.g. SSO provider) | **access-control** |\n| Dynamic placement | A GVC `locationQuery` picks locations by tag (e.g. `cpln/country`) instead of a fixed list | **query-spec** |\n| Fleet inventory & bulk ops | `cpln KIND query --tag tier=frontend` finds every matching resource to act on | **cpln** |\n| Built-in behaviors | Reserved `cpln/*` tags switch on features (protection, sticky sessions, mTLS, …) | see below |\n| Console organization | List columns, custom logos, saved groups, and the Query filter all read tags | see below |\n\nThe 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.\n\n## Setting tags\n\n| Where | How |\n|:---|:---|\n| CLI, dedicated | `cpln KIND tag NAME --tag key=value` (repeatable); `--remove-tag key` drops one |\n| CLI, on create | `cpln KIND create ... --tag key=value` |\n| CLI, generic update | `cpln KIND update NAME --set tags.key=value` (kinds with no `tag` subcommand, e.g. `user`) |\n| MCP | The `create_*` / `update_*` tool for the kind accepts a `tags` object |\n| Manifest | A top-level `tags:` map, then `cpln apply -f FILE` |\n\n```bash\ncpln workload tag my-api --tag environment=production --tag team=payments\ncpln workload tag my-api --remove-tag team\n```\n\n**`=` 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).\n\n## A taxonomy that earns its keep\n\nTags 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:\n\n| Key | Example values | Drives |\n|:---|:---|:---|\n| `environment` | `production`, `staging`, `dev` | RBAC scope, dashboards, promotion |\n| `team` / `owner` | `payments`, `platform` | ownership, on-call routing, group queries |\n| `tier` | `frontend`, `backend`, `data` | fleet ops, firewall / policy scope |\n| `app` | `checkout`, `billing-api` | grouping multi-workload apps |\n| `managed-by` | `terraform`, `console` | drift detection, IaC ownership |\n\nTag 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).\n\n## Built-in tags that change behavior\n\nThe `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.\n\n**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**.\n\n```bash\ncpln workload tag WORKLOAD --tag cpln/protected=true # block delete\ncpln workload tag WORKLOAD --remove-tag cpln/protected # allow delete\n```\n\n**Workload behavior:**\n\n| Tag | Value | Effect |\n|:---|:---|:---|\n| `cpln/timeoutSecondsOverride` | seconds (≤3600) | Raise the request timeout past the 600s ceiling |\n| `cpln/largeDisk` | `true` | Allocate a large ephemeral disk |\n| `cpln/tracingDisabled` | `true` | Turn off distributed tracing for this workload |\n| `cpln/publishNotReadyAddresses` | `true` | Route internal traffic to replicas before they pass readiness |\n| `cpln/discoverCrossGvcReplicas` | `true` | Discover replicas in other GVCs over mTLS |\n| `cpln/bypassProxyOutbound` | `true` | Skip the service-mesh proxy on outbound traffic |\n| `cpln/disableServiceMeshInboundPort` / `...OutboundPort` | port | Exclude one port from the service mesh |\n| `cpln/externalAuth*` | family | Route every request through an external authorization service (`...Address` required; see **workload-security**) |\n| `cpln/rateLimit*` | family | Enforce limits via an external rate-limit service (`...Address` required; see **cdn-rate-limiting**) |\n\nBYOK / Direct-LB workloads add `cpln/disableServiceMesh`, `cpln/disableServiceMeshOutboundCIDR`, and `cpln/k8sClusterRole`.\n\n**GVC — sticky sessions** (apply to every workload in the GVC): `cpln/sessionCookie` (cookie name) plus `cpln/sessionDuration` (a Go duration, e.g. `30m`).\n\n**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.\n\n## Auto-populated tags you can target\n\nSome tags are set *by the platform* and are read-only — their value is that you can **query** them:\n\n| Tag | On | Use |\n|:---|:---|:---|\n| `cpln/city` / `cpln/country` / `cpln/continent` | location | Select locations by geography in a GVC `locationQuery` |\n| `firebase/sign_in_provider` | user | Auto-enroll users by SSO provider in a group `memberQuery` |\n| `syncer.cpln.io/source` / `syncer.cpln.io/lastError` | secret | Trace External-Secret-Syncer ownership and its last sync error |\n| `cpln/release` | helm-managed resources | Identify what `cpln helm` created |\n\n## In the Console\n\n| Tag | UI behavior |\n|:---|:---|\n| `cpln/protected` | Toggled by the lock switch; blocks the Delete action |\n| Any tag whose value is a URL (`https://`, `http://`, `ws://`, `wss://`) | Rendered as a clickable link in the resource's Tag Links |\n| `cpln/console.tagColumns` (org) | Surfaces chosen tags as list columns, e.g. `workload=env,team;gvc=region` |\n| `cpln/custom-logo` / `cpln/custom-logo-dark` (org) | Custom org logo in the sidebar |\n| `resourceGroup::KEY[::VALUE]` (org) | Saved, pinnable resource groups in the sidebar nav |\n\nThe **Query** button on any list maps directly to the query spec (match All / Any / None) — see **query-spec**.\n\n## Worked examples\n\n**Production RBAC by tag (retroactive).** Tag the workloads, then grant once:\n\n```bash\ncpln workload tag checkout payments-api --tag environment=production\ncpln policy create --name prod-operators --target-kind workload \\\n --query-tag environment=production # then add a binding — see access-control\n```\n\nNew workloads tagged `environment=production` fall under the policy automatically.\n\n**Fleet query.** Find every frontend workload to audit or roll: `cpln workload query --tag tier=frontend`.\n\n## Gotchas\n\n| Trap | Detail |\n|:---|:---|\n| Booleans match as strings | A tag stored `true` is the string `\"true\"` — query `value: \"true\"`, not `true`, or it matches nothing |\n| Set-time type matters | `--tag n=5` stores a number, `--tag n:5` a string; query the same type you stored |\n| No inheritance | A GVC's tags do **not** flow to its workloads — tag each resource you want matched |\n| Mutable on immutable resources | Name and type are fixed, but tags are always editable — even on the org |\n| Protected blocks delete | `cpln/protected=true` makes deletes fail until you remove the tag |\n| Removal | `--remove-tag key` (or set the value `null`); an empty value is kept as a marker, not deleted |\n| Case-sensitive | Keys and values are exact-match; `Prod` is not `prod` |\n\n## Verify\n\n- `cpln KIND get NAME -o yaml` — confirm the `tags:` block.\n- `cpln KIND query --tag key=value` — confirm the resource is selected by the tag a policy or group will use.\n\n## Related skills\n\n- **query-spec** — the query language: operators, match modes, and the three fields tags feed (`targetQuery`, `memberQuery`, `locationQuery`).\n- **access-control** — policy `targetQuery` and group `memberQuery` in context.\n- **workload-security** / **cdn-rate-limiting** — the `cpln/externalAuth*` and `cpln/rateLimit*` tag families.\n- **domain** — `cpln/clientCertificateValidation`, `cpln/skipDNSCheck`, `cpln/wildcard`.\n- **cpln** — the full CLI resource-command map.\n\n## Documentation\n\n- [Tags](https://docs.controlplane.com/core/misc.md) · [Query](https://docs.controlplane.com/core/query.md) · [Resource Protection](https://docs.controlplane.com/guides/resource-protection.md) · [Workload special tags](https://docs.controlplane.com/reference/workload/general.md)\n"
}SHA-256: 73b3f3e54ef2463ac3d94f74b3bf8f717dea5b2fbccbe6ea43e1ab8a2435d759