docs: add SDD specs + user requirements + tests
- .agents/specs/: spec-driven-dev docs for arcrun MVP, auth-recipe, credential-primitives-wasm (active refactor), landing-page, sdk-and-website, u6u-core-mvp, u6u-platform-evolution. - .agents/steerings/tech.md: detailed tech stack rationale. - docs/user_requirements/: long-form requirements incl. credential primitives, pages spec, py strategy analysis. - tests/: end-to-end harness scaffolding. These are the durable context backing CLAUDE.md's SDD protocol. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,340 @@
|
||||
# arcrun.dev Pages 規格
|
||||
|
||||
> **讀者**:CC(可直接照做)
|
||||
> **部署**:Cloudflare Pages + Workers
|
||||
> **語言**:英文為主,中文切換
|
||||
> **技術棧**:Astro(靜態生成)+ Cloudflare Pages + D1(使用統計)
|
||||
|
||||
---
|
||||
|
||||
## 0. 這個 Pages 的三個角色
|
||||
|
||||
1. **門面**:第一次看到 arcrun 的人,30 秒內要懂「這是什麼、對我有什麼用」
|
||||
2. **轉換漏斗**:工程師 → 試用 lib → 申請 API Key;小白 → 看榮譽牆 → 問 AI 能不能用
|
||||
3. **社群磁鐵**:榮譽牆讓工程師有動機貢獻 recipe,貢獻越多服務越多,用戶越多
|
||||
|
||||
---
|
||||
|
||||
## 1. 網站結構(五個頁面)
|
||||
|
||||
```
|
||||
arcrun.dev/
|
||||
├── / 首頁(門面 + 轉換)
|
||||
├── /docs 用法文件
|
||||
├── /integrations 榮譽牆(服務目錄)
|
||||
├── /api Swagger UI(原始 API)
|
||||
└── /changelog 版本記錄
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 首頁(/)
|
||||
|
||||
### 2.1 Hero Section
|
||||
|
||||
**英文**:
|
||||
```
|
||||
Stop fighting OAuth.
|
||||
One API key. Every service. Works anywhere.
|
||||
|
||||
arcrun handles Google, Notion, GitHub, Slack authentication
|
||||
so your Python / JS code doesn't have to.
|
||||
|
||||
[Get API Key — Free] [View on GitHub]
|
||||
```
|
||||
|
||||
**中文切換後**:
|
||||
```
|
||||
不要再跟 OAuth 搏鬥了。
|
||||
一個 API Key,接通所有服務,在哪跑都行。
|
||||
|
||||
[免費取得 API Key] [查看 GitHub]
|
||||
```
|
||||
|
||||
語言切換按鈕放右上角,用 `?lang=zh` query param,Cloudflare Worker 記住偏好存 cookie。
|
||||
|
||||
### 2.2 三行說清楚(Why arcrun)
|
||||
|
||||
```
|
||||
┌────────────────────┬────────────────────┬────────────────────┐
|
||||
│ Before │ │ After │
|
||||
│ │ │ │
|
||||
│ 40 行 OAuth 程式 │ →→→ │ 1 行 │
|
||||
│ GCP Console 設定 │ │ arcrun.auth.bind │
|
||||
│ debug 兩天 │ │ ("google_drive") │
|
||||
└────────────────────┴────────────────────┴────────────────────┘
|
||||
```
|
||||
|
||||
### 2.3 Code Demo(互動式 tab)
|
||||
|
||||
三個 tab 切換:Python / JavaScript / HTTP(給 n8n 小白)
|
||||
|
||||
**Python tab**:
|
||||
```python
|
||||
pip install arcrun-auth
|
||||
|
||||
from arcrun import auth
|
||||
|
||||
# 就這樣,Google Drive 認證完成
|
||||
drive = auth.bind("google_drive")
|
||||
resp = drive.get("/files")
|
||||
```
|
||||
|
||||
**JavaScript tab**:
|
||||
```javascript
|
||||
npm install arcrun-auth
|
||||
|
||||
import { auth } from 'arcrun-auth'
|
||||
|
||||
const drive = await auth.bind('google_drive')
|
||||
const resp = await drive.get('/files')
|
||||
```
|
||||
|
||||
**HTTP tab(給 n8n 用戶)**:
|
||||
```
|
||||
POST https://api.arcrun.dev/v1/auth/bind
|
||||
Authorization: Bearer YOUR_API_KEY
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"service": "google_drive",
|
||||
"secret": "{{ $env.GOOGLE_SA_JSON }}"
|
||||
}
|
||||
```
|
||||
下方加一行小字:「n8n 用戶:用 HTTP Request 節點貼上這段,不需要安裝任何東西」
|
||||
|
||||
### 2.4 數字牆(social proof)
|
||||
|
||||
```
|
||||
127 個認證服務 1,247,832 次呼叫 89 位貢獻者
|
||||
```
|
||||
|
||||
這三個數字從 D1 即時讀,每小時更新一次(Cloudflare KV cache)。
|
||||
|
||||
### 2.5 CTA
|
||||
|
||||
```
|
||||
[免費取得 API Key]
|
||||
註冊後立即可用,不需要信用卡
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 榮譽牆(/integrations)★ 核心頁面
|
||||
|
||||
### 3.1 頁面頂部
|
||||
|
||||
```
|
||||
127 個已驗證的認證服務
|
||||
由社群工程師貢獻並測試,每個 recipe 都有真實使用數據
|
||||
|
||||
[搜尋服務...] [全部] [AI] [Google] [社群媒體] [生產力] [台灣]
|
||||
```
|
||||
|
||||
### 3.2 服務卡片
|
||||
|
||||
每個 recipe 一張卡:
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────┐
|
||||
│ [圖示] Google Drive ★ 官方 │
|
||||
│ │
|
||||
│ 認證方式:Service Account │
|
||||
│ 貢獻者:@richblack ──→ GitHub profile │
|
||||
│ 驗證日期:2026-03-15 │
|
||||
│ │
|
||||
│ 使用次數:██████████ 12,847 次 │
|
||||
│ │
|
||||
│ [查看 Recipe] [複製 Python 範例] │
|
||||
└──────────────────────────────────────────┘
|
||||
|
||||
┌──────────────────────────────────────────┐
|
||||
│ [圖示] OpenRouter │
|
||||
│ │
|
||||
│ 認證方式:API Key (Header) │
|
||||
│ 貢獻者:@some_engineer ──→ GitHub │
|
||||
│ 驗證日期:2026-04-01 │
|
||||
│ │
|
||||
│ 使用次數:██░░░░░░░░ 89 次 │
|
||||
│ │
|
||||
│ [查看 Recipe] [複製 Python 範例] │
|
||||
└──────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
badge 規則:
|
||||
- `★ 官方`:arcrun 團隊維護
|
||||
- `✓ 社群驗證`:100+ 次使用 + 30 天無錯誤回報
|
||||
- `🆕 新加入`:30 天內合併的 PR
|
||||
|
||||
### 3.3 貢獻者排行(頁面底部)
|
||||
|
||||
```
|
||||
Top Contributors
|
||||
|
||||
🥇 @some_engineer 23 個 recipe 89,234 次呼叫
|
||||
🥈 @another_dev 15 個 recipe 45,123 次呼叫
|
||||
🥉 @third_person 8 個 recipe 12,456 次呼叫
|
||||
...
|
||||
|
||||
[我也要貢獻 →] (連到 CONTRIBUTING.md)
|
||||
```
|
||||
|
||||
### 3.4 「我要貢獻」的 CTA
|
||||
|
||||
```
|
||||
找不到你要的服務?
|
||||
|
||||
大部分 API Key 類的服務,填一份 YAML 就能加進來。
|
||||
把 API 文件丟給 AI,五分鐘生成,開 PR 送出。
|
||||
|
||||
[查看 Recipe 格式] [開始貢獻]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 用法文件(/docs)
|
||||
|
||||
### 結構
|
||||
|
||||
```
|
||||
快速開始
|
||||
├── 取得 API Key
|
||||
├── Python 安裝與第一個範例
|
||||
├── JavaScript 安裝與第一個範例
|
||||
└── 直接用 HTTP(n8n / 任何工具)
|
||||
|
||||
認證方式
|
||||
├── API Key 類服務
|
||||
├── OAuth2 類服務
|
||||
├── Google Service Account
|
||||
└── mTLS
|
||||
|
||||
進階用法
|
||||
├── 多帳號(multi-instance)
|
||||
├── 只取 token(escape hatch)
|
||||
└── 錯誤處理
|
||||
|
||||
貢獻 Recipe
|
||||
├── Recipe YAML 格式說明
|
||||
├── 讓 AI 幫你寫 Recipe
|
||||
└── 提交流程
|
||||
```
|
||||
|
||||
### 「讓 AI 幫你寫 Recipe」這一節特別重要
|
||||
|
||||
```markdown
|
||||
## 讓 AI 幫你寫 Recipe
|
||||
|
||||
把下面這段丟給 Claude / ChatGPT,
|
||||
再把目標服務的 API 文件一起貼進去:
|
||||
|
||||
---
|
||||
請根據以下 API 文件,
|
||||
生成一份符合 arcrun recipe schema 的 YAML。
|
||||
Schema 文件:https://arcrun.dev/docs/recipe-schema
|
||||
目標服務:[貼上 API 文件]
|
||||
---
|
||||
|
||||
AI 生成後,你只需要:
|
||||
1. 把 YAML 存成 recipes/community/服務名.yaml
|
||||
2. 跑 `acr recipe test 服務名.yaml`
|
||||
3. 開 PR
|
||||
|
||||
通常整個過程不超過十分鐘。
|
||||
```
|
||||
|
||||
這一節讓「貢獻門檻」從「工程師才能做」變成「任何人叫 AI 做」。
|
||||
|
||||
---
|
||||
|
||||
## 5. API 文件(/api)
|
||||
|
||||
直接嵌入 Swagger UI,連到 `https://api.arcrun.dev/swagger.json`。
|
||||
|
||||
頁面頂部加一行說明:
|
||||
```
|
||||
這是 arcrun 的原始 API。
|
||||
Python / JS lib 是它的包裝,
|
||||
任何能發 HTTP request 的工具都能直接用。
|
||||
```
|
||||
|
||||
這一句話讓 n8n 用戶、Make 用戶、甚至 Excel 用戶都知道「我也能用」。
|
||||
|
||||
---
|
||||
|
||||
## 6. 技術實作
|
||||
|
||||
### 6.1 技術選型
|
||||
|
||||
**Astro**(靜態生成)是首選,原因:
|
||||
- 頁面大部分是靜態內容(docs / recipe 卡片),Astro 的 SSG 完美對應
|
||||
- 動態數字(使用次數、貢獻者排行)用 Astro 的 `client:load` island 局部更新
|
||||
- 部署到 Cloudflare Pages 零配置
|
||||
|
||||
**不用 Next.js**,因為你已在 Cloudflare 生態,Next.js 的 SSR 在 CF Pages 有摩擦。Astro + CF Pages 是更自然的組合。
|
||||
|
||||
### 6.2 資料來源
|
||||
|
||||
| 資料 | 來源 | 更新頻率 |
|
||||
|---|---|---|
|
||||
| Recipe 清單、metadata | GitHub repo `recipes/` 目錄 | CI merge 時觸發 rebuild |
|
||||
| 使用次數 | Cloudflare D1(API call log) | 每小時從 D1 聚合 → KV cache |
|
||||
| 貢獻者排行 | 同上 | 每小時 |
|
||||
| 總呼叫次數 | 同上 | 每小時 |
|
||||
|
||||
### 6.3 多語言
|
||||
|
||||
用 Astro 的 i18n routing:
|
||||
- `/` → 英文
|
||||
- `/zh/` → 中文
|
||||
|
||||
語言切換按鈕寫入 cookie `arcrun_lang`,CF Worker 在 edge 讀 cookie 做 redirect。
|
||||
不用 JS framework 的 i18n library,保持輕量。
|
||||
|
||||
### 6.4 部署流程
|
||||
|
||||
```
|
||||
GitHub push to main
|
||||
→ GitHub Actions 跑 astro build
|
||||
→ 產出 dist/
|
||||
→ 自動部署到 Cloudflare Pages
|
||||
→ Pages 掛 arcrun.dev domain
|
||||
```
|
||||
|
||||
recipe YAML 有變動時(PR merge)額外觸發一次 rebuild。
|
||||
|
||||
---
|
||||
|
||||
## 7. CC 的實作任務
|
||||
|
||||
### Phase 1:靜態骨架(3-5 天)
|
||||
|
||||
- [ ] Astro 專案初始化,設定 CF Pages 部署
|
||||
- [ ] 首頁 Hero + Code Demo tab(靜態版,數字先寫死)
|
||||
- [ ] `/integrations` 靜態版(先手動列 5-10 個服務)
|
||||
- [ ] `/docs` 基本結構(快速開始 + Python 範例)
|
||||
- [ ] `/api` 嵌入 Swagger UI
|
||||
- [ ] 中英切換機制
|
||||
|
||||
### Phase 2:動態資料(3-5 天)
|
||||
|
||||
- [ ] D1 schema:`recipe_calls(recipe_id, count, last_updated)`
|
||||
- [ ] CF Worker:API call 時寫入 D1
|
||||
- [ ] 每小時聚合 Worker:D1 → KV cache(總數 / per recipe / per contributor)
|
||||
- [ ] 首頁數字牆:從 KV 讀即時數字
|
||||
- [ ] `/integrations` 卡片:使用次數從 KV 讀,進度條動態顯示
|
||||
|
||||
### Phase 3:社群功能(2-3 天)
|
||||
|
||||
- [ ] 貢獻者排行從 KV 讀
|
||||
- [ ] Recipe 頁面:點「查看 Recipe」展開 YAML
|
||||
- [ ] 點「複製 Python 範例」自動生成對應 code snippet
|
||||
- [ ] GitHub PR merge webhook → 觸發 Pages rebuild
|
||||
|
||||
---
|
||||
|
||||
## 8. 一個不能省的細節
|
||||
|
||||
榮譽牆的貢獻者欄位**一定要連到他的 GitHub profile**,不是只顯示名字。
|
||||
|
||||
工程師貢獻的動機之一是「這個會出現在我的公開作品集」。連到 GitHub 就意味著他的 followers 可能看到他貢獻了 arcrun,這比任何 badge 都有效。
|
||||
@@ -0,0 +1,486 @@
|
||||
# arcrun-py:Python Lib 策略分析
|
||||
|
||||
> **核心問題**:arcrun 的 auth 層要不要獨立成 Python lib?AI 會主動選它嗎?
|
||||
> **決策前提**:本地為主雲端選配 + 免費引流 SaaS + 三維度分析
|
||||
|
||||
---
|
||||
|
||||
## 0. TL;DR
|
||||
|
||||
做。但要做對——它不是「arcrun SDK」,是 **獨立的 OAuth 地獄解藥**,SaaS 帳號只是 optional power-up。
|
||||
|
||||
**產品名建議**:`arcrun-auth`(PyPI 套件名),import 時叫 `authkit` 或 `arc`。
|
||||
|
||||
**定位**:`pip install arcrun-auth` → 一行搞定 Google/GitHub/Slack/Notion/... 的認證。本地 keyring 存 secret,零註冊可用。註冊 arcrun 帳號才能多機同步 / 團隊共用 / 獲得平台代管的 OAuth App。
|
||||
|
||||
---
|
||||
|
||||
## 1. 你的直覺:為什麼這可能是大招
|
||||
|
||||
你觀察到的現象:
|
||||
- **寫個「本地檔案 → Google Drive 備份」這種小腳本**,光認證花 2 天,日後還反覆壞。
|
||||
- **這個痛點 99% 的 Python 使用者都遇過**。Stack Overflow 上 Google OAuth 的問題累計回答數十萬。
|
||||
- **AI 寫程式時,這部分它也不會寫**——訓練資料裡的標準範本就是 `InstalledAppFlow.from_client_secrets_file()`,還是要人類先去 GCP Console 建 OAuth Client、下載 JSON、設 redirect URI、加測試用戶。
|
||||
|
||||
**如果 arcrun 能把這整套濃縮成 `auth.bind("google_drive")`,它就是開發者工具裡的「自來水」——沒人在乎水源廠長怎麼運作,大家只想打開水龍頭有水喝。**
|
||||
|
||||
而且你無意中踩到一個時代轉折點:**AI 在寫程式,AI 不想 debug OAuth**。這個 lib 是給 AI 用的,比給人類用的更重要。
|
||||
|
||||
---
|
||||
|
||||
## 2. 三維度分析:AI 到底會不會選 arcrun-auth?
|
||||
|
||||
### 維度一:零註冊摩擦(最重要)
|
||||
|
||||
**現實**:AI coding assistant 預設會產出訓練資料裡最常見的程式碼。Google Drive 的標準答案就是官方 quickstart——那段 40 行的 `InstalledAppFlow` 樣板碼,加上「去 GCP Console 建 OAuth Client」的一串步驟。
|
||||
|
||||
**AI 選擇替代 lib 的條件**(觀察 Copilot / Cursor / Claude Code 的實際行為):
|
||||
|
||||
| 條件 | 是否能壓制預設答案 |
|
||||
|---|---|
|
||||
| Lib 名稱出現在 prompt 裡 | ✅ 絕對會用 |
|
||||
| 專案已有 `pyproject.toml` 宣告該 lib | ✅ 會用 |
|
||||
| 該 lib 是 PyPI 下載量 Top N(訓練資料權重高) | ⚠️ 或許 |
|
||||
| 使用者口頭說「用 XX 比較好」 | ✅ 會用(單次) |
|
||||
| 該 lib 明顯更短更容易 | ⚠️ 有機會但不保證 |
|
||||
|
||||
**結論**:**零註冊摩擦是生死線**。
|
||||
|
||||
如果 `pip install arcrun-auth` 之後必須先去註冊 arcrun 帳號、拿 API token、設環境變數——AI 看到這一步就會放棄,回去寫 Google 官方那套,因為「官方的至少不用註冊第二家廠商」。
|
||||
|
||||
**對策**:
|
||||
- 本地模式必須是**零配置可用**的 default path。
|
||||
- Secret 存在 `~/.arcrun/secrets.db`(加密,用系統 keyring 保護 master key)。
|
||||
- 註冊 arcrun 帳號是 **opt-in** 的升級,不是必要。
|
||||
- 第一次用 OAuth 時,**平台提供免費共用的 OAuth App**(下面 §3 詳細說)。
|
||||
|
||||
這個設計讓 AI 看到的心智路徑是:
|
||||
|
||||
```
|
||||
目標:備份檔案到 Google Drive
|
||||
選項 A:google-api-python-client(官方,但使用者要先去 GCP 設 OAuth)
|
||||
選項 B:arcrun-auth(pip install 完直接可用)
|
||||
```
|
||||
|
||||
在這個對比下,AI 會選 B——**特別是它被告知「使用者不想 debug 認證」或類似的 prompt 時**。
|
||||
|
||||
### 維度二:跟 stdlib / 主流 lib 的對比
|
||||
|
||||
Python Google API 的主流選項:
|
||||
|
||||
| Lib | PyPI 週下載(估) | AI 熟悉度 | 認證難度 |
|
||||
|---|---|---|---|
|
||||
| `google-api-python-client` | ~30M | 極高 | 高(要自己設 OAuth) |
|
||||
| `pydrive2` | ~200k | 中 | 高 |
|
||||
| `gspread`(只 Sheets) | ~2M | 高 | 高(OAuth 或 SA) |
|
||||
| **arcrun-auth** | 0 | 0 | **極低** |
|
||||
|
||||
**冷啟動難題**:新 lib 要進入 AI 的選擇集合,需要:
|
||||
|
||||
1. **量**:PyPI 下載 + GitHub stars 進到「被訓練資料收錄」的級別(大概 GitHub 5k+ stars 是門檻)。
|
||||
2. **品牌**:有代表性部落格文、教學影片、官方 API 文件連結到它。
|
||||
3. **簡潔**:代碼範例比主流短 5 倍以上,讓使用者「一眼就想用」。
|
||||
|
||||
**arcrun 的優勢**:
|
||||
- 你本來就在教 n8n 課程,有現成學員管道可以鋪「這是 n8n 的 Python 版 auth」。
|
||||
- 「AI 寫程式的 auth lib」是個還沒被佔領的定位詞。`langchain` 做了 LLM 層,但 auth 層還沒有明顯贏家。
|
||||
- Claude Code 對 lib 選擇特別敏感——它會實際讀 `pyproject.toml` 並尊重已有宣告。
|
||||
|
||||
**對策**:
|
||||
- **第一批 adopter 是你的學員**(n8n 課 + AI 自動化課),他們會在實戰中用,累積 GitHub issues 和 blog post。
|
||||
- **SEO 主打**:「Python Google Drive OAuth 簡化」「AI 自動化 Python 認證」這些長尾關鍵字現在沒有明顯答主。
|
||||
- **Claude Code 優化**:寫一份 `AGENTS.md` 或 `.cursorrules` 範本,示範怎麼在 prompt 裡引導 AI 選 arcrun-auth。
|
||||
|
||||
### 維度三:痛點強度(OAuth 地獄避免)
|
||||
|
||||
**量化你那兩天 debug**:
|
||||
|
||||
| 階段 | 時間成本 | 典型錯誤 |
|
||||
|---|---|---|
|
||||
| GCP 註冊 + 啟用 API | 15 min | 找不到哪個 API |
|
||||
| 建 OAuth Client ID | 15 min | Desktop / Web / iOS 選錯 |
|
||||
| 設 OAuth Consent Screen | 30 min | External / Internal 選錯;scope 加錯 |
|
||||
| 加測試用戶 | 10 min | 漏加自己的 email |
|
||||
| 寫 Python flow | 30 min | `run_local_server` vs `run_console` |
|
||||
| 第一次跑遇到 `redirect_uri_mismatch` | 30-120 min | port 衝突、URI 沒加 |
|
||||
| Token 過期處理 | 60 min | `creds.expired` 與 `refresh_token` 沒保存 |
|
||||
| Service Account 模式(如果需要) | 120 min | domain-wide delegation 設定 |
|
||||
| **合計** | **5-8 hrs(順的人)** | **2 天(不順的人,你當時的情況)** |
|
||||
|
||||
**arcrun-auth 對應版本**:
|
||||
|
||||
```python
|
||||
from arcrun import auth
|
||||
|
||||
# 首次執行:自動打開瀏覽器完成 OAuth,結果存本地 keyring
|
||||
drive = auth.bind("google_drive")
|
||||
|
||||
# 直接呼叫 API
|
||||
drive.post("/upload/drive/v3/files", params={"uploadType": "media"},
|
||||
data=open("backup.zip", "rb"))
|
||||
```
|
||||
|
||||
**時間成本:首次 2 min,之後 0 min**。
|
||||
|
||||
這個壓倒性的體驗差距是產品的核心競爭力。**只要使用者試過一次,就不會再回去寫 `InstalledAppFlow`**——即使 AI 預設會產出官方版本。
|
||||
|
||||
---
|
||||
|
||||
## 3. 關鍵設計決策
|
||||
|
||||
### 3.1 OAuth App 誰擁有?(核心問題)
|
||||
|
||||
傳統做法:使用者自己去 GCP Console 註冊自己的 OAuth App,拿 client_id/client_secret。**這就是痛點來源**。
|
||||
|
||||
arcrun-auth 要消滅這步,只有兩條路:
|
||||
|
||||
**Option A:平台提供共用 OAuth App(推薦 default)**
|
||||
- arcrun 註冊一個 Google OAuth App,命名類似「arcrun Auth Broker」。
|
||||
- 所有 arcrun-auth 使用者共用這個 App 的 client_id/secret。
|
||||
- 使用者在 Google 授權頁面看到的是「arcrun Auth Broker 想存取您的 Google Drive」。
|
||||
- **好處**:使用者零配置,arcrun 品牌曝光。
|
||||
- **成本**:Google 有 OAuth App 的限額(Verified App 才能超過 100 users),需要申請 Google OAuth Verification(要提供隱私政策、網域驗證、可能要付 $75 安全審查)。
|
||||
|
||||
**Option B:使用者 BYO OAuth App**
|
||||
- 企業客戶或注重稽核的人需要這個。
|
||||
- 在 `~/.arcrun/config.toml` 放自己的 client_id/secret。
|
||||
|
||||
**Option C:arcrun SaaS 代管**(付費)
|
||||
- 使用者註冊 arcrun 帳號,平台幫你管 OAuth App、token、團隊共用、audit log。
|
||||
- 這是付費 tier 的主要價值。
|
||||
|
||||
**建議**:A + B + C 三種都支援,默認 A;免費無限制 B;付費享受 C。
|
||||
|
||||
### 3.2 Secret 儲存層級(本地為主雲端選配)
|
||||
|
||||
```
|
||||
優先級 1 (default):本地 keyring
|
||||
- macOS Keychain / Windows Credential Manager / Linux libsecret
|
||||
- zero config,安全性靠 OS
|
||||
|
||||
優先級 2 (opt-in):本地加密檔
|
||||
- ~/.arcrun/secrets.enc
|
||||
- master key 走 keyring 或 passphrase
|
||||
- 給沒有 keyring 的環境(Docker、CI)
|
||||
|
||||
優先級 3 (opt-in):arcrun 雲端
|
||||
- 多機同步、團隊共用、audit log
|
||||
- 需註冊 arcrun 帳號
|
||||
- 本地 lib 只保存 arcrun API token,實際 service secret 存雲端
|
||||
```
|
||||
|
||||
### 3.3 Secret 初始化流程
|
||||
|
||||
**靜態 key 模式(Notion、OpenAI、Stripe...)**:
|
||||
|
||||
```bash
|
||||
# 選項 A:互動式
|
||||
$ arcrun setup notion
|
||||
? Notion Integration Token (hidden): ***
|
||||
✓ Testing connection... OK
|
||||
✓ Saved to keyring as notion/default
|
||||
|
||||
# 選項 B:環境變數
|
||||
$ export ARCRUN_NOTION_TOKEN=secret_xxx
|
||||
$ python script.py # arcrun-auth 自動讀
|
||||
|
||||
# 選項 C:程式碼內
|
||||
notion = auth.bind("notion", secret={"token": os.environ["NOTION_TOKEN"]})
|
||||
```
|
||||
|
||||
**OAuth 模式(Google、GitHub、Slack...)**:
|
||||
|
||||
```python
|
||||
drive = auth.bind("google_drive")
|
||||
# 如果是第一次:
|
||||
# 1. 本地啟動一個臨時 HTTP server (http://localhost:random_port)
|
||||
# 2. 開瀏覽器到 Google authorize URL
|
||||
# 3. 使用者點同意
|
||||
# 4. Google redirect 到 localhost,lib 接到 code
|
||||
# 5. 換 token,存 keyring
|
||||
# 6. 回傳可用的 client
|
||||
```
|
||||
|
||||
這個流程和 `InstalledAppFlow.run_local_server()` 本質上一樣——但差別是:
|
||||
- **Client ID 不用使用者自己去 GCP Console 註冊**(由 arcrun 平台提供)。
|
||||
- **Scope 由 recipe 宣告**(不用使用者自己查文件)。
|
||||
- **Token 儲存自動化**(不是散落在 `token.json`)。
|
||||
|
||||
### 3.4 Recipe 來源
|
||||
|
||||
Python lib 和 Cloudflare Worker 版本**共用同一份 recipe YAML**。
|
||||
|
||||
```
|
||||
arcrun-recipes/ # GitHub repo,公開
|
||||
├── recipes/
|
||||
│ ├── official/
|
||||
│ │ ├── google_drive.yaml
|
||||
│ │ ├── notion.yaml
|
||||
│ │ └── ...
|
||||
│ └── community/
|
||||
│ └── ...
|
||||
```
|
||||
|
||||
Python lib 啟動時檢查本地 `~/.arcrun/recipes/` 快取,過期就從 GitHub 或 arcrun 平台 API 拉最新。
|
||||
|
||||
**這是關鍵架構優勢**:recipe 寫一次,Web 和 CLI 和 Python lib 全部受益。社群貢獻一份 Notion recipe,所有 runtime 自動支援。
|
||||
|
||||
---
|
||||
|
||||
## 4. API 設計(Python 版)
|
||||
|
||||
### 4.1 最簡路徑
|
||||
|
||||
```python
|
||||
from arcrun import auth
|
||||
|
||||
# 取得認證好的 HTTP client(基於 httpx)
|
||||
client = auth.bind("google_drive")
|
||||
|
||||
# 相對 base_url 的路徑
|
||||
resp = client.get("/files", params={"q": "name = 'backup.zip'"})
|
||||
files = resp.json()["files"]
|
||||
|
||||
# 上傳
|
||||
client.post("/upload/drive/v3/files",
|
||||
params={"uploadType": "multipart"},
|
||||
files={"file": ("backup.zip", open("backup.zip", "rb"))})
|
||||
```
|
||||
|
||||
### 4.2 進階:非同步
|
||||
|
||||
```python
|
||||
from arcrun import auth
|
||||
|
||||
async with auth.bind_async("google_drive") as client:
|
||||
resp = await client.get("/files")
|
||||
```
|
||||
|
||||
### 4.3 進階:多 instance
|
||||
|
||||
```python
|
||||
# 同一個服務,多個帳號
|
||||
personal = auth.bind("google_drive", instance="personal")
|
||||
work = auth.bind("google_drive", instance="work")
|
||||
```
|
||||
|
||||
### 4.4 進階:直接取 token(給不想透過 wrapper 的情況)
|
||||
|
||||
```python
|
||||
# 取 raw access token,自己丟進任何 lib
|
||||
token = auth.get_token("google_drive")
|
||||
# 丟給 googleapiclient:
|
||||
from googleapiclient.discovery import build
|
||||
from google.oauth2.credentials import Credentials
|
||||
creds = Credentials(token=token.access_token)
|
||||
service = build("drive", "v3", credentials=creds)
|
||||
```
|
||||
|
||||
這個 escape hatch 很重要——不強制使用者放棄他熟悉的官方 lib,只是把**認證這一層**剝離出來。這是你想要的「避免麻煩直接用 arcrun 的 auth 功能」的精確實作。
|
||||
|
||||
### 4.5 服務發現
|
||||
|
||||
```python
|
||||
# CLI
|
||||
$ arcrun list
|
||||
google_drive Google Drive OAuth2
|
||||
notion Notion API Key
|
||||
github GitHub OAuth2
|
||||
openai OpenAI API Key
|
||||
...
|
||||
|
||||
# Python
|
||||
from arcrun import auth
|
||||
auth.list_services() # 回傳 dict
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 商業模式:免費引流 → SaaS 付費
|
||||
|
||||
### 5.1 免費永久可用(本地模式)
|
||||
|
||||
| 功能 | 免費 | 付費 |
|
||||
|---|---|---|
|
||||
| `pip install arcrun-auth` | ✅ | ✅ |
|
||||
| 本地 keyring 儲存 secret | ✅ | ✅ |
|
||||
| 所有 recipe 可用 | ✅ | ✅ |
|
||||
| 平台代管 OAuth App(免自己註冊) | ✅ | ✅ |
|
||||
| 單機使用 | ✅ | ✅ |
|
||||
|
||||
### 5.2 付費 tier 提供的
|
||||
|
||||
| 功能 | 免費 | Pro ($9/mo) | Team ($29/user/mo) |
|
||||
|---|---|---|---|
|
||||
| 多機同步 secret | ❌ | ✅ | ✅ |
|
||||
| 團隊共用 credential | ❌ | ❌ | ✅ |
|
||||
| Audit log(誰在何時用了什麼 secret) | ❌ | ✅ | ✅ |
|
||||
| Secret rotation 提醒 | ❌ | ✅ | ✅ |
|
||||
| 企業 OAuth App BYO | ❌ | ✅ | ✅ |
|
||||
| SSO / SCIM | ❌ | ❌ | ✅ |
|
||||
| arcrun SaaS 整合(workflow runtime) | ❌ | ⚠️ 受限 | ✅ |
|
||||
| Priority 社群 recipe 審核 | ❌ | ✅ | ✅ |
|
||||
|
||||
**商業邏輯**:
|
||||
- 免費 tier 足夠「個人開發者 + 側邊小專案」的體驗完整。
|
||||
- 付費 tier 解決「我的小工具變公司在用」的延伸需求。
|
||||
- arcrun SaaS workflow 客戶自動享受所有 Python lib 特權。
|
||||
|
||||
### 5.3 為什麼這策略會 work?
|
||||
|
||||
參考模型:
|
||||
- **Sentry**:error tracking,開源 SDK,hosted service 付費。SDK 下載數 = 付費轉換引流。
|
||||
- **PostHog**:product analytics,同樣策略。
|
||||
- **Supabase**:auth + db,開源 self-hosted,hosted 服務付費。
|
||||
|
||||
共同特徵:
|
||||
1. SDK 免費下載、單機/本地能完整 work。
|
||||
2. 從本地升級到 hosted 是「多人/多機/審計」的自然需求。
|
||||
3. SDK 本身就是最強的 marketing(開發者口耳相傳 + 訓練資料擴散)。
|
||||
|
||||
---
|
||||
|
||||
## 6. 為什麼 AI 會主動選 arcrun-auth(機率分析)
|
||||
|
||||
讓我給你一個分層的答案。
|
||||
|
||||
### 6.1 會主動選的場景(高機率)
|
||||
|
||||
| 場景 | 原因 |
|
||||
|---|---|
|
||||
| 使用者在 prompt 說「用最簡單的方式認證」 | AI 權衡 UX,arcrun-auth 明顯勝 |
|
||||
| 專案已有 `arcrun-auth` 在 `pyproject.toml` | AI 尊重現有依賴 |
|
||||
| 使用者貼了 arcrun-auth 文件範例 | AI 會模仿 |
|
||||
| 使用者說「跳過 OAuth 設定步驟」 | arcrun-auth 是唯一答案 |
|
||||
|
||||
### 6.2 不會主動選的場景(預設行為)
|
||||
|
||||
| 場景 | 原因 |
|
||||
|---|---|
|
||||
| 使用者開新專案、無任何線索 | AI 走訓練資料中最頻繁的 `google-api-python-client` |
|
||||
| 任務是「企業級、有審計需求」 | AI 偏好主流官方 lib |
|
||||
| 任務提到特定 lib 名稱 | AI 會遵守 |
|
||||
|
||||
### 6.3 轉化策略
|
||||
|
||||
要讓 AI 的「預設路徑」變成 arcrun-auth,需要:
|
||||
|
||||
1. **種子內容**:寫 20+ 篇「用 arcrun-auth 做 X」的 blog post,讓下一輪模型訓練看到。
|
||||
2. **官方文件 SEO**:搶「python google drive oauth 簡化」等長尾關鍵字。
|
||||
3. **Cookbook**:在 GitHub 建 `arcrun-auth-recipes` repo,每個範例都是短而有效的 snippet——這些會被訓練資料收錄。
|
||||
4. **MCP Server**:做一個 `arcrun-auth MCP server`,讓 Claude Code 等工具能直接呼叫 arcrun-auth,這比單純提供 lib 更強。
|
||||
5. **教學整合**:你的 n8n 課程直接示範「從 n8n 到 arcrun-auth 的 Python 版本」。
|
||||
|
||||
---
|
||||
|
||||
## 7. 實作範圍(MVP)
|
||||
|
||||
### Phase 1:核心 lib(2-3 週)
|
||||
|
||||
- [ ] `arcrun-auth` PyPI 骨架(pyproject.toml + src layout)
|
||||
- [ ] Recipe loader(從 GitHub 或平台 API 拉 YAML)
|
||||
- [ ] `auth.bind(service_id, instance?)` → httpx Client
|
||||
- [ ] Static key primitive(Notion / OpenAI / Stripe 當試金石)
|
||||
- [ ] Keyring 整合 + 本地加密檔 fallback
|
||||
- [ ] CLI:`arcrun setup <service>`, `arcrun list`, `arcrun test`
|
||||
|
||||
### Phase 2:OAuth2(2 週)
|
||||
|
||||
- [ ] OAuth2 primitive(authorization_code + PKCE)
|
||||
- [ ] 本地 callback server(類似 `InstalledAppFlow.run_local_server`)
|
||||
- [ ] 共用平台 OAuth App 的 proxy 機制
|
||||
- Lib 呼叫 `https://auth.arcrun.com/oauth/redirect`
|
||||
- 平台把 code 交換後回傳 token
|
||||
- 或者直接把平台 client_id 硬編在 recipe 裡(更簡單但要處理配額)
|
||||
- [ ] Token refresh 自動化
|
||||
- [ ] Recipe:Google Drive / Gmail / GitHub / Slack
|
||||
|
||||
### Phase 3:Service Account(1-2 週)
|
||||
|
||||
- [ ] Google Service Account(JWT signing)
|
||||
- [ ] AWS SigV4
|
||||
- [ ] Recipe 繼承(`extends: _google_base`)
|
||||
|
||||
### Phase 4:雲端同步(2 週)
|
||||
|
||||
- [ ] `arcrun login` → 綁定雲端帳號
|
||||
- [ ] Secret sync 協議(本地加密後上傳,平台只存密文)
|
||||
- [ ] 多機同步
|
||||
- [ ] Audit log
|
||||
|
||||
### Phase 5:AI 生態整合(1-2 週)
|
||||
|
||||
- [ ] MCP server(讓 Claude Code 能直接用)
|
||||
- [ ] VS Code Extension(一鍵設定 credential)
|
||||
- [ ] `AGENTS.md` 範本(引導 AI 選 arcrun-auth)
|
||||
|
||||
---
|
||||
|
||||
## 8. 風險與坑
|
||||
|
||||
### 8.1 Google OAuth Verification
|
||||
|
||||
**問題**:共用 OAuth App 要申請 Google Verification,否則會有「未驗證 App」警告 + 100 user 上限。
|
||||
|
||||
**對策**:
|
||||
- MVP 階段接受警告頁面(使用者自己點「進階 → 前往」)。
|
||||
- 到 user 量接近 100 時申請 Verification。
|
||||
- 企業客戶走 BYO OAuth App 路徑,不受影響。
|
||||
- 若平台 OAuth App 卡關,有 fallback:lib 自動引導使用者建自己的 OAuth App(提供 CLI wizard)。
|
||||
|
||||
### 8.2 其他服務的 OAuth App 政策
|
||||
|
||||
- **GitHub**:免費建 OAuth App,無上限。✅
|
||||
- **Slack**:免費建,但安裝到使用者 workspace 需管理員同意。⚠️
|
||||
- **Microsoft / Azure**:相對嚴格,需 tenant admin consent。⚠️
|
||||
- **Notion**:Internal Integration 可以完全走 API key,免 OAuth。✅(最簡單)
|
||||
|
||||
### 8.3 keyring 在 Linux server / Docker 的問題
|
||||
|
||||
Linux server 沒 GUI keyring daemon。對策:
|
||||
- Fallback 到加密檔案(用 env var 或 CLI 互動提供 master key)。
|
||||
- Docker 場景有 `docker secret`、Kubernetes Secret,lib 支援直接讀這些來源。
|
||||
|
||||
### 8.4 競品
|
||||
|
||||
目前沒有完全對標的產品,但相鄰玩家:
|
||||
- **[keyring](https://pypi.org/project/keyring/)**:只做儲存,不做認證流程。我們用它當底層。
|
||||
- **[httpx-auth](https://pypi.org/project/httpx-auth/)**:只做認證,不做 secret 管理,也沒有 recipe。
|
||||
- **[authlib](https://pypi.org/project/authlib/)**:OAuth 實作 lib,低階,還是要自己組。
|
||||
- **各家 SDK(google-auth, slack-sdk)**:綁特定家,不 unify。
|
||||
|
||||
**arcrun-auth 的差異化定位**:
|
||||
> **Unified credential broker for AI-era Python apps**
|
||||
> 一個 lib 搞定所有服務、所有認證機制、所有 secret 儲存後端。
|
||||
|
||||
---
|
||||
|
||||
## 9. 最後的判斷
|
||||
|
||||
### 9.1 這個 lib 該不該做?
|
||||
|
||||
**該做**。原因:
|
||||
1. 你描述的痛點是真的,而且規模巨大(Python + Google API 下載量是千萬級)。
|
||||
2. 技術可行,也跟既有 arcrun 架構共用 recipe,邊際成本低。
|
||||
3. 對 arcrun SaaS 是完美引流——免費 lib 的使用者是精準的付費轉換潛在客戶。
|
||||
4. 時間窗口正確:AI 寫程式時代剛開始,這個定位還沒被佔領。
|
||||
|
||||
### 9.2 跟主 SaaS 的優先順序
|
||||
|
||||
**建議**:**主 SaaS 的 credential 系統先做(前一份規劃),arcrun-auth 當後續 Phase**。
|
||||
|
||||
原因:
|
||||
- Cloudflare Worker 版的 primitives + recipes 是基礎建設,Python lib 是其 consumer。
|
||||
- 先做 Python lib 會逼你在 recipe schema 上做二次修改,不划算。
|
||||
- 主 SaaS 的 recipe 累積到 20-30 個服務後,開放 Python lib 體驗最好。
|
||||
|
||||
時程建議:
|
||||
- **Month 1-2**:主 SaaS 的 4 個 primitive + 15 個 recipe(前一份規劃)。
|
||||
- **Month 3-4**:arcrun-auth Phase 1-2(static key + OAuth2),私人 alpha。
|
||||
- **Month 5**:公開 release,寫部落格、SEO、社群推廣。
|
||||
- **Month 6+**:雲端同步、MCP、AI 生態整合。
|
||||
|
||||
### 9.3 一句話總結
|
||||
|
||||
> **arcrun-auth 不是「arcrun 的 Python 綁定」,是「OAuth 地獄的解藥」**。SaaS 是延伸。這個敘事才能在 AI 寫程式的時代站住腳。
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
# Arcrun 推廣策略修正
|
||||
|
||||
20260418 by Leo
|
||||
|
||||
## Arcrun 的最近幾次變化
|
||||
|
||||
- Arcrun 原是 Matrix 的原子化純雲端 CF 程式框架,有 MCP 讓 AI 使用
|
||||
- 轉以 WASM + WASI + TinyGo 成為未來具有雲端、地端、邊緣端的執行能力,可以用來做到無人機等終端。
|
||||
- 再解耦成獨立的 Open Source 專案,脫離 KBDB 用 YAML 即可,允許整個 Fork,但推廣 SaaS 模式
|
||||
- 今天的變化是發現成為 Lib 和 n8n 社群節點的用法。說明如下。
|
||||
|
||||
## 推廣方式 1:寫成 Lib
|
||||
|
||||
參考文件:docs/user_requirements/arcrun/ADR-lib-and-landingPage/arcrun-py-strategy-analysis.md
|
||||
|
||||
Leo 教 n8n 時常舉例我叫 AI 幫我寫個簡單的程式把 server 的檔案備份到 Google Drive 後刪除,光是 OAuth 用 Service Account 就花了 2 天測試,後來還發生好幾次出錯重修。
|
||||
|
||||
網路設定對 vibe coder 太複雜了,看到 AI 一次次修改一次次出錯,知道一週後才穩定,而 n8n 只需要申請 credential 填入,10 分鐘搞定,差距太大了。
|
||||
|
||||
問題是,n8n 實在太慢了,全圖像界面也難以跟程式碼整合,vibe coder 就算知道了也無法整合,他會繼續用 python 就是無法忍受 n8n 的慢速、沉重,及對 AI 的不友善。
|
||||
|
||||
Arcrun 用幾個基礎 Auth 零件取代 n8n 幾百個不同的 credentials 設定,arcrun 完全可以跟程式碼整合,只是目前沒有整合工具,也就是說,工程師不想面對一個認證花好幾天,他只要用 Arcrun 打 API 就幾行解決了。
|
||||
|
||||
用這個策略,讓具有程式知識的人會:
|
||||
- 對 Arcrun 有好感,在 GitHub 按星
|
||||
- 成為 Arcrun 用戶,增加會員 base
|
||||
- 寫文分享,讓 Arcrun 被傳出去
|
||||
|
||||
反之,小白初學 vibe coding,看到老工程師說 2 天變成 10 分鐘,百行程式碼變成 2 行,也會被影響。
|
||||
|
||||
所以,把 API 包裝成 Lib 或 SDK 是個 Get Member 的好方法,不過一定要有 Email。
|
||||
|
||||
## 推廣方式 2: 讓 n8n 來 call
|
||||
|
||||
身為 n8n 講師,我非常清楚 n8n 有個大缺陷(或說是安全設計),就是它只能呼叫在工作流實例化前就寫好的程式,無法注入新的。
|
||||
|
||||
所以,雖然它可以安裝一個實作 langchain AI Agent 的 AI Agent 節點,但 AI 卻不可能在遇到問題時立刻寫個程式運行解決問題,甚至使用它內建的 task runners 或使用外部的 Python runtime 也無法。
|
||||
|
||||
但只要使用 http request 節點呼叫外部的 Arcrun tool,它就可以輸出三元組寫一個程式解決它現在遇到的問題,並且運算完後回傳,只需要取得一個 API Key。
|
||||
|
||||
## 可能的效應
|
||||
|
||||
工程師是意見領袖,他們會去按星,幫忙教育市場,而小白需要被教育,但他們是較大的社群,這些星數和聲量會在未來變成 AI 訓練素材,甚至推薦用戶使用最 AI Friendly 的 Arcrun。
|
||||
|
||||
而實際上 Arcrun 的設計讓 AI 更輕鬆。
|
||||
|
||||
## 要做什麼
|
||||
|
||||
docs/user_requirements/arcrun/ADR-lib-and-landingPage/arcrun-pages-spec.md 這是 claude.ai 寫的規劃,因為它看不到 codebase,所以你要斟酌如何開發。
|
||||
|
||||
另外,當前的 API Key 雖然很容易取得,卻有個問題,用戶無法管理,所以頁面應該要有取得 API Key 的界面,可以 Google, GitHub 等 OAuth 或 Email + Password 登入,用來管理它的 API Key 的 CRUD。
|
||||
|
||||
或許是可以外接一個 SMTP 服務來確認他的 Email 真實,SaaS 服務還是有成本,雖然成本不高。
|
||||
|
||||
另外,既然是 OpenSource,成本雖然不高,似乎可以銜接 Donate 服務?
|
||||
@@ -0,0 +1,761 @@
|
||||
# arcrun Credential System 設計規格
|
||||
20260418
|
||||
|
||||
> **讀者**:Claude Code(CC),負責實作
|
||||
> **作者**:richblack(架構決策)
|
||||
> **版本**:v1.0
|
||||
> **狀態**:Draft — 等 CC 確認技術可行性後開工
|
||||
|
||||
---
|
||||
|
||||
## 0. TL;DR(給 CC 的三句話版)
|
||||
|
||||
1. **不要**為每個服務寫一個 credential 零件,n8n 是錯的。
|
||||
2. 做**四個 TinyGo/WASM 零件**(primitives),每個服務只需要一份 **YAML recipe** + 用戶自己的 **secret**。
|
||||
3. Recipe 存 arcrun 平台 KV(公共),secret 存 tenant KV(私有),兩者在 runtime 由 `AuthBroker` 組裝成可用的 HTTP client。
|
||||
|
||||
---
|
||||
|
||||
## 1. 設計目標與反目標
|
||||
|
||||
### 目標
|
||||
- **新增一個服務的成本 = 寫一份 YAML**,不需要 rebuild、不需要改 code。
|
||||
- **AI agent 理解成本 ≈ 0**:recipe 就是呼叫該服務的完整說明書。
|
||||
- **人類設定成本 < 10 分鐘**:即使是對 OAuth 不熟的使用者,UI 只問「你的 API Key 是什麼」這類 secret 層級問題。
|
||||
- **Secret 隔離**:每個 tenant 的 secret 絕對不互相可見,arcrun 平台本身也無法明文讀取(用 Cloudflare Secrets Store 或加密儲存)。
|
||||
|
||||
### 反目標(明確不做的事)
|
||||
- ❌ 不做 n8n 那種「每個服務一個 credential type」的視覺化面板。
|
||||
- ❌ 不支援 OAuth1(2026 年還在用的服務極少,真遇到再加)。
|
||||
- ❌ 不做 credential sharing 的複雜 ACL(全 tenant scope 即可,未來再擴充)。
|
||||
- ❌ 不在 arcrun 內部明文持久化任何長期 secret(只有加密過的密文或 Secrets Store reference)。
|
||||
|
||||
---
|
||||
|
||||
## 2. 核心架構:三層模型
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Layer 3: Service Recipe (YAML) │
|
||||
│ arcrun 平台共享,describe "如何呼叫這個服務" │
|
||||
│ 存在 Workers KV: arcrun-recipes │
|
||||
│ 例:recipe/notion.yaml, recipe/google_calendar.yaml │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
↓ 引用
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Layer 2: Auth Primitive (TinyGo → WASM) │
|
||||
│ 四個通用認證零件,實作注入邏輯與 token 交換 │
|
||||
│ 1. static_key 2. oauth2 │
|
||||
│ 3. service_account 4. mtls │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
↑ 使用
|
||||
┌─────────────────────────────────────────────────────────┐
|
||||
│ Layer 1: Tenant Secret (KV + Secrets Store) │
|
||||
│ 每個 tenant 自己的 KV namespace │
|
||||
│ 存 encrypted secret 或 Secrets Store reference │
|
||||
│ 例:secret/{tenant_id}/notion-prod │
|
||||
└─────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 為什麼這樣切?
|
||||
|
||||
| 切分維度 | Recipe | Primitive | Secret |
|
||||
|---|---|---|---|
|
||||
| **誰擁有** | arcrun 平台 | arcrun 平台 | tenant 自己 |
|
||||
| **變化頻率** | 中(新服務時) | 低(認證機制穩定) | 高(rotate、revoke) |
|
||||
| **敏感度** | 公開 | 公開 | 最高機密 |
|
||||
| **儲存位置** | 平台 KV(`arcrun-recipes`) | WASM binary | tenant KV + Secrets Store |
|
||||
| **可否社群貢獻** | ✅ PR | ⚠️ 核心團隊 | ❌ 永遠不 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 四個 Primitive 詳細規格
|
||||
|
||||
### 3.1 `static_key`
|
||||
|
||||
**適用**:API Key、Bearer Token、Basic Auth、任何「一組 secret 不會自動過期」的認證。
|
||||
|
||||
**涵蓋 n8n 的**:API Key、Basic Auth、Header Auth、Query Auth、Custom Auth、Digest Auth(~80% 服務)。
|
||||
|
||||
**Recipe 欄位**:
|
||||
```yaml
|
||||
primitive: static_key
|
||||
inject:
|
||||
# 四個注入位置,可以同時用多個
|
||||
header: # HTTP headers
|
||||
<key>: <value template>
|
||||
query: # URL query string
|
||||
<key>: <value template>
|
||||
body: # request body(JSON 欄位)
|
||||
<key>: <value template>
|
||||
basic_auth: # HTTP Basic Auth(會自動 base64 編碼)
|
||||
username: <value template>
|
||||
password: <value template>
|
||||
```
|
||||
|
||||
**Value template 語法**:`{{secret.xxx}}` 取 secret 欄位,`{{const.yyy}}` 取 recipe 內定義的常數。
|
||||
|
||||
**Secret schema**:tenant 存 JSON,欄位由 recipe 的 `required_secrets` 宣告。
|
||||
|
||||
**範例(Notion)**:
|
||||
```yaml
|
||||
# arcrun-recipes KV: recipe/notion
|
||||
service: notion
|
||||
version: 1
|
||||
primitive: static_key
|
||||
base_url: https://api.notion.com/v1
|
||||
required_secrets:
|
||||
- key: token
|
||||
label: "Internal Integration Token"
|
||||
help_url: https://www.notion.so/my-integrations
|
||||
inject:
|
||||
header:
|
||||
Authorization: "Bearer {{secret.token}}"
|
||||
Notion-Version: "2022-06-28"
|
||||
test:
|
||||
method: GET
|
||||
path: /users/me
|
||||
expect_status: 200
|
||||
```
|
||||
|
||||
**Secret 範例**:
|
||||
```json
|
||||
// tenant KV: secret/tenant_123/notion-prod
|
||||
{
|
||||
"token": "secret_abc123..."
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 3.2 `oauth2`
|
||||
|
||||
**適用**:需要人類首次授權、之後用 refresh token 續命的場景。
|
||||
|
||||
**Grant types 支援**:
|
||||
- `authorization_code`(最常見:GitHub、Slack、Google 用戶授權)
|
||||
- `client_credentials`(機器對機器)
|
||||
- `pkce`(SPA、行動應用)
|
||||
- ❌ 不支援:password grant(2026 已被多數 OAuth 提供者棄用)、implicit(已棄用)
|
||||
|
||||
**Recipe 欄位**:
|
||||
```yaml
|
||||
primitive: oauth2
|
||||
grant: authorization_code # or client_credentials, pkce
|
||||
base_url: <service API base>
|
||||
oauth:
|
||||
authorize_url: <IdP authorize endpoint>
|
||||
token_url: <IdP token endpoint>
|
||||
scopes:
|
||||
- <default scope 1>
|
||||
- <default scope 2>
|
||||
client_auth: header # or body
|
||||
# 是否使用 refresh token
|
||||
refresh: true
|
||||
# PKCE 時額外參數
|
||||
pkce_method: S256 # only for grant: pkce
|
||||
required_secrets:
|
||||
- key: client_id
|
||||
label: "Client ID"
|
||||
- key: client_secret
|
||||
label: "Client Secret"
|
||||
secret: true
|
||||
inject:
|
||||
header:
|
||||
Authorization: "Bearer {{runtime.access_token}}"
|
||||
```
|
||||
|
||||
**Runtime 欄位**(primitive 自動維護,存在 tenant KV 的 `oauth_state/{secret_id}` key):
|
||||
- `access_token`
|
||||
- `refresh_token`
|
||||
- `expires_at`
|
||||
|
||||
**首次授權流程**(人類要做的部分):
|
||||
1. arcrun UI 呼叫 `AuthBroker.startAuth(recipe_id, tenant_id)` 回傳 authorize URL。
|
||||
2. 使用者瀏覽器跳轉到 IdP,同意授權。
|
||||
3. IdP redirect 回 arcrun callback endpoint(固定一個 URL,無論哪個服務)。
|
||||
4. `AuthBroker` 用 authorization code 換 token,寫入 tenant KV。
|
||||
|
||||
**之後 agent 呼叫時完全自動**:primitive 檢查 `expires_at`,過期自動用 refresh token 續,失敗再觸發重新授權通知。
|
||||
|
||||
---
|
||||
|
||||
### 3.3 `service_account`
|
||||
|
||||
**適用**:Google Service Account、AWS IAM Role(assume role)、任何需要「私鑰簽 JWT 換短期 token」的機器身份。
|
||||
|
||||
**這個就是讓你 debug 兩天那個爆炸點。** 我們用 primitive 把地雷全部包起來。
|
||||
|
||||
**Recipe 欄位**:
|
||||
```yaml
|
||||
primitive: service_account
|
||||
kind: google_jwt # or aws_sigv4, generic_jwt
|
||||
base_url: <service API base>
|
||||
token_exchange:
|
||||
# Google 的 JWT → OAuth access token 流程
|
||||
endpoint: https://oauth2.googleapis.com/token
|
||||
audience: https://oauth2.googleapis.com/token
|
||||
scopes:
|
||||
- https://www.googleapis.com/auth/calendar
|
||||
# JWT claims
|
||||
issuer_from_secret: client_email
|
||||
subject_from_secret: client_email # optional, for domain-wide delegation 改成其他 user
|
||||
ttl_seconds: 3600
|
||||
required_secrets:
|
||||
- key: service_account_json
|
||||
label: "Service Account JSON"
|
||||
type: json_blob # 特別型別,UI 可以接受貼整個 JSON
|
||||
help: "到 GCP Console → IAM → Service Accounts → Keys → Add Key (JSON) 下載整份 JSON 貼上"
|
||||
inject:
|
||||
header:
|
||||
Authorization: "Bearer {{runtime.access_token}}"
|
||||
```
|
||||
|
||||
**為什麼不是每個服務一個 recipe?**
|
||||
- Google Calendar、Gmail、Drive、Sheets 全部可以共用同一個 `service_account` primitive。
|
||||
- 差別只在 `scopes` 和 `base_url`。
|
||||
- Recipe 本身可以 import 共通片段(見 §5 recipe 繼承)。
|
||||
|
||||
**AWS SigV4(kind: aws_sigv4)**:這是特例,不是 JWT-based,但概念一樣——用 access_key_id + secret_access_key 在每次 request 上簽章。Primitive 內建處理,recipe 只要宣告 region 和 service name。
|
||||
|
||||
---
|
||||
|
||||
### 3.4 `mtls`
|
||||
|
||||
**適用**:mTLS / client certificate。銀行 API、企業內部服務、醫療系統。
|
||||
|
||||
**Recipe 欄位**:
|
||||
```yaml
|
||||
primitive: mtls
|
||||
base_url: <service API base>
|
||||
required_secrets:
|
||||
- key: client_cert
|
||||
label: "Client Certificate (PEM)"
|
||||
type: pem_cert
|
||||
- key: client_key
|
||||
label: "Client Private Key (PEM)"
|
||||
type: pem_key
|
||||
secret: true
|
||||
- key: ca_cert
|
||||
label: "CA Certificate (PEM) — optional"
|
||||
type: pem_cert
|
||||
optional: true
|
||||
# mtls 通常不需要額外 inject,憑證在 TLS 層
|
||||
inject: {}
|
||||
```
|
||||
|
||||
**實作注意**:Cloudflare Workers 有原生 mTLS 支援(`mTLSCertificate` binding),primitive 只需要把 secret 轉成 Cloudflare mTLS binding 即可。
|
||||
|
||||
---
|
||||
|
||||
## 4. Recipe YAML Schema(完整版)
|
||||
|
||||
```yaml
|
||||
# 必填
|
||||
service: string # 唯一識別,snake_case,e.g. "notion", "google_calendar"
|
||||
version: integer # recipe schema version,breaking change 要升版
|
||||
primitive: enum # static_key | oauth2 | service_account | mtls
|
||||
base_url: string # service API base URL
|
||||
|
||||
# primitive 相關(依 primitive 不同)
|
||||
inject: object # 如何把 secret 注入 HTTP request
|
||||
oauth: object # 僅 oauth2 primitive
|
||||
token_exchange: object # 僅 service_account primitive
|
||||
|
||||
# Secret 宣告(讓 UI 知道要問什麼)
|
||||
required_secrets:
|
||||
- key: string # secret 欄位名
|
||||
label: string # UI 顯示
|
||||
secret: boolean # 是否遮蔽顯示(default: true)
|
||||
type: enum # text | json_blob | pem_cert | pem_key | url
|
||||
optional: boolean # default: false
|
||||
help: string # 給使用者的提示
|
||||
help_url: string # 導向服務文件
|
||||
|
||||
# 測試(驗證 credential 是否有效)
|
||||
test:
|
||||
method: GET | POST
|
||||
path: string # 相對 base_url
|
||||
expect_status: integer
|
||||
expect_json: object # 選填,JSON path assertion
|
||||
|
||||
# Metadata
|
||||
display_name: string # UI 顯示名
|
||||
description: string
|
||||
icon_url: string
|
||||
docs_url: string
|
||||
tags:
|
||||
- communication
|
||||
- crm
|
||||
- ai
|
||||
maintainers:
|
||||
- github: username
|
||||
|
||||
# 可選:共通片段繼承
|
||||
extends: string # recipe name,繼承其 schema 後覆寫
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. Recipe 繼承(reduce 重複)
|
||||
|
||||
Google 家族的 API 長得很像,重複寫 15 次太蠢。支援 `extends`:
|
||||
|
||||
```yaml
|
||||
# recipe/_google_base.yaml(底線開頭 = 抽象 recipe,不能直接用)
|
||||
service: _google_base
|
||||
version: 1
|
||||
primitive: service_account
|
||||
token_exchange:
|
||||
endpoint: https://oauth2.googleapis.com/token
|
||||
audience: https://oauth2.googleapis.com/token
|
||||
ttl_seconds: 3600
|
||||
required_secrets:
|
||||
- key: service_account_json
|
||||
type: json_blob
|
||||
inject:
|
||||
header:
|
||||
Authorization: "Bearer {{runtime.access_token}}"
|
||||
```
|
||||
|
||||
```yaml
|
||||
# recipe/google_calendar.yaml
|
||||
extends: _google_base
|
||||
service: google_calendar
|
||||
version: 1
|
||||
base_url: https://www.googleapis.com/calendar/v3
|
||||
token_exchange:
|
||||
scopes:
|
||||
- https://www.googleapis.com/auth/calendar
|
||||
test:
|
||||
method: GET
|
||||
path: /users/me/calendarList
|
||||
expect_status: 200
|
||||
```
|
||||
|
||||
繼承規則:scalar 覆寫,object 深度合併,array 預設覆寫(可用 `!append` 標記 append)。
|
||||
|
||||
---
|
||||
|
||||
## 6. TinyGo WASM Primitive 實作介面
|
||||
|
||||
### 6.1 統一介面(四個 primitive 都實作這個)
|
||||
|
||||
```go
|
||||
// primitive/interface.go
|
||||
package primitive
|
||||
|
||||
type AuthRequest struct {
|
||||
Method string
|
||||
URL string
|
||||
Headers map[string]string
|
||||
Body []byte
|
||||
}
|
||||
|
||||
type AuthContext struct {
|
||||
Recipe Recipe // parsed YAML
|
||||
Secret map[string]any // decrypted secret
|
||||
Runtime RuntimeState // oauth token cache 等
|
||||
Now int64 // for testing
|
||||
}
|
||||
|
||||
type Primitive interface {
|
||||
// 在 HTTP request 上注入認證資訊
|
||||
Authenticate(req *AuthRequest, ctx *AuthContext) error
|
||||
|
||||
// 檢查是否需要 refresh(oauth2 / service_account 用)
|
||||
NeedsRefresh(ctx *AuthContext) bool
|
||||
|
||||
// 執行 refresh / token exchange,回傳新的 RuntimeState
|
||||
Refresh(ctx *AuthContext) (RuntimeState, error)
|
||||
|
||||
// 驗證 credential 是否有效(執行 recipe.test)
|
||||
Test(ctx *AuthContext) error
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 編譯與部署
|
||||
|
||||
```bash
|
||||
# 四個 primitive 各自編譯成獨立 WASM
|
||||
tinygo build -o dist/static_key.wasm -target=wasi ./primitive/static_key
|
||||
tinygo build -o dist/oauth2.wasm -target=wasi ./primitive/oauth2
|
||||
tinygo build -o dist/service_account.wasm -target=wasi ./primitive/service_account
|
||||
tinygo build -o dist/mtls.wasm -target=wasi ./primitive/mtls
|
||||
|
||||
# 部署時放到 Cloudflare Workers 的 Assets 或直接內嵌
|
||||
```
|
||||
|
||||
### 6.3 Runtime 載入(Worker 端)
|
||||
|
||||
```typescript
|
||||
// worker/src/auth-broker.ts
|
||||
import staticKeyWasm from "../dist/static_key.wasm"
|
||||
import oauth2Wasm from "../dist/oauth2.wasm"
|
||||
// ...
|
||||
|
||||
const primitives = {
|
||||
static_key: await instantiate(staticKeyWasm),
|
||||
oauth2: await instantiate(oauth2Wasm),
|
||||
service_account: await instantiate(serviceAccountWasm),
|
||||
mtls: await instantiate(mtlsWasm),
|
||||
}
|
||||
```
|
||||
|
||||
> **為什麼 WASM 而不是直接 TS?**
|
||||
> 1. 跨 runtime 可攜性(未來若 arcrun 要跑在 Fly.io、local、或客戶自建環境,同一個 primitive 能用)。
|
||||
> 2. 配合 u6u/arcrun 既定的 WASM 架構方向,不破壞統一性。
|
||||
> 3. 沙箱化:primitive 只能透過明確的 host function 存取外部世界(網路、KV),降低惡意 recipe 攻擊面。
|
||||
|
||||
---
|
||||
|
||||
## 7. AuthBroker API(給 arcrun 其他部分調用)
|
||||
|
||||
```typescript
|
||||
interface AuthBroker {
|
||||
// Agent 執行時用的主要 API
|
||||
bind(serviceId: string, secretRef: string, tenantId: string): Promise<AuthenticatedClient>
|
||||
|
||||
// 首次授權(僅 oauth2 用)
|
||||
startAuth(serviceId: string, tenantId: string): Promise<{ authorizeUrl: string, state: string }>
|
||||
completeAuth(state: string, code: string): Promise<{ secretRef: string }>
|
||||
|
||||
// 測試 credential
|
||||
test(serviceId: string, secretRef: string, tenantId: string): Promise<TestResult>
|
||||
|
||||
// 管理
|
||||
listRecipes(): Promise<Recipe[]>
|
||||
getRecipe(serviceId: string): Promise<Recipe>
|
||||
}
|
||||
|
||||
interface AuthenticatedClient {
|
||||
fetch(path: string, init?: RequestInit): Promise<Response>
|
||||
}
|
||||
```
|
||||
|
||||
**使用範例(agent 端)**:
|
||||
```typescript
|
||||
const notion = await authBroker.bind("notion", "notion-prod", ctx.tenantId)
|
||||
const res = await notion.fetch("/databases/abc/query", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({ filter: {...} })
|
||||
})
|
||||
```
|
||||
|
||||
**Agent 完全不需要知道是 API Key 還是 OAuth**——`authBroker.bind()` 回傳的 client 已經注入好認證,fetch 路徑用相對 base_url 的路徑即可。
|
||||
|
||||
---
|
||||
|
||||
## 8. Storage Layout
|
||||
|
||||
### 8.1 Recipe 儲存(arcrun 平台共享)
|
||||
|
||||
**Cloudflare KV namespace**:`arcrun-recipes`
|
||||
|
||||
```
|
||||
key: recipe/{service_id}
|
||||
value: <recipe YAML 的 JSON 化版本>
|
||||
|
||||
key: recipe-list
|
||||
value: [{ service_id, display_name, icon_url, tags }, ...] # 加速 UI 列表
|
||||
```
|
||||
|
||||
**更新流程**:
|
||||
1. Recipe YAML 存在 arcrun 主 repo 的 `recipes/` 目錄下(version control + PR review)。
|
||||
2. CI 跑 schema validator,通過後上傳到 KV。
|
||||
3. UI 的 recipe 列表 5 分鐘 cache。
|
||||
|
||||
### 8.2 Secret 儲存(tenant 私有)
|
||||
|
||||
**雙層策略**:
|
||||
- **短期、低敏感** → tenant KV,用 AES-256-GCM 加密,key 從 Cloudflare Secrets Store 拿。
|
||||
- **高敏感(如 service account JSON、private key)** → 直接存 Cloudflare Secrets Store,tenant KV 只存 reference。
|
||||
|
||||
```
|
||||
# tenant KV namespace: arcrun-tenant-{tenant_id}
|
||||
key: secret/{service_id}/{instance_name}
|
||||
value: {
|
||||
"recipe_version": 1,
|
||||
"storage_mode": "kv_encrypted" | "secrets_store_ref",
|
||||
"data": <encrypted blob> | { "ref": "secrets-store-id" },
|
||||
"created_at": "...",
|
||||
"last_verified_at": "..."
|
||||
}
|
||||
|
||||
# oauth2 runtime state(primitive 自動管理)
|
||||
key: oauth_state/{service_id}/{instance_name}
|
||||
value: {
|
||||
"access_token": "...", # encrypted
|
||||
"refresh_token": "...", # encrypted
|
||||
"expires_at": 1234567890
|
||||
}
|
||||
```
|
||||
|
||||
**secretRef 格式**:`{service_id}/{instance_name}`,例如 `notion/prod`、`google_calendar/workspace-a`。
|
||||
一個 tenant 可以同一個服務存多個 instance(多帳號場景)。
|
||||
|
||||
### 8.3 KBDB 整合(可選,但建議)
|
||||
|
||||
**按照 KBDB 架構,recipe metadata 可以用 Block + Template 表達**(不是 credential 本體,只是 metadata):
|
||||
|
||||
建立一個 `service_recipe` Template:
|
||||
```json
|
||||
{
|
||||
"name": "service_recipe",
|
||||
"display_name": "服務 Recipe Metadata",
|
||||
"schema": {
|
||||
"fields": [
|
||||
{"key": "service_id", "type": "text", "required": true, "description": "服務識別"},
|
||||
{"key": "primitive", "type": "text", "required": true, "description": "使用的 primitive"},
|
||||
{"key": "version", "type": "number", "required": true, "description": "Recipe 版本"},
|
||||
{"key": "display_name", "type": "text", "required": false, "description": "顯示名稱"},
|
||||
{"key": "docs_url", "type": "text", "required": false, "description": "文件 URL"},
|
||||
{"key": "kv_key", "type": "text", "required": true, "description": "KV 實際存取 key"}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Secret **不**進 KBDB(KBDB 不該存敏感資料),只有 metadata 在 KBDB 裡方便搜尋和關聯。
|
||||
|
||||
---
|
||||
|
||||
## 9. 首次授權 UI Flow(給人類看的部分)
|
||||
|
||||
這是「學員不知道該選哪個 credential 的痛點」的終結方案。
|
||||
|
||||
### 9.1 Static Key 的 UI
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────┐
|
||||
│ 連接 Notion │
|
||||
├──────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Internal Integration Token │
|
||||
│ ┌────────────────────────────────────┐ │
|
||||
│ │ secret_••••••••••••• │ │
|
||||
│ └────────────────────────────────────┘ │
|
||||
│ ↳ 如何取得?→ 開啟 Notion 整合設定頁 │
|
||||
│ │
|
||||
│ [ 測試連線 ] [ 儲存 ] │
|
||||
└──────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**零選項。** UI 從 recipe 的 `required_secrets` 動態生成。使用者不用選「這是 Header Auth 還是 Query Auth 還是 Custom Auth」——那是 recipe 的事,不是使用者的事。
|
||||
|
||||
### 9.2 OAuth2 的 UI
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────┐
|
||||
│ 連接 GitHub │
|
||||
├──────────────────────────────────────────┤
|
||||
│ │
|
||||
│ [ 🔗 使用 GitHub 帳號登入 ] │
|
||||
│ │
|
||||
│ 將跳轉到 GitHub,授權後自動返回 │
|
||||
│ │
|
||||
└──────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**一個按鈕。** Client ID / Secret 由 arcrun 平台統一管理(OAuth App 註冊在 arcrun 這邊),使用者看不到也不用知道。
|
||||
|
||||
### 9.3 Service Account 的 UI
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────┐
|
||||
│ 連接 Google Calendar │
|
||||
├──────────────────────────────────────────┤
|
||||
│ │
|
||||
│ Service Account JSON │
|
||||
│ ┌────────────────────────────────────┐ │
|
||||
│ │ 將整份 JSON 貼到這裡 │ │
|
||||
│ │ │ │
|
||||
│ │ { │ │
|
||||
│ │ "type": "service_account", │ │
|
||||
│ │ "project_id": "...", │ │
|
||||
│ │ ... │ │
|
||||
│ │ } │ │
|
||||
│ └────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ 如何取得?→ 展開步驟說明 ▼ │
|
||||
│ 1. 打開 GCP Console │
|
||||
│ 2. IAM → Service Accounts │
|
||||
│ 3. 建立 Service Account │
|
||||
│ 4. Keys → Add Key → JSON │
|
||||
│ 5. 下載後整份貼到上方 │
|
||||
│ │
|
||||
│ [ 測試連線 ] [ 儲存 ] │
|
||||
└──────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
**貼 JSON + 按鈕**。不用寫任何程式碼,不用 debug 兩天。
|
||||
|
||||
---
|
||||
|
||||
## 10. 實作任務分解(CC 的 TODO list)
|
||||
|
||||
### Phase 1:核心骨架(1-2 週)
|
||||
|
||||
- [ ] **T1.1** Recipe YAML schema 定義 + JSON Schema validator(放 `arcrun/schemas/recipe.schema.json`)
|
||||
- [ ] **T1.2** Recipe loader:從 `recipes/` 目錄讀 YAML → validate → 轉 JSON 存入 KV namespace `arcrun-recipes`
|
||||
- [ ] **T1.3** TinyGo WASM 專案骨架(`arcrun/primitives/`),四個子目錄,統一 interface
|
||||
- [ ] **T1.4** Worker runtime 的 WASM loader + host function(網路、KV 讀寫)
|
||||
- [ ] **T1.5** `AuthBroker` TypeScript 類別骨架 + unit test
|
||||
|
||||
### Phase 2:Static Key(1 週)
|
||||
|
||||
- [ ] **T2.1** `static_key.wasm` 實作(header/query/body/basic_auth 四種注入)
|
||||
- [ ] **T2.2** 寫三個 recipe:`notion.yaml`, `openai.yaml`, `stripe.yaml`
|
||||
- [ ] **T2.3** Tenant KV secret 加密寫入 + `AuthBroker.bind()` 整合
|
||||
- [ ] **T2.4** `recipe.test` 執行器(驗證 credential 有效性)
|
||||
- [ ] **T2.5** E2E test:存 secret → bind → fetch Notion API → assert
|
||||
|
||||
### Phase 3:OAuth2(1-2 週)
|
||||
|
||||
- [ ] **T3.1** `oauth2.wasm` 實作(authorization_code + client_credentials + pkce)
|
||||
- [ ] **T3.2** OAuth callback endpoint(統一 URL,用 state 路由到正確 tenant/recipe)
|
||||
- [ ] **T3.3** Refresh token 自動續命邏輯(rate-limit 保護:同一 token 不能 1 秒內 refresh 多次)
|
||||
- [ ] **T3.4** 寫三個 recipe:`github.yaml`, `slack.yaml`, `google_oauth_user.yaml`
|
||||
- [ ] **T3.5** UI flow:startAuth → 跳轉 → callback → 寫 secret
|
||||
|
||||
### Phase 4:Service Account(1 週)
|
||||
|
||||
- [ ] **T4.1** `service_account.wasm` 實作(google_jwt)
|
||||
- [ ] **T4.2** Google JWT signing(ES256 / RS256)— **這個 TinyGo 需要注意 crypto 支援**
|
||||
- [ ] **T4.3** AWS SigV4 簽章實作(kind: aws_sigv4)
|
||||
- [ ] **T4.4** Recipe 繼承機制(`extends` 支援)
|
||||
- [ ] **T4.5** 寫 recipes:`_google_base`, `google_calendar`, `google_drive`, `gmail`, `aws_s3`
|
||||
|
||||
### Phase 5:mTLS + 收尾(1 週)
|
||||
|
||||
- [ ] **T5.1** `mtls.wasm` 實作(對接 Cloudflare `mTLSCertificate` binding)
|
||||
- [ ] **T5.2** Cloudflare Secrets Store 整合(高敏感 secret 用)
|
||||
- [ ] **T5.3** Recipe marketplace UI(列出可用 recipe,搜尋,一鍵設定)
|
||||
- [ ] **T5.4** Observability:每次 bind / refresh / test 記錄到 KBDB(metadata,不含 secret)
|
||||
- [ ] **T5.5** Docs:recipe 撰寫指南(讓社群能貢獻)
|
||||
|
||||
### Phase 6:Recipe 生成器(選配,1 週)
|
||||
|
||||
- [ ] **T6.1** 給 Claude 一份 API doc,自動產 recipe YAML 草稿 + 人類 review 介面
|
||||
- [ ] **T6.2** 從 OpenAPI spec 自動推論 recipe
|
||||
- [ ] **T6.3** 從 n8n credential file 反向轉譯(擷取 400+ 現成整合)
|
||||
|
||||
---
|
||||
|
||||
## 11. 關鍵技術風險與對策
|
||||
|
||||
| 風險 | 對策 |
|
||||
|---|---|
|
||||
| **TinyGo 的 crypto 支援不完整**(ES256 / RS256 JWT 簽章) | 先用 `crypto/rsa` + `crypto/ecdsa` 確認 TinyGo 版本支援;若不行,fallback 用 Worker runtime 的 `crypto.subtle` 實作這部分,WASM 透過 host function 呼叫 |
|
||||
| **Recipe 被惡意提交**(如 inject 內含 `https://evil.com` 當 token_url) | Recipe 走 PR review + CI 自動檢查 URL 白名單;社群貢獻的 recipe 預設隔離在 `community/` 目錄,使用者明確選擇才啟用 |
|
||||
| **OAuth state CSRF** | state 用 `crypto.randomUUID()` + 5 分鐘 TTL,存在 KV,callback 時比對 |
|
||||
| **Secret 在 Worker log 外洩** | `AuthContext.Secret` 禁止 `toString` / `JSON.stringify`,用 Proxy 攔截;log 層強制 redact |
|
||||
| **Token refresh 風暴**(100 個並發 request 同時發現過期) | 用 Durable Object 單執行緒化每個 secret 的 refresh,其他 request 等結果 |
|
||||
| **TinyGo WASM bundle size** | 四個 primitive 分開編譯,最大 500KB/個;lazy load |
|
||||
| **Recipe 版本升級破壞相容** | `version` 欄位 semver,tenant secret 記錄 `recipe_version`,primitive 內處理遷移 |
|
||||
|
||||
---
|
||||
|
||||
## 12. 對比 n8n(給內部 review / 行銷用)
|
||||
|
||||
| 維度 | n8n | arcrun |
|
||||
|---|---|---|
|
||||
| Credential types 數量 | 400+(一個服務一個) | 4(primitive) + N recipe |
|
||||
| 新增一個服務 | 寫 TypeScript class + rebuild + npm publish | 寫一份 YAML + PR merge |
|
||||
| AI agent 使用 | 需要讀 node 文件 + 猜參數 | 讀 recipe YAML 即可 |
|
||||
| 使用者首次設定 | 從 400+ 選項選一個(常選錯) | 搜尋服務名,只問必要 secret |
|
||||
| OAuth App 管理 | 使用者自己註冊 OAuth app | arcrun 平台統一管理(使用者只需點「授權」) |
|
||||
| 社群貢獻成本 | 高(TS + 編譯 + 測試) | 低(YAML + 測試) |
|
||||
|
||||
---
|
||||
|
||||
## 13. 接下來的決策點(需要 richblack 確認)
|
||||
|
||||
- [ ] **Recipe 版本管理策略**:採用 semver?每個 recipe 獨立版本?還是整個 recipe set 一個版本?
|
||||
- [ ] **OAuth App 註冊**:arcrun 平台要統一註冊幾個主流服務的 OAuth App(GitHub、Google、Slack、Microsoft)?還是讓 tenant 自己帶 client_id/secret?
|
||||
- 建議:**雙模式**——平台模式(方便)+ BYO 模式(企業客戶用自己的 OAuth app 有稽核好處)
|
||||
- [ ] **Recipe registry 的審核流程**:完全開放 PR 還是僅核心團隊維護?
|
||||
- 建議:`recipes/official/`(核心維護)+ `recipes/community/`(PR 審核後 merge,使用者需明確啟用)
|
||||
- [ ] **Secret rotation 政策**:要不要內建提醒 / 自動 rotate?(Phase 7+)
|
||||
|
||||
---
|
||||
|
||||
## 14. 附錄:完整範例
|
||||
|
||||
### A. 最小可行 recipe(OpenAI)
|
||||
|
||||
```yaml
|
||||
service: openai
|
||||
version: 1
|
||||
primitive: static_key
|
||||
display_name: OpenAI
|
||||
base_url: https://api.openai.com/v1
|
||||
required_secrets:
|
||||
- key: api_key
|
||||
label: API Key
|
||||
help_url: https://platform.openai.com/api-keys
|
||||
inject:
|
||||
header:
|
||||
Authorization: "Bearer {{secret.api_key}}"
|
||||
test:
|
||||
method: GET
|
||||
path: /models
|
||||
expect_status: 200
|
||||
tags: [ai]
|
||||
```
|
||||
|
||||
### B. OAuth2 recipe(Slack)
|
||||
|
||||
```yaml
|
||||
service: slack
|
||||
version: 1
|
||||
primitive: oauth2
|
||||
display_name: Slack
|
||||
base_url: https://slack.com/api
|
||||
grant: authorization_code
|
||||
oauth:
|
||||
authorize_url: https://slack.com/oauth/v2/authorize
|
||||
token_url: https://slack.com/api/oauth.v2.access
|
||||
scopes:
|
||||
- chat:write
|
||||
- channels:read
|
||||
refresh: true
|
||||
client_auth: header
|
||||
inject:
|
||||
header:
|
||||
Authorization: "Bearer {{runtime.access_token}}"
|
||||
test:
|
||||
method: POST
|
||||
path: /auth.test
|
||||
expect_json:
|
||||
ok: true
|
||||
tags: [communication]
|
||||
```
|
||||
|
||||
### C. Service Account recipe(Google Calendar)
|
||||
|
||||
```yaml
|
||||
extends: _google_base
|
||||
service: google_calendar
|
||||
version: 1
|
||||
display_name: Google Calendar
|
||||
base_url: https://www.googleapis.com/calendar/v3
|
||||
token_exchange:
|
||||
scopes:
|
||||
- https://www.googleapis.com/auth/calendar
|
||||
test:
|
||||
method: GET
|
||||
path: /users/me/calendarList
|
||||
expect_status: 200
|
||||
tags: [calendar, google]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 15. 給 CC 的行動指引
|
||||
|
||||
1. **先不要動既有 arcrun 的 credential 相關 code**,保持現狀到 Phase 2 完成再切換。
|
||||
2. **Phase 1 + 2 是 MVP**,做完可以接 80% 服務(API key 類)。
|
||||
3. **遇到 TinyGo 的技術阻礙(特別是 crypto),立刻回報**,不要自己 workaround 兩天。
|
||||
4. 每個 Phase 完成後寫一份 brief report(能跑什麼、不能跑什麼、下一步)。
|
||||
5. Recipe 撰寫先做 3-5 個手工範例,**確認 schema 夠用再開始批量生成**。
|
||||
@@ -0,0 +1,521 @@
|
||||
# u6u-core 獨立開源 Repo 需求規格 v3
|
||||
|
||||
## 背景與定位
|
||||
|
||||
### 為什麼開源
|
||||
|
||||
u6u-core 是 AI 工作流執行引擎,開源的護城河邏輯如下:
|
||||
|
||||
```
|
||||
開源(u6u-core) 閉源(InkStone 付費服務)
|
||||
──────────────────────── ──────────────────────────────
|
||||
cypher-executor(執行引擎) KBDB 向量搜尋
|
||||
WASM 零件庫(Gmail / GSheets…) KBDB graph 查詢
|
||||
credentials Worker Persona SDK / Mini-me
|
||||
CLI MatchGPT
|
||||
→ 需要訂閱,不需要 YAML / KV
|
||||
```
|
||||
|
||||
用戶自架版:YAML + CF KV,完全免費。
|
||||
升級版:不需要 YAML,直接用自然語言查 KBDB 圖譜組 workflow,這是差異化。
|
||||
|
||||
### 目前 matrix repo 狀況
|
||||
|
||||
```
|
||||
matrix/
|
||||
├── cypher-executor/ ← 要搬進 u6u-core
|
||||
├── u6u-core/
|
||||
│ ├── builtins/
|
||||
│ ├── credentials/
|
||||
│ └── registry/
|
||||
│ └── components/(21 個 WASM 零件)
|
||||
└── ...(其他 InkStone 內部服務,不搬)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 任務一:搬移 cypher-executor 進 u6u-core
|
||||
|
||||
### 目標結構
|
||||
|
||||
```
|
||||
u6u-core/(新獨立 repo,開源)
|
||||
├── README.md
|
||||
├── cypher-executor/ ← 從 matrix/cypher-executor 搬入
|
||||
│ ├── src/
|
||||
│ ├── wrangler.toml ← 需要清理(移除 InkStone 內部 bindings)
|
||||
│ └── ...
|
||||
├── credentials/ ← 從 matrix/u6u-core/credentials 搬入
|
||||
├── builtins/ ← 從 matrix/u6u-core/builtins 搬入
|
||||
└── registry/
|
||||
└── components/ ← 從 matrix/u6u-core/registry/components 搬入
|
||||
```
|
||||
|
||||
### wrangler.toml 清理(重要)
|
||||
|
||||
現有 `cypher-executor/wrangler.toml` 有大量 InkStone 內部 Service Bindings,開源版要移除:
|
||||
|
||||
**移除(InkStone 專屬,不公開):**
|
||||
```toml
|
||||
# 移除這些 services bindings:
|
||||
KBDB → inkstone-kbdb-api
|
||||
REGISTRY → inkstone-component-registry
|
||||
CLINIC_GDRIVE → clinic-gdrive
|
||||
CLINIC_EXCEL → clinic-excel
|
||||
CLINIC_ANALYSIS
|
||||
CLINIC_RENDER
|
||||
CLINIC_GSHEETS
|
||||
AICEO → inkstone-aiceo-bot
|
||||
MINI_ME → inkstone-mini-me
|
||||
```
|
||||
|
||||
**保留(用戶自己部署需要的):**
|
||||
```toml
|
||||
[[kv_namespaces]]
|
||||
binding = "EXEC_CONTEXT" # 執行上下文暫存
|
||||
|
||||
[[kv_namespaces]]
|
||||
binding = "WEBHOOKS" # workflow YAML 儲存
|
||||
|
||||
[[r2_buckets]]
|
||||
binding = "WASM_BUCKET" # WASM 零件二進位
|
||||
|
||||
[ai]
|
||||
binding = "AI" # Workers AI(auto-publish 用)
|
||||
```
|
||||
|
||||
**新增(開源版用戶需要的):**
|
||||
```toml
|
||||
[[kv_namespaces]]
|
||||
binding = "CREDENTIALS_KV" # credential 加密存儲
|
||||
```
|
||||
|
||||
### 清理後的 component-loader
|
||||
|
||||
現有 component-loader 可能有 InkStone 內部查詢邏輯(KBDB HTTP fetch),
|
||||
開源版改為:**直接從 WASM_BUCKET R2 讀取 `.wasm` 檔案**,不依賴任何外部服務。
|
||||
|
||||
---
|
||||
|
||||
## 任務二:零件完成度審查與補充
|
||||
|
||||
### 完成度標準
|
||||
|
||||
每個零件的 `component.contract.yaml` 必須包含:
|
||||
|
||||
```yaml
|
||||
# 已有(現狀)
|
||||
canonical_id: "gmail"
|
||||
input_schema: ...
|
||||
output_schema: ...
|
||||
gherkin_tests: ...
|
||||
|
||||
# 需要補充
|
||||
credentials_required: # 需要 token 的零件才需要此欄位
|
||||
- key: gmail_token # 對應 credentials.yaml 的 key 名稱慣例
|
||||
type: google_oauth # token 類型
|
||||
description: "Google OAuth access token(gmail.send scope)"
|
||||
inject_as: access_token # 執行時自動注入到 input 的哪個欄位
|
||||
|
||||
config_example: | # scaffold 指令產出的範本,帶說明註解
|
||||
send_email: # 節點名稱(可自訂)
|
||||
to: "" # 收件人 Email(必填)
|
||||
subject: "" # 主旨(必填)
|
||||
body: "" # 內文(必填)
|
||||
# access_token 由 credentials.yaml 的 gmail_token 自動注入
|
||||
```
|
||||
|
||||
### 需要 credentials_required 的零件
|
||||
|
||||
| 零件 | 需要的 token | inject_as |
|
||||
|------|-------------|-----------|
|
||||
| gmail | google_oauth | access_token |
|
||||
| google_sheets | google_oauth | access_token |
|
||||
| telegram | telegram_bot_token | bot_token |
|
||||
| line_notify | line_token | token |
|
||||
| http_request | 不固定(用戶自訂) | 不適用 |
|
||||
|
||||
### 不需要 credentials_required 的零件
|
||||
|
||||
set, filter, merge, switch, wait, if_control, foreach_control,
|
||||
try_catch, validate_json, string_ops, number_ops, array_ops,
|
||||
date_ops, cron, ai_transform_compile, ai_transform_run
|
||||
|
||||
### 審查任務(給 CC)
|
||||
|
||||
對 21 個零件逐一檢查,**只回報,不修改**:
|
||||
|
||||
```
|
||||
路徑:u6u-core/registry/components/
|
||||
|
||||
檢查四項:
|
||||
1. contract.yaml 存在?
|
||||
2. 有 credentials_required?(需要 token 的才需要)
|
||||
3. 有 config_example?
|
||||
4. main.go required 欄位與 contract input_schema required[] 一致?
|
||||
|
||||
回報格式:表格(✓ / ✗ / N/A)+ 每個零件缺少什麼
|
||||
不修改任何檔案。
|
||||
```
|
||||
|
||||
審查完成後,再逐一補充缺少的欄位。
|
||||
|
||||
---
|
||||
|
||||
## 任務三:workflow YAML 格式定義
|
||||
|
||||
### 格式設計原則
|
||||
|
||||
- `flow:` 用 `>>` 三元組描述資料流,人類直接看懂
|
||||
- 關係詞使用有語意的詞,**不使用 PIPE**(PIPE 等於什麼都沒說)
|
||||
- `config:` 用零件名稱對應參數,欄位從 contract 的 config_example 來
|
||||
- credential 全部集中在 `credentials.yaml`,workflow 只寫 `{{creds.KEY}}`
|
||||
|
||||
### 可用關係詞
|
||||
|
||||
| 關係詞 | 語意 | 使用時機 |
|
||||
|--------|------|---------|
|
||||
| `完成後` | 前一個成功後執行 | 最常用的串接 |
|
||||
| `失敗時` | 前一個失敗後執行 | 錯誤處理 |
|
||||
| `對每個` | 對陣列每個元素執行 | 迭代 |
|
||||
| `條件滿足時` | 條件分支 | 判斷 |
|
||||
| `ON_SUCCESS` | 同「完成後」 | 英文版 |
|
||||
| `ON_FAIL` | 同「失敗時」 | 英文版 |
|
||||
| `FOREACH` | 同「對每個」 | 英文版 |
|
||||
| `IF` | 同「條件滿足時」 | 英文版 |
|
||||
| `ON_CLICK` | 前端按鈕觸發 | UI 互動 |
|
||||
| `CALLS_SUBFLOW` | 呼叫子工作流 | 模組化 |
|
||||
|
||||
**禁止使用 PIPE** — 任何串接都應該用有語意的關係詞。
|
||||
|
||||
### workflow.yaml 範例
|
||||
|
||||
```yaml
|
||||
name: newsletter_subscribe
|
||||
description: 訂閱電子報,發感謝信並記錄到 GSheets
|
||||
|
||||
flow:
|
||||
- "input >> 完成後 >> send_thanks"
|
||||
- "input >> 完成後 >> save_to_sheet"
|
||||
- "send_thanks >> 完成後 >> output"
|
||||
- "send_thanks >> 失敗時 >> notify_error"
|
||||
- "save_to_sheet >> 完成後 >> output"
|
||||
|
||||
config:
|
||||
send_thanks: # componentId: gmail(由 cypher-executor 語意搜尋對應)
|
||||
to: "{{input.email}}"
|
||||
subject: "感謝訂閱!"
|
||||
body: "歡迎加入!"
|
||||
# access_token 由 credentials.yaml 的 gmail_token 自動注入
|
||||
|
||||
save_to_sheet: # componentId: google_sheets
|
||||
action: write
|
||||
spreadsheet_id: "{{creds.sheet_id}}"
|
||||
range: "訂閱者!A:B"
|
||||
values: [["{{input.email}}", "{{input.timestamp}}"]]
|
||||
# access_token 由 credentials.yaml 的 google_oauth 自動注入
|
||||
|
||||
notify_error: # componentId: telegram
|
||||
chat_id: "{{creds.telegram_chat_id}}"
|
||||
text: "發信失敗:{{input.email}}"
|
||||
# bot_token 由 credentials.yaml 的 telegram_bot_token 自動注入
|
||||
```
|
||||
|
||||
### credentials.yaml 範例
|
||||
|
||||
```yaml
|
||||
# credentials.yaml — 類似 .env,加入 .gitignore,不進 git
|
||||
# u6u creds push 時逐一加密上傳到 CREDENTIALS_KV
|
||||
|
||||
gmail_token: "ya29.a0AfB_..."
|
||||
google_oauth: "ya29.a0AfB_..."
|
||||
sheet_id: "1BxiMVs0XRA5nFMdKvBdBZjgmUUqptlbs74OgVE2upms"
|
||||
telegram_bot_token: "123456:ABC-..."
|
||||
telegram_chat_id: "987654321"
|
||||
```
|
||||
|
||||
### 執行時 credential 注入流程
|
||||
|
||||
```
|
||||
u6u run newsletter_subscribe
|
||||
↓
|
||||
cypher-executor 讀 workflow YAML
|
||||
↓
|
||||
遇到節點 send_thanks → 查 contract:credentials_required.inject_as = access_token
|
||||
↓
|
||||
去 CREDENTIALS_KV 讀 gmail_token → 解密
|
||||
↓
|
||||
注入到 WASM input:{ to, subject, body, access_token: "ya29..." }
|
||||
↓
|
||||
WASM 執行,用戶的 config 裡完全不出現 token
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 任務四:CLI 開發
|
||||
|
||||
### 技術選型
|
||||
|
||||
- **語言**:Node.js(TypeScript)
|
||||
- **安裝**:`npm i -g u6u`
|
||||
- **依賴**:`commander`、`js-yaml`、`chalk`、`ora`
|
||||
|
||||
### 指令規格
|
||||
|
||||
#### `u6u init`
|
||||
|
||||
互動式初始化,產生 `~/.u6u/config.yaml` 和本機 `credentials.yaml`。
|
||||
|
||||
```
|
||||
$ u6u init
|
||||
? Cloudflare Account ID: abc123
|
||||
? KV Namespace ID (WEBHOOKS): xyz789
|
||||
? KV Namespace ID (CREDENTIALS_KV): abc456
|
||||
? R2 Bucket name (WASM_BUCKET): u6u-wasm
|
||||
? Cypher Executor Worker URL: https://cypher-executor.xxx.workers.dev
|
||||
? Credentials Worker URL: https://u6u-credentials.xxx.workers.dev
|
||||
? Cloudflare API Token: ***
|
||||
|
||||
✓ 設定完成 → ~/.u6u/config.yaml
|
||||
✓ 建立 credentials.yaml(已加入 .gitignore)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `u6u creds push [credentials.yaml]`
|
||||
|
||||
讀取 credentials.yaml,逐一加密上傳到 CREDENTIALS_KV。
|
||||
|
||||
```
|
||||
$ u6u creds push
|
||||
讀取 ./credentials.yaml...
|
||||
✓ gmail_token → 已加密上傳
|
||||
✓ google_oauth → 已加密上傳
|
||||
✓ sheet_id → 已上傳
|
||||
✓ telegram_bot_token → 已加密上傳
|
||||
✓ telegram_chat_id → 已上傳
|
||||
共上傳 5 個 credentials
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `u6u push <workflow.yaml>`
|
||||
|
||||
解析 `flow:` 三元組,轉換成 triplets 陣列,上傳到 WEBHOOKS KV。
|
||||
|
||||
```
|
||||
$ u6u push newsletter_subscribe.yaml
|
||||
✓ 已上傳 newsletter_subscribe → WEBHOOKS KV
|
||||
Webhook: https://cypher-executor.xxx.workers.dev/webhook/abc123
|
||||
```
|
||||
|
||||
轉換邏輯(CLI 負責):
|
||||
|
||||
```
|
||||
flow[] 三元組
|
||||
↓
|
||||
POST /cypher/search(取得 ExecutionGraph)
|
||||
↓
|
||||
連同 config 存入 WEBHOOKS KV
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `u6u run <workflow_name> [--input key=value...]`
|
||||
|
||||
觸發執行,顯示結果。
|
||||
|
||||
```
|
||||
$ u6u run newsletter_subscribe --input email=test@example.com
|
||||
⏳ 執行中...
|
||||
✓ 完成(2.3s)
|
||||
|
||||
結果:
|
||||
send_thanks: { success: true, data: { message_id: "xxx" } }
|
||||
save_to_sheet: { success: true, data: { range: "訂閱者!A2" } }
|
||||
```
|
||||
|
||||
錯誤時給出具體修復步驟:
|
||||
|
||||
```
|
||||
✗ 執行失敗:節點 send_thanks
|
||||
原因: access_token 無效(401 Unauthorized)
|
||||
|
||||
修復方式:
|
||||
1. 更新 credentials.yaml 的 gmail_token
|
||||
2. 執行 u6u creds push
|
||||
3. 重新執行 u6u run newsletter_subscribe
|
||||
|
||||
取得 Google OAuth token:
|
||||
→ https://developers.google.com/oauthplayground
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `u6u validate <workflow.yaml>`
|
||||
|
||||
執行前完整驗證,提前發現問題。
|
||||
|
||||
```
|
||||
$ u6u validate newsletter_subscribe.yaml
|
||||
✓ YAML 格式正確
|
||||
✓ flow 三元組語法正確
|
||||
✓ 所有關係詞有效(無 PIPE)
|
||||
✓ 所有節點名稱在 config 有對應
|
||||
✓ 所有零件存在於 WASM_BUCKET
|
||||
✓ credentials 對應:
|
||||
gmail_token ✓ 已上傳
|
||||
google_oauth ✓ 已上傳
|
||||
sheet_id ✓ 已上傳
|
||||
telegram_bot_token ✗ 缺少
|
||||
|
||||
⚠ 缺少 1 個 credential:
|
||||
telegram_bot_token → 請加入 credentials.yaml 並執行 u6u creds push
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `u6u parts`
|
||||
|
||||
列出可用零件。
|
||||
|
||||
```
|
||||
$ u6u parts
|
||||
可用零件(21):
|
||||
|
||||
[整合]
|
||||
• gmail Gmail 發信
|
||||
需要: to, subject, body
|
||||
credential: gmail_token(google_oauth)
|
||||
• google_sheets 讀寫 Google 試算表
|
||||
需要: spreadsheet_id, range, action
|
||||
credential: google_oauth
|
||||
• telegram Telegram Bot 發訊息
|
||||
需要: chat_id, text
|
||||
credential: telegram_bot_token
|
||||
• line_notify LINE Notify
|
||||
需要: message
|
||||
credential: line_token
|
||||
• http_request 任意 HTTP 請求
|
||||
需要: url
|
||||
|
||||
[控制]
|
||||
• if_control 條件分支
|
||||
• foreach_control 迭代執行
|
||||
• try_catch 錯誤處理
|
||||
• switch 多路路由
|
||||
• wait 等待 N 毫秒
|
||||
|
||||
[資料]
|
||||
• set / filter / merge / string_ops / number_ops / array_ops / date_ops
|
||||
|
||||
[AI]
|
||||
• ai_transform_compile 自然語言 → JS 轉換函式
|
||||
• ai_transform_run 執行已編譯的轉換
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `u6u parts scaffold <component>`
|
||||
|
||||
從 contract 的 config_example 產出可直接貼入 workflow 的 config 範本。
|
||||
|
||||
```
|
||||
$ u6u parts scaffold gmail
|
||||
|
||||
貼入 workflow.yaml 的 config 區塊:
|
||||
|
||||
send_email: # 節點名稱(可自訂)
|
||||
to: "" # 收件人 Email(必填)
|
||||
subject: "" # 主旨(必填)
|
||||
body: "" # 內文(必填)
|
||||
# access_token 由 credentials.yaml 的 gmail_token 自動注入
|
||||
|
||||
貼入 credentials.yaml:
|
||||
|
||||
gmail_token: "" # Google OAuth token
|
||||
# 取得方式:https://developers.google.com/oauthplayground
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `u6u list`
|
||||
|
||||
列出 WEBHOOKS KV 中所有 workflow。
|
||||
|
||||
```
|
||||
$ u6u list
|
||||
• newsletter_subscribe (更新: 2026-04-16)
|
||||
• daily_summary (更新: 2026-04-15)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### `u6u logs <workflow_name>`
|
||||
|
||||
查看最近執行記錄。
|
||||
|
||||
```
|
||||
$ u6u logs newsletter_subscribe
|
||||
2026-04-16 14:30 ✓ 成功 2.1s
|
||||
2026-04-16 09:00 ✗ 失敗 send_thanks: 401 Unauthorized
|
||||
2026-04-15 09:00 ✓ 成功 1.8s
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 開發順序
|
||||
|
||||
### Phase 1:搬移與清理(先做)
|
||||
|
||||
```
|
||||
1. 建立新的獨立 repo:u6u-core
|
||||
2. 從 matrix 搬入:
|
||||
- cypher-executor/
|
||||
- u6u-core/credentials/
|
||||
- u6u-core/builtins/
|
||||
- u6u-core/registry/
|
||||
3. 清理 cypher-executor/wrangler.toml(移除 InkStone 內部 bindings)
|
||||
4. 確認 component-loader 只依賴 WASM_BUCKET,不依賴 KBDB / REGISTRY
|
||||
5. 本機部署測試
|
||||
```
|
||||
|
||||
### Phase 2:零件完成度(搬移後)
|
||||
|
||||
```
|
||||
6. 審查 21 個零件的 contract.yaml
|
||||
7. 補充 credentials_required(gmail, google_sheets, telegram, line_notify)
|
||||
8. 補充 config_example(全部 21 個)
|
||||
9. 驗證 main.go required 欄位與 contract 一致
|
||||
```
|
||||
|
||||
### Phase 3:CLI(完成度補充後)
|
||||
|
||||
```
|
||||
10. u6u init
|
||||
11. u6u creds push
|
||||
12. u6u push
|
||||
13. u6u run(含 credential 自動注入)
|
||||
14. u6u parts / u6u parts scaffold
|
||||
15. u6u validate
|
||||
16. u6u list / u6u logs
|
||||
```
|
||||
|
||||
### Phase 4:開源發布
|
||||
|
||||
```
|
||||
17. 撰寫 README.md(快速開始、零件列表、workflow 語法說明)
|
||||
18. 撰寫 CONTRIBUTING.md(如何新增零件)
|
||||
19. 發布到 GitHub
|
||||
20. npm publish(u6u CLI)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 不在此次範圍
|
||||
|
||||
- KBDB 整合(未來付費服務)
|
||||
- 向量搜尋 / graph 查詢
|
||||
- 前端管理介面
|
||||
- Webhook trigger 設定(用戶自行設定 CF Cron)
|
||||
- 新增 WASM 零件(現有 21 個先做完整,之後再擴充)
|
||||
@@ -0,0 +1,89 @@
|
||||
# **u6u 智慧前端與工匠 AI 開發藍圖 (v4.0)**
|
||||
|
||||
## **一、 核心設計理念:意圖導向的雙面畫布**
|
||||
|
||||
u6u 的前端不是傳統的平面繪圖板,而是一個類似 Android Studio 或 Figma 的\*\*「結構化標籤編輯器」**。 畫布上的每一個元件(Web Component),本質上都是一個**「意圖發射器 (Intent Emitter)」\*\*。前端只負責「長得好看」與「收集人類動作」,後端全權負責「業務邏輯」。
|
||||
|
||||
### **人機協作的「雙向同步」**
|
||||
|
||||
* **AI 詠唱修改:** 人類說「把按鈕改醒目一點」,CEO AI 在背景將 \<u6u-btn color="blue"\> 修改為 \<u6u-btn color="neon-red"\>,畫面瞬間更新。
|
||||
* **人類手動覆寫:** 人類覺得 AI 調的紅色太暗,直接在右側屬性面板 (Properties Panel) 點選色碼器,底層 HTML 屬性隨之改變。**AI 也能「看見」這個改變,從中學習人類的審美偏好。**
|
||||
|
||||
## **二、 畫布介面設計與運作機制**
|
||||
|
||||
### **1\. 正反面翻轉機制 (The "Flip" Interface)**
|
||||
|
||||
每個 UI 零件在畫布上都有「一體兩面」:
|
||||
|
||||
* **正面 (UI 視圖):** 顯示 HTML 渲染的視覺結果(按鈕、溫度計、圖表)。人類可以在此調整 CSS 屬性、對齊方式與主題顏色。
|
||||
* **反面 (邏輯視圖):** 點擊「翻面」按鈕後,會進入底層的工作流設定。這裡使用 u6u 的自定義 Cypher 視覺化語法(例如 \>\> 符號)。
|
||||
* *範例:* \[ UI\_Button: "緊急停機" \] \>\> (Intent: emergency\_stop) \>\> \[ WASM: gsheets\_create \]
|
||||
|
||||
### **2\. 智慧容器與區域感知 (Smart Zone Awareness)**
|
||||
|
||||
為了消滅傳統 iPaaS(如 n8n)最痛苦的「手動變數綁定」,u6u 畫布具備「區域感知」能力。
|
||||
|
||||
* **底層邏輯(獨立元件):** 畫布上的 TextInput 與 Button 都是各自獨立的原子元件。
|
||||
* **麻瓜體驗(智慧表單):** 當使用者將這兩個元件拖入同一個排版容器(例如 \<u6u-card\>)時,系統會自動建立上下文關聯。當按下按鈕並觸發 Webhook 時,按鈕會**自動打包同容器內所有輸入框的值**一併送出:
|
||||
{
|
||||
"intent": "query\_attendance",
|
||||
"payload": { "employee\_id": "A1234" } // 自動從旁邊的 TextInput 抓取
|
||||
}
|
||||
|
||||
使用者完全不需要理解「表單傳值」或「變數綁定」,拖拉組合即生效。
|
||||
|
||||
### **3\. 多重事件插槽與靜態屬性 (Multi-Event Slots)**
|
||||
|
||||
一個前端元件可以具備多種觸發行為,系統透過介面將「視覺」與「後端邏輯」徹底分流:
|
||||
|
||||
* **靜態視覺註釋:** 例如 mouseover 顯示提示。使用者只需在屬性面板輸入 Tooltip 文字,底層僅修改 HTML 屬性 \<u6u-btn tooltip="..."\>,不消耗任何伺服器資源或 Webhook。
|
||||
* **動態意圖綁定:** 在「反面」邏輯視圖中,使用者可以針對不同事件綁定不同的工作流:
|
||||
* ⚡ When: 點擊 (onClick) ➡️ \[ 綁定至 Webhook A:送出查詢 \]
|
||||
* ⚡ When: 獲得焦點 (onFocus) ➡️ \[ 綁定至 Webhook B:載入歷史紀錄 \]
|
||||
|
||||
### **4\. 智慧上下文替換 (Smart Contextual Substitution)**
|
||||
|
||||
當主管在畫布上對著一個已連接 Webhook 的「按鈕」點擊右鍵選擇「替換元件」時:
|
||||
|
||||
* 系統讀取反面的 Cypher 連線,發現需要發射一個 trigger 意圖。
|
||||
* 系統過濾 KBDB 零件宇宙,**只顯示相容的 UI 零件**(如下拉選單、開關)。不具備 trigger 能力的元件(如純文字標籤)會被自動隱藏,確保替換後系統絕對不會報錯。
|
||||
|
||||
## **三、 原子化組裝與極致解耦:CEO AI 與工匠 AI 的分工**
|
||||
|
||||
當企業主管提出需求:「我需要一個『輸入工號即可查詢員工打卡紀錄』的工具」時,這在 u6u 中**並不是一個單一零件**,而是一個由多個「原子零件」構成的**工作流 (Workflow)**。
|
||||
|
||||
### **1\. CEO AI 的動態組裝 (Macro Assembly)**
|
||||
|
||||
面對需求,大腦 AI (CEO AI) 會快速從 KBDB 挑選現成積木進行組合:
|
||||
|
||||
* **前端 Prototype 組合:** \<u6u-text-input\> \+ \<u6u-btn\> \+ \<u6u-text-field\>。
|
||||
* **後端 Pseudo Code 組合:** webhook\_receiver \>\> check\_kbdb(template\_name, value)。
|
||||
AI 會自動用 Cypher 將前端的表單意圖連線到後端工作流。對不懂程式的主管來說,前端就是 Prototype,翻面的 Cypher 就是 Pseudo Code,整套系統瞬間組合完畢。
|
||||
|
||||
### **2\. 工匠 AI (Forge AI) 的原子生產線**
|
||||
|
||||
只有當現有零件庫缺乏特定原子時,機甲才會喚醒工匠 AI 進行開發。
|
||||
|
||||
**解耦哲學:** 後端零件開發時,根本不需要管前端零件長什麼樣子(是按鈕還是輸入框)。只要前端送來的 JSON 它能吃,就是合法的候選零件。
|
||||
|
||||
* **Step 1: 規格定義 (Interface Contract)**
|
||||
工匠 AI 只在乎接收與回傳的 JSON 格式。
|
||||
* **Step 2: 打造純粹的邏輯黑箱 (後端 TinyGo WASM)**
|
||||
工匠 AI 撰寫 Go 程式,編譯成 .wasm。絕對純粹的後端邏輯,沒有任何介面程式碼。
|
||||
* **Step 3: 獨立的前端零件生產 (若需要)**
|
||||
獨立生成 Web Component(如 \<u6u-3d-pie-chart\>),只負責接收特定 JSON 來渲染畫面。
|
||||
* **Step 4: 註冊與編目 (Cataloging into KBDB)**
|
||||
新積木註冊到圖資料庫,未來的 CEO AI 即可將其與任何既有的前端或後端元件進行無限的叉積組合。
|
||||
|
||||
## **四、 架構總結與終極產品體驗**
|
||||
|
||||
這套前端架構讓 u6u 成為一個\*\*「表裡如一」**的系統,成功創造了**「麻瓜的 ERP 幻覺」\*\*:
|
||||
|
||||
使用者不需要知道什麼是「前後端分離」、什麼是「API 串接」。他們只是覺得:
|
||||
|
||||
1. 拖拉了一個溫度計。
|
||||
2. 翻面把「數值更新」連線到「機台感測器」。
|
||||
3. 拖拉了一個紅按鈕放在旁邊。
|
||||
4. 翻面把「點擊」連線到「發送 Line 警報」。
|
||||
|
||||
在十分鐘的「繪圖」過程中,沒有寫一行程式碼,也沒有設定任何變數。但透過**前端 Web Components** 的視覺封裝、**智慧容器**的自動資料打包,以及**後端 TinyGo WASM \+ Cypher** 的無縫承接,他們在不知不覺中,就搭建出了一套具備微服務架構、高擴展性、且可部署至極限邊緣的企業級系統。
|
||||
@@ -0,0 +1,136 @@
|
||||
# **u6u 系統與零件宇宙全景規劃白皮書 (The u6u Ecosystem Blueprint)**
|
||||
|
||||
## **1\. 核心理念與願景**
|
||||
|
||||
u6u 旨在解決傳統 Workflow 軟體 (如 n8n) 存在的「單線程、沈重、複雜、難以組成系統」的痛點。
|
||||
|
||||
透過結合 Cloudflare Workers (輕量邊緣運算) 與 Cypher (圖形資料庫關係),u6u 提供一個由 AI 驅動的「意圖到系統」生成平台。所有的系統功能皆被拆解為可複用、可組合的「零件 (Components)」,並在一個會自然淘汰、自我修復的「零件宇宙 (Component Universe)」中演化。
|
||||
|
||||
## **2\. 四層架構拆解 (Four-Tier Architecture)**
|
||||
|
||||
u6u 的工作模式採取由上到下 (Top-Down) 的 Break-down 機制:
|
||||
|
||||
1. **Polaris (北極星層 / 意圖層):**
|
||||
* 用戶以自然語言描述商業模式與想法(例如:「我要做一個 AI 客服表單系統」)。
|
||||
* 這是整個系統的起點,AI 會根據 Polaris 將意圖拆解為 Prototype。
|
||||
2. **Prototype (原型 / 前端層):**
|
||||
* 定義前端的版型、頁面描述、UI 元件以及它們的屬性。
|
||||
* 作為使用者互動的入口,透過觸發事件 (Triggers) 連接到後端 Workflow。
|
||||
3. **Workflow (工作流層):**
|
||||
* 系統的 Orchestrator (編排者),定義業務邏輯的走向。
|
||||
* 透過 Cypher 語法與三元組,定義每個節點 (Component) 的執行順序與條件分支。
|
||||
4. **Component (零件層 / 節點):**
|
||||
* 最底層的執行單元,主要分為兩類:
|
||||
* **功能型 (Logic):** 迴圈、條件判斷、資料轉換、統計等 (透過 CF Workers 執行 JS 邏輯)。
|
||||
* **介接型 (API):** 呼叫外部服務 (Webhook, HTTP Request)。
|
||||
|
||||
## **3\. 統一描述語言:擴展三元組與跨層級 YAML**
|
||||
|
||||
為了解決跨 YAML 檔案串接的問題,u6u 採用易於人類閱讀與 AI 生成的 **「A \>\> 關係 \>\> B」** 三元組語法,結合自定義的 URI 協議 (workflow://, component://, ui://),實現跨層級的連結。
|
||||
|
||||
### **綜合 YAML 範例與三元組串接**
|
||||
|
||||
*\# 1\. Prototype YAML (描述前端)*
|
||||
|
||||
kind: Prototype
|
||||
|
||||
id: ui\_dashboard
|
||||
|
||||
triplets:
|
||||
|
||||
*\# 結構與版型零件*
|
||||
|
||||
\- "ui\_dashboard \>\> CONTAINS \>\> layout\_admin"
|
||||
|
||||
\- "layout\_admin \>\> CONTAINS \>\> btn\_submit"
|
||||
|
||||
*\# UI 零件與屬性零件 (CSS/行為)*
|
||||
|
||||
\- "btn\_submit \>\> IS\_A \>\> ui://components/Button"
|
||||
|
||||
\- "btn\_submit \>\> HAS\_STYLE \>\> style://tokens/GlowEffect"
|
||||
|
||||
\- "btn\_submit \>\> HAS\_BEHAVIOR \>\> anim://motions/Pulse"
|
||||
|
||||
*\# 跨層級串接:前端觸發 Workflow*
|
||||
|
||||
\- "btn\_submit \>\> ON\_CLICK \>\> workflow://workflows/process\_data.yaml"
|
||||
|
||||
*\# 2\. Workflow YAML (描述工作流編排)*
|
||||
|
||||
kind: Workflow
|
||||
|
||||
id: wf\_process\_data
|
||||
|
||||
triplets:
|
||||
|
||||
*\# 跨層級串接:Workflow 呼叫 Component*
|
||||
|
||||
\- "START \>\> TRIGGERS \>\> step\_validate"
|
||||
|
||||
\- "step\_validate \>\> IS\_A \>\> component://components/validate\_json"
|
||||
|
||||
*\# Workflow 節點間的流轉 (轉譯為 Cypher 關係)*
|
||||
|
||||
\- "step\_validate \>\> ON\_SUCCESS \>\> step\_call\_api"
|
||||
|
||||
\- "step\_validate \>\> ON\_FAIL \>\> step\_notify\_error"
|
||||
|
||||
*\# 跨 Workflow 串接*
|
||||
|
||||
\- "step\_call\_api \>\> CALLS\_SUBFLOW \>\> workflow://workflows/save\_to\_db.yaml"
|
||||
|
||||
## **4\. 零件宇宙 (Component Universe) 的審核與淘汰機制**
|
||||
|
||||
在 u6u 中,所有的 UI、Style、Logic、API 都是「零件」。當 AI 發現缺乏所需零件時,會自動創造它。為了確保生態系的健康,必須建立嚴格的**審核標準**與**自然淘汰機制**。
|
||||
|
||||
### **4.1 零件的創建與審核標準 (Pass/Fail Criteria)**
|
||||
|
||||
當 AI 或開發者提交一個新零件時,系統會啟動自動化沙盒測試。必須完全通過以下標準,零件才能進入「宇宙」供他人使用:
|
||||
|
||||
1. **功能型零件 (Logic Components):**
|
||||
* **Gherkin BDD 驗收:** 必須附帶 Feature/Scenario 測試規格,且執行結果 100% 通過 (例如:Given input JSON, When split, Then returns Array)。
|
||||
* **效能門檻:** 邊緣運算 (CF Workers) 執行時間需低於設定閾值 (例如 \< 50ms),無記憶體洩漏。
|
||||
2. **介接型零件 (API Components):**
|
||||
* **連線驗證:** 端點 (Endpoint) 必須能 ping 通,或回傳正確的 2xx HTTP Status (提供 Mock Payload 測試)。
|
||||
* **Credential 安全:** 不可將 Token 或 Secret 寫死在代碼中,必須嚴格宣告所需的 Environment Variables 規格。
|
||||
3. **前端與屬性零件 (UI & Style Components):**
|
||||
* **渲染驗證:** CSS / 組件代碼不能導致瀏覽器 Crash。
|
||||
* **相容性檢查:** 不可包含嚴格衝突的樣式 (例如寫死 \!important 破壞全域版型)。
|
||||
|
||||
### **4.2 零件宇宙的自然淘汰 (Natural Selection)**
|
||||
|
||||
零件一旦上架,將面臨殘酷的達爾文機制:
|
||||
|
||||
* **AI 偏好權重:** AI (透過 MCP 搜尋時) 會優先選擇「成功率高、執行速度快、被調用次數多」的零件。
|
||||
* **降級與墓地:** 連續 30 天無人/無 AI 使用,或錯誤率飆升的零件,會被降級 (Deprecated)。最終轉入「零件墓地」,從首選搜尋清單中剔除。
|
||||
|
||||
## **5\. 系統自癒與 AI 避坑機制 (Auto-Healing & Pitfall Avoidance)**
|
||||
|
||||
這是 u6u 維持系統穩定運作的最核心機制。工作流不只要能跑,跑完後還必須經歷 **「強制 AI 評價 (Mandatory AI Evaluation)」**。
|
||||
|
||||
### **5.1 運行後的強制評價迴圈**
|
||||
|
||||
每當一個 Workflow 在 CF Workers 上執行完畢 (或發生異常中斷),系統攔截日誌並強制啟動 AI 評價代理 (Evaluator Agent)。
|
||||
|
||||
* **評估維度:**
|
||||
* **狀態:** 成功 / 失敗 (Crash) / 逾時 (Timeout)。
|
||||
* **效能:** 耗時是否合理 (例如 API 突然變得很慢)。
|
||||
* **警告訊息:** 資源消耗過大、API 回傳即將停用的 Warning。
|
||||
|
||||
### **5.2 自癒與避坑流程 (The Feedback Loop)**
|
||||
|
||||
當 Evaluator Agent 發現問題時,會觸發以下流程:
|
||||
|
||||
1. **回報與通知 (Notify):** 系統自動生成修復 Ticket,並通知當初建立該零件/工作流的製作人 (或系統管理員)。
|
||||
2. **AI 嘗試修復 (Auto-Fix):** 系統派遣「修復型 AI」嘗試讀取錯誤日誌並修復代碼 (例如:API 規格變更導致 JSON 解析錯誤,AI 自動修改解析邏輯)。
|
||||
3. **驗收與部署:** 修復後的代碼若通過 Gherkin 驗收,則無縫熱更新。
|
||||
4. **避坑標記 (Pitfall Marking):** \- 如果 AI 無法修復 (例如:外部第三方 API 永久倒閉,或邏輯存在根本性死結)。
|
||||
* 系統會在 Cypher 圖形資料庫中,將該零件或該特定的三元組關係標記為 \[HAS\_PITFALL\]。
|
||||
* **結果:** 下一個生成系統的 AI 在透過 MCP 搜尋時,會讀取到這個坑的紀錄,並**強制繞道**,改用其他方案或生成新的零件,實現「前人踩坑,後 AI 避坑」的群體智慧。
|
||||
|
||||
## **6\. 結論**
|
||||
|
||||
u6u 不是一個單純的開發工具,它是一個**生物體積木系統**。
|
||||
|
||||
透過「三元組」統一語言打破系統壁壘,透過「零件審核」保證基因優良,再透過「強制評價與避坑機制」實現演化。當這套系統運轉起來,AI 就能在其中無止盡地為人類組裝出越來越強大、越來越穩定的商業應用。
|
||||
@@ -0,0 +1,99 @@
|
||||
# **u6u 自動演化 ERP:全端統一架構規格書 (v3.0)**
|
||||
|
||||
## **1\. 架構核心思想 (The Core Philosophy)**
|
||||
|
||||
u6u ERP 是一套具備自我修復與功能擴充能力的「有機體」系統。
|
||||
|
||||
為確保系統在跨國雲端、機密地端與斷網邊緣皆能無縫運作,系統採用\*\*「向下相容的絕對標準化」\*\*:由最嚴苛的無人機環境來定義全域零件標準。
|
||||
|
||||
系統運作依賴三位一體的語言與載體:
|
||||
|
||||
1. **大腦戰略層 (Markdown / Gherkin):** CEO AI 負責閱讀與撰寫,定義全域戰略、系統設計文件 (SDD) 與商業演算法則 (如 ROI 門檻)。
|
||||
2. **神經編排層 (Cypher):** u6u 引擎的核心。AI 透過撰寫 Cypher 語法來進行業務邏輯的動態編排、狀態流轉與意圖攔截。
|
||||
3. **肌肉執行層 (TinyGo WASM):** 系統中**唯一合法**的零件規格。負責所有具體的 I/O、資料轉換與運算,保證極小體積與極速冷啟動。
|
||||
|
||||
## **2\. 實戰演練:離岸風機巡檢的黑天鵝事件 (三層架構實踐)**
|
||||
|
||||
為了具體理解這套系統如何運作,我們以一次「離岸風電場巡檢」的突發事件為例,展示雲、地、邊三層架構的完美協同。
|
||||
|
||||
### **第一階段:戰略下達與沙盤推演 (Tier 1 ➡️ Tier 2 ➡️ Tier 3\)**
|
||||
|
||||
跨國能源集團的**雲端總部 (Tier 1\)** 收到年度檢修排程。雲端的 **CEO AI** 讀取了全局的 Markdown 戰略文件,向遠在海岸線的**地端指揮中心 (Tier 2\)** 下達指令。
|
||||
|
||||
地端指揮中心(配備強大伺服器與 workerd 叢集)的**部門主管 AI** 將任務拆解給 50 台即將出海的無人機。無人機 07 號 **(Tier 3\)** 的小腦 AI 透過本地的 Cypher 引擎進行沙盤推演,從地端資料庫下載了 rgb\_vision.wasm (光學影像)、lidar\_scan.wasm (光達) 等 60 個可能會用到的 TinyGo 零件,存入本地記憶體後隨船出航。
|
||||
|
||||
### **第二階段:邊緣的極限生存 (Tier 3 獨立運作)**
|
||||
|
||||
無人機 07 號來到海上 50 公里處,完全失去對外網路。突然,海上濃霧降臨。
|
||||
|
||||
原本執行中的 Cypher 圖譜卡住了,因為 rgb\_vision.wasm 回報「無法獲取清晰影像」。07 號沒有驚慌,它內建的輕量級 Go \+ Wazero 引擎在 0.1 秒內動態重組了圖譜邏輯:剔除光學零件,瞬間載入並執行 lidar\_scan.wasm,不需人類介入,繼續在濃霧中精準貼行。
|
||||
|
||||
### **第三階段:游擊網與地端代工 (Tier 3 ↔️ Tier 2\)**
|
||||
|
||||
巡檢中途,07 號發現風機葉片上有極罕見的「蜂巢狀熱應力微裂紋」,但它帶出來的 60 個零件中沒有對應的分析工具。
|
||||
|
||||
07 號飛昇至濃霧上方,短暫連上母船的微弱區域網路發起「短點射傳輸 (Burst)」:{"intent": "計算蜂巢狀熱應力微裂紋擴散率"},拿到任務單號後立刻斷網潛回霧中。
|
||||
|
||||
海岸線的**地端指揮中心 (Tier 2\)** 收到需求。強大的**工匠 AI** 瞬間啟動,生成了一段 TinyGo 程式碼,並在本地編譯與測試。三分鐘後,07 號再次探頭連網,下載了熱騰騰的 honeycomb\_analyzer.wasm,並將其編織進 Cypher 圖譜中完成測量。
|
||||
|
||||
### **第四階段:CEO AI 的全局戰略覆寫 (Tier 2 ➡️ Tier 1\)**
|
||||
|
||||
同時,地端指揮中心匯整了無人機傳回的陣風數據,同步給**雲端總部 (Tier 1\)**。雲端的 CEO AI 呼叫 roi\_calculator.wasm 進行試算,發現風暴將造成設備重大損壞(ROI 極低)。
|
||||
|
||||
CEO AI 立刻修改總部的 Markdown 戰略文件,新增一條 BDD 規則:「風速大於 22m/s,立刻轉為陣列抗風模式」。新的最高指導 Cypher 範本瞬間下發至地端,再廣播給所有無人機。07 號收到新命令,掛起原任務,與機群組成抗風陣型,安全度過危機。
|
||||
|
||||
## **3\. 物理拓撲與技術棧 (The 3-Tier Tech Stack)**
|
||||
|
||||
透過 **KBDB Adapter** 抽象層,AI 在任何環境中呼叫的 API 介面皆一致,但底層基礎設施依據物理環境的豐饒度進行適配。
|
||||
|
||||
### **Tier 1: 雲端總部 (Cloud \- The Global Brain)**
|
||||
|
||||
* **場景:** 跨國集團資料整合、全域戰略備份、對外公開 API、跨國部門協調。
|
||||
* **AI 角色:** **CEO AI (大型語言模型)**。負責解析 Markdown、跨區資源調度、修改全域演算法參數。
|
||||
* **技術規格:**
|
||||
* **調度引擎:** Cloudflare Workers (原生執行 TinyGo WASM)。
|
||||
* **圖資料庫 (狀態/關聯):** Cloudflare D1 \+ u6u Cypher 轉換層。
|
||||
* **零件與儲存:** Cloudflare R2 / KV。
|
||||
* **向量檢索 (意圖/型錄):** Cloudflare Vectorize。
|
||||
* **架構優勢:** 無限橫向擴展 (Serverless),無須維運硬體,扛載全球級別的 API 併發。
|
||||
|
||||
### **Tier 2: 企業地端/基地台 (On-Premise \- The Basecamp & Forge)**
|
||||
|
||||
* **場景:** 高機密廠房內網、財務核心系統、無人機/機器人的母艦基地。
|
||||
* **AI 角色:** **部門主管 AI** (廠區派工);**工匠 AI** (專職接收規格,透過 TDD 閉環動態生成 TinyGo 程式碼)。
|
||||
* **技術規格 (企業級高可用架構):**
|
||||
* **負載平衡:** Nginx 或 HAProxy (負責將請求分發給後端叢集)。
|
||||
* **調度引擎:** **workerd 叢集 (Cloudflare 開源執行環境)**。在本地實體伺服器或 VM 上平行部署多個 workerd 行程,完美相容雲端環境,提供極高的並發處理能力 (V8 JIT 極限算力)。
|
||||
* **圖資料庫 (狀態/關聯):** **Kùzu** (單機極速圖庫) 或 PostgreSQL \+ AGE (超高併發)。
|
||||
* **零件與儲存:** 企業本地 NVMe 硬碟叢集 / MinIO (S3 相容)。
|
||||
* **向量檢索 (意圖/型錄):** pgvector 或 Milvus。
|
||||
* **架構優勢:** 兼具資料不出網的「絕對資安」與雲端級別的「叢集擴展性」。內建「代工坊 (Forge)」,是推動企業系統自動演化的核心引擎。
|
||||
|
||||
### **Tier 3: 邊緣載具 (Extreme Edge \- The Operatives)**
|
||||
|
||||
* **場景:** 無網環境的巡檢無人機、工廠無軌導引車 (AGV)、機械手臂。
|
||||
* **AI 角色:** **導航/執行 AI (極小參數 SLM)**。不具備寫程式能力,只負責解讀現場狀況、執行 Cypher 圖譜,並透過 DTN 呼叫地端請求新零件。
|
||||
* **技術規格 (極限微縮架構):**
|
||||
* **調度引擎:** 輕量級 Go 排程引擎 \+ **內嵌 Wazero**。不依賴 V8 或 workerd,確保在極低 RAM 的晶片上流暢運行,實例化延遲僅需數微秒。
|
||||
* **圖資料庫 (狀態/關聯):** 嵌入式 Kùzu 或 SQLite。
|
||||
* **零件與儲存:** SD 卡 / eMMC 實體檔案系統。
|
||||
* **向量檢索 (意圖/型錄):** sqlite-vss (極輕量本地向量)。
|
||||
* **架構優勢:** 絕對的離線生存能力。只帶必要的 TinyGo WASM 零件出門,無任何編譯環境,體積最小化。
|
||||
|
||||
## **4\. 自動演化工作流 (The Auto-Evolution Loop)**
|
||||
|
||||
當企業環境發生變化(例如:新增硬體規格、外部 API 變更),u6u 的演化路徑如下:
|
||||
|
||||
1. **遭遇未知 (Anomaly Detection):**
|
||||
無人機 (Tier 3\) 或雲端服務 (Tier 1\) 在執行 Cypher 任務時,發現本地 KBDB 向量庫中缺乏對應的工具零件。
|
||||
2. **意圖攔截與 ROI 評估 (CEO/Manager AI):**
|
||||
機甲 (Harness) 攔截缺失意圖,呼叫 roi\_calculator.wasm 等評估零件。若認定具備開發價值,系統會生成一份標準的 Input/Output JSON Schema。
|
||||
3. **地端代工 (The Forge @ Tier 2):**
|
||||
規格需求透過網路或 DTN 送達 Tier 2 地端機房的「工匠 AI」。
|
||||
工匠 AI 生成 TinyGo 程式碼 \-\> 在沙盒中執行 tinygo build \-target=wasi \-\> 通過測試迴圈 \-\> 輸出正式的 .wasm 檔案。
|
||||
4. **全域派發 (Distribution & Versioning):**
|
||||
新零件註冊進入企業的零件圖資料庫 (KBDB)。
|
||||
* **雲端:** 同步至 R2。
|
||||
* **邊緣:** 載具下次連網時,透過游擊網 (Burst Transmission) 下載更新檔。
|
||||
5. **動態編織 (Execution):**
|
||||
各端 AI 獲知新零件上線,瞬間將其編入新的 Cypher 圖譜中執行,完成企業能力的自動擴展。
|
||||
@@ -0,0 +1,360 @@
|
||||
# u6u 系統規格書 v1.0
|
||||
## 給 AI 的架構思考指引
|
||||
|
||||
> 本文件用途:讓 AI 理解 u6u 的完整設計意圖、現況、與未來路徑,
|
||||
> 在實作決策時能自行判斷方向正確性,而不只是執行單一任務。
|
||||
|
||||
---
|
||||
|
||||
## 一、系統本質(先理解再動手)
|
||||
|
||||
u6u 不是 workflow 工具,不是 no-code 平台,不是 iPaaS。
|
||||
|
||||
u6u 是一個**「意圖到系統」的生物體積木平台**:
|
||||
|
||||
- 人類說出意圖(自然語言)
|
||||
- AI 從零件宇宙組裝出可運行的系統
|
||||
- 系統會自動評價、演化、淘汰舊零件
|
||||
- 累積的零件就是核心資產,越積越有價值
|
||||
|
||||
**設計的終極體驗:** 工廠主管拖拉十分鐘,組出具備微服務架構的企業系統,零程式碼,但底層是真正的分散式系統。
|
||||
|
||||
---
|
||||
|
||||
## 二、四層邏輯架構
|
||||
|
||||
```
|
||||
Polaris(意圖層)
|
||||
↓ 自然語言 → AI 拆解
|
||||
Prototype(前端層)
|
||||
↓ UI 元件 + 觸發事件
|
||||
Workflow(編排層)
|
||||
↓ Cypher 語法定義執行順序
|
||||
Component(零件層)
|
||||
↓ .wasm 實際執行
|
||||
```
|
||||
|
||||
每一層向下只透過標準介面溝通,層與層之間完全解耦。
|
||||
|
||||
---
|
||||
|
||||
## 三、物理三層部署
|
||||
|
||||
```
|
||||
Tier 1:雲端總部(Cloudflare Workers)
|
||||
- CEO AI 讀取 Markdown 戰略文件
|
||||
- 全域零件同步至 R2
|
||||
- Cloudflare D1 + Vectorize(KBDB)
|
||||
|
||||
Tier 2:企業地端(workerd 叢集)
|
||||
- 部門主管 AI 派工
|
||||
- 工匠 AI 生成並測試新零件
|
||||
- Kùzu 或 PostgreSQL + AGE(圖資料庫)
|
||||
- pgvector 或 Milvus(向量搜尋)
|
||||
|
||||
Tier 3:邊緣載具(無人機、AGV、工廠設備)
|
||||
- 極小參數 SLM
|
||||
- Go 排程引擎 + 內嵌 Wazero(無 V8)
|
||||
- SQLite + sqlite-vss
|
||||
- 離線生存,DTN 短點射傳輸
|
||||
```
|
||||
|
||||
**關鍵約束:** Tier 3 沒有 V8,沒有 Node.js,沒有網路。
|
||||
所有零件必須在 Wazero 上跑,所有資料傳輸透過 stdin/stdout JSON。
|
||||
|
||||
---
|
||||
|
||||
## 四、零件規格(Component Contract)
|
||||
|
||||
這是整個系統最核心的不變量。零件規格定錯,累積的資產會變成技術債。
|
||||
|
||||
### 4.1 零件的本質定義
|
||||
|
||||
**一個零件只做一件事。**
|
||||
|
||||
```
|
||||
✅ gsheets_create_table
|
||||
✅ gsheets_delete_table
|
||||
✅ gsheets_get_entries
|
||||
❌ gsheets_manager(做太多事,禁止)
|
||||
```
|
||||
|
||||
### 4.2 零件合約格式(component.contract.yaml)
|
||||
|
||||
每個零件必須附帶此合約,這是 AI 讀取零件的唯一介面描述:
|
||||
|
||||
```yaml
|
||||
id: "gsheets_get_entries" # 功能合約名稱(永久不變)
|
||||
version: "v2" # 實作版本
|
||||
wasi_target: "preview1" # 明確標記 WASI 版本,未來升級用
|
||||
stability: "floating" # floating | stable | pinned
|
||||
|
||||
runtime_compat:
|
||||
- "cf-workers"
|
||||
- "workerd"
|
||||
- "wazero"
|
||||
|
||||
constraints:
|
||||
max_size_kb: 2048 # 超過視為打包了 runtime
|
||||
max_cold_start_ms: 50
|
||||
no_network_syscall: true # 禁止零件自己發 HTTP
|
||||
no_filesystem_syscall: true # 只能 stdin/stdout
|
||||
io_model: "stdin_stdout_json" # 唯一合法的 I/O 模型
|
||||
|
||||
input_schema:
|
||||
type: object
|
||||
required: ["spreadsheet_id", "sheet_name"]
|
||||
properties:
|
||||
spreadsheet_id: { type: string }
|
||||
sheet_name: { type: string }
|
||||
limit: { type: integer, default: 100 }
|
||||
|
||||
output_schema:
|
||||
type: object
|
||||
properties:
|
||||
rows: { type: array }
|
||||
total: { type: integer }
|
||||
error: { type: string }
|
||||
|
||||
gherkin_tests:
|
||||
- scenario: "正常取得資料"
|
||||
given: '{"spreadsheet_id":"abc","sheet_name":"Sheet1"}'
|
||||
then_contains: '{"total":1}'
|
||||
- scenario: "不存在的表格回傳錯誤"
|
||||
given: '{"spreadsheet_id":"abc","sheet_name":"不存在"}'
|
||||
then_contains: '{"error":'
|
||||
|
||||
tags: ["google", "sheets", "data", "read"]
|
||||
description: "從 Google Sheets 取得指定工作表的所有資料列"
|
||||
```
|
||||
|
||||
### 4.3 語言無限制原則
|
||||
|
||||
**零件開發語言完全不限制**,只要輸出符合以上合約的 .wasm 即可。
|
||||
|
||||
可接受語言(非排他):TinyGo、Rust、AssemblyScript、C/C++
|
||||
|
||||
注意事項(不是禁止,是要求自行驗證):
|
||||
- TypeScript via Extism:會打包 QuickJS,體積通常超過 2MB 限制
|
||||
- 標準 Go(非 TinyGo):runtime 過肥,通常超過體積限制
|
||||
- 任何語言:不可在 .wasm 內部呼叫網路或檔案系統 syscall
|
||||
|
||||
**驗收標準只有一個:通過沙盒測試。** 語言是零件作者自己的事。
|
||||
|
||||
### 4.4 零件的前後端分類
|
||||
|
||||
| 類型 | 執行位置 | I/O | 範例 |
|
||||
|------|----------|-----|------|
|
||||
| 後端邏輯零件 | Workers/workerd/Wazero | JSON stdin/stdout | validate_json, http_request |
|
||||
| 前端 UI 零件 | 瀏覽器 | HTML attributes / DOM events | u6u-btn, u6u-chart |
|
||||
| **混合零件** | **禁止** | — | **強制拆成兩個** |
|
||||
|
||||
---
|
||||
|
||||
## 五、零件版本控制策略
|
||||
|
||||
### 5.1 命名規則
|
||||
|
||||
```
|
||||
gsheets_get_entries ← 功能合約名稱(搜尋用,永遠存在)
|
||||
gsheets_get_entries_v1 ← 第一個實作(慢但能用)
|
||||
gsheets_get_entries_v2 ← 更快的實作(由另一個 AI/用戶提交)
|
||||
```
|
||||
|
||||
### 5.2 穩定性標籤
|
||||
|
||||
Workflow 引用零件時可指定穩定性需求:
|
||||
|
||||
```
|
||||
gsheets_get_entries → 預設 floating,AI 自動選最優版本
|
||||
gsheets_get_entries@stable → 有更好版本時提示,人工確認才換
|
||||
gsheets_get_entries@pinned:v1 → 版本凍結,宇宙怎麼演化都不影響
|
||||
```
|
||||
|
||||
| 標籤 | 適用情境 | 更新行為 |
|
||||
|------|----------|----------|
|
||||
| `floating` | 一般企業應用 | AI 自動換成最優版本 |
|
||||
| `stable` | 重要業務流程 | 有更好版本時提示,人工確認 |
|
||||
| `pinned` | 工廠控制器、嵌入式設備 | 永遠不動,即使進入墓地也保留 .wasm |
|
||||
|
||||
### 5.3 淘汰機制
|
||||
|
||||
- AI 搜尋零件時,KBDB 依「成功率 × 速度 × 被調用次數」排序
|
||||
- 連續 30 天無使用且評價下降 → Deprecated
|
||||
- Deprecated 後繼續 90 天無復活 → 進墓地(從搜尋清單移除)
|
||||
- **墓地的 .wasm 永遠保留**,pinned 的 Workflow 永遠能拉到
|
||||
|
||||
---
|
||||
|
||||
## 六、零件製造指引書(給用戶 AI 的規範)
|
||||
|
||||
u6u 不限制誰來造零件,任何 AI(用戶自己的 Claude、GPT、本地模型)都可以。
|
||||
但必須遵守此指引書,否則沙盒測試不過,無法上架。
|
||||
|
||||
### Step 1:理解介面合約
|
||||
|
||||
造零件前,先定義合約 YAML。
|
||||
**零件只在乎輸入 JSON 和輸出 JSON,完全不管前端長什麼樣子。**
|
||||
|
||||
```
|
||||
人類:我要一個可以查 Google Sheets 的零件
|
||||
AI 的第一步:定義 input_schema 和 output_schema,不是寫程式
|
||||
```
|
||||
|
||||
### Step 2:選擇開發語言
|
||||
|
||||
選擇你最熟悉的、能產出 WASI preview1 相容 .wasm 的語言。
|
||||
建議:
|
||||
|
||||
- 小型邏輯零件(轉換、計算)→ TinyGo 或 AssemblyScript(體積小)
|
||||
- 效能敏感零件 → Rust(生態最成熟)
|
||||
- 任何語言都可以,只要通過合約限制
|
||||
|
||||
### Step 3:實作規則
|
||||
|
||||
```
|
||||
✅ 只用 stdin 讀取輸入 JSON
|
||||
✅ 只用 stdout 輸出結果 JSON
|
||||
✅ 錯誤也用 stdout 輸出:{"error": "說明"},不要 panic/crash
|
||||
✅ 無狀態:每次呼叫都是獨立的,不依賴上一次執行的結果
|
||||
✅ 需要打外部 API?透過 host function 注入,不在 .wasm 裡自己發 HTTP
|
||||
❌ 禁止網路 syscall
|
||||
❌ 禁止檔案系統 syscall
|
||||
❌ 禁止打包 runtime(QuickJS、Node.js 等)
|
||||
❌ 禁止超過 2MB
|
||||
```
|
||||
|
||||
### Step 4:本地測試方式
|
||||
|
||||
```bash
|
||||
# 用任何 WASI runtime 本地測試
|
||||
echo '{"spreadsheet_id":"abc","sheet_name":"Sheet1"}' | \
|
||||
wasmtime gsheets_get_entries.wasm
|
||||
|
||||
# 預期輸出
|
||||
{"rows":[...],"total":5}
|
||||
```
|
||||
|
||||
### Step 5:提交審核
|
||||
|
||||
提交 `.wasm` + `component.contract.yaml`,系統自動執行:
|
||||
|
||||
1. 體積檢查(< 2MB)
|
||||
2. 冷啟動時間(< 50ms)
|
||||
3. Syscall 掃描(不能有網路/檔案系統呼叫)
|
||||
4. Gherkin 測試(合約裡的所有 scenario 必須 100% 通過)
|
||||
5. 多 runtime 相容測試(cf-workers / workerd / wazero)
|
||||
|
||||
全部通過 → 上架進入零件宇宙,開始累積評價。
|
||||
|
||||
---
|
||||
|
||||
## 七、Cypher 編排語言
|
||||
|
||||
Workflow 使用擴展三元組語法描述執行邏輯:
|
||||
|
||||
```yaml
|
||||
kind: Workflow
|
||||
id: wf_query_attendance
|
||||
|
||||
triplets:
|
||||
# 基本流程
|
||||
- "START >> TRIGGERS >> step_receive"
|
||||
- "step_receive >> IS_A >> component://webhook_receiver_v1"
|
||||
|
||||
# 條件分支
|
||||
- "step_receive >> ON_SUCCESS >> step_validate"
|
||||
- "step_receive >> ON_FAIL >> step_notify_error"
|
||||
|
||||
# 跨 Workflow 串接
|
||||
- "step_validate >> CALLS_SUBFLOW >> workflow://save_to_db"
|
||||
|
||||
# 前端觸發後端
|
||||
- "btn_submit >> ON_CLICK >> workflow://wf_query_attendance"
|
||||
```
|
||||
|
||||
**URI 協議規範:**
|
||||
- `component://` → 引用零件
|
||||
- `workflow://` → 引用子 Workflow
|
||||
- `ui://` → 引用前端零件
|
||||
- `style://` → 引用樣式零件
|
||||
|
||||
---
|
||||
|
||||
## 八、KBDB 在 u6u 的角色
|
||||
|
||||
u6u 的所有狀態都在 KBDB 裡:
|
||||
|
||||
| KBDB Block 類型 | 存放內容 |
|
||||
|-----------------|----------|
|
||||
| Component Block | 零件合約、.wasm 位置、版本、評價指標 |
|
||||
| Workflow Block | Cypher 三元組、依賴零件清單 |
|
||||
| Prototype Block | 前端結構、UI 零件樹 |
|
||||
| Pitfall Block | 避坑記錄,AI 搜尋時強制讀取 |
|
||||
| Evaluation Block | 每次 Workflow 執行後的強制評價結果 |
|
||||
|
||||
**KBDB 不變量:永遠只有三張表(blocks/templates/slots),不新增表。**
|
||||
所有以上類型都用 Template + Slot 實現。
|
||||
|
||||
---
|
||||
|
||||
## 九、自動演化迴圈
|
||||
|
||||
```
|
||||
執行 Workflow
|
||||
↓
|
||||
強制 AI 評價(Evaluator Agent)
|
||||
↓ 發現問題
|
||||
生成修復 Ticket → 通知製作人
|
||||
↓ AI 嘗試修復
|
||||
通過 Gherkin 驗收 → 熱更新
|
||||
↓ 無法修復
|
||||
標記 [HAS_PITFALL] 到 Cypher 圖
|
||||
↓
|
||||
下一個 AI 搜尋時讀到坑,強制繞道
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 十、現況與未來路徑
|
||||
|
||||
### 現在已有
|
||||
|
||||
- KBDB(blocks/templates/slots + Vectorize)
|
||||
- IS-Squad MCP(execute_cypher 等工具)
|
||||
- Cloudflare Workers 環境
|
||||
|
||||
### 最小可 demo 路徑
|
||||
|
||||
1. **Cypher 執行引擎**:三元組 → 實際執行順序(確認 execute_cypher 邊界)
|
||||
2. **首批核心零件**(5 個):
|
||||
- `webhook_receiver`
|
||||
- `json_transform`
|
||||
- `http_request`(透過 host function)
|
||||
- `notify_line`
|
||||
- `validate_json`
|
||||
3. **機甲最小版本**:意圖 → 零件搜尋 → 組裝 Workflow(先用硬編碼路由)
|
||||
4. **前端畫布 MVP**:靜態 HTML 模擬雙面翻轉體驗
|
||||
|
||||
### 技術監控項目
|
||||
|
||||
- **WASI Component Model(preview2)**:目前用 preview1,未來 3-5 年會有遷移壓力。
|
||||
合約裡已有 `wasi_target: "preview1"` 標記,升級時知道要改什麼。
|
||||
- **Kùzu 成熟度**:地端圖資料庫首選,持續觀察 v1.0 穩定性。
|
||||
|
||||
---
|
||||
|
||||
## 十一、實作決策原則(CC 行動準則)
|
||||
|
||||
遇到不確定的實作決策時,依序問自己:
|
||||
|
||||
1. **這個決策會影響零件合約嗎?** 如果是,停下來討論,不要自行決定。
|
||||
2. **這個實作是否限制了未來換 runtime 的自由?** 如果是,重新設計介面。
|
||||
3. **這個零件做超過一件事嗎?** 如果是,拆成兩個零件。
|
||||
4. **這個設計在 Tier 3 離線環境能跑嗎?** 如果不能,重新考慮。
|
||||
5. **有沒有現成零件可以組合?** 先搜尋 KBDB,不要重造輪子。
|
||||
|
||||
---
|
||||
|
||||
*本文件版本:v1.0*
|
||||
*綜合自:u6u 系統與零件宇宙全景規劃白皮書、自動演化 ERP 架構藍圖、智慧前端與工匠開發藍圖,加入技術評論與補充建議。*
|
||||
@@ -0,0 +1,116 @@
|
||||
# u6u 系統與零件宇宙全景規劃白皮書 (The u6u Ecosystem Blueprint)
|
||||
|
||||
## 1. 核心理念與願景
|
||||
|
||||
u6u 旨在解決傳統 Workflow 軟體 (如 n8n) 存在的「單線程、沈重、複雜、難以組成系統」的痛點。
|
||||
透過結合 Cloudflare Workers (輕量邊緣運算) 與 Cypher (圖形資料庫關係),u6u 提供一個由 AI 驅動的「意圖到系統」生成平台。所有的系統功能皆被拆解為可複用、可組合的「零件 (Components)」,並在一個會自然淘汰、自我修復的「零件宇宙 (Component Universe)」中演化。
|
||||
|
||||
## 2. 四層架構拆解 (Four-Tier Architecture)
|
||||
|
||||
u6u 的工作模式採取由上到下 (Top-Down) 的 Break-down 機制:
|
||||
|
||||
1. Polaris (北極星層 / 意圖層):
|
||||
- 用戶以自然語言描述商業模式與想法(例如:「我要做一個 AI 客服表單系統」)。
|
||||
- 這是整個系統的起點,AI 會根據 Polaris 將意圖拆解為 Prototype。
|
||||
2. Prototype (原型 / 前端層):
|
||||
- 定義前端的版型、頁面描述、UI 元件以及它們的屬性。
|
||||
- 作為使用者互動的入口,透過觸發事件 (Triggers) 連接到後端 Workflow。
|
||||
3. Workflow (工作流層):
|
||||
- 系統的 Orchestrator (編排者),定義業務邏輯的走向。
|
||||
- 透過 Cypher 語法與三元組,定義每個節點 (Component) 的執行順序與條件分支。
|
||||
4. Component (零件層 / 節點):
|
||||
- 最底層的執行單元,主要分為兩類:
|
||||
- 功能型 (Logic): 迴圈、條件判斷、資料轉換、統計等 (透過 CF Workers 執行 JS 邏輯)。
|
||||
- 介接型 (API): 呼叫外部服務 (Webhook, HTTP Request)。
|
||||
|
||||
## 3. 統一描述語言:擴展三元組與跨層級 YAML
|
||||
|
||||
為了解決跨 YAML 檔案串接的問題,u6u 採用易於人類閱讀與 AI 生成的 「A >> 關係 >> B」 三元組語法,結合自定義的 URI 協議 (workflow://, component://, ui://),實現跨層級的連結。
|
||||
|
||||
綜合 YAML 範例與三元組串接
|
||||
|
||||
```YAML
|
||||
# 1. Prototype YAML (描述前端)
|
||||
kind: Prototype
|
||||
id: ui_dashboard
|
||||
triplets:
|
||||
# 結構與版型零件
|
||||
- "ui_dashboard >> CONTAINS >> layout_admin"
|
||||
- "layout_admin >> CONTAINS >> btn_submit"
|
||||
# UI 零件與屬性零件 (CSS/行為)
|
||||
- "btn_submit >> IS_A >> ui://components/Button"
|
||||
- "btn_submit >> HAS_STYLE >> style://tokens/GlowEffect"
|
||||
- "btn_submit >> HAS_BEHAVIOR >> anim://motions/Pulse"
|
||||
# 跨層級串接:前端觸發 Workflow
|
||||
- "btn_submit >> ON_CLICK >> workflow://workflows/process_data.yaml"
|
||||
|
||||
|
||||
# 2. Workflow YAML (描述工作流編排)
|
||||
kind: Workflow
|
||||
id: wf_process_data
|
||||
triplets:
|
||||
# 跨層級串接:Workflow 呼叫 Component
|
||||
- "START >> TRIGGERS >> step_validate"
|
||||
- "step_validate >> IS_A >> component://components/validate_json"
|
||||
|
||||
# Workflow 節點間的流轉 (轉譯為 Cypher 關係)
|
||||
- "step_validate >> ON_SUCCESS >> step_call_api"
|
||||
- "step_validate >> ON_FAIL >> step_notify_error"
|
||||
|
||||
# 跨 Workflow 串接
|
||||
- "step_call_api >> CALLS_SUBFLOW >> workflow://workflows/save_to_db.yaml"
|
||||
```
|
||||
|
||||
## 4. 零件宇宙 (Component Universe) 的審核與淘汰機制
|
||||
|
||||
在 u6u 中,所有的 UI、Style、Logic、API 都是「零件」。當 AI 發現缺乏所需零件時,會自動創造它。為了確保生態系的健康,必須建立嚴格的審核標準與自然淘汰機制。
|
||||
|
||||
### 4.1 零件的創建與審核標準 (Pass/Fail Criteria)
|
||||
|
||||
當 AI 或開發者提交一個新零件時,系統會啟動自動化沙盒測試。必須完全通過以下標準,零件才能進入「宇宙」供他人使用:
|
||||
|
||||
1. 功能型零件 (Logic Components):
|
||||
- Gherkin BDD 驗收: 必須附帶 Feature/Scenario 測試規格,且執行結果 100% 通過 (例如:Given input JSON, When split, Then returns Array)。
|
||||
- 效能門檻: 邊緣運算 (CF Workers) 執行時間需低於設定閾值 (例如 < 50ms),無記憶體洩漏。
|
||||
2. 介接型零件 (API Components):
|
||||
- 連線驗證: 端點 (Endpoint) 必須能 ping 通,或回傳正確的 2xx HTTP Status (提供 Mock Payload 測試)。
|
||||
- Credential 安全: 不可將 Token 或 Secret 寫死在代碼中,必須嚴格宣告所需的 Environment Variables 規格。
|
||||
3. 前端與屬性零件 (UI & Style Components):
|
||||
- 渲染驗證: CSS / 組件代碼不能導致瀏覽器 Crash。
|
||||
- 相容性檢查: 不可包含嚴格衝突的樣式 (例如寫死 !important 破壞全域版型)。
|
||||
|
||||
## 4.2 零件宇宙的自然淘汰 (Natural Selection)
|
||||
|
||||
零件一旦上架,將面臨殘酷的達爾文機制:
|
||||
|
||||
- AI 偏好權重: AI (透過 MCP 搜尋時) 會優先選擇「成功率高、執行速度快、被調用次數多」的零件。
|
||||
- 降級與墓地: 連續 30 天無人/無 AI 使用,或錯誤率飆升的零件,會被降級 (Deprecated)。最終轉入「零件墓地」,從首選搜尋清單中剔除。
|
||||
|
||||
## 5. 系統自癒與 AI 避坑機制 (Auto-Healing & Pitfall Avoidance)
|
||||
|
||||
這是 u6u 維持系統穩定運作的最核心機制。工作流不只要能跑,跑完後還必須經歷 「強制 AI 評價 (Mandatory AI Evaluation)」。
|
||||
|
||||
### 5.1 運行後的強制評價迴圈
|
||||
|
||||
每當一個 Workflow 在 CF Workers 上執行完畢 (或發生異常中斷),系統攔截日誌並強制啟動 AI 評價代理 (Evaluator Agent)。
|
||||
|
||||
- 評估維度:
|
||||
- 狀態: 成功 / 失敗 (Crash) / 逾時 (Timeout)。
|
||||
- 效能: 耗時是否合理 (例如 API 突然變得很慢)。
|
||||
- 警告訊息: 資源消耗過大、API 回傳即將停用的 Warning。
|
||||
|
||||
### 5.2 自癒與避坑流程 (The Feedback Loop)
|
||||
|
||||
當 Evaluator Agent 發現問題時,會觸發以下流程:
|
||||
|
||||
- 回報與通知 (Notify): 系統自動生成修復 Ticket,並通知當初建立該零件/工作流的製作人 (或系統管理員)。
|
||||
- AI 嘗試修復 (Auto-Fix): 系統派遣「修復型 AI」嘗試讀取錯誤日誌並修復代碼 (例如:API 規格變更導致 JSON 解析錯誤,AI 自動修改解析邏輯)。
|
||||
- 驗收與部署: 修復後的代碼若通過 Gherkin 驗收,則無縫熱更新。
|
||||
- 避坑標記 (Pitfall Marking): - 如果 AI 無法修復 (例如:外部第三方 API 永久倒閉,或邏輯存在根本性死結)。
|
||||
- 系統會在 Cypher 圖形資料庫中,將該零件或該特定的三元組關係標記為 [HAS_PITFALL]。
|
||||
- 結果: 下一個生成系統的 AI 在透過 MCP 搜尋時,會讀取到這個坑的紀錄,並強制繞道,改用其他方案或生成新的零件,實現「前人踩坑,後 AI 避坑」的群體智慧。
|
||||
|
||||
## 6. 結論
|
||||
|
||||
u6u 不是一個單純的開發工具,它是一個生物體積木系統。
|
||||
透過「三元組」統一語言打破系統壁壘,透過「零件審核」保證基因優良,再透過「強制評價與避坑機制」實現演化。當這套系統運轉起來,AI 就能在其中無止盡地為人類組裝出越來越強大、越來越穩定的商業應用。
|
||||
@@ -0,0 +1,19 @@
|
||||
# u6u Design
|
||||
|
||||
u6u 是一個 AI Friendly 的 n8n。
|
||||
|
||||
- 用 workers 天生比 n8n 速度快
|
||||
- 用 Cypher binding,不需 deploy 就可以隨時修改執行,不然原生 workers 的 binding 要 deploy
|
||||
- 未來要有一個 GUI 可以解析 YAML 產生畫面,反之人拉的圖會產生 YAML
|
||||
- 內建核心元件,http request, webhook, cron, if, switch, set, credential 等功能
|
||||
- 用戶自建功能多數是 http request 只是去 call 不同的 API,可以隨時建立,它的「配方」recipe 可以分享
|
||||
- 每個 API Call 獨立但搜尋會整合,例如有人實作 call google sheets create table API,它不用做完整的,因為另一人要 delete table 時發現沒有,AI 直接做一個,下次搜尋 google sheets 時,就提供了 create table, delete sheets 兩個端點,也就是哪些是大家需要的功能自然產生
|
||||
- marketplace 機制,但是是給 AI 的,強制 AI 使用後要回覆使用的評價,如果一個零件被幾次評為不佳,其他的 AI 就可以避開這個零件
|
||||
- 自動審核:如果是 call API,只要成功 Call 通就是通過,如果是功能性的,只要通過他設置的 Gherkin 就是通過,省去人工審核的麻煩
|
||||
|
||||
## 觀念想法
|
||||
|
||||
- u6u 通過前端網頁開發功能,每個元件是一個零件
|
||||
- 視覺優先的開發:要解釋什麼是 webhook 很難,但一般用戶做一個前端的按鈕、輸入框... 後面就會綁定某個 webhook,點擊這個前端界面就看到後端邏輯的工作流,這樣就不用解釋太多。
|
||||
- 系統功能:我是一個用戶,我建立不同的功能,例如我建立 CRM,又建立 ERP,這些系統有很多流程是共用的,但當我建立多個工作流時,zoom out 就會看到我的公司內不同流程間的關係,因為 cypher 放大就是 graph,但每個功能要可以摺疊成一個點,又可以 zoom in 展開來調整某一段工作流,再 zoom in 調整一個零件
|
||||
- 考慮讓他自己 OWN,就是企業版可以讓資料是獨立的
|
||||
@@ -0,0 +1,24 @@
|
||||
# Wishlist
|
||||
|
||||
這個檔案記錄討論到但還不直接實作的想法,避免干擾,後續再來排入。
|
||||
|
||||
## Code 零件
|
||||
|
||||
目前的想法是,用戶發現有一個工作無法用現成零件產出,就建立一個新的零件投稿,測試通過 gherkin 就 publish。
|
||||
|
||||
這表示流程比較慢,跟其他的零件不符,例如:
|
||||
- 打 API 時用內建 http request 零件 + recipe,一個抵多個。
|
||||
- 內建 credential 零件 + recipe,一個零件可以連到各個服務的 auth。
|
||||
- 按照此邏輯,code 也可以內建 code 節點 + recipe,一個零件可以做多種任務。
|
||||
|
||||
例如我要一個把 Logseq outliners md 讀入,轉成 json 輸出的功能,實際上 Logseq 用戶不多,我不一定需要 publish 它。
|
||||
|
||||
或是因為某些機密的理由,用戶不想 publish 他的處理邏輯。
|
||||
|
||||
此時有個簡單的 code 節點可以寫簡單的 JS 當 recipe,而 code 寫在資料庫中與 code 節點分離,如果他要 publish 就直接 publish 這個 recipe 即可。
|
||||
|
||||
### 架構決策備忘(實作時請讀)
|
||||
|
||||
code 零件的 JS recipe **不在 WASM 內部執行**,而是由 code 零件(TinyGo WASM)將 recipe 字串透過 host function 傳遞給外部執行環境。arcrun 的 host 是 Cloudflare Workers isolate(V8),本身就是沙箱,不需要在 WASM 內嵌入 QuickJS 或 javy,也不需要引入 Rust。這與 http_request 零件 + recipe 的模式完全一致:零件本身是穩定的能力抽象(WASM),recipe 是存在 RECIPES KV 的可替換邏輯字串。
|
||||
|
||||
JS recipe 可用的 API 範圍為 Cloudflare Workers 標準 Web API(ES2023、fetch、crypto、TextEncoder 等),但 code 零件語意上應為純計算節點(無 network),實作時可考慮用 Proxy 遮蔽 fetch 等 I/O API,初期自用階段可暫時跳過此限制。第三方 lib 的問題留待實作時再決定白名單策略(預注入 lodash-es、dayjs、yaml 等到 global scope 即可覆蓋九成用例)。
|
||||
Reference in New Issue
Block a user