# คู่มือ — Setup Wrangler, login Cloudflare และสร้าง API token

เตรียมบัญชีและ CLI สำหรับ [บท 08 — Cloudflare deployment](../lessons/08-cloudflare-deploy.md) ของ **AI Web Studio — ออกแบบและพัฒนาเว็บไซต์ด้วย AI**, ส่วนหนึ่งของ **977-121 Module: Website Design and Development**, มหาวิทยาลัยสงขลานครินทร์ วิทยาเขตภูเก็ต

ใช้เป็น **prework หรือเรียนต่อด้วยตัวเอง 30–45 นาที** เวลาอบรมยังคง **2 วัน วันละ 4 ชั่วโมง รวม 8 ชั่วโมงรวมพัก** ผู้เรียนเลือกวิธีรับรองตัวตนหนึ่งวิธีให้เหมาะกับเครื่อง ไม่จำเป็นต้องสร้าง token เพิ่มหาก OAuth ใช้งานได้และไม่มีงาน CI

**ตรวจข้อมูล:** 9 กันยายน 2026 · **CLI ของโครงการที่ตรวจ:** Wrangler `4.130.0` · ใช้บัญชีและ resource ของผู้เรียนสำหรับแบบฝึกหัด

## ผลลัพธ์ที่ต้องทำได้

- เรียก Wrangler จาก repository และอธิบายว่าใช้เวอร์ชันใด
- เลือก OAuth login หรือ API token ได้ตามลักษณะงาน
- ยืนยัน account เป้าหมายและตรวจสิทธิ์ Workers/D1 ก่อน deploy
- เก็บ token ใน environment ของ CLI/CI โดยไม่ส่งไป frontend หรือ Worker runtime
- แยกหลักฐานว่า token ยังใช้ได้ ออกจากหลักฐานว่า deploy และ migration สำเร็จ

## 1. รู้จัก credential แต่ละชนิด

| ชื่อ | ใช้กับอะไร | ใช้ในบทนี้อย่างไร |
| --- | --- | --- |
| Wrangler OAuth login | ให้ CLI ทำงานกับ Cloudflare ในนามผู้ใช้ที่อนุญาตผ่าน browser | ทางหลักสำหรับเครื่องผู้เรียน |
| Cloudflare API token | เรียก Cloudflare API ภายใต้ permission/resource scope ที่กำหนด | ทางเลือกสำหรับ CI หรือ environment ที่จัดการ credential เอง |
| Global API key | credential ที่ผูกกับผู้ใช้และมีขอบเขตกว้าง | ไม่จำเป็นสำหรับเส้นทางของคอร์สนี้ |
| Cloudflare Access service token | ผ่านการควบคุมเข้าแอปที่ป้องกันด้วย Cloudflare Access | ใช้แทน API token ของ Wrangler ไม่ได้ |
| Worker secret เช่น `DEMO_HMAC_KEY` | ให้โค้ดแอปใช้งานขณะรับ request | ตั้งแยกในบท deploy ไม่ใช่ token ของ CLI |

คำว่า “access token” ในโจทย์ deploy นี้หมายถึง **API token สำหรับจัดการ Cloudflare** ส่วน [Cloudflare Access service token](https://developers.cloudflare.com/cloudflare-one/access-controls/service-credentials/service-tokens/) เป็นคู่ Client ID/Client Secret สำหรับเข้าแอปที่ป้องกันด้วย Access ไม่ได้ให้สิทธิ์ deploy Worker

![Cloudflare Worker รับเส้นทาง API เชื่อม D1 และส่งไฟล์หน้าเว็บจาก Static Assets โดยแยก local กับ remote](/diagrams/cloudflare-deployment.svg)

[เปิดแผนภาพ Cloudflare](/diagrams/cloudflare-deployment.html) แผนภาพนี้แสดง runtime ของแอป ส่วน Wrangler ใช้ credential จากเครื่องผู้พัฒนาเพื่อส่งโค้ดและจัดการ resource ไม่ต้องส่ง credential นั้นไปกับ request ของนักศึกษาที่เปิดเว็บ

## 2. ติดตั้งและตรวจ Wrangler

เปิด terminal ที่ root ของ source code หลักสูตร โปรเจกต์นี้ใช้ **Node.js 22 ขึ้นไป** และมี Wrangler ใน `devDependencies` กับ lockfile แล้ว:

```bash
node --version
npm --version
npm ci
npx wrangler --version
npx wrangler login --help
```

ใช้ `npm ci` เพื่อติดตั้งตาม lockfile และ `npx wrangler` เพื่อเรียก CLI ของโปรเจกต์ ไม่จำเป็นต้องติดตั้ง global อีกชุด หากเป็น **โปรเจกต์ใหม่ที่ยังไม่มี Wrangler** จึงเพิ่มเป็น dev dependency ตาม [คู่มือติดตั้ง Wrangler](https://developers.cloudflare.com/workers/wrangler/install-and-update/):

```bash
npm install --save-dev wrangler@latest
```

ผลที่คาดหวังคือ `npx wrangler --version` แสดงเวอร์ชัน และ `login --help` แสดง flags ที่รุ่นนั้นรองรับ อย่ารันคำสั่งอัปเกรดใน source หลักสูตรโดยไม่ตั้งใจ เพราะจะเปลี่ยน dependency/lockfile ที่ใช้ตรวจงาน

Local Worker และ D1 จำลองของคอร์สเริ่มได้โดยไม่ login อ่าน [บท 00](../lessons/00-setup-and-web-basics.md) ก่อน ส่วนการทำงานกับ Cloudflare account จริงต้องทำขั้นตอนรับรองตัวตนด้านล่าง

## 3. ทางเลือก A — ล็อกอินผ่าน browser

สำหรับเครื่องส่วนตัวที่เปิด browser จาก terminal เดียวกันได้:

```bash
npx wrangler login
```

ทำตามลิงก์ที่ Wrangler แสดง ตรวจว่าอยู่ในหน้า Cloudflare ที่ถูกต้อง เลือกบัญชีผู้ใช้และอ่านสิทธิ์ที่จะอนุญาต เมื่อ CLI แจ้งว่าสำเร็จ ให้ตรวจ:

```bash
npx wrangler whoami
```

เทียบ account name/ID กับ Cloudflare Dashboard หากมีหลาย account ให้เลือก account สำหรับแบบฝึกหัดให้ชัด **Account ID ไม่ใช่ API token และไม่ใช่ Zone ID** การ login สำเร็จไม่ได้ยืนยันว่ามีสิทธิ์แก้ทุก account ที่มองเห็น

### ใช้ SSH, container หรือเครื่อง shared

[Device login รองรับตั้งแต่ Wrangler 4.119.0](https://developers.cloudflare.com/changelog/post/2026-08-04-wrangler-login-device-flow/) และมีในรุ่น `4.130.0` ของโครงการ วิธีนี้ไม่ต้องใช้ localhost callback จาก browser กลับมายัง terminal:

```bash
npx wrangler login --device
```

เปิด verification URL และกรอกรหัสตามคำแนะนำของ CLI ให้เสร็จ แล้วรัน `npx wrangler whoami` อีกครั้ง หาก CLI ของผู้เรียนไม่มี `--device` ให้ดูคู่มือรุ่นนั้นหรือใช้ API token ในหัวข้อถัดไป อย่าเปิด callback server เพิ่มโดยไม่ตรวจเครื่อง

Browser login แบบปกติใช้ temporary callback port **8976** เป็นค่าเริ่มต้น และมี `--callback-host`, `--callback-port` กับ `--browser=false` ตาม [คำสั่ง authentication ของ Wrangler](https://developers.cloudflare.com/workers/wrangler/commands/general/) การไม่เปิด browser อัตโนมัติไม่ได้ย้าย callback มาอยู่เครื่องผู้ใช้ให้เอง บนเครื่อง shared ต้องอ่าน `/home/dev/projects/shared-infra/reserve-port.md` และตรวจ/จองพอร์ตก่อนใช้ flow ที่เปิด listener; พอร์ตของคอร์ส 3320–3323 มีหน้าที่ของตนอยู่แล้ว อย่านำไปทับกัน

### เลือก account ให้แน่นอน

ใช้ `account_id` ใน Wrangler config หรือ `CLOUDFLARE_ACCOUNT_ID` ใน environment ของ session ตามวิธีที่ทีมเลือก ค่าในเอกสารนี้เป็น placeholder ให้แทนด้วย account ของตน และอย่าแก้ Worker name/database ID ของผู้สอนเพื่อไปเขียน resource ร่วมโดยไม่ตั้งใจ

```jsonc
{
  "account_id": "YOUR_CLOUDFLARE_ACCOUNT_ID"
}
```

ตัวอย่างนี้เป็น **field ที่นำไปรวมใน `wrangler.jsonc` เดิม** ไม่ใช่ไฟล์ config ทั้งฉบับ ห้ามแทนที่ไฟล์เดิมจน `main`, `assets` หรือ D1 bindings หาย

## 4. ทางเลือก B — สร้าง Cloudflare API token

บทนี้ใช้ **user API token** ตาม [คู่มือ Create an API token](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/):

1. เข้า [Cloudflare Dashboard — API Tokens](https://dash.cloudflare.com/profile/api-tokens) ด้วยผู้ใช้ของตน หรือเปิด **My Profile → API Tokens**
2. เลือก **Create Token → Custom token → Get started** เพื่อกำหนดสิทธิ์เอง
3. ตั้งชื่อที่บอกงาน เช่น `ai-web-studio-deploy-2026-09` ชื่อไม่ใช่ค่าลับของ token
4. เพิ่ม **Permissions** ตามตารางด้านล่าง และตั้ง **Account Resources → Include → Specific account** เป็น account สำหรับแบบฝึกหัด
5. ตั้ง **TTL / วันหมดอายุ** ให้ครอบคลุมช่วงใช้จริง เช่น หมดอายุหลังจบการทบทวนบทเรียน ใช้ IP filter เฉพาะเมื่อรู้ IP ขาออกที่คงที่ของเครื่อง/CI; IP ของ Wi-Fi และ hosted runner อาจเปลี่ยนได้
6. เลือก **Continue to summary** ตรวจชื่อ account สิทธิ์ และอายุ แล้ว **Create Token**
7. คัดลอกค่าที่แสดงครั้งเดียวเข้า secret manager ของตนหรือช่อง secret ของ CI หากปิดไปโดยไม่เก็บ ให้สร้างใหม่ อย่าแนบหน้าที่แสดงค่าลับในงานส่ง

### สิทธิ์สำหรับ Worker + Static Assets + D1 ของคอร์ส

| งานที่ต้องทำ | Permission ที่เลือก | Resource scope |
| --- | --- | --- |
| Deploy Worker และ upload Static Assets | **Account → Workers Scripts → Edit** | เฉพาะ account ของแบบฝึกหัด |
| สร้าง/อ่าน D1 และ apply remote migration | **Account → D1 → Edit** | เฉพาะ account ของแบบฝึกหัด |
| ให้ `whoami` แสดงข้อมูลผู้ใช้และค้น account ได้ครบ เมื่อจำเป็น | **User → User Details → Read** และ **User → Memberships → Read** | ข้อมูลผู้ใช้เจ้าของ token; เป็นสิทธิ์เสริมสำหรับตรวจตัวตน |

Dashboard อาจใช้คำว่า **Edit** ขณะที่เอกสาร API ใช้ **Write**: [Static Assets upload session](https://developers.cloudflare.com/api/resources/workers/subresources/scripts/subresources/assets/subresources/upload/methods/create/) รับ Workers Scripts Write, [สร้าง D1](https://developers.cloudflare.com/api/resources/d1/subresources/database/methods/create/) ใช้ D1 Write และ [อ่านรายการ D1](https://developers.cloudflare.com/api/resources/d1/subresources/database/methods/list/) รับ D1 Read หรือ Write สิทธิ์ D1 Edit จัดการฐานข้อมูลใน account ที่เลือกได้ จึงควรใช้ account และฐานข้อมูลสำหรับฝึกโดยเฉพาะ

การ deploy ไป `workers.dev` ตาม config ของคอร์สไม่ต้องเพิ่ม DNS/Zone permission ล่วงหน้า ถ้าบทฝึกเพิ่มเติมมีการสร้างหรือแก้ `routes` จึงพิจารณา **Zone → Workers Routes → Edit** จำกัดเฉพาะ zone นั้น ส่วน custom domain ให้ตรวจสิทธิ์ของ endpoint ที่ใช้แยกอีกครั้ง ดู [รายการ permission](https://developers.cloudflare.com/fundamentals/api/reference/permissions/) และ [Workers token template](https://developers.cloudflare.com/fundamentals/api/reference/template/); template เป็นจุดเริ่มต้นที่ต้องตรวจ scope ไม่ใช่คำตอบว่าทุกสิทธิ์จำเป็นเสมอ

ไม่ต้องสร้าง [Global API key](https://developers.cloudflare.com/fundamentals/api/get-started/keys/) สำหรับแบบฝึกหัดนี้ ส่วน [account-owned API token](https://developers.cloudflare.com/fundamentals/api/get-started/account-owned-tokens/) เป็นหัวข้อต่อยอดสำหรับ integration ระยะยาวที่ต้องแยกจากบัญชีบุคคล ไม่ใช้สลับกับ user token ในตัวอย่าง verify ด้านล่างโดยไม่ตรวจ endpoint

## 5. นำ token เข้า environment อย่างปลอดภัย

ทำหลังสร้าง token แล้ว เลือก block ให้ตรงกับ shell ไม่พิมพ์ค่า token เป็นส่วนหนึ่งของคำสั่งที่อาจติด history และไม่เก็บลง `wrangler.jsonc`, prompt หรือ source control

### Bash — Linux, WSL หรือ Bash บน macOS

```bash
read -r -s -p "Cloudflare API token: " CLOUDFLARE_API_TOKEN
export CLOUDFLARE_API_TOKEN
read -r -p "Cloudflare Account ID: " CLOUDFLARE_ACCOUNT_ID
export CLOUDFLARE_ACCOUNT_ID
npx wrangler whoami
```

`read -s` ซ่อนตัวอักษรของ token ตัวอย่างนี้ใช้ Bash; หากใช้ zsh ให้เปิด `bash` ก่อนหรือใช้ secret manager/environment workflow ของ shell นั้น

### Windows PowerShell

```powershell
$cfTokenInput = Read-Host "Cloudflare API token" -AsSecureString
$env:CLOUDFLARE_API_TOKEN = [System.Net.NetworkCredential]::new("", $cfTokenInput).Password
$env:CLOUDFLARE_ACCOUNT_ID = Read-Host "Cloudflare Account ID"
Remove-Variable cfTokenInput
npx wrangler whoami
```

ทั้งสองวิธีตั้งค่าให้ process ใน terminal รอบนั้น ไม่ได้เก็บเป็น credential ถาวร เมื่อต้องทำ CI ให้ตั้ง `CLOUDFLARE_API_TOKEN` เป็น secret ของ CI และส่งเป็น environment ให้ step ที่ต้องใช้ ส่วน `CLOUDFLARE_ACCOUNT_ID` เป็นตัวเลือก account ดู [System environment variables](https://developers.cloudflare.com/workers/wrangler/system-environment-variables/) และ [ตัวอย่าง CI authentication](https://developers.cloudflare.com/workers/ci-cd/external-cicd/gitlab-cicd/)

อย่าเก็บ deploy token ใน `.env`/`.dev.vars` ของแอปหรือใช้ `wrangler secret put CLOUDFLARE_API_TOKEN` เพราะ token นี้ใช้โดย CLI/CI ไม่ใช่ Worker runtime ไม่ต้องแสดง `env`, `printenv`, `set` หรือค่าลับให้ AI เพื่อช่วย debug

**ลำดับ credential:** เมื่อมี `CLOUDFLARE_API_TOKEN` มันจะถูกใช้ก่อน OAuth ที่บันทึกจาก `wrangler login` จึงอาจเห็น token เก่าทำให้คำสั่งล้มเหลวแม้เพิ่ง login สำเร็จ ให้ล้างตัวแปรตามหัวข้อ 7 และตรวจ secret source ของ terminal/CI ก่อนกลับไปทดสอบ OAuth ตาม [Wrangler authentication](https://developers.cloudflare.com/workers/wrangler/commands/general/)

## 6. ตรวจให้ตรงกับสิ่งที่ต้องการพิสูจน์

| การตรวจ | พิสูจน์อะไร | ยังไม่พิสูจน์อะไร |
| --- | --- | --- |
| `wrangler --version` | CLI เรียกได้และรู้รุ่น | login/account permissions |
| `wrangler whoami` | ตัวตนหรือ authentication ที่ CLI ใช้ และข้อมูล account ที่อ่านได้ | การเขียน Worker หรือ D1 สำเร็จ |
| Token verify API | สถานะ active ของ token ชนิดนั้น | permission ทุก operation |
| `wrangler d1 list` | เรียกอ่านรายการ D1 ภายใต้ account/สิทธิ์นั้นได้ | migration เขียนสำเร็จ |
| `npm run deploy:check` | bundle/config ผ่าน dry-run | remote credential และ deploy จริง |
| Deploy + remote smoke test | ผลการเผยแพร่และการทำงานตามขอบเขตที่ตรวจจริง | ความพร้อมธุรกิจทุกด้าน |

### ตรวจสถานะ user API token โดยไม่พิมพ์ค่าลับ

สำหรับผู้เลือก API token: สร้างไฟล์ `verify-cloudflare-token.mjs` ในเครื่องฝึก ใส่โค้ดด้านล่างแล้วเรียกด้วย Node.js ที่ติดตั้งไว้ โค้ดอ่าน token จาก environment และส่งไปยัง [user token verification endpoint](https://developers.cloudflare.com/fundamentals/api/get-started/create-token/) โดยตรง ไม่มีค่าลับใน source หรือ command arguments:

```javascript
const token = process.env.CLOUDFLARE_API_TOKEN;

if (!token) {
  console.error("CLOUDFLARE_API_TOKEN is not set");
  process.exitCode = 1;
} else {
  try {
    const response = await fetch(
      "https://api.cloudflare.com/client/v4/user/tokens/verify",
      {
        headers: { Authorization: `Bearer ${token}` },
        signal: AbortSignal.timeout(15000),
      },
    );
    const body = await response.json();
    const active = response.ok && body.success === true && body.result?.status === "active";
    console.log(JSON.stringify({
      httpStatus: response.status,
      success: body.success === true,
      status: body.result?.status ?? "unknown",
      errorCodes: (body.errors ?? []).map((error) => error.code),
    }, null, 2));
    if (!active) process.exitCode = 1;
  } catch {
    console.error("Token verification failed: check network, timeout, or response format.");
    process.exitCode = 1;
  }
}
```

```bash
node verify-cloudflare-token.mjs
```

ผลผ่านคือ HTTP `200`, `success: true`, `status: "active"` และ exit code `0` ผลนี้ยังไม่ยืนยันว่าเลือก account ถูกหรือมีสิทธิ์ deploy ครบ ตัวอย่างใช้ **user API token**; ผู้ใช้ OAuth ข้ามการตรวจ endpoint นี้ได้

### ตรวจ account และ resource แบบอ่านอย่างเดียว

ใน repository ที่ตั้ง account ถูกแล้ว ทดลอง:

```bash
npx wrangler whoami
npx wrangler d1 list
```

บัญชีที่ยังไม่มี D1 อาจได้รายการว่าง ซึ่งต่างจาก error ว่าไม่มีสิทธิ์ `whoami` อาจแสดงข้อมูลไม่ครบถ้า token ไม่มี User Details/Memberships Read ให้ตรวจ `account_id` ที่ตั้งไว้และผล resource read ก่อนสรุปว่า token เสีย

`npm run deploy:check` ใช้ [Wrangler deploy --dry-run](https://developers.cloudflare.com/workers/wrangler/commands/workers/) เพื่อตรวจ bundle/config เท่านั้น ส่วนขั้นสร้าง D1, migration และ deploy ให้ทำต่อใน [บท 08](../lessons/08-cloudflare-deploy.md) หลังตรวจ resource เป้าหมายเรียบร้อย

## 7. Logout, เปลี่ยน token และจบ session

เมื่อจะออกจาก **OAuth session** ของเครื่องที่ใช้งานอยู่:

```bash
npx wrangler logout
```

สำหรับ **API token** ให้ล้าง environment ของ terminal เมื่อไม่ต้องใช้แล้ว:

```bash
unset CLOUDFLARE_API_TOKEN CLOUDFLARE_ACCOUNT_ID
```

PowerShell:

```powershell
Remove-Item Env:CLOUDFLARE_API_TOKEN -ErrorAction SilentlyContinue
Remove-Item Env:CLOUDFLARE_ACCOUNT_ID -ErrorAction SilentlyContinue
```

`wrangler logout` จัดการ OAuth ที่เก็บในเครื่อง ไม่ได้ revoke API token ส่วนการล้าง environment ก็ไม่ใช่การ revoke token ที่ Cloudflare เมื่อต้องเปลี่ยน token ให้สร้างตัวใหม่ที่ scope ถูกต้อง อัปเดตผู้ใช้งาน/CI และตรวจผลก่อนเพิกถอนตัวเก่าจากหน้า API Tokens ใน Dashboard หาก token เคยรั่ว ให้เพิกถอน/เปลี่ยนทันทีและตรวจการใช้งานตามกระบวนการของทีม ไม่แก้ด้วยการลบข้อความออกจาก Git commit ล่าสุดอย่างเดียว

## 8. แก้ปัญหาที่พบบ่อย

| อาการ | ตรวจอะไรและทำต่ออย่างไร |
| --- | --- |
| `wrangler` ไม่พบ หรือ `--device` ไม่รองรับ | อยู่ root ของ repo หรือไม่; รัน `npm ci`, `npx wrangler --version` และ `login --help` ก่อนเลือก flow ของรุ่นนั้น |
| Browser อนุญาตแล้วแต่ terminal ยังรอ | ถ้า browser อยู่คนละเครื่องหรือ callback ไปไม่ถึง ให้ใช้ device login; อย่า kill process หรือเปลี่ยนพอร์ต shared โดยเดา |
| เพิ่ง OAuth login แต่ Wrangler แจ้งว่าใช้ API token | ตรวจเพียงว่ามี `CLOUDFLARE_API_TOKEN` หรือไม่ แล้วล้างค่าจาก session/secret source ที่ไม่ต้องการตามหัวข้อ 7 |
| Verify active แต่ deploy ได้ `403` | เทียบ Account ID, Account Resources และ permission ของ operation ที่ล้มเหลว; เพิ่มเฉพาะสิทธิ์ที่งานต้องใช้ |
| `whoami` ไม่แสดง email/account ครบ | ตรวจสิทธิ์ User Details Read/Memberships Read หรือใช้ account ที่ระบุใน config; ไม่ต้องเปลี่ยนเป็น Global API key |
| D1 list ว่าง | อาจยังไม่มีฐานข้อมูลใน account นั้น ตรวจ account ก่อนสร้างในบท 08 |
| Verify ไม่ active หรือถูกปฏิเสธ | ตรวจว่าใช้ user token ถูกตัว หมดอายุ/ถูก revoke หรือมี IP filter ที่ไม่ตรงหรือไม่; อย่าส่งค่าลับให้ผู้สอน |
| ผ่าน dry-run แต่ remote migration ไม่ผ่าน | Dry-run ไม่ได้ทดสอบ D1 write ตรวจ D1 permission, account และ database เป้าหมายจาก error จริง |

## 9. Prompt ให้ AI ช่วยตรวจความพร้อมก่อน login/deploy

```text
ช่วยตรวจความพร้อม Cloudflare สำหรับ repository AI Web Studio นี้แบบอ่านอย่างเดียว
อ่าน package.json, wrangler.jsonc, กฎ AGENTS.md/CLAUDE.md และ shared-infra ที่อ้างถึง
ตรวจ Node/npm/Wrangler version และ flags จาก help ที่ติดตั้งจริง

สรุป:
1. ใช้ CLI จาก dependency ของโปรเจกต์ได้หรือไม่ และคำสั่ง setup ที่มีจริง
2. งานนี้ใช้ OAuth login, device login หรือ API token เหมาะกว่า เพราะอะไร
3. ต้องเลือก account และสิทธิ์ Workers/D1 อย่างไรสำหรับ config นี้
4. แยก credential ของ CLI/CI ออกจาก Worker runtime secrets
5. เสนอคำสั่งตรวจ read-only และบอกว่าแต่ละคำสั่งยังไม่พิสูจน์อะไร

อย่าแสดงค่า environment, token, cookie หรือ credential file
หากจะตรวจ environment ให้รายงานเพียงว่ามีการตั้งค่าหรือไม่ ไม่พิมพ์ค่า
ยังไม่ login/logout, สร้าง/เพิกถอน token, เปิด port, สร้าง D1, migrate หรือ deploy
ห้ามอ้างว่า token active หรือสิทธิ์พร้อมจากการเห็นชื่อ variable หรือ dry-run ผ่าน
ส่ง checklist สั้น พร้อม source/คำสั่งอ้างอิงและสิ่งที่ยังไม่ทดสอบ
```

## ส่งงานก่อนเริ่มบท deploy

- Node/Wrangler version และวิธี login ที่เลือก
- ยืนยันว่า account ตรงกับแบบฝึกหัด โดยไม่แนบ credential
- หากใช้ API token: ชื่อ token, permission/resource scope และวันหมดอายุที่เลือก ไม่แนบค่าลับ
- ผล `whoami`/D1 read หรือ error code ที่ตัดข้อมูลส่วนตัวออกแล้ว
- ข้อจำกัดที่ยังไม่ได้ตรวจ และแผนล้าง/revoke credential เมื่อจบการใช้งาน

เกณฑ์ผ่านคืออธิบาย credential และ account ได้ถูก พร้อมหลักฐานตรวจตามขอบเขตจริง ไม่ใช่เพียงมี screenshot ว่า “login สำเร็จ”


เมื่อ login พร้อมแล้ว ทดลอง [deploy เว็บหลักสูตรตัวอย่างแบบ Static Assets](deploy-course-website-cloudflare.md) ด้วย config แยกและชื่อ Worker ของตนเองได้ โดยไม่ต้องสร้างฐานข้อมูล
