Add a Storage tab listing and managing Cloudflare's account-scoped storage
primitives — R2 buckets, KV namespaces, and D1 databases. Management only
(list/create/delete); the object/key/row data planes are out of scope.
- CloudflareClient: r2/buckets, storage/kv/namespaces, d1/database list+create
+delete.
- CloudflareService: combined list_storage (each product fetched independently so
a missing token scope degrades to a per-product error, not a dead tab),
validated create/delete for each. R2 bucket names validated S3-style.
- /api/v1/cloudflare/zones/:id/storage* routes (read any user; writes admin).
- StoragePanel (three generic create/list/delete sections; R2 notes its
S3-compatibility for future backup targeting); api methods; SCSS.
No new tables — wiring an R2 bucket as an S3 backup backend (minting scoped R2
keys) is a deliberate follow-up, noted in the UI.
Tests: aggregate listing + per-product error degradation, R2 name validation,
create/delete, KV/D1 required-field guards (6).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>