# Implementation Plan: arcrun MVP

## Overview

依照 Design 的七個 Phase 實作。原則：最小異動，不重寫現有邏輯，只 cherry-pick + carve-out + supplement。
所有 Phase 1–3 工作在 `matrix` repo 對應目錄驗證後再搬到新 repo。

**PR #2（claude/review-mvp-specs-8Bvdu）狀態：** 初始實作已提交，已修復以下問題後準備 merge：
- CF API Token 傳至 arcrun.dev 安全問題（已修復）
- 加密 fallback 格式不相容（已修復）
- submitComponent KBDB 依賴（已修復，改用 SUBMISSIONS_KV）
- Webhook 路由缺 analytics（已修復）
- `require()` 在 ES module 中（已修復）
- api 類零件 `no_network_syscall: true` 錯誤（已修復）

---

## Phase 1：搬移與清理

- [x] 1. 建立 `arcrun` 獨立 repo 並初始化
  - [x] 1.1 在 GitHub 建立新的 public repo（使用 matrix monorepo 的 `arcrun/` 子目錄代替，PR #2）
  - [x] 1.2 設定 `.gitignore`（排除 `node_modules/`、`.wrangler/`、`credentials.yaml`、`~/.arcrun/`）
  - [x] 1.3 從 `matrix` cherry-pick 四個目錄：
    - `matrix/cypher-executor/` → `arcrun/cypher-executor/`
    - `matrix/u6u-core/credentials/` → `arcrun/credentials/`
    - `matrix/u6u-core/registry/components/` → `arcrun/registry/components/`
  - _Requirements: 1.6_

- [x] 2. 清理 `cypher-executor/wrangler.toml`
  - [x] 2.1 移除 9 個 InkStone Service Bindings（KBDB、REGISTRY、CLINIC_*、AICEO、MINI_ME）
  - [x] 2.2 確認保留：`EXEC_CONTEXT`、`WEBHOOKS`、`WASM_BUCKET`、`AI`
  - [x] 2.3 新增 `CREDENTIALS_KV` 與 `ANALYTICS_KV` KV namespace binding
  - [x] 2.4 更新 `name` 為 `arcrun-cypher-executor`
  - _Requirements: 1.1, 1.2, 1.3_

- [x] 3. 改寫 `cypher-executor/src/lib/component-loader.ts`
  - [x] 3.1 移除對 MINI_ME、KBDB、InkStone bindings 的 hardcode
  - [x] 3.2 實作三層邏輯：builtin Map → WASM_BUCKET R2 直讀 → 結構化錯誤
  - _Requirements: 1.4, 1.5_

- [x] 4. 移除對 InkStone bindings 的依賴程式碼
  - [x] 4.1 刪除 `autoPublishMissing.ts`（依賴 REGISTRY binding）
  - [x] 4.2 移除所有 `env.KBDB`、`env.REGISTRY`、`env.MINI_ME`、`env.AICEO`、`env.CLINIC_*` 引用
  - _Requirements: 1.1, 1.5_

- [ ] 5. 本機驗證
  - [ ] 5.1 `cd arcrun/cypher-executor && wrangler dev` 能啟動（無 binding 錯誤）
  - [ ] 5.2 `GET /health` 回傳 `{ ok: true }`
  - [ ] 5.3 上傳 `validate_json.wasm` 到 WASM_BUCKET，執行 `POST /execute` 能正常回傳結果
  - _Requirements: 1.5, 5.5_

---

## Phase 2：零件完整度補充

- [x] 6. api 類零件 `no_network_syscall` 修正
  - [x] 6.1 gmail、telegram、google_sheets、line_notify、http_request 改為 `no_network_syscall: false`
  - _Requirements: 2.1_

- [ ] 7. 審查 21 個零件 contract.yaml 並補充 `credentials_required`
  - [ ] 7.1 確認 gmail、google_sheets、telegram、line_notify 有 `credentials_required`（PR #2 已加入，需驗證格式正確）
  - [ ] 7.2 確認所有 21 個零件有 `config_example` 欄位
  - [ ] 7.3 驗證 `main.go` required 欄位與 `contract.yaml` input_schema.required[] 一致
  - _Requirements: 2.1, 2.2, 2.3_

---

## Phase 3：Credential 注入整合

- [x] 10. `credential-injector.ts` 已實作（`arcrun/cypher-executor/src/actions/credential-injector.ts`）
  - [x] 10.1 讀取 contract.yaml from R2，解析 `credentials_required`
  - [x] 10.2 從 `CREDENTIALS_KV` 讀取 AES-GCM 加密 token，注入到 input 對應欄位（inject_as）
  - [x] 10.3 credential 不存在時拋出結構化錯誤（含 key 名稱與修復步驟）
  - _Requirements: 3.4, 3.5, 3.6_

- [ ] 11. 驗證 credential 注入整合進 graph-executor
  - [ ] 11.1 確認 `graph-executor.ts` 在節點執行前正確呼叫 `injectCredentials`
  - [ ] 11.2 確認注入只影響 WASM input，不修改 WEBHOOKS KV 中儲存的 workflow 定義
  - _Requirements: 3.4, 3.5_

- [ ] 12. 端對端測試（手動）
  - [ ] 12.1 建立 `credentials.yaml`，加入測試 token
  - [ ] 12.2 執行 `acr creds push`，確認寫入 CREDENTIALS_KV 格式為 `{ encrypted, iv }`（無 `mode: 'base64'`）
  - [ ] 12.3 執行含 credential 的 workflow，確認 inject_as 欄位正確注入
  - _Requirements: 3.4, 3.5_

---

## Phase 4：CLI 開發

- [x] 13. CLI 專案骨架已建立（`arcrun/cli/`）
  - [x] 13.1 `package.json`（name: `arcrun`，bin: `acr`）
  - [x] 13.2 `tsconfig.json`（module: NodeNext）
  - [x] 13.3 所有 10 個指令已實作骨架
  - _Requirements: 4.1_

- [x] 14. `acr init` 已實作，修正項：
  - [x] 14.1 Standard 模式不再傳送 `cf_api_token` 至 arcrun.dev（只傳 `email`）
  - [x] 14.2 `require()` 改用 `await import()` 修正 ES module 相容
  - _Requirements: 4.2, 6.3_

- [x] 15. `acr creds push` 已實作
  - [x] 15.1 讀取 `credentials.yaml`，AES-GCM 加密後寫入用戶 CF KV（`cred:{name}`）
  - [x] 15.2 加密 fallback（base64）已移除，key 不足時直接拋錯提示生成指令
  - _Requirements: 4.3, 6.5_

- [x] 16. `acr push` 已實作
  - _Requirements: 4.4_

- [x] 17. `acr run` 已實作
  - _Requirements: 4.5_

- [ ] 18. `acr validate` credential 檢測邏輯有誤，需修復
  - [ ] 18.1 `extractCredentialRefs()` 目前掃描 `{{creds.xxx}}` 語法，但 injection 使用 `inject_as` key
  - [ ] 18.2 改為讀取 contract.yaml 的 `credentials_required[].key`，與 `cred:{key}` KV 存在性比對
  - _Requirements: 4.6_

- [x] 19. `acr parts`、`acr parts scaffold`、`acr parts publish` 已實作
  - [ ] 19.1 `acr parts` 中 YAML 解析改用 `js-yaml`（目前用 regex，可能解析失敗）
  - _Requirements: 4.7, 4.8_

- [x] 20. `acr list` 與 `acr logs` 已實作
  - _Requirements: 4.9, 4.10_

---

## Phase 5：開源發布準備

- [x] 21. README.md 已撰寫（`arcrun/README.md`）
- [x] 22. CONTRIBUTING.md 已撰寫（`arcrun/CONTRIBUTING.md`）
- [ ] 23. 安全審查（PR merge 前執行）
  - [ ] 23.1 搜尋 `.workers.dev` InkStone 網域
  - [ ] 23.2 確認 wrangler.toml 所有 KV id 欄位留空
  - [ ] 23.3 確認 `credentials.yaml` 在 `.gitignore` 中
  - _Requirements: 5.4_

- [ ] 24. 發布（安全審查後）
  - [ ] 24.1 `npm publish`（CLI package `arcrun`）
  - _Requirements: 5.1_

---

## Phase 6：Standard 模式 — auth-worker 與用戶 KV 代存取

- [ ] 25. 建立 `auth-worker`（新 Worker，部署至 `api.arcrun.dev`）
  - [ ] 25.1 建立 `auth-worker/` 目錄，初始化 Hono + wrangler.toml
  - [ ] 25.2 實作 `POST /register`：接收 `{ email, account_id, kv_namespace_id }` + CF API Token 透過 header 傳入
    - **不在 request body 中接收 CF API Token**（Token 透過 header `CF-Api-Token` 傳入，減少 TLS 以外的洩漏面）
    - 生成 `tenant_id` 與 `api_key`，存入 `ACCOUNTS_KV`
  - [ ] 25.3 Bindings：`ACCOUNTS_KV`
  - _Requirements: 6.1, 6.2_

- [ ] 26. 改造 `cypher-executor` 支援 multi-tenant 用戶 KV 代存取
  - [ ] 26.1 讀取 `MULTI_TENANT` env var（目前已宣告但未讀取），實作 tenant middleware
  - [ ] 26.2 `X-Arcrun-API-Key` → 查 `ACCOUNTS_KV` → 取得用戶 cf_api_token + kv_namespace_id → 建立 `CfKvClient`
  - [ ] 26.3 `CfKvClient` 已實作（`arcrun/cli/src/lib/cf-api.ts`），需移植到 `cypher-executor/src/lib/`
  - [ ] 26.4 `credential-injector.ts` 改用 userKv 取得加密 credential
  - [ ] 26.5 webhook 路由注入 userKv
  - _Requirements: 6.4, 6.5, 6.6_

- [ ] 27. 端對端測試（用戶 KV 隔離）
  - _Requirements: 6.4, 6.5_

---

## Phase 7：公眾零件統計與貢獻審核

- [x] 28. Analytics 基礎設施已建立
  - [x] 28.1 `execution-logger.ts` 建立，`writeExecutionVerdict` 寫入 `ANALYTICS_KV`（fire-and-forget）
  - [x] 28.2 `/execute` 路由已整合 `waitUntil(writeExecutionVerdict(...))`
  - [x] 28.3 `/webhooks/:token/trigger` 路由已補上 `waitUntil(writeExecutionVerdict(...))`
  - _Requirements: 7.2_

- [x] 29. registry Worker analytics 端點（2026-07-31，CP arcrun-usable 步驟 6）
  - [x] 29.1 新增 `POST /analytics/record` 路由，更新 `ANALYTICS_KV` 計數器（`stats:{hash_id}:{version}`）
    - 註：KV 無 CAS，「原子更新」在 KV 上做不到——read-modify-write，併發偶有丟計數，統計用途可接受（誠實限制）
    - 衍生值（success_rate 0..1／avg_duration_ms／call_count）回填 `comp:` 記錄（查詢讀取端），計數器是唯一真相源
  - [x] 29.2 `GET /components/:id`、`/components/search` 回傳的 `success_rate`、`avg_duration_ms`、`call_count` 隨執行更新（欄位既存，本次讓它有真資料）
  - [x] 29.3 cypher-executor 執行收尾對用到的**每顆零件**回寫（`execution-evaluator.ts` 從 stub 改真實作；`/cypher/execute` 與 webhook 路徑都掛，waitUntil fire-and-forget；成敗判定＝trace error 或 output.success===false）
  - 實測（本地 wrangler dev ×2，registry 8788＋cypher 8787＋REGISTRY_BASE_URL 指本地）：同一零件 http_request 跑 5 次（3 成功＋2 失敗 404）→ `GET /components/http_request` success_rate 1→0.6、call_count 0→5；`/cypher/search` 節點回 `success_rate: 0.6`
  - _Requirements: 7.3, 7.6_

- [x] 30. `author` 欄位已加入 contract.yaml 規格
  - _Requirements: 7.1_

- [x] 31. 零件提交審核流程已實作（`arcrun/registry/src/actions/submitComponent.ts`）
  - [x] 31.1 沙盒驗收流程（sandboxAcceptance.ts）：size_check + syscall_scan 已實作；cold_start + gherkin_tests 為 Phase 0 mock
  - [x] 31.2 `SUBMISSIONS_KV` 儲存元數據，預設 `visibility: author_only`
  - [ ] 31.3 `PATCH /submit/:id/approve` → 將 visibility 改為 `public`（待實作）
  - [ ] 31.4 Gherkin 測試執行（取代 mock）
  - _Requirements: 8.2, 8.3, 8.4, 8.5_

---

## 待辦（無相依順序，可平行處理）

- [ ] A. `builtins/` 清理：`initComponents.ts` 仍用舊的 HTTP endpoint 模式上架零件（`buildComponentDefs` 含 URL），應改為呼叫 `POST /submit` 送 WASM binary + contract，或直接移除 builtins（功能已整合到 registry）
- [ ] B. `validate` 指令 credential 檢測邏輯修復（見 Phase 4 Task 18）
- [ ] D. `acr parts` YAML 解析改用 `js-yaml`

---

## Notes

- 標記 `*` 的子任務為選填，可跳過以加速 MVP 交付
- Gherkin 測試執行（sandbox 步驟 d）為 Phase 0 mock，Phase 7 補充
- cold-start 測量（sandbox 步驟 b）為 Phase 0 mock，Phase 2 補充
- CF API Token 永遠不離開用戶本機，arcrun.dev 只收 email + account_id + kv_namespace_id
