# Tags

> Key/value labels on every resource, inherited down the hierarchy, for cost allocation, ownership and environment separation.

Every resource you provision on ClutchCall — a trunk, a phone number, a
robot, a live input, a VPN network — can carry **tags**: key/value pairs you
define. Tags are how you answer questions the resource ids cannot:

- Which of these belongs to the Mumbai contact centre?
- What does the payments team owe this month?
- What is still on the pilot plan, and what is in production?

Tags are read-only to the platform. Nothing changes behaviour because of a
tag; they exist so that **you** can group, filter and charge back.

## Key/value, not labels

A tag is a key and a value: `env=prod`, `cost_center=4411`, `owner=platform-team`.

A flat label (`mumbai`) cannot be aggregated, because nothing says which
question it answers. `site=mumbai` can be grouped and summed. One value per
key per resource, so "the cost centre of this trunk" always has exactly one
answer.

A tag may have an empty value. `pii` on its own is a marker: the key is
present, and that is the whole statement.

### Key grammar

Keys start with a letter or digit and may contain letters, digits and
`_ . : / = + - @`, up to 128 characters. Values are free text up to 256
characters.

Namespaced keys work, and are a good habit once several teams tag the same
tenant: `finance:cost_center`, `sre:oncall`.

## Inheritance

**A tag set on a parent applies to everything beneath it.** This is the part
that makes tagging survive contact with a real estate of resources.

Tag a trunk, and every phone number on it inherits the tag. Tag a site, and
every fleet, robot and robot topic beneath it inherits. Tag the organization,
and everything in the tenant inherits.

```
organization  env=prod  cost_center=HQ
└── site "Mumbai"                cost_center=MUM-OPS
    └── fleet "warehouse-1"      fleet_tier=gold
        └── robot "lin-0034"     env=staging
            └── topic "/cmd_vel"
```

The robot's effective tags are:

| Key           | Value      | Set on           |
| ------------- | ---------- | ---------------- |
| `env`         | `staging`  | the robot itself |
| `fleet_tier`  | `gold`     | its fleet        |
| `cost_center` | `MUM-OPS`  | its site         |
| `owner`       | *(if set)* | the organization |

`/cmd_vel` inherits all four, one level further down.

**The nearest owner wins.** The robot sets `env=staging`, so that beats the
organization's `env=prod` for the robot and everything under it. To make an
exception, set the key on the resource; to remove the exception, unset it and
the inherited value comes back.

Inheritance is computed, never copied. Retagging a site takes effect on every
resource beneath it at once — there is no fan-out write that can half-apply
and leave the estate inconsistent.

> **NOTE:**
> A resource that is not attached to a parent still inherits from the
> organization. A phone number with no trunk, or a robot not yet assigned to a
> fleet, is not excluded from org-wide tags.

## Where tags show up

- **Inline on the resource.** Every resource's own screen has a tag editor.
  Inherited tags are shown too, dimmed and dashed, naming the ancestor they
  came from — so you never "fix" a value on the wrong row.
- **In lists.** Resource tables show each row's effective tags.
- **On the Tags screen.** Browse any resource type, filter by tag, and tag
  many resources at once.

## Filtering

Filter expressions match against **effective** tags, so a resource that
inherits a value is found by it.

| Expression       | Matches                                       |
| ---------------- | --------------------------------------------- |
| `env=prod`       | resources whose effective `env` is `prod`     |
| `env!=staging`   | everything except those where `env` is `staging` |
| `pii`            | resources carrying the `pii` key at all       |

Several expressions combine with AND.

## Governance

Once spend is grouped by a key, the spelling has to be one thing. A **tag
policy** pins a key down:

- **Allowed values** close a key to a vocabulary. Writing `env=Production`
  when the policy allows `prod | staging | dev` is rejected. This is enforced
  at write time, because a closed vocabulary that only notices afterwards has
  already failed at its job.
- **Required** marks a key that every resource should carry. This is
  **reported, not enforced** — the Compliance view lists what is missing it.
  A governance rule must never be able to block provisioning.

Compliance counts against effective tags, so a resource inheriting the key
from its parent is compliant.

## Managed tags

Some tags are written by the platform rather than by you. They appear
outlined in a warning colour and cannot be edited or removed — the platform
bills on them, so a tenant rewriting one would be rewriting its own invoice.

## Permissions

| Action                     | Who                              |
| -------------------------- | -------------------------------- |
| Read tags                  | any member                       |
| Add, change, remove tags   | owner, admin, developer          |
| Create or remove policies  | owner, admin                     |

Tagging sits on the same rung as changing a trunk or a VDN, not on plain
membership: once chargeback groups by `cost_center`, editing a tag moves
money.

## Over the API and MCP

Every operation is available on the control-plane API under `tags.*`, and
over MCP with the `mcp:tags:read`, `mcp:tags:write` and `mcp:tags:delete`
scopes. Tags have their own scope domain rather than sitting inside another
product's, because they cut across every product — a key minted to read the
fleet should not silently reach the billing estate.

Common calls:

| Operation         | Does                                                     |
| ----------------- | -------------------------------------------------------- |
| `tags.kinds`      | what can be tagged, and what each type inherits from      |
| `tags.list`       | one resource's tags, direct and inherited, with sources   |
| `tags.listBulk`   | the same for a page of resources, in one round trip       |
| `tags.set`        | merge tags onto a resource                                |
| `tags.bulkSet`    | apply a tag set to many resources at once                 |
| `tags.unset`      | remove keys from a resource                               |
| `tags.resources`  | every resource of one type matching a filter              |
| `tags.searchAll`  | the same question across every resource type              |
| `tags.compliance` | what is missing a required tag                            |
