Cloudflare Workers クイックスタート
NW DB は素の HTTP と fetch だけで動くので、 Cloudflare Workers / Pages からそのまま呼べます。専用 SDK は要りません。
2種類の鍵
この2つは用途が違います。取り違えると、ワークスペース全体が公開されます。
| 鍵 | 置き場所 | 何を意味するか |
|---|---|---|
| nwdb_pk_... | ブラウザに置いてよい | どのアプリか。単体では何の権限も無い |
| nwdb_... | Workers Secrets / サーバのみ | ワークスペース全体を操作できる。ブラウザ禁止 |
# シークレットキーは必ず Secrets へ。wrangler.toml の [vars] は
# デプロイ成果物に平文で入ります。
npx wrangler secret put NWDB_SECRET_KEY1. アプリを登録する(サーバ側で一度だけ)
publishable key はページのソースにあり誰でも読めます。他人のサイトからの利用を止めるのはallowedOrigins の一覧だけです。空のままだとそのアプリは拒否されます(「どこからでも可」ではなく「未設定」とみなします)。
curl -X POST https://api.nwdb.dev/api/v1/apps \
-H "X-API-Key: $NWDB_SECRET_KEY" \
-H "X-Workspace-ID: $NWDB_WORKSPACE_ID" \
-H 'Content-Type: application/json' \
-d '{
"name": "my-app",
"allowedOrigins": ["https://myapp.pages.dev"],
"jwtIssuer": "https://securetoken.google.com/<your-firebase-project>",
"jwtAudience": "<your-firebase-project>",
"jwtJwksUrl": "https://www.googleapis.com/service_accounts/v1/jwk/securetoken@system.gserviceaccount.com"
}'jwtJwksUrl は利用者を認証しているサービスの公開鍵です。 Firebase / Auth0 / Clerk / 任意の OIDC が使えます。NW DB 側で利用者アカウントを作る必要はありません。
2. 行の見せ方を決める
これを設定していないテーブルは、アプリ利用者から一切触れません(403 APP_TABLE_NOT_PROTECTED)。 行レベルセキュリティはテーブル単位のオプトインで、設定していないテーブルには ポリシーが1つも付きません。そのまま通すと「保護していない」が「誰でも読める」に なってしまうため、未設定は不通として扱います。
curl -X POST https://api.nwdb.dev/api/v1/apps/row-security \
-H "X-API-Key: $NWDB_SECRET_KEY" \
-H "X-Workspace-ID: $NWDB_WORKSPACE_ID" \
-H 'Content-Type: application/json' \
-d '{"table": "notes", "ownerColumn": "owner", "enabled": true}'ownerColumn には、利用者の JWT のsub を保存している列を指定します。 以後、アプリ利用者は自分の行しか読み書きできません。
アプリ利用者が使える範囲
publishable key + 利用者トークンで到達できるのは /records/:table/records だけで、 しかも上記の RLS を設定したテーブルに限られます。
| 経路 | アプリ利用者 | シークレットキー |
|---|---|---|
| records(RLS 設定済み) | 自分の行のみ | 全行 |
| records(RLS 未設定) | 403 APP_TABLE_NOT_PROTECTED | 全行 |
| SQL / スキーマ / ストレージ / ベクトル / 監査 / 課金 | 403 APP_ROUTE_FORBIDDEN | 可 |
スキーマ・SQL・ストレージ・課金・監査はワークスペース管理者の操作であって、 その利用者が触るものではありません。ベクトル検索とファイルは、行とは所有者の 決め方が違うので、それぞれの所有権ルールを決めてから開けます。
3. ブラウザから呼ぶ
// ブラウザ / Pages から直接。中継するバックエンドは要りません。
const res = await fetch("https://api.nwdb.dev/api/v1/records/notes/records", {
headers: {
"X-NWDB-Key": PUBLISHABLE_KEY, // バンドルに入れてよい
"X-Workspace-ID": WORKSPACE_ID,
Authorization: `Bearer ${await user.getIdToken()}`,
},
});4. Workers から呼ぶ(信頼されたバックエンド)
シークレットキーを使うルートは、必ず呼び出し元を認証してから通してください。workers.dev の URL は知っている人なら誰でも叩けるので、 認証を挟まないプロキシは「公開された、無認証の、ワークスペース全体への入口」になります。 Worker が信頼されたバックエンドとして扱われるのは、あなたが利用者を確かめているからであって、Worker だからではありません。
export default {
async fetch(request, env) {
// ここがあなたの利用者認証。セッション、あなたの発行した JWT、なんでもよい。
// 無いなら、このルートは公開してはいけない。
const user = await authenticateYourUser(request, env);
if (!user) return new Response("Unauthorized", { status: 401 });
const upstream = await fetch(
"https://api.nwdb.dev/api/v1/records/notes/records",
{
headers: {
"X-API-Key": env.NWDB_SECRET_KEY, // Secrets から。ブラウザへ出さない
"X-Workspace-ID": env.NWDB_WORKSPACE_ID,
},
},
);
// 本文はストリームのまま返す。
return new Response(upstream.body, {
status: upstream.status,
headers: { "Content-Type": "application/json", "Cache-Control": "no-store" },
});
},
};トークンを比較する場合は crypto.subtle.timingSafeEqual を使ってください。=== は一致した文字数だけ処理時間が伸びるので、 当て推量を繰り返せば値が割り出せます。長さの違いで例外にならないよう、両者を SHA-256 に通してから比べます。
キーはロールを絞って発行する
curl -X POST https://api.nwdb.dev/api/v1/workspaces/$NWDB_WORKSPACE_ID/api-keys \
-H "X-API-Key: $ADMIN_KEY" -H 'Content-Type: application/json' \
-d '{"name": "cloudflare-worker", "role": "viewer", "expiresInDays": 90}'role はadmin /editor /viewer、expiresInDays は 1〜3650 です。省略すると admin かつ無期限になります。読むだけの用途に admin を渡す理由は無く、 viewer なら書き込めずマスキングも効きます。
実際の挙動
| 送ったもの | 結果 |
|---|---|
| publishable key + 利用者JWT + 登録済みオリジン | 200 — 自分の行のみ |
| publishable key のみ(JWTなし) | 401 APP_TOKEN_REQUIRED |
| 登録していないオリジンから | 403 ORIGIN_NOT_ALLOWED |
| 他人所有の行を書き込み | 403 ROW_NOT_PERMITTED |
| 自分所有の行を書き込み | 201 |
注意
- キャッシュしないでください。 API 応答は利用者ごとに内容が変わります(RLS とマスキング)。 Cloudflare のキャッシュに乗せると、ある利用者の行が別の利用者へ配られます。 キャッシュしてよいのは公開ページと静的アセットだけです
- publishable key が漏れても慌てなくてよい。 元から公開前提であり、権限は JWT と RLS が決めます。 気になる場合は
POST /api/v1/apps/:id/rotateで差し替えられます - Hyperdrive で PostgreSQL へ直結する構成は当面推奨しません。NW DB API の 認証・課金・監査・ワークスペース分離・レート制限を全て迂回するためです
動くスターター一式(Worker + ブラウザ直の両方を1つのデプロイ単位に収めたもの)は、 リポジトリの examples/cloudflare-worker にあります。 REST の全体像は REST API クイックスタート、 完全な OpenAPI 定義は https://api.nwdb.dev/api/v1/docs を参照してください。