pi-cloudflare 0.6.4 → 0.6.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-cloudflare",
3
- "version": "0.6.4",
3
+ "version": "0.6.6",
4
4
  "description": "Cloudflare Agent Plugin and native Pi extension providing official skills and cf_-prefixed MCP tools.",
5
5
  "keywords": [
6
6
  "agent-plugin",
package/plugin.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
3
3
  "name": "pi-cloudflare",
4
- "version": "0.6.4",
4
+ "version": "0.6.6",
5
5
  "description": "Cloudflare skills and cf_-prefixed MCP tools, with a native Pi adapter and an Agent Plugins 1.0 portable runtime.",
6
6
  "author": {
7
7
  "name": "0xPlayerOne",
@@ -48,6 +48,38 @@ Same-origin `/api/v4/*` in page context carries the session:
48
48
  - `POST /api/v4/user/tokens` with `{name, policies}` → capture `result.value` from **that** response.
49
49
  - Verify with the token itself (`GET /user`, one scoped read per new group — full matrix below), hand the secret over once, destroy every local copy (`chmod 600` while it lives, then delete). Rollback is dashboard roll, not delete + recreate (there is no public roll route — see `skills/cloudflare-token-roll/SKILL.md`).
50
50
 
51
+ ## Bulk scope changes: PUT, and the write-path trap
52
+
53
+ `PUT /api/v4/user/tokens/:id` replaces the whole policy set, so build the new
54
+ `{name, policies}` by **merging** current groups with the additions and diffing
55
+ the read-back afterward. The secret survives, so there is no re-wiring.
56
+
57
+ Two traps make this fail in ways that look like a permissions bug:
58
+
59
+ - **Writes are WAF-challenged without the dashboard's own headers.** `PUT` /
60
+ `POST` from page context returns `403` with `content-type: text/html` and a
61
+ "Just a moment..." body, while `GET` on the same URL returns `200`. Add the
62
+ first-party write headers to any mutating call:
63
+
64
+ ```js
65
+ headers: {
66
+ 'Content-Type': 'application/json',
67
+ Origin: 'https://dash.cloudflare.com',
68
+ Referer: 'https://dash.cloudflare.com/profile/api-tokens',
69
+ 'X-Cross-Site-Security': 'dash',
70
+ }
71
+ ```
72
+
73
+ A `403` that is HTML is the challenge; a `403` that is JSON is a real scope
74
+ error. Check `content-type` before diagnosing.
75
+
76
+ - **A successful PUT takes ~2–3 minutes to propagate.** Immediately after
77
+ updating, roughly a third of the newly granted endpoints still answer
78
+ `403 Authentication error`; all of them flipped to `200` within ~2 minutes
79
+ (measured 2026-09-11 across 13 endpoints, four probes over 135s, stable from
80
+ the first probe onward). Do not re-PUT or conclude a group mapping is wrong
81
+ during that window — sleep, then re-probe.
82
+
51
83
  ## React-select mechanics (dash dropdowns)
52
84
 
53
85
  - Menus open on control mousedown, not input click; options may expose no a11y role until open — snapshot after opening, act on fresh uids only.
@@ -59,7 +91,13 @@ Same-origin `/api/v4/*` in page context carries the session:
59
91
  - Run `CLOUDFLARE_API_TOKEN=<paste-once> node scripts/verify-api-token.mjs` (identity, token status, Workers scripts read).
60
92
  - Then one live read per relied-upon group, all passing on the reference token: `GET /user`, `GET /accounts`, Workers scripts list, KV namespaces list, R2 buckets list, D1 databases list, Hyperdrive configs list, zones list, zone routes list, account read, memberships list, audit-logs list (proves Logs Read), `GET /accounts/{id}/workers/observability/usage` with millisecond-epoch `from`/`to` (proves Workers Observability Read — live-proven 2026-09-10 on both accounts).
61
93
  - Zone Cache Rules Edit (only when granted): `GET /zones/:id/rulesets/phases/http_request_cache_settings/entrypoint` — expect `200` with the entrypoint, or `10003` (no entrypoint yet) which also proves the group is present. Live-proven 2026-09-09: created zone rule `landing-marketplace-edge-300s` (`http.host eq "pinkbinder.shop" and starts_with(http.request.uri.path, "/api/marketplace")`, edge+browser TTL 300s override-origin) after adding this group.
62
- - Known non-gaps, do not chase: `GET /user/tokens/:id` returns `9109` by design (tokens cannot manage tokens); zone-analytics `10000` without the Zone Analytics group is correct least privilege (observability rollups go through the separate obs MCP, not this token); Workers Tail needs a websocket (group presence + dashboard UI is the check); Logpush jobs `401` (no Logpush group exposed to API tokens dashboard only, verified 2026-09-10).
94
+ - Zone Response Compression Edit (live-proven 2026-09-11): `PUT /zones/:id/rulesets/phases/http_response_compression/entrypoint` succeeds; a `403 request is not authorized` means the group is absent. Worth having because Cloudflare's built-in compression omits `model/gltf-binary`, so GLB payloads otherwise ship raw forced brotli measured 44% off (21.35 MB 11.77 MB across a scene catalogue). Verify on a real hostname: zone rules do **not** apply to `*.workers.dev`, which bypasses the zone.
95
+ - Zone Transform Rules Edit (live-proven missing 2026-09-11): `PUT /zones/:id/rulesets/phases/http_response_headers_transform/entrypoint`. This is the **only** way to change `Cache-Control` on Workers Static Assets responses — `_headers` files are ignored and zone Cache Rules do not apply. See `docs/workers-static-assets-caching.md`. The same group gates single redirects (`http_request_dynamic_redirect`).
96
+ - Zone DNS Edit (live-proven missing 2026-09-11): `GET /zones/:id/dns_records` — `403 Authentication error` means absent. Needed for apex/subdomain cutovers; note that attaching a Workers **custom domain** does *not* require it (that works through `wrangler deploy` with a `custom_domain` route), so a missing DNS group is not a blocker for that specific move.
97
+ - Full audit set (live-proven 2026-09-11, one bulk PUT, all 137 groups verified stored and exercised): the merge-safe probe set is one read per new domain — `GET /zones/:id/settings` (Zone Settings), `/zones/:id/pagerules` (Page Rules), `/zones/:id/snippets` (Snippets), `/zones/:id/healthchecks` (Health Checks), `/zones/:id/waiting_rooms`, `/zones/:id/bot_management`, `/zones/:id/page_shield/scripts`, `/accounts/:id/rulesets` (Account Rulesets), `/accounts/:id/security-center/insights` (Security Center Insights), `/accounts/:id/dns_settings`, `/accounts/:id/images/v1`, `/accounts/:id/ai/models/search`, `/accounts/:id/vectorize/v2/indexes`, `/accounts/:id/pages/projects`, `/accounts/:id/access/groups`, `/accounts/:id/gateway`, `/accounts/:id/devices/posture`, `/accounts/:id/logpush/jobs`. **`Logs Write` unlocks `GET /accounts/:id/logpush/jobs`** — the earlier "Logpush 401s, dashboard only" note in this file was wrong; it was a missing group, not a missing surface.
98
+ - Disambiguate plan gates from scope gaps by replaying the failing call with the **full dashboard session** (no token). If the session also fails, it is entitlement, not scope. Confirmed entitlement-only surfaces (2026-09-11): Containers (`401`, Workers Paid), Workers for Platforms dispatch (`403 10121`), Spectrum (`403 10007`), Argo Smart Routing (`401 1015`), SSL for SaaS custom hostnames (`403 1404`, no quota), Stream (`403`). Also sunset for everyone: the Zone Analytics REST API (`404 1015` — use GraphQL).
99
+ - Operator entitlements are plan-gated and fail with an explicit message, not a silent no-match: `matches` (regex) needs a Business or WAF Advanced plan (`not entitled: the use of operator Matches is not allowed`), while `in`, `eq`, `starts_with`, `extension`, `len`, and `substring` work on Free. Prefer those when authoring rules for a free zone.
100
+ - Known non-gaps, do not chase: `GET /user/tokens/:id` returns `9109` by design (tokens cannot manage tokens); zone-analytics `10000` without the Zone Analytics group is correct least privilege (observability rollups go through the separate obs MCP, not this token); Workers Tail needs a websocket (group presence + dashboard UI is the check); Logpush **datasets** (`404 10001`) and Zone versions (`404 10001`) expose no API-token surface. Workers custom-domain endpoints (`/accounts/{id}/workers/domains`) answer `405 Method not allowed for this authentication scheme` for both API tokens and the wrangler OAuth token — manage custom domains through `wrangler deploy` routes, not this endpoint.
63
101
  - Workers Builds (live-proven 2026-09-07): `GET /accounts/{id}/builds/builds/{uuid}` plus `/logs` read; trigger PATCH and build-token DELETE verified with the Edit level.
64
102
  - Template drift is real: the dashboard template grows over time (Builds/Agents/Containers/Observability/Pages appeared after the doc was written). Enumerate required groups per task from `docs/api-token.md`; never assume the template equals the need.
65
103
  - A 403 naming a missing group later means extend-then-verify, not a new token: same flow, one more row.