Files
Arcrun/.agents/specs/arcrun/landing-page.md
T
Leo 13b01328c1 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>
2026-04-20 17:48:24 +08:00

326 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# arcrun.dev Landing Page — SDD
> **目標**:給工程師一個門面,可以取得 API Key、管理 Key、探索 APISwagger),同時藉此獲得會員 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.jsApp 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 PagesNext.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 credentials
- `RECIPES`auth recipes
新增需求:
- **USERS_KV**:存 user 帳號,key = `user:{provider}:{provider_user_id}`
- value: `{ email, display_name, api_key, created_at, provider }`
- **SESSIONS_KV**:存 login sessionkey = `sess:{session_id}`
- value: `{ api_key, email, expires_at }`
- TTL = 7 天
兩個 KV 都加到 cypher-executor `wrangler.toml`
### 1.4 OAuth — Dogfooding 自己的 Auth Recipe
登入用 arcrun 自己的 auth recipe
- 不是用 arcrun auth recipe 的 `http_request` runner 去打第三方
- 而是 **直接複用 recipe YAML 裡定義的 OAuth App 設定(client_id/secret**
- Worker 端實作 standard OAuth2 authorization_code flow
**支援提供商(MVP**
- Googlegoogle_drive recipe 的 OAuth App,或另建 arcrun-login Google App
- GitHubgithub 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 email`
- `GITHUB_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 callbackPages Function
├── /dashboard API Key 管理(需登入)
├── /api Swagger UI(嵌入 swagger.json
└── /integrations 服務目錄(靜態,20 個 recipe)
```
---
## 3. 登入 / OAuth 流程
### 3.1 流程圖
```
用戶點「Google 登入」
→ GET /auth/google/startWorker 端)
→ redirect 到 Google OAuthstate = random, 存 SESSIONS_KV sess:state:{state} = {provider, redirect_back}
→ 用戶同意
→ GET /auth/callback?code=...&state=...Worker 端)
→ 驗 state
→ 用 code 換 access_tokenPOST google token endpoint
→ 用 token 取 userinfoGET google userinfo
→ upsert USERS_KV user:{provider}:{provider_id} = {email, display_name, api_key, ...}
→ 若新用戶:呼叫現有 /register?email=... 取得 arcrun API Key
→ 建立 sessionSESSIONS_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
新增邏輯:
1. 若 USERS_KV 已有此 user → 直接用記錄裡的 api_key
2. 若新 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 / HTTPn8n 用戶)
[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>` JSCDN
- `url: 'https://cypher.arcrun.dev/swagger.json'`(現有 Worker 已有 `/docs` openapi 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 新增:
```toml
[[kv_namespaces]]
binding = "USERS_KV"
id = "<to be created>"
[[kv_namespaces]]
binding = "SESSIONS_KV"
id = "455d0505c7534883a4d4985ab8295857"
```
---
## 7. 環境變數 / Secrets
### cypher-executorWorker 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_idread:user + user:email scope
GITHUB_CLIENT_SECRET GitHub OAuth App client_secret
SESSION_SECRET 隨機 32 bytes,用於 HMAC session ID(或直接用 UUID
```
### landingPages Environment Variables
```
NEXT_PUBLIC_API_BASE https://cypher.arcrun.dev
```
---
## 8. 實作步驟(Checklist
### Phase 1cypher-executor 後端擴充
- [x] `wrangler kv:namespace create USERS_KV` → 填入 wrangler.toml (id: 25bef01d079148919578894434d58c4d)
- [x] `wrangler kv:namespace create SESSIONS_KV` → 填入 wrangler.toml (id: 455d0505c7534883a4d4985ab8295857)
- [x] 建立 `arcrun/cypher-executor/src/routes/auth.ts`
- [x] GET `/auth/google/start`
- [x] GET `/auth/github/start`
- [x] GET `/auth/callback`(換 token → userinfo → upsert USERS_KV → 建 session → Set-Cookie → redirect
- [x] POST `/auth/logout`
- [x] GET `/me`(讀 session cookie 或 API Key header
- [x] PUT `/me/api-key/rotate`
- [x] DELETE `/me/api-key`revoke
- [x]`src/index.ts` 掛載 `authRouter`
- [ ] `wrangler secret put GOOGLE_CLIENT_ID` 等 4 個 secrets ← **用戶需自建 Google/GitHub OAuth App**
- [x] `wrangler deploy` ← 已部署(Worker version 7877857b
### Phase 2Next.js Landing 專案
- [x] `npx create-next-app@latest arcrun/landing --typescript --tailwind --app`
- [x] 設定 `@cloudflare/next-on-pages`Next.js 15 + .npmrc legacy-peer-deps
- [ ] 建立 `middleware.ts`(保護 /dashboard,讀 `arcrun_session` cookie)← 待做
- [x] 首頁(`app/page.tsx`):Hero + Code Demo tab + CTA
- [x] 登入頁(`app/login/page.tsx`):Google / GitHub 按鈕(href 到 cypher.arcrun.dev/auth/google/start
- [x] Dashboard`app/dashboard/page.tsx`):顯示 API KeyRotate / Revoke 按鈕
- [x] Swagger UI`app/api-docs/page.tsx`):client component,動態 import swagger-ui CDN
- [x] 服務目錄(`app/integrations/page.tsx`):靜態,列 20 個 recipe
- [ ] 中英切換 ← 低優先,可延後
- [x] `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`
- [x] `/integrations` 正確列出 20 個服務
---
## 9. 待決事項(開始實作前確認)
| 問題 | 預設決策 |
|---|---|
| Google OAuth App 是否要另建(只有 email scope? | 是,另建;auth recipe 的 App 不動 |
| Rotate 後舊 credentials 是否遷移? | 不遷移,顯示提示 |
| Domain arcrun.dev 是否已購入且在 Cloudflare | 假設是(wrangler.toml 有設 zone_name |
| 登入後 redirect 預設到 /dashboard | 是,可從 `?redirect=` 覆寫 |