Self-hosted 開源:WASM 零件 + recipe + cypher-executor,跑在你自己的 Cloudflare。 此為重建的乾淨歷史起點(移除曾誤 commit 的 GCP SA 金鑰,舊歷史保留在 richblack/arcrun 與本地 backup 分支)。含: - acr init --self-hosted installer(建 KV/R2 + codeload 拉預編譯 wasm + wrangler deploy + seed recipe) - recipe push 把關(資料外流提醒 + 打通檢查) - 19 個正當零件預編譯 wasm(claude_api/km_writer/kbdb_upsert_block 排除:違反 DECISIONS §1) - CLI / cypher-executor / registry / 完整 SDD Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
12 KiB
arcrun.dev Landing Page — SDD
目標:給工程師一個門面,可以取得 API Key、管理 Key、探索 API(Swagger),同時藉此獲得會員 Email。 原則:先快速可用,不追求功能完整。榮譽牆、Python Lib 是後期。
0. 範圍(這份 SDD 涵蓋)
| 功能 | 說明 |
|---|---|
| 首頁 Hero | 說明 arcrun 是什麼,CTA 取得 API Key |
| OAuth 登入 | Google / GitHub(用自己的 auth recipe — dogfooding) |
| API Key 管理 | 查看、Rotate、Revoke |
| Swagger UI | 嵌入 /api,讓工程師直接試打 |
榮譽牆 /integrations |
靜態骨架,先列 20 個 recipe,無動態數字 |
| 中英切換 | ?lang=zh |
不在本次範圍:Python lib、Donate 整合、Social Proof 即時數字、貢獻者排行。
1. 技術選型
1.1 框架:Next.js(App Router)
選 Next.js 而非 Astro 的原因:
finally-click已有完整 Next.js + OAuth 回調實作,可直接複用模式- API Key 管理頁有登入態保護需求,Next.js 的 middleware 最直接
- Cloudflare Pages 支援 Next.js(
@cloudflare/next-on-pages) - Astro 在動態路由保護上摩擦較多
1.2 部署:Cloudflare Pages
arcrun.dev → Cloudflare Pages(Next.js)
API calls → cypher.arcrun.dev(現有 Worker)
1.3 儲存:現有 cypher-executor CREDENTIALS_KV + 新增 USERS_KV
現有 cypher-executor Worker 已有:
CREDENTIALS_KV:{api_key}:cred:{name}存 tenant credentialsRECIPES:auth recipes
新增需求:
- USERS_KV:存 user 帳號,key =
user:{provider}:{provider_user_id}- value:
{ email, display_name, api_key, created_at, provider }
- value:
- SESSIONS_KV:存 login session,key =
sess:{session_id}- value:
{ api_key, email, expires_at } - TTL = 7 天
- value:
兩個 KV 都加到 cypher-executor wrangler.toml。
1.4 OAuth — Dogfooding 自己的 Auth Recipe
登入用 arcrun 自己的 auth recipe:
- 不是用 arcrun auth recipe 的
http_requestrunner 去打第三方 - 而是 直接複用 recipe YAML 裡定義的 OAuth App 設定(client_id/secret)
- Worker 端實作 standard OAuth2 authorization_code flow
支援提供商(MVP):
- Google(google_drive recipe 的 OAuth App,或另建 arcrun-login Google App)
- GitHub(github recipe 的 OAuth App)
登入 OAuth App 與 auth recipe 的 OAuth App 可以是同一個(只要 scopes 包含 openid profile email),但更乾淨的做法是登入用獨立的 Google/GitHub App(只要 email scope),auth recipe 用的是資源存取 App。
決策:登入用獨立 OAuth App
GOOGLE_CLIENT_ID、GOOGLE_CLIENT_SECRET— 只申請openid profile emailGITHUB_CLIENT_ID、GITHUB_CLIENT_SECRET— 只申請read:user+user:email- 以 Worker Secret 方式存入 cypher-executor
2. 頁面結構
arcrun.dev/
├── / 首頁(Hero + Code snippet + CTA)
├── /login 登入頁(Google / GitHub 按鈕)
├── /auth/callback OAuth callback(Pages Function)
├── /dashboard API Key 管理(需登入)
├── /api Swagger UI(嵌入 swagger.json)
└── /integrations 服務目錄(靜態,20 個 recipe)
3. 登入 / OAuth 流程
3.1 流程圖
用戶點「Google 登入」
→ GET /auth/google/start(Worker 端)
→ redirect 到 Google OAuth(state = random, 存 SESSIONS_KV sess:state:{state} = {provider, redirect_back})
→ 用戶同意
→ GET /auth/callback?code=...&state=...(Worker 端)
→ 驗 state
→ 用 code 換 access_token(POST google token endpoint)
→ 用 token 取 userinfo(GET google userinfo)
→ upsert USERS_KV user:{provider}:{provider_id} = {email, display_name, api_key, ...}
→ 若新用戶:呼叫現有 /register?email=... 取得 arcrun API Key
→ 建立 session:SESSIONS_KV sess:{session_id} = {api_key, email, ...},TTL=7d
→ Set-Cookie: arcrun_session={session_id}; HttpOnly; Secure; SameSite=Lax
→ redirect 到 /dashboard
3.2 「若新用戶取得 API Key」的邏輯
現有 /register endpoint 接受 email 回傳 api_key(HMAC 確定性)。
但 landing page 需要的是真正綁定到用戶帳號的 key,且用戶可以 rotate/revoke。
方案:延伸現有 register endpoint
/register 目前:HMAC(secret, email) → 確定性 api_key,存 CREDENTIALS_KV
新增邏輯:
- 若 USERS_KV 已有此 user → 直接用記錄裡的 api_key
- 若新 user → 呼叫現有
/register(保持 HMAC 確定性邏輯)→ 拿到 api_key → 存入 USERS_KV
好處:不破壞現有 register 邏輯;登入後的 dashboard 顯示的 key = 現有 key = 封測用的 key。
3.3 Rotate / Revoke
- Rotate:產生新 UUID v4 key → 更新 USERS_KV 記錄 → 舊 key 失效(透過把新 key 加到 CREDENTIALS_KV,舊 key 的資料都跟著 API Key 命名空間走,所以 credentials 會留在舊 namespace)
- 簡化版:Rotate 後顯示提示「您的 workflow credentials 已和舊 Key 分離,請重新設定」
- Revoke:USERS_KV 記錄
revoked: true→ Worker middleware 拒絕此 key
4. API 端點(新增到 cypher-executor)
GET /auth/google/start → redirect 到 Google OAuth
GET /auth/github/start → redirect 到 GitHub OAuth
GET /auth/callback?code=&state= → 換 token、建立 session
POST /auth/logout → 清 session cookie
GET /me → 回傳當前登入用戶資訊(需 session cookie 或 API Key)
PUT /me/api-key/rotate → 產生新 key
DELETE /me/api-key → Revoke(標記撤銷)
5. 前端頁面設計
5.1 首頁(/)
Hero:
Stop fighting OAuth.
One API key. Every service. Works anywhere.
[Get API Key — Free] [View on GitHub]
Before/After:
40 行 OAuth 程式碼 → auth.bind("google_drive")
Code Demo(三個 tab):
Python / JavaScript / HTTP(n8n 用戶)
[Get Free API Key] 按鈕
5.2 登入頁(/login)
arcrun
登入或建立帳號
[Continue with Google]
[Continue with GitHub]
不需要信用卡。API Key 立即可用。
5.3 Dashboard(/dashboard)
歡迎,{display_name}
您的 API Key
┌────────────────────────────────┐
│ ak_xxxxxxxxxxxxxxxxxxxx [複製] │
└────────────────────────────────┘
[Rotate Key] [Revoke Key]
使用說明:
Authorization: Bearer {key}
或 X-Arcrun-API-Key: {key}
[登出]
5.4 Swagger UI(/api)
- 嵌入
<SwaggerUIBundle>JS(CDN) url: 'https://cypher.arcrun.dev/swagger.json'(現有 Worker 已有/docsopenapi endpoint)- 頂部說明:「這是 arcrun 的原始 API。Python / JS lib 是它的包裝,任何能發 HTTP request 的工具都能直接用。」
5.5 服務目錄(/integrations)
- 靜態列出 20 個 auth recipe(從 seed data 產生)
- 每個 recipe:名稱、認證方式(static_key / service_account)、所需 credentials
- 「找不到你要的服務?開 PR 貢獻 Recipe」CTA
6. 檔案結構
arcrun/landing/ ← 新 Next.js 專案
├── app/
│ ├── layout.tsx
│ ├── page.tsx 首頁
│ ├── login/
│ │ └── page.tsx
│ ├── dashboard/
│ │ ├── page.tsx
│ │ └── middleware.ts (或 root middleware)
│ ├── api-docs/
│ │ └── page.tsx Swagger UI
│ └── integrations/
│ └── page.tsx
├── middleware.ts 保護 /dashboard(讀 cookie)
├── lib/
│ └── auth.ts session helpers
├── public/
├── next.config.ts
├── package.json
└── wrangler.toml CF Pages 設定
cypher-executor 新增:
arcrun/cypher-executor/src/routes/
├── auth.ts ← 新增(OAuth start/callback/logout/me)
cypher-executor wrangler.toml 新增:
[[kv_namespaces]]
binding = "USERS_KV"
id = "<to be created>"
[[kv_namespaces]]
binding = "SESSIONS_KV"
id = "455d0505c7534883a4d4985ab8295857"
7. 環境變數 / Secrets
cypher-executor(Worker Secrets)
GOOGLE_CLIENT_ID Google OAuth App client_id(僅 openid profile email scope)
GOOGLE_CLIENT_SECRET Google OAuth App client_secret
GITHUB_CLIENT_ID GitHub OAuth App client_id(read:user + user:email scope)
GITHUB_CLIENT_SECRET GitHub OAuth App client_secret
SESSION_SECRET 隨機 32 bytes,用於 HMAC session ID(或直接用 UUID)
landing(Pages Environment Variables)
NEXT_PUBLIC_API_BASE https://cypher.arcrun.dev
8. 實作步驟(Checklist)
Phase 1:cypher-executor 後端擴充
wrangler kv:namespace create USERS_KV→ 填入 wrangler.toml (id: 25bef01d079148919578894434d58c4d)wrangler kv:namespace create SESSIONS_KV→ 填入 wrangler.toml (id: 455d0505c7534883a4d4985ab8295857)- 建立
arcrun/cypher-executor/src/routes/auth.ts- GET
/auth/google/start - GET
/auth/github/start - GET
/auth/callback(換 token → userinfo → upsert USERS_KV → 建 session → Set-Cookie → redirect) - POST
/auth/logout - GET
/me(讀 session cookie 或 API Key header) - PUT
/me/api-key/rotate - DELETE
/me/api-key(revoke)
- GET
- 在
src/index.ts掛載authRouter wrangler secret put GOOGLE_CLIENT_ID等 4 個 secrets ← 用戶需自建 Google/GitHub OAuth Appwrangler deploy← 已部署(Worker version 7877857b)
Phase 2:Next.js Landing 專案
npx create-next-app@latest arcrun/landing --typescript --tailwind --app- 設定
@cloudflare/next-on-pages(Next.js 15 + .npmrc legacy-peer-deps) - 建立
middleware.ts(保護 /dashboard,讀arcrun_sessioncookie)← 待做 - 首頁(
app/page.tsx):Hero + Code Demo tab + CTA - 登入頁(
app/login/page.tsx):Google / GitHub 按鈕(href 到 cypher.arcrun.dev/auth/google/start) - Dashboard(
app/dashboard/page.tsx):顯示 API Key,Rotate / Revoke 按鈕 - Swagger UI(
app/api-docs/page.tsx):client component,動態 import swagger-ui CDN - 服務目錄(
app/integrations/page.tsx):靜態,列 20 個 recipe - 中英切換 ← 低優先,可延後
wrangler pages deploy→ https://42a8d302.arcrun-landing.pages.dev- Cloudflare dashboard 設定 arcrun.dev custom domain → arcrun-landing Pages project
Phase 3:驗收(待 OAuth Secrets 填入後)
- Google / GitHub OAuth 完整流程(登入 → dashboard → 看到 key)
- Rotate:新 key 出現
- Revoke:舊 key 的 API 呼叫回傳 401
- Swagger UI 正常載入,可試打
/health /integrations正確列出 20 個服務
9. 待決事項(開始實作前確認)
| 問題 | 預設決策 |
|---|---|
| Google OAuth App 是否要另建(只有 email scope)? | 是,另建;auth recipe 的 App 不動 |
| Rotate 後舊 credentials 是否遷移? | 不遷移,顯示提示 |
| Domain arcrun.dev 是否已購入且在 Cloudflare? | 假設是(wrangler.toml 有設 zone_name) |
| 登入後 redirect 預設到 /dashboard | 是,可從 ?redirect= 覆寫 |