← Docs

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_KEY

1. アプリを登録する(サーバ側で一度だけ)

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}'

roleadmin /editor /viewerexpiresInDays は 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 を参照してください。