一時プレビューアカウントを使うと、Cloudflare に認証する前に Workers をデプロイしてテストできます。その後、アカウントを引き継いで、デプロイと対応リソースを保持できます。
Cloudflare Drop ↗ は、静的サイト向けに、このプレビューと引き継ぎのライフサイクルを示しています。プラットフォームは REST API を使い、生成したアプリケーションに同様の体験を提供できます。
設計の背景は Temporary Cloudflare Accounts for AI agents ↗ を参照してください。
アカウントのプロビジョニングを誰が制御するかで、連携方法を選びます。
| 連携 | 使う場面 | プロビジョニングの動作 |
|---|---|---|
Wrangler と wrangler deploy --temporary |
AI エージェントまたはツールが Wrangler を実行する | Wrangler がアカウントを作成または再利用し、Claim URL を表示します |
REST API(api.cloudflare.com/client/v4/provisioning/previews) |
プラットフォームのバックエンドがデプロイ体験を制御する | バックエンドが一時的な資格情報と Claim URL を受け取ります |
本番および継続的インテグレーション / 継続的デプロイ(CI/CD)では、永続的な Cloudflare アカウントを使います。wrangler login または Cloudflare API トークン で認証します。
AI エージェントまたはツールがデプロイコマンドを実行する場合は、Wrangler を使います。Wrangler がプルーフオブワークのチャレンジ、資格情報、Claim URL を管理します。
Wrangler 4.102.0 以降は、未認証のデプロイを --temporary で再実行する案内を表示します。
-
Wrangler をバージョン 4.102.0 以降にインストールまたは更新します。
インストール手順は インストールと更新 を参照してください。
-
AI エージェントにデプロイ用のプロンプトを渡します。
例は次のとおりです。
Make a very simple Hello World Cloudflare Worker in TypeScript and deploy it using the Wrangler CLI. Do not ask me questions. -
エージェントに
wrangler deployを実行させます。未認証かつ非対話のセッションでは、Wrangler は次のような出力を表示します。
To continue without logging in, rerun this command with `--temporary`. Wrangler will use a temporary account and print a claim URL.この出力は、エージェントに
--temporary付きでコマンドを再実行するよう伝えます。 -
--temporaryを付けてデプロイを再実行します。npx wrangler deploy --temporaryyarn wrangler deploy --temporarypnpm wrangler deploy --temporaryWrangler は次のような出力を表示します。
Continuing means you accept Cloudflare's Terms of Service (https://www.cloudflare.com/terms/) and Privacy Policy (https://www.cloudflare.com/privacypolicy/). Temporary account ready: Account: example-name (created) Claim within: 60 minutes Claim URL: https://dash.cloudflare.com/claim-preview?claimToken=<CLAIM_TOKEN> Uploaded example-worker Deployed example-worker triggers https://example-worker.example-name.workers.dev -
(任意)アカウントを引き継ぐ前に、変更を再デプロイします。
資格情報と Claim URL が有効なあいだ、Wrangler はアカウントをキャッシュして再利用します。出力で、Wrangler がアカウントを作成したか再利用したかを確認できます。
wrangler loginまたはwrangler logoutを実行すると、Wrangler はキャッシュしたアカウントをクリアします。Wrangler はこれらの一時的な値を、現在の OS ユーザーのグローバル設定ディレクトリに保存します。このディレクトリをプラットフォーム利用者間で共有しないでください。
プラットフォームのバックエンドがデプロイを制御する場合は、REST API を使います。バックエンドは、ユーザーが認証する前にアカウントをプロビジョニングし、対応リソースをデプロイします。
プロビジョニングとデプロイの呼び出しは、すべてバックエンドから行います。プロビジョニングのレスポンスには、機密の資格情報と Claim URL が含まれます。
次の図は、ユーザーがプレビューしてデプロイを引き継ぐあいだ、プラットフォームが一時的な資格情報をバックエンドに保持する流れです。
flowchart LR
accTitle: プラットフォームのプレビューと引き継ぎの構成
accDescr: ユーザーが Cloudflare のポリシーに同意し、プラットフォーム UI でプレビューを要求します。信頼できるプラットフォームバックエンドが一時アカウントを作成し、account.apiToken を非公開のまま保持して Worker をデプロイし、プレビュー URL と Claim URL だけを UI に返します。Claim URL は、対象ユーザーにだけ見せるベアラー資格情報です。ユーザーは Cloudflare ダッシュボードでアカウントを引き継ぎます。以降のプラットフォームからのデプロイには、別の OAuth フローが必要です。
USER((ユーザー))
subgraph PLATFORM["プラットフォーム"]
direction TB
UI["プラットフォーム UI<br/>一時 API トークンなし"]
BACKEND["信頼できるプラットフォームバックエンド<br/>account.apiToken を保存"]
UI -->|"2. プレビューを要求"| BACKEND
BACKEND -->|"10. プレビュー URL とベアラーの Claim URL のみ"| UI
end
subgraph CLOUDFLARE["Cloudflare"]
direction TB
API["Cloudflare API"]
DASHBOARD["Cloudflare ダッシュボード<br/>アカウントを引き継ぐ"]
end
USER -->|"1. ポリシーに同意し、アプリケーションを生成"| UI
BACKEND -->|"3. チャレンジを要求"| API
API -->|"4. チャレンジパラメーター"| BACKEND
BACKEND -->|"5. チャレンジをローカルで解く"| BACKEND
BACKEND -->|"6. 解とともに一時アカウントを作成"| API
API -->|"7. アカウント ID、API トークン、Claim URL"| BACKEND
BACKEND -->|"8. Worker をデプロイし、サブドメインを要求"| API
API -->|"9. workers.dev サブドメイン"| BACKEND
UI -->|"11. ライブプレビューと対象ユーザー限定の Claim リンクを表示"| USER
USER -->|"12. サインインして引き継ぎを完了"| DASHBOARD
DASHBOARD -.->|"引き継ぎ後は任意"| OAUTH["以降のプラットフォームデプロイ用の<br/>別の OAuth フロー"]
一時アカウントを作成する前に、プルーフオブワークのチャレンジを要求します。
curl "https://api.cloudflare.com/client/v4/provisioning/previews/challenge" \
-X POST \
-H "Content-Type: application/json" \
--data '{}'レスポンスには、チャレンジトークン、シード、難易度パラメーターが含まれます。
{
"success": true,
"result": {
"challengeToken": "<CHALLENGE_TOKEN>",
"seed": "<BASE64URL_32_BYTE_SEED>",
"k": 8000,
"g": 2000
},
"errors": [],
"messages": []
}連続する SHA-256 のチェックポイントチェーンを計算して、チャレンジを解きます。
seedを Base64URL としてデコードします。32 バイトになる必要があります。checkpoint[0] = SHA-256(seed)を計算します。0からk - 1までの各セグメントについて、直前のチェックポイントからg回の連続 SHA-256 ハッシュを計算し、結果を追加します。- すべての
k + 1個のチェックポイントを連結します。各チェックポイントは 32 バイトです。 - 連結したバイト列を標準 Base64 でエンコードします。その値を
solution.checkpointsとして送ります。
チャレンジを解く前に、k と g が正の整数であることを確認します。seed が 32 バイトにデコードできない場合、または k * g が 64,000,000 を超える場合は、チャレンジを拒否します。
次の Node.js の例は、これらの上限を適用し、作成リクエストで必要なオブジェクトを返します。
import { createHash } from "node:crypto";
function sha256(value) {
return createHash("sha256").update(value).digest();
}
export function solvePreviewChallenge({ challengeToken, seed, k, g }) {
const seedBytes = Buffer.from(seed, "base64url");
if (seedBytes.length !== 32) {
throw new Error("seed must decode to 32 bytes");
}
if (!Number.isInteger(k) || k <= 0) {
throw new Error("k must be a positive integer");
}
if (!Number.isInteger(g) || g <= 0) {
throw new Error("g must be a positive integer");
}
if (k * g > 64_000_000) {
throw new Error("k * g must not exceed 64,000,000");
}
const checkpoints = [];
let hash = sha256(seedBytes);
checkpoints.push(hash);
for (let segment = 0; segment < k; segment++) {
for (let iteration = 0; iteration < g; iteration++) {
hash = sha256(hash);
}
checkpoints.push(hash);
}
return {
challengeToken,
solution: {
checkpoints: Buffer.concat(checkpoints).toString("base64"),
},
};
}import { createHash } from "node:crypto";
type PreviewChallenge = {
challengeToken: string;
seed: string;
k: number;
g: number;
};
function sha256(value: Uint8Array): Buffer {
return createHash("sha256").update(value).digest();
}
export function solvePreviewChallenge({
challengeToken,
seed,
k,
g,
}: PreviewChallenge) {
const seedBytes = Buffer.from(seed, "base64url");
if (seedBytes.length !== 32) {
throw new Error("seed must decode to 32 bytes");
}
if (!Number.isInteger(k) || k <= 0) {
throw new Error("k must be a positive integer");
}
if (!Number.isInteger(g) || g <= 0) {
throw new Error("g must be a positive integer");
}
if (k * g > 64_000_000) {
throw new Error("k * g must not exceed 64,000,000");
}
const checkpoints: Buffer[] = [];
let hash = sha256(seedBytes);
checkpoints.push(hash);
for (let segment = 0; segment < k; segment++) {
for (let iteration = 0; iteration < g; iteration++) {
hash = sha256(hash);
}
checkpoints.push(hash);
}
return {
challengeToken,
solution: {
checkpoints: Buffer.concat(checkpoints).toString("base64"),
},
};
}アカウント作成の前に、ユーザーに Cloudflare の 利用規約 ↗ と プライバシーポリシー ↗ への同意を求めます。ユーザーが両方に同意したあとでのみ、acceptTermsOfService を "yes" に設定します。
その後、必須のポリシーフィールドとともに、プルーフオブワークの解を送ります。
curl "https://api.cloudflare.com/client/v4/provisioning/previews" \
-X POST \
-H "Content-Type: application/json" \
--data '{
"termsOfService": "https://www.cloudflare.com/terms/",
"privacyPolicy": "https://www.cloudflare.com/privacypolicy/",
"acceptTermsOfService": "yes",
"challengeToken": "<CHALLENGE_TOKEN>",
"solution": {
"checkpoints": "<BASE64_CHECKPOINTS>"
}
}'レスポンスには、一時的な資格情報と Claim URL が含まれます。
{
"success": true,
"result": {
"account": {
"id": "<TEMPORARY_ACCOUNT_ID>",
"name": "<TEMPORARY_ACCOUNT_NAME>",
"type": "standard",
"apiToken": "<TEMPORARY_ACCOUNT_API_TOKEN>",
"tokenId": "<TEMPORARY_TOKEN_ID>",
"expiresAt": "<ACCOUNT_EXPIRES_AT>"
},
"claim": {
"token": "<CLAIM_TOKEN>",
"url": "https://dash.cloudflare.com/claim-preview?claimToken=<CLAIM_TOKEN>",
"expiresAt": "<CLAIM_EXPIRES_AT>"
}
},
"errors": [],
"messages": []
}レスポンスを使う前に、success が true であることを確認します。account.id、account.apiToken、account.expiresAt、claim.url、claim.expiresAt が存在することも確認します。
対応する Cloudflare API エンドポイントでは、account.id と account.apiToken を使います。一時的な値は、対応するリソース操作にだけ使います。
一時アカウントのトークンは、永続アカウントのすべての API 権限を持ちません。非対応の操作は認可エラーを返します。
次の例は、Workers Script Upload API で Worker をアップロードしてデプロイし、その後アカウントの workers.dev サブドメインを取得します。
curl "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/workers/scripts/$SCRIPT_NAME" \
-X PUT \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN" \
-F 'metadata={"main_module":"worker.mjs","compatibility_date":"<YYYY-MM-DD>"};type=application/json' \
-F 'worker.mjs=@worker.mjs;type=application/javascript+module'一時的な資格情報で Get Subdomain エンドポイント を呼び出します。
curl "https://api.cloudflare.com/client/v4/accounts/$CLOUDFLARE_ACCOUNT_ID/workers/subdomain" \
-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN"workers.dev で公開するスクリプトでは、result.subdomain とスクリプト名を組み合わせてデプロイ URL を作ります。形式は https://<SCRIPT_NAME>.<SUBDOMAIN>.workers.dev です。
一時アカウントをプロビジョニングしたあと、対応するリソース操作には Cloudflare TypeScript SDK ↗ を使います。
import Cloudflare from "cloudflare";
export async function deployWorker(
accountId: string,
apiToken: string,
scriptName: string,
compatibilityDate: string,
scriptContent: string,
) {
const client = new Cloudflare({ apiToken });
const workerModule = new File([scriptContent], "worker.mjs", {
type: "application/javascript+module",
});
await client.workers.scripts.update(scriptName, {
account_id: accountId,
metadata: {
main_module: "worker.mjs",
compatibility_date: compatibilityDate,
},
files: [workerModule],
});
const { subdomain } = await client.workers.subdomains.get({
account_id: accountId,
});
return `https://${scriptName}.${subdomain}.workers.dev`;
}デプロイ URL と claim.url は、対象ユーザーに渡します。
対象ユーザーは、60 分以内に引き継ぎを完了する必要があります。期限前に Claim URL を開いただけでは足りません。
URL を開き、Cloudflare にサインインするかアカウントを作成し、ダッシュボードの案内を完了します。
ユーザーが引き継ぎを完了しない場合、Cloudflare はアカウントとそのリソースを削除します。
Wrangler を使う場合、一時的な資格情報または Claim URL が期限切れになったら、wrangler deploy --temporary を再実行します。Wrangler は新しいアカウントをプロビジョニングし、新しい Claim URL を表示します。
REST 連携では、引き継ぎ前に account.expiresAt または claim.expiresAt を過ぎた場合、新しいチャレンジとアカウントを要求します。
引き継ぎ後、Worker と対応リソースは、引き継いだアカウントに残ります。
Wrangler を続けて使う場合は wrangler login を実行し、--temporary なしでデプロイします。引き継ぎによって、プラットフォームがアカウントへ永続的にアクセスできるようになるわけではありません。
以降のデプロイでは、Cloudflare OAuth クライアント など、通常の認証済みフローで、引き継いだアカウントを接続します。
次の表は、対応する機能と上限の概要です。一時的な資格情報は、これらのリソースのすべての操作を許可するわけではありません。
| 対応するプロダクトまたはリソース | 対応する機能または上限 |
|---|---|
| Workers | workers.dev へのデプロイ |
| Workers Static Assets | 最大 1,000 ファイル。各アセットは最大 5 MiB |
| Workers KV | 名前空間の作成、一覧、名前変更、削除。キーの put、get、list、delete。一括の put、get、delete |
| D1 | データベース 1 つ。データベースあたり最大 100 MB、合計 100 MB |
| Durable Objects | Durable Object のバインディングとマイグレーション付きで Workers をデプロイ |
| Hyperdrive | データベース設定は最大 2 つ、接続は 10 |
| Queues | キューは最大 10 |
| mTLS と CA 証明書 | wrangler cert のアップロード、一覧、削除 |
account.apiTokenは、対応するリソース操作を認可します。ブラウザーのレスポンスやクライアント側のコードに出さないでください。claim.urlはベアラー資格情報として扱います。URL を持つ人はだれでも、一時アカウントの所有権を引き継げます。- 両方の値は、対象ユーザーにスコープしたバックエンドストレージまたはサーバー側セッションストレージにだけ保存します。
claim.urlはそのユーザーにだけ渡します。 - 両方の値をログ、分析、サポート用テレメトリから除外します。不要になったら保存したコピーを削除し、返されたいずれかの有効期限を過ぎないようにします。
- Cloudflare は、アカウント作成前にプルーフオブワークの確認を求めます。Wrangler はこの確認を処理します。REST 連携では解を送信する必要があります。
- Cloudflare は一時アカウントの作成をレート制限します。再試行する前に待つか、永続アカウントで認証してください。
--temporaryは未認証の利用だけをサポートします。既存の OAuth、API トークン、またはグローバル API キーの資格情報があるとエラーになります。--temporaryはグローバルフラグではありません。一時的な資格情報に対応するコマンドだけがこのフラグを持ちます。- 一時アカウントのプロビジョニングは、デフォルトの公開 API エンドポイント経由でのみ利用できます。FedRAMP High API エンドポイントでは利用できません。
- 追加の不正利用防止チェックに失敗したリクエストは、Cloudflare が拒否することがあります。