dodo-mcp 1.0.6 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/README.md +74 -20
  2. package/dist/cli/main.js +152 -28
  3. package/dist/cli/main.js.map +1 -1
  4. package/dist/cli/menu.js +2 -2
  5. package/dist/cli/menu.js.map +1 -1
  6. package/dist/config/globalConfig.js +7 -3
  7. package/dist/config/globalConfig.js.map +1 -1
  8. package/dist/config/tunnelConfig.js +2 -1
  9. package/dist/config/tunnelConfig.js.map +1 -1
  10. package/dist/projects/ownerAdmin.js +86 -0
  11. package/dist/projects/ownerAdmin.js.map +1 -0
  12. package/dist/projects/registry.js +90 -9
  13. package/dist/projects/registry.js.map +1 -1
  14. package/dist/security/projectAccess.js +69 -0
  15. package/dist/security/projectAccess.js.map +1 -0
  16. package/dist/security/projectAuthority.js +5 -1
  17. package/dist/security/projectAuthority.js.map +1 -1
  18. package/dist/server/appServer.js +23 -9
  19. package/dist/server/appServer.js.map +1 -1
  20. package/dist/server/bootstrap.js +9 -1
  21. package/dist/server/bootstrap.js.map +1 -1
  22. package/dist/server/configUi/app.css +8 -0
  23. package/dist/server/configUi/app.js +142 -18
  24. package/dist/server/configUi/index.html +50 -13
  25. package/dist/server/installationRuntime.js +6 -2
  26. package/dist/server/installationRuntime.js.map +1 -1
  27. package/dist/server/instructions.js +1 -1
  28. package/dist/server/instructions.js.map +1 -1
  29. package/dist/server/ipcDispatch.js +3 -0
  30. package/dist/server/ipcDispatch.js.map +1 -1
  31. package/dist/server/localConfig.js +80 -13
  32. package/dist/server/localConfig.js.map +1 -1
  33. package/dist/services/ai/subagents.js +1 -1
  34. package/dist/services/ai/subagents.js.map +1 -1
  35. package/dist/services/android/adbBackend.js +106 -0
  36. package/dist/services/android/adbBackend.js.map +1 -0
  37. package/dist/services/android/androidPolicy.js +61 -0
  38. package/dist/services/android/androidPolicy.js.map +1 -0
  39. package/dist/services/android/androidService.js +444 -0
  40. package/dist/services/android/androidService.js.map +1 -0
  41. package/dist/services/android/protocol.js +39 -0
  42. package/dist/services/android/protocol.js.map +1 -0
  43. package/dist/services/multimodal/storage.js +10 -1
  44. package/dist/services/multimodal/storage.js.map +1 -1
  45. package/dist/services/schedules/scheduleService.js +8 -1
  46. package/dist/services/schedules/scheduleService.js.map +1 -1
  47. package/dist/setup/componentProbes.js +7 -1
  48. package/dist/setup/componentProbes.js.map +1 -1
  49. package/dist/setup/setup.js +11 -1
  50. package/dist/setup/setup.js.map +1 -1
  51. package/dist/store/db.js +14 -0
  52. package/dist/store/db.js.map +1 -1
  53. package/dist/tools/agentRuntimeTools.js +2 -3
  54. package/dist/tools/agentRuntimeTools.js.map +1 -1
  55. package/dist/tools/androidTools.js +113 -0
  56. package/dist/tools/androidTools.js.map +1 -0
  57. package/dist/tools/catalog.js +3 -0
  58. package/dist/tools/catalog.js.map +1 -1
  59. package/dist/tools/context.js +85 -5
  60. package/dist/tools/context.js.map +1 -1
  61. package/dist/tools/projectTools.js +1 -1
  62. package/dist/tools/projectTools.js.map +1 -1
  63. package/dist/tools/surface.js +18 -11
  64. package/dist/tools/surface.js.map +1 -1
  65. package/dist/tunnel/control.js +11 -4
  66. package/dist/tunnel/control.js.map +1 -1
  67. package/dist/tunnel/log.js +32 -0
  68. package/dist/tunnel/log.js.map +1 -1
  69. package/dist/tunnel/supervisor.js +103 -24
  70. package/dist/tunnel/supervisor.js.map +1 -1
  71. package/docs/ANDROID.md +105 -28
  72. package/docs/ARCHITECTURE.md +16 -7
  73. package/docs/AUTH.md +6 -0
  74. package/docs/COMPATIBILITY.md +14 -7
  75. package/docs/MANUAL_ACCEPTANCE.md +40 -6
  76. package/docs/PROJECTS.md +73 -2
  77. package/docs/RELEASE_1.1.0.md +69 -0
  78. package/docs/RELEASE_1.2.0.md +75 -0
  79. package/docs/RELEASE_NOTES.md +30 -0
  80. package/docs/SECURITY.md +45 -6
  81. package/docs/TEST_REPORT.md +96 -0
  82. package/docs/TUNNEL.md +79 -16
  83. package/docs/adr/048-persistent-connection-mode.md +3 -1
  84. package/docs/adr/049-android-adb-control.md +52 -0
  85. package/docs/adr/050-cloudflare-local-and-project-access.md +67 -0
  86. package/docs/adr/README.md +2 -0
  87. package/package.json +6 -2
  88. package/schemas/global-config.schema.json +1 -0
  89. package/schemas/tools.compact.json +312 -9
  90. package/schemas/tools.hybrid.json +485 -152
  91. package/schemas/tools.json +3610 -534
@@ -33,6 +33,7 @@ HTTP MCP 127.0.0.1:21730 ──► surface registry ──► policy/invocation
33
33
  ├─ changes and jobs
34
34
  ├─ Git/intelligence/LSP
35
35
  ├─ assistance/multimodal/workflow
36
+ ├─ Android ADB ──► exact-device view/control policy
36
37
  ├─ Context Engine ──► evidence + L0–L6 cache
37
38
  ├─ Memory ──► reviewed evidence + stale lifecycle
38
39
  ├─ Runtime Intelligence ──► durable tasks + bounded evidence
@@ -260,9 +261,9 @@ gateways Report ผูก revision, dataset, dependency lock, config และ h
260
261
 
261
262
  ## Tool surfaces
262
263
 
263
- - Complete capability catalog 125 individual definitions (Core 104 + Advanced Agent Runtime 17 + Sub-agents 4)
264
- - Full live catalog ค่าเริ่มต้น 121 definitions; owner เปิด Sub-agent MCP exposure แล้วเป็น 125
265
- - Compact catalog 19 definitions: overview, discover และ gateways
264
+ - Complete capability catalog 138 individual definitions (Core 104 + Advanced Agent Runtime 17 + Sub-agents 4 + Android ADB 13)
265
+ - Full live catalog ค่าเริ่มต้น 134 definitions; owner เปิด Sub-agent MCP exposure แล้วเป็น 138
266
+ - Compact catalog 20 definitions: overview, discover และ gateways รวม `dodo_mobile`
266
267
  - Hybrid catalog 49 definitions: compact core ตามด้วย direct tools
267
268
 
268
269
  `schemas/tools.json` เป็น complete full schema ส่วน compact และ hybrid เป็น schema แยก
@@ -306,7 +307,14 @@ loopback metrics port และ bounded restart count Token ถูก resolve
306
307
  store หรือ owner-controlled env/private-file reference เมื่อเริ่ม process และส่งผ่าน
307
308
  child environment โดยไม่เข้า argv
308
309
 
309
- managed supervisor เป็น foreground process มี state machine `starting → connecting → connected/backoff → stopped/failed`, private bounded/redacted log และ authenticated singleton IPC `status/logs/stop` การ stop อ้างอิง live `ChildProcess` ที่ supervisor ถืออยู่เท่านั้น Local mode ไม่ spawn process และ `doctor` ตรวจ local/public health โดยไม่จัดการ Cloudflare account หรือ DNS
310
+ การเชื่อมต่อมีสามโหมด: `local` เป็น loopback-only, `external` ใช้ public origin แต่
311
+ เจ้าของเป็นผู้รัน `cloudflared`, และ `tunnel` ให้ DODO เป็นเจ้าของ child process
312
+ เฉพาะ managed supervisor ของ `tunnel` มี state machine
313
+ `starting → connecting → connected/backoff → stopped/failed`, private
314
+ bounded/redacted log และ authenticated singleton IPC `status/logs/stop` การ stop
315
+ อ้างอิง live `ChildProcess` ที่ supervisor ถืออยู่เท่านั้น `local` และ `external`
316
+ ไม่ spawn process ส่วน `doctor` ตรวจ local/public health โดยไม่จัดการ Cloudflare
317
+ account หรือ DNS
310
318
 
311
319
  `TunnelRuntime` ผูก supervisor หนึ่งตัวกับ DODO HTTP process และยอมเริ่มเฉพาะเมื่อ
312
320
  saved mode เป็น Tunnel พร้อม credential reference Runtime ส่งค่าผ่าน `TUNNEL_TOKEN`
@@ -318,9 +326,10 @@ Remote Config ไม่เปลี่ยน bind ของ Local Config แล
318
326
  app `RemoteConfigGateway` ถือ pairing/session digest กับ expiry ใน memory, proxy เฉพาะ
319
327
  `/config`, `/config/assets/*`, `/config/api/*` และส่ง request ไป loopback owner server
320
328
  ด้วย internal capability เดิม CLI เปิด/ต่ออายุผ่าน authenticated installation IPC
321
- เฉพาะเมื่อ persistent Tunnel mode ทำงานอยู่ IPC ไม่รับ credential หรือสลับ connection
322
- mode การหมดอายุล้าง code/session และทำให้ namespace กลับเป็น 404 โดยไม่หยุด
323
- MCP/OAuth/Tunnel
329
+ เมื่อ process ใช้ public mode (`external` หรือ `tunnel`) ใน `external` เจ้าของต้อง
330
+ ดูแล public route เอง ส่วน `tunnel` ต้องมี DODO-owned supervisor ที่กำลังทำงาน IPC
331
+ ไม่รับ credential หรือสลับ connection mode การหมดอายุล้าง code/session และทำให้
332
+ namespace กลับเป็น 404 โดยไม่หยุด MCP/OAuth/Cloudflare process
324
333
 
325
334
  ## Optional services
326
335
 
package/docs/AUTH.md CHANGED
@@ -2,6 +2,12 @@
2
2
 
3
3
  ## MCP OAuth
4
4
 
5
+ > **Simple Project Access Policy** — นอกจาก OAuth scopes และ client ACL แล้ว โปรเจกต์
6
+ > ที่ลงทะเบียนแต่ละตัวมีระดับของตัวเอง (`read`/`edit`/`full`) ที่เป็นเพดานเพิ่มอีกชั้น
7
+ > สิทธิ์จริง = token scopes ∩ grant scopes ∩ (personal ? grant : client ACL) ∩ ระดับโปรเจกต์
8
+ > ระดับนี้บีบได้อย่างเดียว ไม่เคยขยาย และไม่แทนที่ OAuth ดู
9
+ > [docs/PROJECTS.md](PROJECTS.md)
10
+
5
11
  MCP HTTP ใช้ OAuth 2.1 authorization code + PKCE S256:
6
12
 
7
13
  1. client discover protected resource metadata
@@ -8,11 +8,12 @@
8
8
  | macOS | รองรับ coding, HTTP, STDIO, Local Config และ optional native integrations ตาม permission |
9
9
  | Linux | รองรับ coding, HTTP, STDIO, Local Config และ optional integrations ตาม desktop/runtime environment |
10
10
  | Windows | Deferred — มี candidate code/tests แต่ยังไม่ประกาศ native support จนกว่าจะผ่าน Windows 11 จริง |
11
- | Android / Termux | Experimental — core CLI และ text/code MCP เริ่มได้โดยไม่บังคับ Sharp; optional integrations ต้องตรวจแยก |
11
+ | Android / ADB | ควบคุม physical device/emulator จาก macOS/Linux/Windows/Termux ได้เมื่อ Platform-Tools พร้อมและเจ้าของอนุญาต exact serial |
12
+ | Android / Termux host | Experimental — core CLI และ text/code MCP เริ่มได้โดยไม่บังคับ Sharp; optional integrations ต้องตรวจแยก |
12
13
  | MCP HTTP | OAuth protected MCP endpoint ที่ `/mcp` |
13
14
  | MCP STDIO | Full surface เป็นค่าเริ่มต้น |
14
15
  | Local Config | loopback owner control ที่ 21731; เปิด bounded Remote Config `/config` ผ่าน 21730 ได้ครั้งละไม่เกิน 1 ชั่วโมง |
15
- | Cloudflare Tunnel | เลือก persistent `local` หรือ DODO-owned `tunnel`; credential อยู่ใน OS store/reference และ child `cloudflared` หยุดพร้อม DODO |
16
+ | Cloudflare | เลือก persistent `local` (loopback), `external` (Cloudflare Local ที่เจ้าของรันเอง) หรือ `tunnel` (DODO ดูแล process); credential ใช้เฉพาะ `tunnel` และอยู่ใน OS store/reference |
16
17
  | Package | `dodo-mcp` |
17
18
  | CLI | `dodo` |
18
19
 
@@ -27,13 +28,13 @@ Effectful tools และ jobs ยังทำงานใน active workspace
27
28
 
28
29
  ## Tool surfaces
29
30
 
30
- - HTTP default: Compact 19 tools
31
- - STDIO default: Full 121 tools; เปิด Sub-agent MCP exposure แล้วเป็น 125
31
+ - HTTP default: Compact 20 tools
32
+ - STDIO default: Full 134 tools; เปิด Sub-agent MCP exposure แล้วเป็น 138
32
33
  - explicit Hybrid: 49 tools
33
34
 
34
- Complete capability schema มี 125 operations ค่าเริ่มต้น `exposeSubagentsToMcp=false`
35
+ Complete capability schema มี 138 operations ค่าเริ่มต้น `exposeSubagentsToMcp=false`
35
36
  ซ่อน `subagent_spawn/status/result/control` จาก MCP เท่านั้น หน้าเว็บ Chat & Tasks ยัง
36
- ใช้ได้ Compact/Hybrid คงจำนวน 19/49 tool names แต่กรอง operation enum, instructions
37
+ ใช้ได้ Compact/Hybrid คงจำนวน 20/49 tool names แต่กรอง operation enum, instructions
37
38
  และ discover index ให้ตรงกับ live runtime หลังเปลี่ยนค่าต้อง restart และให้ client
38
39
  โหลด catalog ใหม่
39
40
  - explicit override: `--tools compact|full|hybrid`
@@ -55,6 +56,11 @@ Advanced Agent Runtime ใช้ SQLite และ invocation pipeline เดิ
55
56
  exec ต้องใช้ explicit argv และ executable ที่ JobManager รองรับ ส่วน browser/desktop/
56
57
  media/workflow ขึ้นกับ optional capability ของ platform เช่นเดิม
57
58
 
59
+ Android ADB family มี 13 operations ใน Full และรวมอยู่ใน `dodo_mobile` ของ Compact
60
+ owner ต้องอนุญาต exact serial แบบ view/control ผ่าน Local Config หรือ `dodo android`
61
+ ก่อน Pair/connect/root และ ADB server management ไม่อยู่ใน MCP catalog ส่วน install/push
62
+ ใช้ expected SHA-256 และ private staging ตาม shared workspace guards
63
+
58
64
  ## Optional capabilities
59
65
 
60
66
  Desktop, browser, media, speech, LSP และ OS sandbox ต้องตรวจ dependency และ OS permission ด้วย `dodo setup --check` หรือ `dodo doctor` ระบบจะรายงาน `NOT_SUPPORTED` เมื่อ environment ยังไม่พร้อม และจะไม่เปิด permission หรือดาวน์โหลด model โดยอัตโนมัติ
@@ -69,7 +75,8 @@ desktop และ browser ยังไม่ถือว่ารองรับ
69
75
 
70
76
  `dodo setup --components cloudflared` ตรวจ executable ได้ทุก OS การติดตั้งอัตโนมัติ
71
77
  รองรับ Homebrew บน macOS ส่วน Linux/Windows ใช้ signed official package ที่เจ้าของติดตั้งเอง
72
- โหมด Tunnel ต้องมี public origin และ credential reference ที่ผ่านการตรวจแล้ว ค่า
78
+ โหมด Cloudflare Local ต้องมี public origin แต่ไม่รับ credential และไม่ supervise
79
+ `cloudflared` โหมด DODO Tunnel ต้องมี public origin และ credential reference ที่ผ่านการตรวจแล้ว ค่า
73
80
  `--os-credential` ใช้ macOS Keychain, Windows Credential Manager หรือ Linux Secret
74
81
  Service ส่วน env/file references มีไว้สำหรับ owner-controlled headless environment
75
82
 
@@ -2,6 +2,10 @@
2
2
 
3
3
  ผล manual ต้องบันทึกเป็น `MANUAL_PASS` หรือ `MANUAL_NOT_RUN` พร้อมวันเวลาและ environment ห้ามเดาผลจาก automated test
4
4
 
5
+ สถานะ release 1.2.0: UI/authority/connection-mode fixtures ผ่านอัตโนมัติ แต่การใช้
6
+ **Cloudflare Local** และ **DODO Tunnel** ผ่าน public hostname จริงยัง
7
+ `MANUAL_NOT_RUN` จนกว่าเจ้าของจะทดสอบด้วย Tunnel/DNS/credential จริง
8
+
5
9
  สถานะล่าสุดของ owner-state setup/import gate: `MANUAL_NOT_RUN` (2026-09-14) ชุด automated ใช้ fixture แยกและไม่แตะ config/OAuth/tunnel ของผู้ใช้
6
10
 
7
11
  สถานะ live Cloudflare connection smoke ของรุ่น 1.0.2: `MANUAL_PASS` (2026-09-15) บน
@@ -26,18 +30,19 @@ connection smoke เดิมไม่ได้อ้างว่า AI client
26
30
  10. ตรวจ `dodo tunnel doctor` แยก local/public health และไม่กล่าวว่า AI client connected
27
31
  11. ตรวจ process list ว่า argv ไม่มี token และ `dodo tunnel logs`/audit/config ไม่มี token
28
32
  12. ทดสอบ OAuth + MCP ผ่าน public origin แล้วหยุด DODO; ยืนยัน owned child หยุดตาม
29
- 13. เปิด Local Config เลือก Local แล้ว restart; ตรวจว่าไม่เริ่ม cloudflared และ Active MCP URL เป็น loopback
30
- 14. เลือก Tunnel ผ่าน Local Config พร้อม write-only token แล้ว restart; ตรวจว่าช่องไม่ถูกเติมกลับและ endpoint เป็น public
31
- 15. บันทึก macOS และ Linux Docker แยก environment; Windows manual result แยกตามเครื่องจริง
33
+ 13. เปิด Local Config เลือก **เฉพาะเครื่อง (Loopback)** แล้ว restart; ตรวจว่าไม่เริ่ม cloudflared และ Active MCP URL เป็น loopback
34
+ 14. เลือก **Cloudflare Local (ติดตั้งในเครื่อง)** พร้อม public origin; ตรวจว่าช่อง token ถูกปิด, DODO ไม่เริ่ม/หยุด cloudflared และ endpoint เป็น public หลัง restart
35
+ 15. เลือก **DODO Tunnel** พร้อม write-only token แล้ว restart; ตรวจว่าช่องไม่ถูกเติมกลับและ endpoint เป็น public
36
+ 16. บันทึก macOS และ Linux Docker แยก environment; Windows manual result แยกตามเครื่องจริง
32
37
 
33
- ## Remote Config ผ่าน Tunnel
38
+ ## Remote Config ผ่าน Cloudflare
34
39
 
35
40
  Automated Chromium fixture ผ่านแล้วทั้ง 1440×900 และ 390×844 โดยใช้ isolated
36
41
  loopback public-origin fixture: จับคู่, dashboard/assets/API, workspace-bound mutation,
37
42
  หมดอายุและปิดเป็น 404 ทำงานจริง การตรวจผ่าน public Cloudflare hostname จริงยัง
38
43
  `MANUAL_NOT_RUN`
39
44
 
40
- 1. เลือก Tunnel แบบ persistent และรัน DODO จน `dodo tunnel status` รายงาน connected
45
+ 1. ทดสอบสองรอบ: (ก) Cloudflare Local โดยเจ้าของรัน tunnel เอง และ (ข) DODO Tunnel จน `dodo tunnel status` รายงาน connected
41
46
  2. จาก terminal อื่นรัน `dodo --web`; คำสั่งต้องไม่ถามหรือส่ง Tunnel token ผ่าน IPC
42
47
  3. ตรวจว่า process ไม่ restart และ MCP/OAuth/workspace epoch เดิมไม่เปลี่ยน
43
48
  4. เปิด URL `/config` จากอีกอุปกรณ์ ตรวจว่า URL ไม่มี query/fragment secret
@@ -47,7 +52,7 @@ loopback public-origin fixture: จับคู่, dashboard/assets/API, worksp
47
52
  8. รัน `dodo --web` อีกครั้ง ตรวจ session เดิมถูกยกเลิกและได้ code ใหม่
48
53
  9. รัน `dodo web --close` ตรวจ `/config`, assets และ API เป็น 404 แต่ `/healthz`, OAuth และ `/mcp` ยังอยู่
49
54
  10. เปิดใหม่แล้วรอ 1 ชั่วโมง ตรวจ namespace ปิดเองโดยไม่หยุด MCP/Tunnel
50
- 11. เปลี่ยน persistent mode เป็น Local แล้ว restart; `dodo --web` ต้องถูกปฏิเสธและไม่เริ่ม Tunnel เอง
55
+ 11. เปลี่ยน persistent mode เป็นเฉพาะเครื่อง (Loopback) แล้ว restart; `dodo --web` ต้องถูกปฏิเสธและไม่เริ่ม Tunnel เอง
51
56
  12. ตรวจ config, audit, tunnel log, browser local/session storage และ process argv ว่าไม่มี Tunnel token, pairing code หรือ session token
52
57
 
53
58
  ## Setup foundation
@@ -88,6 +93,17 @@ loopback public-origin fixture: จับคู่, dashboard/assets/API, worksp
88
93
 
89
94
  ## Local Config
90
95
 
96
+ 0b. โปรเจกต์และระดับการเข้าถึง (2026-09-16) — **MANUAL_NOT_RUN**:
97
+ บนเครื่อง Windows จริงที่ใช้ tunnel จริง ให้ตรวจว่า
98
+ (ก) เพิ่มโปรเจกต์จากหน้า Projects ด้วย path + ชื่อ + ระดับเดียว แล้วใช้งานได้ทันที
99
+ โดยไม่ต้องตั้ง client ACL/trust เพิ่ม
100
+ (ข) สั่ง AI ว่า "ใช้ DODO แก้โปรเจกต์ auto-upload" แล้ว AI resolve ชื่อได้เอง
101
+ และแก้ไฟล์ในโปรเจกต์ที่ถูกต้อง
102
+ (ค) ตั้งระดับเป็น `read` แล้วคำสั่งเขียน/รันถูกปฏิเสธจริง
103
+ (ง) แถบสถานะ Tunnel ไม่กระพริบระหว่างใช้งานต่อเนื่อง และ `dodo tunnel status`
104
+ แสดง phase/`lastReadyAt` ที่สอดคล้องกับความเป็นจริง
105
+ (จ) banner ตอน start ไม่พูดถึง ACL เมื่ออยู่ในโหมดส่วนตัว
106
+
91
107
  0. UI ใหม่ (2026-09-14): ตรวจบนเครื่องจริงว่า (ก) nav 8 หน้าใช้ได้ทั้ง desktop และมือถือ
92
108
  (ข) tooltip `?` เปิดด้วยการแตะบนอุปกรณ์ touch จริงและ screen reader อ่านได้
93
109
  (ค) กล่องยืนยัน SweetAlert แสดงก่อนการลบ/ยกเลิก/เปลี่ยนโหมดทุกครั้ง
@@ -301,6 +317,24 @@ Automated catalog/API/Chromium/fresh-package fixtures: **AUTOMATED_PASS**
301
317
 
302
318
  เพิ่ม MCP connection ใน client ที่ต้องการ ใช้ OAuth, scan tools และบันทึกจำนวน tools ที่ client แสดงจริง หาก catalog ถูก cache ให้ recreate connection ตาม client instructions
303
319
 
320
+ ## Android / ADB
321
+
322
+ ใช้ fixture device/emulator ที่ไม่มีข้อมูลเจ้าของ แล้วบันทึก serial แบบ redact เมื่อเผยแพร่:
323
+
324
+ 1. ตรวจ `dodo setup --check --components adb` และ `dodo android devices`
325
+ 2. เปิด view ชั่วคราวให้ exact serial แล้วทดสอบ info, capture, UI, logcat, packages และ bounded file read
326
+ 3. ยืนยันว่า serial อื่นและ read-only OAuth token เข้าไม่ได้
327
+ 4. เปิด control แล้วทดสอบ tap/key/app launch บน fixture app โดย capture ใหม่หลังทุก action
328
+ 5. สร้าง APK/file fixture ใน workspace อ่าน SHA-256 แล้วทดสอบ install/push
329
+ 6. เปลี่ยน source หลังอ่าน hash และตรวจว่า `FILE_CHANGED` เกิดก่อน ADB effect
330
+ 7. ทดสอบ advanced device-side shell กับ harmless `echo` และยืนยันว่า pair/connect/root ถูกปฏิเสธ
331
+ 8. ถอนสิทธิ์ระหว่าง session แล้วตรวจ action ถัดไปถูกปฏิเสธ
332
+ 9. ตรวจ Local Config ที่ desktop และ 390px รวม keyboard/focus/error state
333
+ 10. ลบ fixture app/file และรัน `dodo android disable`
334
+
335
+ Physical Android device/emulator: **MANUAL_NOT_RUN** จนกว่าจะทำรายการนี้บน hardware
336
+ หรือ emulator จริง Automated FakeAdb ไม่เปลี่ยนสถานะ manual gate
337
+
304
338
  ## DodoBench และ release gate
305
339
 
306
340
  Automated fixtures: รัน `npm run bench`, `npm run release:gate` บน macOS และ
package/docs/PROJECTS.md CHANGED
@@ -7,13 +7,84 @@ project ID แบบ opaque และคงที่เพื่ออ้าง
7
7
  ## คำสั่ง
8
8
 
9
9
  ```bash
10
- dodo project add /absolute/path/to/project
11
- dodo project add /absolute/path/to/project --name "Web application"
10
+ dodo project add /absolute/path/to/project --name "auto-upload" --access full
11
+ dodo project add "C:\\Users\\User\\Desktop\\auto-upload" --name "auto-upload" --access edit
12
+ dodo project access "auto-upload" --mode edit
12
13
  dodo project list
13
14
  dodo project info prj_xxxxxxxxxxxx
14
15
  dodo project remove prj_xxxxxxxxxxxx --yes
15
16
  ```
16
17
 
18
+ `dodo project access` รับได้ทั้ง **ชื่อโปรเจกต์** และ project ID เว็บ Local Config
19
+ และ CLI เรียก owner-administration service ตัวเดียวกัน (`src/projects/ownerAdmin.ts`)
20
+ จึงใช้ validation, การยืนยันและ audit ชุดเดียวกัน ไม่มี permission logic แยกสองชุด
21
+
22
+ ## Simple Project Access Policy
23
+
24
+ ตอนเพิ่มโปรเจกต์ให้เลือก **ระดับการเข้าถึง** เพียงค่าเดียว:
25
+
26
+ | ระดับ | ความหมาย | OAuth scopes ที่เป็นเพดาน |
27
+ |---|---|---|
28
+ | `read` | อ่านอย่างเดียว — อ่าน ค้นหา วิเคราะห์ | `dodo:read` |
29
+ | `edit` | แก้ไข — อ่านและแก้ไฟล์ | `dodo:read` + `dodo:write` |
30
+ | `full` | ทำงานเต็มรูปแบบ — อ่าน แก้ไฟล์ และรันคำสั่ง/ทดสอบ | `dodo:read` + `dodo:write` + `dodo:exec` |
31
+
32
+ ระดับนี้เป็น **เพดาน ไม่ใช่การให้สิทธิ์** สิทธิ์จริงคือส่วนที่ทับกันของ
33
+
34
+ ```text
35
+ OAuth token scopes ∩ grant scopes ∩ (personal ? grant : client ACL ของ workspace) ∩ ระดับของโปรเจกต์
36
+ ```
37
+
38
+ ดังนั้น token ที่มีแค่ `dodo:read` จะยังอ่านได้อย่างเดียวแม้โปรเจกต์เป็น `full`
39
+ และโปรเจกต์ `read` ก็เขียนไม่ได้แม้ token จะมี `dodo:write` การเปลี่ยนระดับไม่แตะ
40
+ OAuth, trust, approval, path/secret guards, expected hash, sandbox หรือ audit
41
+
42
+ ใน **โหมดส่วนตัว** (ค่าเริ่มต้น) เพิ่มโปรเจกต์แล้วใช้ได้ทันที ไม่ต้องตั้ง client ACL
43
+ หรือ trust ซ้ำต่อโปรเจกต์ ใน **โหมดแยกสิทธิ์** ยังต้องอนุญาต client ต่อโปรเจกต์ตามเดิม
44
+ และระดับของโปรเจกต์จะบีบให้แคบลงอีกชั้น (ไม่เคยขยาย)
45
+
46
+ ### การอัปเกรดจากรุ่นก่อนหน้า
47
+
48
+ โปรเจกต์ที่ลงทะเบียนไว้ก่อนมีนโยบายนี้จะได้ระดับ `full` — เพราะ `full` **ไม่บีบอะไรเพิ่ม**
49
+ สิทธิ์จริงจึงเท่าเดิมทุกประการ (ยังถูกจำกัดด้วย OAuth scopes, client ACL ในโหมดแยกสิทธิ์,
50
+ trust และ guards ทั้งหมด) การบีบให้แคบลงเงียบ ๆ จะเป็นการถอนสิทธิ์ที่เจ้าของไม่ได้สั่ง
51
+ ระดับจะแสดงในหน้า Projects และ `dodo project list` เพื่อให้ลดลงได้เอง
52
+
53
+ ## เรียกโปรเจกต์ด้วยชื่อ
54
+
55
+ ชื่อโปรเจกต์ต้องไม่ซ้ำกัน (เทียบแบบไม่สนตัวพิมพ์) เพราะใช้อ้างอิงโปรเจกต์ในการสั่งงาน AI
56
+
57
+ พูดกับ AI ได้ตรง ๆ ว่า **"ใช้ DODO แก้โปรเจกต์ auto-upload"** แล้ว AI จะ:
58
+
59
+ 1. เรียก `project_overview` พร้อม `targetProject: "auto-upload"` — DODO resolve ชื่อ
60
+ เป็นโปรเจกต์เดียวที่ client นั้นมีสิทธิ์เห็น
61
+ 2. รับ `workspaceId` / `workspaceEpoch` ของโปรเจกต์นั้นกลับมา
62
+ 3. ส่ง `targetProject` พร้อม context นั้นไปกับทุก operation ถัดไป
63
+
64
+ ```jsonc
65
+ project_overview({ targetProject: "auto-upload" })
66
+
67
+ dodo_write({
68
+ targetProject: "auto-upload",
69
+ workspaceId: "ws_…", workspaceEpoch: "boot_…",
70
+ operation: "edit_file",
71
+ args: { /* … */ }
72
+ })
73
+ ```
74
+
75
+ กฎของการ resolve:
76
+
77
+ - เทียบชื่อแบบตัดช่องว่างหัวท้ายและไม่สนตัวพิมพ์
78
+ - ค้นเฉพาะโปรเจกต์ที่ principal นั้นอ่านได้อยู่แล้ว จึงไม่เปิดเผยชื่อหรือ path
79
+ ของโปรเจกต์ที่ไม่มีสิทธิ์
80
+ - ชื่อกำกวม (เช่นข้อมูลเก่าที่ชื่อซ้ำ) → error พร้อมรายชื่อ candidate ที่เห็นได้ ไม่เดา
81
+ - ส่งทั้ง `targetProjectId` และ `targetProject` ที่ชี้คนละโปรเจกต์ → ปฏิเสธ
82
+ - `targetProject` อยู่ระดับบนสุดเท่านั้น ใส่ใน `args` ที่ซ้อนอยู่จะถูกปฏิเสธ
83
+ - หลัง resolve แล้วผ่าน invocation/security pipeline เดิมครบทุกด่าน
84
+
85
+ เจ้าของไม่ต้องรู้หรือพิมพ์ project ID เอง (`targetProjectId` ยังใช้ได้ตามเดิมเพื่อ
86
+ ความเข้ากันได้ย้อนหลัง)
87
+
17
88
  ทุกคำสั่งรองรับข้อมูล local owner เท่านั้น `list`, `info` และ `add` รองรับ
18
89
  `--json`; `remove` ต้องมี `--yes` หลังตรวจ project ID และ path แล้ว
19
90
 
@@ -0,0 +1,69 @@
1
+ # DODO MCP 1.1.0
2
+
3
+ รุ่น 1.1.0 เพิ่ม Android ADB tool family ให้ AI ตรวจและควบคุม physical device หรือ
4
+ emulator ที่เจ้าของอนุญาต พร้อม Local Config และ CLI สำหรับ exact-device permission
5
+
6
+ ## ความสามารถใหม่
7
+
8
+ - Full surface เพิ่ม 13 operations: status, device list/info, screenshot, UI hierarchy,
9
+ logcat, packages, bounded file read, input action, app action, APK install, file push
10
+ และ advanced device-side ADB
11
+ - HTTP Compact เพิ่ม `dodo_mobile` gateway ทำให้ Compact มี 20 tools และยังเข้าถึง
12
+ capability definitions ครบ 138 รายการ; Hybrid คง 49 tools
13
+ - `android_capture` คืน MCP PNG image block จริง และสร้าง snapshot อายุ 30 วินาทีที่
14
+ ผูก client/device/policy สำหรับ tap/swipe/text/key
15
+ - หน้า Local Config ค้นหาอุปกรณ์ เลือก exact serial และตั้ง `view`/`control` ได้
16
+ - CLI เพิ่ม `dodo android devices|status|allow|disable`
17
+ - setup เพิ่ม component `adb` และ deep capability probe ที่เรียกเฉพาะ `adb version`
18
+
19
+ ## Security
20
+
21
+ - ADB ปิดโดยค่าเริ่มต้น และ trusted/bypass ไม่เปิดสิทธิ์นี้
22
+ - view/control grant ทำได้เฉพาะ local owner; persistent grant จำระดับ installation
23
+ ส่วน temporary grant ผูก workspace/epoch
24
+ - ทุก MCP call ยังผ่าน OAuth, `dodo:exec`, project/workspace context, trust/approval,
25
+ idempotency, audit และ exact serial allowlist
26
+ - input action ใช้ fresh client-bound screenshot; password UI values ถูก redact
27
+ - APK/push source ผ่าน workspace path/secret/symlink/hardlink guards, expected SHA-256
28
+ และ private staging copy ที่ลบหลังจบ
29
+ - ไม่ expose pair/connect/root, ADB server management หรือ port forwarding ให้ MCP
30
+ - device-side shell มีผลด้วยสิทธิ์ Android shell user และไม่ใช่ sandbox
31
+
32
+ ## Tool surfaces
33
+
34
+ | Surface | จำนวน |
35
+ |---|---:|
36
+ | Complete Full schema | 138 |
37
+ | Full live default (ซ่อน Sub-agent 4 operations) | 134 |
38
+ | Compact HTTP | 20 |
39
+ | Hybrid | 49 |
40
+
41
+ Generated tools/list-equivalent schema sizes:
42
+
43
+ - Full: 475,008 bytes
44
+ - Compact: 55,373 bytes
45
+ - Hybrid: 125,901 bytes
46
+
47
+ ## อัปเดตและเริ่มใช้
48
+
49
+ ```bash
50
+ npm install -g dodo-mcp@1.1.0
51
+ dodo setup --check --components adb
52
+ dodo android devices
53
+ dodo android allow --device SERIAL --mode control --persist --yes
54
+ dodo start
55
+ ```
56
+
57
+ หลัง restart ให้ remote MCP client refresh/recreate connection ตามพฤติกรรมของ client
58
+ เพื่อรับ `dodo_mobile` และ schema ใหม่ ดูขั้นตอนทั้งหมดใน [ANDROID.md](ANDROID.md)
59
+
60
+ ## ผลตรวจรับ
61
+
62
+ - build/typecheck/lint: `AUTOMATED_PASS`
63
+ - core/integration/security/compatibility: `AUTOMATED_PASS` — 698 passed,
64
+ 35 skipped, 0 failed
65
+ - packaging: `AUTOMATED_PASS` — 16/16
66
+ - Android focused unit/security/HTTP+OAuth/UI: `AUTOMATED_PASS`
67
+ - production dependency audit: `AUTOMATED_PASS` — 0 vulnerabilities
68
+ - physical Android device/emulator with owner hardware: `MANUAL_NOT_RUN`
69
+ - Android/Termux host platform acceptance: `MANUAL_NOT_RUN`
@@ -0,0 +1,75 @@
1
+ # DODO MCP 1.2.0
2
+
3
+ รุ่น 1.2.0 แก้ความกำกวมระหว่าง MCP เฉพาะเครื่องกับ `cloudflared` ที่ติดตั้งในเครื่อง
4
+ และนำสิทธิ์ `อ่าน / แก้ไข / เต็ม` กลับมาแสดงในการ์ดของทุกโปรเจกต์
5
+
6
+ ## การเชื่อมต่อสามโหมด
7
+
8
+ | หน้าเว็บ | ค่า config | ผู้ดูแล `cloudflared` | ใช้ Tunnel token ใน DODO |
9
+ |---|---|---|---|
10
+ | เฉพาะเครื่อง (Loopback) | `local` | ไม่มี | ไม่ใช้ |
11
+ | Cloudflare Local (ติดตั้งในเครื่อง) | `external` | ผู้ใช้ | ไม่รับและไม่อ่าน |
12
+ | DODO Tunnel | `tunnel` | DODO | write-only ผ่าน OS credential store |
13
+
14
+ ```bash
15
+ # AI ในเครื่องเท่านั้น
16
+ dodo tunnel configure --loopback
17
+
18
+ # เจ้าของติดตั้งและรัน cloudflared เอง
19
+ dodo tunnel configure --cloudflare-local --public-url https://mcp.example.com
20
+
21
+ # DODO เริ่มและหยุด cloudflared พร้อมตัวเอง
22
+ dodo tunnel configure --tunnel --public-url https://mcp.example.com --os-credential
23
+ ```
24
+
25
+ ทั้ง Cloudflare Local และ DODO Tunnel ใช้ public origin เป็น OAuth issuer/MCP URL
26
+ แต่มีเพียง DODO Tunnel ที่แตะ credential หรือ supervisor Cloudflare Local ไม่อ้างว่า
27
+ connected เพียงเพราะบันทึก URL และ `dodo tunnel doctor` รายงาน process ownership แยก
28
+ จาก public health
29
+
30
+ ## สิทธิ์แต่ละโปรเจกต์
31
+
32
+ หน้า **โปรเจกต์** แสดงระดับของแต่ละรายการเสมอ:
33
+
34
+ - `read` — อ่าน ค้นหา วิเคราะห์
35
+ - `edit` — เพิ่มสิทธิ์แก้ไฟล์
36
+ - `full` — เพิ่มสิทธิ์รันคำสั่งและทดสอบ
37
+
38
+ ระดับเป็นเพดานเท่านั้น สิทธิ์จริงยังเป็น intersection ของ OAuth token, live grant,
39
+ managed ACL (เมื่อเปิดโหมด managed) และระดับโปรเจกต์ จึงไม่ทำให้ read-only token เขียน
40
+ ได้ และไม่ข้าม workspace ID/epoch, approval, sandbox, path/secret guards, expected hash,
41
+ idempotency หรือ audit
42
+
43
+ โปรเจกต์เดิม migrate เป็น `full` เพื่อไม่ถอนสิทธิ์เงียบ ๆ เจ้าของลดระดับได้จากการ์ด
44
+ โปรเจกต์หรือ CLI:
45
+
46
+ ```bash
47
+ dodo project access "ชื่อโปรเจกต์" --mode read
48
+ dodo project access "ชื่อโปรเจกต์" --mode edit
49
+ dodo project access "ชื่อโปรเจกต์" --mode full
50
+ ```
51
+
52
+ ## อัปเดต
53
+
54
+ ```bash
55
+ npm install -g dodo-mcp@1.2.0
56
+ dodo --version
57
+ dodo start
58
+ ```
59
+
60
+ หลังอัปเดตให้ restart DODO ค่า connection mode หรือ public origin ที่เปลี่ยนจากหน้าเว็บ
61
+ ไม่มีผลกับ process เดิมจนกว่าจะ restart
62
+
63
+ ## ผลตรวจรับ
64
+
65
+ - typecheck/lint: `AUTOMATED_PASS`
66
+ - focused connection/project/OAuth/security/Chromium tests: `AUTOMATED_PASS` —
67
+ 92 passed, 1 skipped, 0 failed
68
+ - core/integration/security/compatibility: `AUTOMATED_PASS` — 726 passed,
69
+ 35 skipped, 0 failed
70
+ - packaging: `AUTOMATED_PASS` — 16/16
71
+ - production dependency audit: `AUTOMATED_PASS` — 0 vulnerabilities
72
+ - immutable release gate และ fresh registry install: ดูผลล่าสุดใน
73
+ [TEST_REPORT.md](TEST_REPORT.md) (ยังไม่อ้างว่าผ่านจนกว่าจะ publish/verify จริง)
74
+ - Cloudflare Local ผ่าน public hostname จริง: `MANUAL_NOT_RUN`
75
+ - DODO Tunnel credential/public hostname จริงของ 1.2.0: `MANUAL_NOT_RUN`
@@ -1,5 +1,35 @@
1
1
  # DODO MCP — Release Notes
2
2
 
3
+ ## 1.2.0 — Cloudflare Local และสิทธิ์ต่อโปรเจกต์ที่มองเห็นได้
4
+
5
+ - แยกการเชื่อมต่อเป็นสามโหมด: เฉพาะเครื่อง (Loopback), Cloudflare Local ที่ผู้ใช้
6
+ รัน `cloudflared` เอง และ DODO Tunnel ที่ DODO ดูแล process
7
+ - Cloudflare Local ใช้ public MCP/OAuth URL โดยไม่รับ/อ่าน Tunnel token และไม่รายงาน
8
+ supervisor connected จาก config อย่างเดียว
9
+ - หน้า Projects แสดงและบันทึกระดับ `read` / `edit` / `full` ของทุกโปรเจกต์จริง
10
+ ในโหมดส่วนตัว ไม่ต้องตามหา Trust/Client ACL หลายส่วน
11
+ - ระดับโปรเจกต์เป็นเพดานที่ intersect กับ OAuth/grant/managed ACL เท่านั้น ไม่เพิ่ม
12
+ สิทธิ์ ไม่ข้าม approval, sandbox, workspace context หรือ file guards
13
+ - Remote Config เปิดผ่าน public Cloudflare ได้ทั้ง owner-managed และ DODO-owned mode;
14
+ loopback-only ยังคงปฏิเสธ
15
+
16
+ ติดตั้งด้วย `npm install -g dodo-mcp@1.2.0` แล้ว restart DODO
17
+
18
+ ## 1.1.0 — Android device tools through owner-approved ADB
19
+
20
+ - เพิ่ม Full 13 `android_*` operations และ Compact `dodo_mobile` gateway สำหรับ
21
+ device info, screenshot/UI, logcat/packages/files, input/app actions, APK install,
22
+ file push และ bounded device-side ADB
23
+ - เพิ่ม exact-serial `off|view|control` policy ผ่าน CLI และ Local Config โดย persistent
24
+ permission เป็นระดับ installation และ temporary permission ผูก workspace/epoch
25
+ - screenshot คืน MCP image block พร้อม caller-bound snapshot; UI password ถูก redact
26
+ - APK/push บังคับ expected SHA-256 และ private staging copy ภายใต้ shared file guards
27
+ - เพิ่ม `adb` setup component, docs, unit/security/HTTP+OAuth/Chromium/packaging tests
28
+ - Complete Full 138, live Full default 134, Compact 20 และ Hybrid คง 49 tools
29
+
30
+ ติดตั้งด้วย `npm install -g dodo-mcp@1.1.0` แล้ว restart DODO และ refresh/recreate MCP
31
+ connection เพื่อโหลด catalog ใหม่ การ pair/connect และยืนยัน RSA ยังเป็น owner action
32
+
3
33
  ## 1.0.6 — Android-safe CLI startup
4
34
 
5
35
  - เปลี่ยน raster image backend เป็น lazy load เพื่อให้ core CLI, transport และ
package/docs/SECURITY.md CHANGED
@@ -67,6 +67,20 @@ Launcher mode ไม่มี active AI workspace และไม่ใช้ CW
67
67
  private inert root ไม่ถูกแสดงต่อ client; OAuth และ authenticated catalog เปิดให้ตั้ง
68
68
  connection ได้ โหมดส่วนตัวซึ่งเป็นค่าเริ่มต้นอนุญาต owner-approved OAuth installation
69
69
  ให้ใช้ target ที่ owner ลงทะเบียนตาม token/profile scopes โดยไม่ต้องสร้าง ACL ซ้ำ
70
+ Simple Project Access Policy เพิ่มเพดานอีกหนึ่งชั้นต่อโปรเจกต์ (`read`/`edit`/`full` →
71
+ `dodo:read` / `+dodo:write` / `+dodo:exec`) บังคับที่จุดเดียวใน
72
+ `src/security/projectAuthority.ts` โดย intersect กับ token scopes, grant scopes และ
73
+ client ACL สิทธิ์จริงจึงเป็นส่วนที่ทับกันทั้งหมด ระดับนี้ **บีบได้อย่างเดียว ไม่เคยขยาย**:
74
+ token ที่มีแค่ `dodo:read` ยังเขียนหรือ exec ไม่ได้แม้โปรเจกต์เป็น `full` workspace ที่
75
+ ไม่ได้อยู่ใน registry (launcher root, stdio cwd) ไม่ถูกบีบเพิ่ม และค่าที่อ่านไม่ออกจะถูก
76
+ ตีเป็น `read` (fail closed) การเพิ่มโปรเจกต์กับการตั้งระดับ commit ใน transaction เดียว
77
+ จึงไม่มีโปรเจกต์ที่ลงทะเบียนครึ่งเดียว
78
+
79
+ `targetProject` (ชื่อโปรเจกต์) route เหมือน `targetProjectId` ทุกประการ: resolve ก่อน
80
+ เข้า pipeline, ค้นเฉพาะโปรเจกต์ที่ principal อ่านได้อยู่แล้ว (ไม่เปิดเผยโปรเจกต์ที่ไม่มีสิทธิ์),
81
+ ชื่อกำกวมหรือ id/ชื่อขัดกันถูกปฏิเสธ, รับเฉพาะ top level และถูกปฏิเสธใน nested args
82
+ ผ่านรายการ routing key ชุดเดียวกัน (`ROUTING_CONTEXT_KEYS`) ทุก dispatcher
83
+
70
84
  โหมด managed ต้องมี target ACL แยกตามเดิม Mutation จาก Local Config ยังผูกกับ current control context
71
85
  workspace/epoch การเลือก startup project เป็น preference เท่านั้นและไม่คัดลอก trust,
72
86
  OAuth grant, client ACL, approval, jobs หรือ workspace epoch
@@ -220,13 +234,37 @@ Full จะไม่ register สี่ Sub-agent definitions และ Compact/
220
234
  ไม่เปลี่ยน trust/profile policy และไม่ข้าม approvals, sandbox, path/secret guards หรือ
221
235
  workspace context ทุก call ที่เปิดให้เห็นยังผ่าน invocation pipeline เดิมทั้งหมด
222
236
 
237
+ ## Android / ADB access
238
+
239
+ ADB ปิดโดยค่าเริ่มต้น การมี `adb` หรืออุปกรณ์ที่เชื่อมอยู่ไม่ใช่ permission เจ้าของต้อง
240
+ เลือก `view` หรือ `control` พร้อม exact serial ผ่าน private Local Config/CLI ก่อน
241
+ temporary policy ผูก workspace/epoch ส่วน persistent policy ผูก installation และถอนได้
242
+ ด้วย `dodo android disable` ทุก MCP operation ยังตรวจ live OAuth grant, `dodo:exec`,
243
+ target project/workspace context, trust/approval, idempotency และ audit ตามปกติ
244
+
245
+ การจับภาพสร้าง snapshot อายุสั้นที่ผูก caller, serial และ policy; input action ใช้และ
246
+ invalidate snapshot ก่อน dispatch UI hierarchy ปิดบัง password field แต่ข้อมูลจาก
247
+ อุปกรณ์ทั้งหมดถือเป็น private untrusted content และไม่ถูกเขียนลง audit log
248
+
249
+ `android_install`/`android_push` ตรวจ source ผ่าน shared workspace/secret/link policy,
250
+ บังคับ expected SHA-256 และส่ง private staging copy ให้ ADB Pair/connect/root, server
251
+ management และ port forwarding เป็น owner action นอก MCP `android_adb` รับเฉพาะ
252
+ device-side command families แบบ bounded และใช้ `shell:false` ที่ฝั่ง host อย่างไรก็ตาม
253
+ device-side shell สามารถเปลี่ยนข้อมูลด้วยสิทธิ์ Android shell user ได้และไม่ใช่ sandbox
254
+
223
255
  ## Cloudflare Tunnel
224
256
 
225
257
  เจ้าของเป็นผู้สร้าง remotely-managed Tunnel, hostname และ DNS DODO ไม่ใช้ Cloudflare
226
- API DODO บันทึกการเลือกแบบ exclusive เป็น `local` หรือ `tunnel` ใน private global
227
- config หากเลือก Tunnel ทุก `dodo start` จะเริ่มเฉพาะ live `cloudflared` child ของ
228
- process นั้นและหยุด child พร้อม DODO หาก credential/readiness ไม่พร้อม startup จะ
229
- fail closed และไม่ fallback ไป Local
258
+ API DODO บันทึกการเลือกแบบ exclusive หนึ่งค่าใน private global config: `local` คือ
259
+ loopback-only, `external` คือ Cloudflare Local ที่เจ้าของรัน `cloudflared` เอง และ
260
+ `tunnel` คือ DODO-owned process เฉพาะ `tunnel` เท่านั้นที่ DODO อ่าน credential,
261
+ เริ่ม child, ตรวจ readiness และหยุด child พร้อม DODO หาก credential/readiness ไม่พร้อม
262
+ startup จะ fail closed และไม่ fallback ไปโหมดอื่น
263
+
264
+ ใน `external` DODO ใช้ public HTTPS origin เป็น OAuth issuer/MCP URL แต่ไม่รับ token,
265
+ ไม่ค้น process และไม่อ้างว่า Tunnel connected จากค่า config เพียงอย่างเดียว เจ้าของ
266
+ ต้องดูแล process และ route เอง `dodo tunnel doctor` แยก public health ออกจาก process
267
+ ownership และ public health ไม่ใช่หลักฐานว่า AI client เชื่อมอยู่
230
268
 
231
269
  Token ถูกเก็บใน macOS Keychain, Windows Credential Manager หรือ Linux Secret Service
232
270
  เมื่อใช้ `--os-credential`; config เก็บ opaque locator เท่านั้น Owner-controlled
@@ -235,11 +273,12 @@ headless deployment อาจเลือก env/private-file reference โด
235
273
  browser storage หรือ setup receipt ค่า `TUNNEL_TOKEN` และ `TUNNEL_TOKEN_FILE` ถูก
236
274
  ปฏิเสธจาก environment ของ MCP jobs เสมอ
237
275
 
238
- Local Config รับ token แบบ write-only เฉพาะ POST ที่ผ่าน private capability,
276
+ Local Config รับ token แบบ write-only เฉพาะเมื่อเลือก DODO Tunnel และ POST ผ่าน private capability,
239
277
  Host/Origin/proxy checks, rate limit และ control-context headers จากนั้นส่งตรงไปยัง
240
278
  reviewed OS credential provider และล้าง request field Response/config/audit ส่งกลับ
241
279
  เฉพาะ credential presence/provider ไม่มี MCP tool สำหรับส่ง token, เปลี่ยน connection
242
- mode หรือควบคุม owner Tunnel
280
+ mode หรือควบคุม owner Tunnel การเลือก Cloudflare Local จะปิดช่อง token และ backend
281
+ ไม่รับหรืออ่าน credential สำหรับโหมดนั้น
243
282
 
244
283
  Tunnel route ต้องชี้ทุก public path ไป MCP/OAuth listener `127.0.0.1:21730` เท่านั้น
245
284
  Local Config `21731`, metrics `21732` และ private IPC ไม่ถูก expose `/config` ที่