頁面施工中

本頁仍在製作中,內容會持續補齊與調整。歡迎先收藏,日後再回來瀏覽並追蹤我的更新。

NAVIGATION
商業價值視角 目錄導覽
Technical Deep Dive / 技術實作解析

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

在大 AI 時代下,如何防禦影子 AI 氾濫,打通「好找、好讀、好分享」的核心安全防護與採用監控。
基於 Same-origin BFF 認證閘、AST 安全打包排除、LLM 職能蒸餾與 Recharts 採用指標的企業級架構。

React 19 Vite 8 Tailwind 4 Supabase Node BFF LLM Pipeline

30 秒極速摘要 (Quick Read)

  • 解決什麼痛點:AI 讓同仁編寫工具的難度降至零,但「影子 AI」帶來的隱私外流、缺乏發布管道(不好找)、原始代碼難讀懂(不好讀)與採用狀況黑箱(好分享)成為企業導入障礙。
  • 核心架構設計:前端採用 React 19 與 Vite 8 提升開發效率;後端廢除瀏覽器直連 Supabase,改接 Next-style API 做 Same-origin BFF 認證隔離,並以 middleware fail-closed 防禦敏感 DB 暴露。
  • AI 知識化提煉:整合 LLM Pipeline。作者上傳前由 Client-side 硬排除敏感檔,後端 ZIP scan 敏感路徑;AI 自動翻譯並蒸餾 Markdown 生成「三分鐘速讀」與「知識透鏡(Knowledge Lens)」,甚至依代碼與配置圖自動繪製流程拓撲圖(AI Flow)。
  • 採用數據飛輪:模組化收集 view/download/tab 切換事件,由 Recharts 視覺化呈現採用趨勢圖,將組織 AI 技能徹底轉譯為可量化、可治理的數位資產。

01 // 設計反思 (Reflection_):在大 AI 時代重新定義平台壁壘

在工具製作成本急速趨近於零的時代,平台的價值不應是「工具目錄」,而是「治理與採用中樞」。

影子 AI 的邊界與責任歸屬

當員工能自行撰寫 AI Skills 呼叫外部 API 時,企業的隱私防護形同虛設。SKILL HUB 的邊界在於「不接管執行環境,只做可驗證的知識化 Ingestion」。 這代表我們不強制託管運行,而是藉由 client-side 預排除、ZIP 安全路徑掃描以及 Admin 審查機制,在源頭過濾隱患。

採用數據與沉沒成本控制

AI 工具寫了沒人知道,維護者會沮喪,組織也會重複造輪子。平台必須具備「採用指標(Usage Signals)」。 當我們得知哪些 Skill 被高頻採用、哪些已過期(Stale),部門主管就能藉此評估維運 ROI,讓 AI 轉型不再停留在喊口號,而是以實打實的採用指標推動。

02 // 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

03 // 設計哲學:以 Markdown 為契約的知識轉譯

大 AI 時代最核心的資產是半結構化的工作手冊。我們選擇以 Markdown 純文字檔作為介面傳輸與分享的核心契約。

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

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

✦ 人類可讀性
Markdown 是純文字,任何同仁都能用本機的記事本或 Obsidian 編輯,不需要下載特定 GUI。
✦ Git 版本追蹤友善
Markdown 的 diff 軌跡極為乾淨,便於安全審查員在 GitHub / GitLab 或 Obsidian 中進行稽核比對。
✦ LLM 解析親和力
LLM 能夠極為穩定地抓取 Markdown 的 YAML Frontmatter 與 H2 章節,將其精確對應為 `knowledge_profile` JSON schema,回填率大於 80%。

04 // 環境隔離設計:每個 Skill 均在獨立的 VIRTUALENV 下解耦

每個 Skill 目錄下各自維護獨立的執行虛擬環境,在 runtime 上完全解耦,不讓 dependency conflict 拖垮整體系統。

# 組織技能包內部打包目錄 (vibeHub 原型結構)
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 // 技術深潛 (Deep Dive):四大核心模組實作代碼剖析

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

在 Step 1 專家匯入時,前端透過 JSZip 在記憶體解析檔案樹。 直接執行硬排除黑名單機制,阻擋將 node_modules、編譯產物與含有明文 key 的 .env 上傳,且在封裝大於 50MB 時直接中斷,保障傳輸效能與資安防禦。

javascript // Front-end ZIP pre-filtering logic
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 > 50 * 1024 * 1024) {
      throw new Error("封裝檔案大小超過 50MB 上限,請縮減打包內容後重試。");
    }
    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 回應。

javascript // LLM parsing retry and truncated repair
async function distillSkill(skillMarkdown, retryCount = 0) {
  // Truncate input 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', // Guaranteed fallback model preset
        messages: [
          { role: 'system', content: 'You are an expert AI competency extractor. Extact 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);
    }
    // Fallback to manual fill required if AI completely fails
    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 安全降級。

javascript // Middleware fail-closed auth controller
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 });
  }
  
  // Forward safely to BFF internal routes
  return next();
}

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

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

javascript // Usage telemetry filter API
async function logTelemetry(req, eventData) {
  const { toolId, eventName, actorId } = eventData;

  // Retrieve tool owner to exclude self-interaction metrics
  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();

  // Exclude authors and administrators from usage telemetry
  if (actorId === tool.author_id || actor.role === "admin") {
    console.log("Telemetry bypassed: self-interaction or admin audit trail.");
    return; // Silent bypass
  }

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

05.1 // 進階架構設計 (Advanced Architecture) 與技術展示

為組織級 AI 技能架設「防護網」:探討 BFF 安全閘、版本差異引擎與 Agent 自動安裝的工作流。

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

系統徹底廢除前端直連 Supabase 的不安全模式,全站 API 統一由 BFF (Backend For Frontend) 會話代理進行存取控制。

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

BFF session proxy architectural flow
▲ 圖 5:Same-origin BFF 安全會話代理與 Middleware 阻斷流向

Deterministic 版本差異快照比對引擎

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

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

Version snapshot diff engine
▲ 圖 6:版本快照比對引擎(監控 Added/Removed/Changed 快照變更)

Agent-native 探索端點與一鍵本機安裝 (Install Helper)

為突破「逛網站搜尋」的傳統漏斗,系統提供給 AI 爬蟲與本機 Agent(如 Claude Code, Cursor)專用的探索 API (/api/agent-catalog/search)。

本機安裝自動化:透過輕量化 PowerShell / Bash 安裝管家,當使用者按下複製安裝時,指令會自動驗證 checksum 下載包,以 symlink 軟連結 方式直接掛載至 Agent 的 Skill 資料夾,實現「免配置一鍵採用」。

Agent-native integration and symlink deployment flow
▲ 圖 7:Agent 語意查詢與 Symlink 軟連結自動掛載安裝機制

06 // 踩坑點與 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 在前端讀取檔案樹時,直接針對黑名單正則進行硬排除,並限制重打包後的 zip Blob 必須小於 50MB 否則拒絕上傳。這不僅節省了 95% 的頻寬,更降低了專家將本地敏感設定(.env)外流的可能。

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**,可在資料庫動態關閉 Full AI,並對一般用戶實施 15次/日 的 AI 呼叫硬限制,保障企業預算與系統高可用。

延伸討論 / Interaction

如果您對本系統的 same-origin BFF、AI Ingestion 知識蒸餾架構或 Recharts telemetry 有興趣,歡迎至 LinkedIn 與我交流。

connect ~/linkedin