/**
* Return Cloudflare package discovery metadata: exports, secrets, and usage notes.
*/
export default async function describeCloudflareToolkit() {
return {
packageId: 'cloudflare',
exports: [
'overview',
'accounts',
'api-v4',
'analytics',
'docs',
'observability-logs',
'rulesets',
'verify',
],
helpers: [
{
export: 'accounts',
purpose:
'List Cloudflare API token aliases (default, kody, pages) and when to use each.',
mutating: false,
requiredSecrets: [],
},
{
export: 'verify',
purpose:
'Verify a Cloudflare API token using the correct endpoint for user-scoped vs account-scoped tokens. Never treat /user/tokens/verify 401 alone as “token invalid.”',
mutating: false,
requiredSecrets: [
'cloudflareApiToken',
'cloudflareApiTokenKodyAccount',
'cloudflarePagesApiToken',
],
},
{
export: 'api-v4',
purpose:
'Call Cloudflare API v4 endpoints under /client/v4/ with an optional account alias or apiTokenSecret.',
mutating: true,
requiredSecrets: [
'cloudflareApiToken',
'cloudflareApiTokenKodyAccount',
'cloudflarePagesApiToken',
],
},
{
export: 'analytics',
purpose:
'Query Cloudflare GraphQL analytics for zone traffic summaries, request paths, statuses, user agents, and outage forensics.',
mutating: false,
requiredSecrets: [
'cloudflareApiToken',
'cloudflareApiTokenKodyAccount',
'cloudflarePagesApiToken',
],
},
{
export: 'docs',
purpose: 'Fetch allowlisted Cloudflare developer docs pages as markdown-oriented text.',
mutating: false,
requiredSecrets: [],
},
{
export: 'observability-logs',
purpose:
'Search Cloudflare Log Explorer datasets with structured filters or custom SQL, with an analytics fallback for missing entitlement.',
mutating: false,
requiredSecrets: [
'cloudflareApiToken',
'cloudflareApiTokenKodyAccount',
'cloudflarePagesApiToken',
],
},
{
export: 'rulesets',
purpose:
'Preview or apply Cloudflare Rulesets/WAF custom rules, including cheap bogus-route blocks before traffic reaches origin.',
mutating: true,
requiredSecrets: [
'cloudflareApiToken',
'cloudflareApiTokenKodyAccount',
'cloudflarePagesApiToken',
],
},
],
notes: [
'Authenticate with account: "default" | "kody" | "pages" (default token: cloudflareApiToken), or apiTokenSecret for an unlisted secret name.',
'Never pass a raw API token string; always reference a Kody secret by alias or name.',
'Approve api.cloudflare.com for each Cloudflare token secret before using authenticated exports.',
'Token verification: use export verify (or /accounts/{account_id}/tokens/verify for account-scoped tokens). /user/tokens/verify often 401s for valid account tokens — that is not proof the secret is broken.',
'Permission checks after verify: 403 means lacks permission; 400/404 on a mutating call against a bad/missing target means the token is authorized for that operation.',
'Use analytics for zone HTTP request aggregates, especially when Log Explorer SQL is unavailable or returns missing entitlement.',
'Use rulesets in dry-run mode first to preview WAF/custom-rule changes; pass apply: true only after review.',
'Use observability-logs for Workers trace events, HTTP request forensics, Access requests, Ray IDs, errors, and slow-request investigations.',
'Use docs for current Cloudflare documentation under allowlisted product prefixes.',
],
}
}