{
  "schema": "aaes/capability-pack/1",
  "provider": "cloudflare",
  "version": "1.0.0",
  "description": "Cloudflare API v4: list zones and DNS records, create, edit and delete DNS records, and purge a zone's cache.",
  "notes": "The endpoint host 'api.cloudflare.invalid' is a reserved non-production placeholder (an RFC 2606 reserved TLD): substitute the real Cloudflare API authority (api.cloudflare.com, or the customer's API host for a partner/custom deployment) before enabling, in every endpoint, in the resource locators and in every egress allowlist entry. The allowlist matches exactly, so endpoints and allowlist must be substituted together, and substitution is a required deployment step. ZONE_ID and DNS_RECORD_ID in the endpoint paths are placeholders the deployment binds to concrete identifiers before enabling.\n\nEvery read endpoint here is a collection read: single-record reads (GET one zone, GET one DNS record) are not registered.\n\nApproval classification: DNS record creation registers as create and deploy, and edit as update and deploy, at the minimum R3 tier: creating or editing A, AAAA, CNAME or MX records provisions or reroutes production traffic routing — a deploy-equivalent effect on live infrastructure, and deploy is one of the designated actions requiring human approval — so it requires that action’s minimum tier; only the partial-edit PATCH is registered, not the PUT overwrite.\n\nDNS record deletion registers as delete at the minimum R3 tier: removing the record that resolves a name can take the service behind it offline — the outage is neither immediate nor guaranteed, because resolver caches and unexpired TTLs can keep stale answers alive until they lapse — and delete is one of the designated actions requiring human approval.\n\nCache purge registers as delete at the minimum R3 tier, judged by effect: the endpoint's caller-controlled body accepts purge_everything=true, which according to the reviewed purge reference removes all files from the zone's cache in every Cloudflare data center and forces all subsequent requests back to the origin — a broad-impact burst of origin load — so an unrestricted body defeats any lower tier, and purge is treated as an irreversible-action equivalent.\n\nExcluded operations: zone creation and zone deletion (DELETE /zones/{zone_id} removes the whole zone and every record and setting in it), the DNS record PUT overwrite, zone settings changes (SSL mode, security level, TLS minimum), WAF and firewall rules, Page Rules and cache rules, Workers scripts and routes, Load Balancers, API token creation/verification/roll and user or account membership management, registrar operations, and every other Cloudflare API.",
  "credential": {
    "secret_ref_id": "secret-ref-cloudflare-api-token",
    "custody": "customer_vault",
    "inject": "header",
    "inject_name": "Authorization",
    "note": "A Cloudflare API token for the customer's own account, held in the client's own secret manager. The stored material must be the complete Authorization header value: the scheme 'Bearer', one separating space, then the token — 'Bearer <token>'.\n\nIssuance is external: a user creates the token in the Cloudflare dashboard (My Profile > API Tokens), choosing the token's permission groups and the zones and accounts it covers; the token value is shown once at creation, so capture it into the vault at that moment.\n\nLeast privilege: grant only the permissions the registered capabilities need — Zone.Zone Read for the zone collection read, Zone.DNS Read/Edit on the bound zone(s) for the DNS capabilities (according to the reviewed DNS records list reference, the endpoint accepts DNS Read or DNS Write), and Cache Purge only where the purge capability is enabled — and scope the token to the specific zones the deployment binds, not All zones.\n\nExpiry and revocation: a token may be created with an optional TTL, after which it fails closed, but a token without one does not expire on its own; revocation is rolling or deleting the token in the dashboard — according to the reviewed roll-token reference (PUT /client/v4/user/tokens/{token_id}/value, requiring the API Tokens Write permission) and Cloudflare's roll-token how-to, rolling generates a new secret and invalidates the previous token while keeping its access and permissions, and the retrieved pages document no grace period, so treat the old value as dead once the roll returns; deleting a token is immediate — and disabling issuance, or the creating user losing permission to create tokens, does not invalidate tokens already issued: each issued token must be rolled or deleted individually.\n\nRotation therefore sits with an external deployment process: the executor injects the stored value verbatim and performs no token lifecycle of its own. Alternative two-header authentication: Cloudflare also still accepts the legacy Global API Key scheme, which authenticates with TWO headers — X-Auth-Email (the account email) plus X-Auth-Key (the global key); according to the reviewed get-started reference the Global API Key is the previous scheme and is less secure than API tokens, and this pack registers the single Bearer header only — a deployment that insists on the legacy key must wire both headers itself and accept that the global key is unscoped and grants everything the account can do.\n\nExecutor hygiene: the value must live only in executor memory for the lifetime of a call, must never be written to logs, traces or diagnostics, and must not appear in crash dumps; a deployment that cannot meet that bar must not enable the pack."
  },
  "capabilities": [
    {
      "capability_id": "cloudflare.zones.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "api.cloudflare.invalid"
      ],
      "endpoint": "https://api.cloudflare.invalid/client/v4/zones",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-cloudflare-api-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "cloudflare-account",
      "description": "List the zones in the account: domain names, plan, status and name servers, which reveal the customer's public-facing estate.\n\nThe registered path covers the collection read only — single-zone reads (GET /zones/{zone_id}) and zone creation or deletion are not registered by this pack.\n\nThe host is a reserved placeholder: substitute the real API authority before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "cloudflare.dns_records.read",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R0",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "api.cloudflare.invalid"
      ],
      "endpoint": "https://api.cloudflare.invalid/client/v4/zones/ZONE_ID/dns_records",
      "method": "GET",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-cloudflare-api-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "read"
      ],
      "resource_id": "cloudflare-zone",
      "description": "List, search, sort and filter one zone's DNS records: names, types, contents, TTLs and proxy state, which reveal internal infrastructure topology; according to the reviewed reference the endpoint accepts the DNS Read or DNS Write permission and takes its filters as query string parameters.\n\nThe registered path covers the collection read only — single-record reads (GET /zones/{zone_id}/dns_records/{dns_record_id}) are not registered. ZONE_ID is a placeholder the deployment binds before enabling.",
      "requires_review": true
    },
    {
      "capability_id": "cloudflare.dns_records.create",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "api.cloudflare.invalid"
      ],
      "endpoint": "https://api.cloudflare.invalid/client/v4/zones/ZONE_ID/dns_records",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-cloudflare-api-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "create",
        "deploy"
      ],
      "resource_id": "cloudflare-zone",
      "description": "Create one DNS record in one zone with the caller-supplied type, name, content, TTL and proxy state in the request body. Registered as create and deploy at the minimum R3 tier: according to the reviewed create reference the body selects the record's type, name, content and proxy state, and a new A, AAAA, CNAME or MX record starts answering production DNS queries for its name within moments — provisioning live traffic routing, a deploy-equivalent effect, and deploy is one of the designated actions requiring human approval.\n\nThis registration does not restrict which record type or content the body may carry; that choice lives with the token's DNS Write permission and the deployment's review. ZONE_ID is a placeholder the deployment binds before enabling.\n\nOn supported AAES-mediated execution paths, the declared irreversible actions require an authorized person’s approval. Observation-only and bypass calls cannot be stopped by this control.",
      "requires_review": true
    },
    {
      "capability_id": "cloudflare.dns_records.update",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "api.cloudflare.invalid"
      ],
      "endpoint": "https://api.cloudflare.invalid/client/v4/zones/ZONE_ID/dns_records/DNS_RECORD_ID",
      "method": "PATCH",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-cloudflare-api-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "update",
        "deploy"
      ],
      "resource_id": "cloudflare-zone",
      "description": "Partially edit one DNS record (the PATCH overwrite-partial form; the PUT full-overwrite form is deliberately not registered). Registered as update and deploy at the minimum R3 tier: according to the reviewed edit reference the caller-controlled body can change the record's content, type-relevant fields and the proxied flag, and changing an A, AAAA, CNAME or MX record's content repoints production traffic for that name — a deploy-equivalent reconfiguration of live traffic routing, and deploy is one of the designated actions requiring human approval.\n\nThis registration does not restrict which fields the body may change. ZONE_ID and DNS_RECORD_ID are placeholders the deployment binds before enabling.\n\nOn supported AAES-mediated execution paths, the declared irreversible actions require an authorized person’s approval. Observation-only and bypass calls cannot be stopped by this control.",
      "requires_review": true
    },
    {
      "capability_id": "cloudflare.dns_records.delete",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "api.cloudflare.invalid"
      ],
      "endpoint": "https://api.cloudflare.invalid/client/v4/zones/ZONE_ID/dns_records/DNS_RECORD_ID",
      "method": "DELETE",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-cloudflare-api-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "delete"
      ],
      "resource_id": "cloudflare-zone",
      "description": "Delete one DNS record. Delete is one of the designated actions requiring human approval at the minimum R3 tier, and the operational effect is name-resolution removal: once the record is gone the name stops being answered with that record's content — subject to resolver caching of prior answers and to other records at the same name, so the timing and extent of any client-visible outage vary and are not guaranteed by this registration; re-creating the record later is a new record with a new id, not an undo of this call. ZONE_ID and DNS_RECORD_ID are placeholders the deployment binds before enabling.\n\nOn supported AAES-mediated execution paths, the declared irreversible actions require an authorized person’s approval. Observation-only and bypass calls cannot be stopped by this control.",
      "requires_review": true
    },
    {
      "capability_id": "cloudflare.cache.purge",
      "version": "1.0.0",
      "kind": "tool",
      "risk_tier": "R3",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN",
      "data_class": "internal",
      "egress_allowlist": [
        "api.cloudflare.invalid"
      ],
      "endpoint": "https://api.cloudflare.invalid/client/v4/zones/ZONE_ID/purge_cache",
      "method": "POST",
      "connector": "http",
      "custody": "customer_vault",
      "secret_ref_id": "secret-ref-cloudflare-api-token",
      "inject": "header",
      "inject_name": "Authorization",
      "actions": [
        "delete"
      ],
      "resource_id": "cloudflare-zone",
      "description": "Purge cached content for one zone; requires the Cache Purge permission. Judged by effect: the caller-controlled body accepts purge_everything=true, which according to the reviewed purge reference removes all files from the zone's cache in every Cloudflare data center and sends every subsequent request back to the origin until the cache refills — a broad-impact burst of origin load that cannot be un-purged — so an unrestricted body defeats any lower tier, and the capability registers as delete at the minimum R3 tier with purge treated as an irreversible-action equivalent.\n\nThe same body also accepts granular purges by files, tags, hosts or prefixes; this registration does not restrict which form the body carries. ZONE_ID is a placeholder the deployment binds before enabling.\n\nOn supported AAES-mediated execution paths, the declared irreversible actions require an authorized person’s approval. Observation-only and bypass calls cannot be stopped by this control.",
      "requires_review": true
    }
  ],
  "resources": [
    {
      "resource_id": "cloudflare-account",
      "kind": "api",
      "locator": "https://api.cloudflare.invalid/client/v4/zones",
      "data_class": "internal",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    },
    {
      "resource_id": "cloudflare-zone",
      "kind": "site",
      "locator": "https://api.cloudflare.invalid/client/v4/zones/ZONE_ID",
      "data_class": "internal",
      "owner": "REPLACE-WITH-ACCOUNTABLE-HUMAN"
    }
  ],
  "review": {
    "state": "library",
    "date": "2026-09-22",
    "sources": [
      "https://developers.cloudflare.com/fundamentals/api/get-started/ (retrieved 2026-09-21)",
      "https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/list/ (retrieved 2026-09-21)",
      "https://developers.cloudflare.com/api/resources/cache/methods/purge/ (retrieved 2026-09-21)",
      "https://developers.cloudflare.com/cache/how-to/purge-cache/purge-everything/ (retrieved 2026-09-21)",
      "https://developers.cloudflare.com/api/resources/zones/methods/list/ (retrieved 2026-09-21)",
      "https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/create/ (retrieved 2026-09-21)",
      "https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/edit/ (retrieved 2026-09-21)",
      "https://developers.cloudflare.com/api/resources/dns/subresources/records/methods/delete/ (retrieved 2026-09-21)",
      "https://developers.cloudflare.com/fundamentals/api/get-started/create-token/ (retrieved 2026-09-21)",
      "https://developers.cloudflare.com/fundamentals/api/how-to/roll-token/ (retrieved 2026-09-21)",
      "https://developers.cloudflare.com/api/resources/user/subresources/tokens/subresources/value/methods/update/ (retrieved 2026-09-21)"
    ],
    "reviewer_id": "aaes-eng"
  }
}
