NAVIGATION
目錄導覽
持續更新中 這頁會持續補實機截圖、架構圖與測試紀錄;目前 demo 區塊先保留替換位置。
Series 03 / 技術架構

SKILL HUB 技能治理與知識化平台架構

平台不執行 Skill;它處理上架、掃描、摘要、版本與 telemetry。
BFF、封裝處理、LLM Ingestion、版本快照與 Usage Signals 各自負責一段資料流。

React 19 Vite 8 Tailwind 4 Supabase Node BFF LLM Pipeline

30 秒極速摘要 (Quick Read)

  • 解決什麼痛點:AI 讓同仁更容易製作工具,也帶來影子 AI、發布管道分散、原始碼難理解與採用成效難衡量等治理問題。
  • 平台邊界:SKILL HUB 不負責執行 Skill,而是治理 Skill 進入組織後的上架、知識化、版本紀錄與採用追蹤流程。
  • 封裝前處理:作者匯入資料夾或 ZIP 時,前端以 JSZip 解析檔案樹,先排除 node_modules.env、build 產物與過大封裝。
  • 資料流切分:Same-origin BFF、Ingestion Pipeline、version snapshot 與 telemetry 各自負責一段,避免 catalog、審核與分析流程混在一起。
  • AI 知識化提煉:LLM Pipeline 將 SKILL.md 轉成「三分鐘速讀」、知識透鏡與流程視圖,協助使用者先理解用途與限制。
  • 採用追蹤:Usage Signals 收集 view、download、tab 切換等事件,Recharts 呈現趨勢,並過濾 Admin 與作者本人的互動。
  • 安全深潛分流:上傳掃描、網站防禦、AI audit 與 user action audit 已拆到 安全治理頁,避免技術頁承載過多細節。

01 // DESIGN REFLECTION 設計反思:工具目錄只能解決「找得到」

工具目錄可以讓同仁找到 Skill,但不能回答它是否安全、誰維護、是否有人採用。SKILL HUB 把這些問題拆到掃描、審核、版本與 telemetry。

影子 AI 的邊界與責任歸屬

若員工自行散佈會呼叫外部 API 的 AI Skills,企業會失去可審核的治理邊界。SKILL HUB 不接管執行環境,而是把上架內容轉成可掃描、可審核、可追蹤的知識資產。 這代表我們不強制託管運行,而是藉由 client-side 預排除、ZIP / path / regex 安全掃描以及 Admin 審查機制,在上架流程中降低風險。

採用數據與沉沒成本控制

AI 工具寫了沒人知道,維護者會沮喪,組織也會重複造輪子。平台必須具備「採用指標(Usage Signals)」。 當我們知道哪些 Skill 被高頻瀏覽、下載或複製,哪些已經過期(Stale),部門主管就能用 view、download 與 stale 訊號判斷維護優先順序。

02 // TECH STACK 技術棧總覽 (Tech Stack at a Glance)

技術模組 語言 / 框架 / Runtime 核心依賴與目的 運行方式
AICS Workspace React 19 + Vite 8 JSZip, Tailwind 4 (提供安全預排除、表單 5 步精靈工作台) Client-side
Same-origin BFF Node.js API (BFF) Cookie-session auth & Supabase SDK (隔絕 DB 直連暴露) BFF Server / Middleware
Ingestion AI Pipeline Node.js (Serverless) Azure OpenAI SDK / LangChain (自動翻譯補值、三分鐘速讀生成) BFF Server (Rate-limited)
Usage Signals Recharts + SQL Analytics Recharts (繪製 14天/8週採用趨勢、熱門 Search 自動優化) Client + Server DB logs
AI Runtime Governance Node.js API + DB-backed Settings Mode toggles, quota gate, token budget, timeout, redacted AI audit BFF Server (Pre-quota Gate)
Admin-Gated Safety Review Supabase RPC + Archive Scanner scan lock, manual_review state, staged package promotion, immutable audit Server-side Workflow

03 // DESIGN PHILOSOPHY 設計取捨:以 Markdown 作為交換格式

在這個專案裡,`SKILL.md` 是最穩定的交換格式。人可以閱讀,Git 可以比對,LLM 也能依章節補出草稿欄位。

資料媒體契約:以 Markdown 純文字做無痛交換

為什麼不設計一套複雜的 JSON 或 UI 生成器,而堅持以 SKILL.md 作為標準包裝?

✦ 人類可讀性
Markdown 是純文字,任何同仁都能用本機的記事本或 Obsidian 編輯,不需要下載特定 GUI。
✦ Git 版本追蹤友善
Markdown 的 diff 軌跡極為乾淨,便於安全審查員在 GitHub / GitLab 或 Obsidian 中進行稽核比對。
✦ LLM 解析親和力
在既有測試樣本中,LLM 可穩定解析 Markdown 的 YAML Frontmatter 與 H2 章節,並輔助回填 knowledge_profile 欄位;實際回填率仍取決於文件結構完整度。

04 // ENVIRONMENT ISOLATION 環境隔離設計:保留可攜式 VIRTUALENV 結構

每個 Skill 套件保留獨立 virtualenv 結構,方便下載後在本機或 Agent 環境隔離執行;平台本身只負責上架、掃描與知識化。

vibeHub-Skills/ (Workspace Structure)
vibeHub-Skills/
├── n8n-automation-skill/
│   ├── .venv/                   # 各 Skill 獨立的 Python 虛擬環境
│   ├── SKILL.md                 # 職能描述 Markdown
│   ├── requirements.txt         # 核心依賴
│   ├── src/                     # 專家執行的腳本目錄
│   └── detail_payload.json      # Client-side 產出之 Ingestion metadata
│
├── teams-notifier-skill/
│   ├── .venv/
│   ├── SKILL.md
│   ├── scripts/send.py
│   └── requirements.txt
虛擬環境解耦考量
  • 防止套件污染:Skill A 使用舊版 requests,Skill B 升級新版,若共用環境會導致改 A 壞 B。
  • 冷啟動效能調優:避免載入大型 AI 分析庫(如 scikit-learn)拖累輕量級爬蟲 Skill 的執行效率。
  • 零干擾複製:任意 Skill 可以直接整包打包下載,在本機或其他專案執行,不需要重新拉取平台依賴。

05 // TECHNICAL DEEP DIVE 技術深潛:核心模組與治理交界

[Module-01] Client-side 預排除與安全打包

在 Step 1 專家匯入時,前端透過 JSZip 在記憶體解析檔案樹。 直接執行硬排除黑名單機制,阻擋將 node_modules、編譯產物與含有明文 key 的 .env 上傳。近期 same-origin package / media upload 已保守收斂到 4 MB,用來避開 Vercel Functions request body ceiling;大型封裝後續應改成 direct-to-storage upload。

src/utils/filter.js
const EXCLUDE_PATTERNS = [
  /node_modules\//i,
  /\.env.*/i,
  /\.git\//i,
  /dist\//i,
  /build\//i,
  /venv\//i,
  /\.venv\//i,
  /tmp\//i
];

async function filterAndPack(files) {
  const zip = new JSZip();
  let totalSize = 0;

  for (const file of files) {
    const isExcluded = EXCLUDE_PATTERNS.some(regex => regex.test(file.path));
    if (isExcluded) continue; // Exclude node_modules, env keys, etc.

    totalSize += file.size;
    if (totalSize > 4 * 1024 * 1024) {
      throw new Error("封裝檔案大小超過 4 MB same-origin 安全上限,請縮減封裝或改走大型檔案上傳流程。");
    }
    zip.file(file.path, file.content);
  }
  return await zip.generateAsync({ type: "blob" });
}

[Module-02] LLM 職能蒸餾 Pipeline

讀取已解包的 SKILL.md,呼叫 Azure OpenAI / OpenAI-compatible 管道。 自動解析並補齊 knowledge_profile(含 expectedOutcomestriggerConditions 等結構化欄位), 並實施超時與 300 行 truncated repair 降級策略,避免大型文檔阻斷 API 回應。

src/services/distill.js
async function distillSkill(skillMarkdown, retryCount = 0) {
  // Truncate to avoid timeout for exceptionally large markdown files
  const maxLines = 300;
  const lines = skillMarkdown.split('\n');
  const truncatedMarkdown = lines.slice(0, maxLines).join('\n');
  
  try {
    const response = await axios.post(
      process.env.VIBEHUB_OPENAI_COMPAT_BASE_URL + '/chat/completions',
      {
        model: 'gpt-5-mini', // Fallback model preset
        messages: [
          { role: 'system', content: 'You are an expert AI competency extractor. Extract JSON conforming to the knowledge_profile schema.' },
          { role: 'user', content: `Extract from this SKILL.md:\n\n${truncatedMarkdown}` }
        ],
        temperature: 0.1
      },
      { timeout: parseInt(process.env.AZURE_OPENAI_REQUEST_TIMEOUT_MS) || 90000 }
    );
    return JSON.parse(response.data.choices[0].message.content);
  } catch (error) {
    if (retryCount < 2) {
      console.warn(`AI Ingestion timeout/error. Retrying... (${retryCount + 1})`);
      return distillSkill(skillMarkdown, retryCount + 1);
    }
    return {
      expectedOutcomes: ["請手動填寫預期成果"],
      triggerConditions: ["請手動填寫觸發條件"],
      prerequisites: ["請手動填寫前置要求"]
    };
  }
}

[Module-03] Same-origin BFF API 與 Session 隔離

廢止 client-side 直接透過 API KEY 連線 Supabase,全站以同網域 BFF(Backend For Frontend)會話層進行認證代理。 採用 Middleware 對敏感 URL(如媒體讀取、package 下載)進行阻斷,當環境變數缺失時觸發 fail-closed 安全降級。

src/middleware.js
export function middleware(req) {
  const sessionToken = req.cookies.get("vibehub-session")?.value;
  
  // Fail-closed protection: if Supabase variables are missing, deny request with 503
  if (!process.env.SUPABASE_URL || !process.env.SUPABASE_SERVICE_ROLE_KEY) {
    console.error("Critical Security: Supabase keys are missing. Triggering fail-closed.");
    return new Response(JSON.stringify({ error: "Service unavailable due to internal security posture." }), { status: 503 });
  }

  // Validate session path
  if (!sessionToken) {
    return new Response(JSON.stringify({ error: "Unauthorized access. Session expired." }), { status: 401 });
  }
  
  return next();
}

[Module-04] Recharts Telemetry 採用監控與排除

在同仁瀏覽、下載包、複製指令、切換詳情頁 tab 時發送 Telemetry 事件。 系統將其記錄於後台稽核表,並自動過濾 Admin 與作者本人,確保 Usage Signals 互動圖表的乾淨度。

src/api/telemetry.js
async function logTelemetry(req, eventData) {
  const { toolId, eventName, actorId } = eventData;

  const { data: tool } = await supabase.from("tools").select("author_id").eq("id", toolId).single();
  const { data: actor } = await supabase.from("users").select("role").eq("id", actorId).single();

  if (actorId === tool.author_id || actor.role === "admin") {
    console.log("Telemetry bypassed: self-interaction or admin audit trail.");
    return;
  }

  await supabase.from("telemetry_logs").insert({
    tool_id: toolId,
    event_name: eventName,
    actor_id: actorId,
    timestamp: new Date().toISOString()
  });
}

[Module-05] AI Runtime 與安全治理交界

AI Ingestion 是技術架構的一部分,但它的風險控制不應散落在每個畫面。這裡只保留架構交界:AI 呼叫先經過 server-side runtime gate,確認 mode、timeout、token budget、quota 與 context files,再進入模型。

上架判定回到 scan status、approval status 與 Admin review。AI 只產出草稿、摘要與風險提示,不直接成為發布權威。

Runtime gate AI mode、quota、timeout 與 token budget 在模型前處理。
Audit boundary Prompt/result 預設只留 redacted preview,完整內容需明確開關。
Decision boundary AI 結果只輔助理解,正式放行仍看掃描與人工審核。
閱讀安全治理深潛

05.1 // ADVANCED ARCHITECTURE 進階架構設計 (Advanced Architecture)

Same-origin BFF 會話代理與安全降級 (Fail-Closed)

系統將前端直連 Supabase 的資料存取收斂到 server-side,全站 API 統一由 BFF (Backend For Frontend) 會話代理進行存取控制。

防禦性設計 (Defensive Design)middleware.js 在檢測到雲端 Supabase Auth 憑證缺失時,不會退回暴露的舊 Anon 連線,而是觸發 Fail-Closed 降級保護,直接向客戶端回應 503 (Service Unavailable),降低配置錯誤造成的資料暴露風險。

https://skill-hub.internal.corp/architecture/bff
實機 DEMO 圖片待補 detail-bff-session-proxy-flow.png

建議放 Same-origin BFF session proxy flow 或實際 API 邊界截圖。

Deterministic 版本差異快照比對引擎

每次 Skill 經重傳改版 (Re-upload) 或 Ingestion 更新時,系統均會在 tool_version_snapshots 內固化當前結構,並自動與上一版本進行比對。

比對引擎會拆解 zip/manifest 並產出具體的 Added / Removed / Changed 差異,並將結果呈現於審查清單中,供 Admin 明確知道「這一次改版,作者到底動了哪些程式碼與 YAML 設定」。

https://skill-hub.internal.corp/console/versions
實機 DEMO 圖片待補 detail-version-snapshot-diff-admin.png

建議放 version snapshot diff 或 Admin review 裡的版本差異畫面。

下一階段:Agent-native 探索端點與安裝輔助

目前 SKILL HUB 的主要採用路徑仍是人進入網站搜尋、閱讀與下載。下一階段應補上 agent-friendly discovery endpoint,例如 /api/agent-catalog/search,讓本機 Agent 能在任務中查詢已發布且有權限讀取的 Skill。

安裝輔助方向:後續可用低風險 PowerShell / Bash helper 驗證 checksum、建立備份,再以 symlink 或 copy 方式安裝到 Claude Code、Codex、Cursor 或 Gemini CLI 的 Skill 目錄。這仍是 roadmap,不應和目前正式上架主線混淆。

https://skill-hub.internal.corp/roadmap/agent-catalog
實機 DEMO 圖片待補 detail-agent-catalog-api-terminal.png

建議放 agent catalog/search endpoint 或 terminal 查詢 demo。

▲ 圖 7 佔位:讓人與 Agent 查詢同一套已發布 Skill catalog。

05.2 // SECURITY GOVERNANCE HANDOFF 安全治理從這裡分流

這頁保留架構邊界,不重複整份防禦鏈

技術架構頁需要回答模組如何拆、資料如何流、哪些地方會降級。上傳掃描、網站入口、AI quota、redacted audit、immutable user action audit 與 roadmap 邊界,已經集中到安全治理頁。


06 // LESSONS LEARNED 踩坑點與 Lessons Learned (故障復盤)

Lesson 1: Same-origin auth 遷移與 Supabase RLS 洩漏風險

問題背景:系統初期為了求快,直接在前端建立 Supabase Client 連線資料庫,並依賴 Row Level Security (RLS) 保護表單。然而安全審計時發現,前端打包的 bundle 會暴露出 Supabase URL 與 Anon Key,且 RLS 設定一旦稍有疏漏(例如忘記關閉 select 的 public bypass),就會造成敏感同仁日誌外洩的風險。

解決方案:遷移至 Same-origin BFF。前端一律發送 /api/session/api/tools 等同網域請求,Supabase Client 收斂到 server-side。Middleware 也採 fail-closed,避免配置錯誤時退回前端直連。

Lesson 2: ZIP 大檔案打包引發 API 傳輸崩潰

問題背景:早期版本的作者上架流程允許使用者直接拖放資料夾,後端直接接收並打包。當使用者將包含 node_modules 或大型編譯產物 (build/) 的目錄誤拖入時,上傳檔案常突破 100MB,造成 Serverless timeout 與網路崩潰。

解決方案:將過濾邏輯左移至 Client-side。利用 JSZip 在前端讀取檔案樹時,直接針對黑名單正則進行硬排除,並把 same-origin 上傳安全上限收斂到 4 MB。大型 package 後續應改走 direct-to-storage upload,避免 binary request body 直接經過 Vercel Function。

Lesson 3: LLM Ingestion 逾時與 Quota 配額阻斷系統運行

問題背景:AI Ingestion 在處理上千行的 SKILL.md 時,常因 Azure OpenAI 推理時間過長,造成 Vercel Serverless Function 觸及 10 秒/30 秒的最大逾時限制而中斷,且頻繁的重試迅速耗光了 API Token 預算。

解決方案:導入兩重防護:一是 truncated repair 降級策略,送入 AI 之前只擷取前 300 行,並在 UI 上對作者標記「部分欄位已降級,請手動確認」;二是於後台提供 AI Runtime Controls,可在資料庫動態關閉完整 AI 蒸餾流程,並對一般用戶實施 15次/日 的 AI 呼叫硬限制,降低預算失控與系統不可用風險。

Lesson 4: AI 審查不能變成自動核准權威

問題背景:如果把 package-safety-review 的 LLM 結論直接當作上架 gate,模型 timeout、quota 用盡、prompt injection 或上下文截斷都可能造成錯誤放行或錯誤阻擋。這會讓治理責任從可驗證的掃描與審核流程,滑向不可穩定重現的模型判斷。

解決方案:AI 只負責「輔助理解」與「風險摘要」。正式放行交給掃描狀態、審核狀態與 Admin sign-off;完整防線已拆到 安全治理頁

延伸討論 / Interaction

如果你想討論 same-origin BFF、AI Ingestion 或 Recharts telemetry 的取捨,歡迎到 LinkedIn 與我交流。

connect ~/linkedin