# Feature:模型共享(Model Sharing)— L 級新功能 > 父文件:[PRD.md](../PRD.md) | 相依既有功能:[模型管理](feature-model-management.md)、[會員系統](feature-auth.md) > 對應 User Stories:US-31 ~ US-40(本檔新增,接續 user-stories.md 既有 US-01~US-30) > 狀態:三方聯合討論中(PM 產出草稿,待 Design / Architect 互審) > 撰寫日期:2026-08-02 --- ## 0. 這份 PRD 的定位(先講清楚,避免誤解範圍) **模型共享不是從零打造的功能,而是在既有「模型管理」功能上,疊加一個「可見性 / 權限」維度。** 反推自既有 code 的現況(重要,這是設計基礎): | 面向 | 現況(已實作) | 本功能要加什麼 | |------|---------------|---------------| | 模型資料模型 | `Model` 有 `OwnerUserID`、`Source`(preset/uploaded/converted)、軟刪。**無 visibility 欄位** | 新增「可見性 / 公開對象」維度 | | 存取控制 | 嚴格 owner-only(`List` 只 filter `OwnerUserID`;`Get`/`download` 非 owner 回 403)+ 系統 preset 公用 | 讓「非 owner 但被授權者」也能看到 / 下載 | | 模型庫 UI(`/models`)| 按**來源**分三區(preset / converted / uploaded),只看自己的 | 新增「共享給我 / 我可見」的維度;分頁、排序、搜尋、filter | | 使用者 / 權限 | OIDC(Member Center)`sub`=userID;users 表有 `org_id`(nullable, 未用)、`roles TEXT[]`(未用) | 「公開對象」要對齊這些既有欄位(同租戶 / 群組概念) | | 下載 | handler 註解已寫明「第一階段 owner-only(**B 分享後續階段**)」 | 本功能正是被預留的「B 分享階段」 | **一句話**:既有系統已經為「分享」預留了骨架(`org_id`、`roles`、download handler 的註解),本功能把這個骨架填血。 --- ## 1. 功能概述與價值主張 **使用者痛點**(反推自 Persona,見 user-research.md): - **阿哲(FAE)**:轉檔 / 調校好一個客戶專用模型後,想給同組 FAE 或客戶直接用,現在只能「下載 → 私訊傳檔 → 對方重新上傳」,模型檔散落、版本混亂。 - **Sarah(SI)**:在多個客戶現場佈署,想把一套驗證過的模型推給整個團隊 workspace,現在每個工程師都要自己上傳一份。 - **Mike(開發者)**:想引用別人分享的公開模型做 A/B test 基準,現在沒有「探索別人模型」的入口。 **核心價值主張**:「**上傳一次,授權共享,團隊即用**」——把模型從「我的私有檔案」升級為「可依身份權限流通的資產」。 **北極星指標關聯**:模型共享降低「取得可用模型」的摩擦 → 提升首次推論成功率與每週推論次數(WAD / 每週推論次數 per user,見 success-metrics.md)。 --- ## 2. 公開對象(可見性)權限模型 — PM 提案 > ⚠️ **本節是全功能的核心設計決策,需 Architect 確認技術可行性、Design 確認 UI 複雜度。** ### 2.1 設計原則 1. **對齊既有 auth 概念**,不自造平行權限系統。既有已有:`OwnerUserID`(擁有者)、`org_id`(租戶 / 組織,nullable)、`roles TEXT[]`。 2. **preset 模型維持不變**:系統 7 預設模型永遠對所有人公開,不納入本功能的可見性控制。 3. **owner 永遠有完整權限**:可設定 / 變更公開對象、可撤銷、可刪除。 4. **漸進式**:Phase A 先做最有價值、技術最單純的層級;複雜的群組 / 租戶留 Phase B。 ### 2.2 提案:可見性層級(Visibility Levels) 在 `Model` 上新增 `Visibility` 欄位,四個層級由私到公: | 層級 | 值(提案) | 誰能看到 / 下載 | 對齊既有概念 | 建議 Phase | |------|-----------|----------------|-------------|-----------| | **私有** | `private` | 只有 owner(= 現況預設行為) | `OwnerUserID` | **P0(預設值)** | | **指定使用者** | `restricted` | owner + 被明確授權的 user 清單 | 新增 share grant 關聯 | **P0** | | **同租戶 / 組織** | `organization` | owner + 同 `org_id` 的所有 user | 既有 `users.org_id` | **P1**(依賴租戶功能成熟度) | | **全公開** | `public` | 所有已登入 user | — | **P1** | **P0(MVP)先做 `private` + `restricted` 兩級**,理由: - `private` 是現況行為,成本近乎 0(只是把隱含的「無 visibility = 私有」顯性化)。 - `restricted`(指定 user 分享)是**痛點最直接的解**(阿哲要給特定同事 / 客戶),且不依賴「租戶 / 群組」這種尚未成熟的概念。 - `organization` / `public` 依賴 `org_id` 租戶模型與內容治理(濫用、審核),成本與風險高,留 P1。 > **待 Architect 確認 A**:`restricted` 的授權清單,建議新增一張 `model_shares` 關聯表(`model_id` × `grantee_user_id` × `permission` × `granted_by` × `created_at`)。這是否與現有 DB migration 策略相容?(既有 migration 到 0005,models 表 index 全 owner-scoped,共享查詢需要新 index / 新表。) > > **待 Architect 確認 B**:`organization` 層級依賴 `users.org_id`,但該欄位目前是「nullable + 未寫入」的 stub。若 P1 要做,需先有「租戶 / org 指派」機制。此依賴請 Architect 評估。 > > **待 Design 確認 C**:四層級的 UI 呈現。P0 兩級相對單純(一個下拉 + 指定 user 的 email/名稱輸入);但「指定 user 清單」的 UX(怎麼搜尋 user、怎麼移除、怎麼顯示已授權清單)需要 Design 設計。 ### 2.3 權限粒度(permission) P0 先做**唯讀分享**(被授權者可**檢視 + 下載 + 用於推論**,但不能改 / 刪 / 二次分享)。 | 權限 | P0 | 說明 | |------|-----|------| | view(看得到、看 profile) | ✅ | 出現在對方的「共享給我」列表 | | download(下載 .nef) | ✅ | 對齊 download handler 的「B 分享階段」 | | use(載入裝置推論) | ✅ | 分享的核心價值:對方能直接用 | | edit / re-share / delete | ❌(P1+) | 只有 owner 能做 | > **待 Architect 確認 D**:`use`(載入裝置推論)牽涉 `load-to-device` 與 download token 簽發。現在 download handler 對非 owner 回 403,`restricted` 要放行「被授權者」——授權檢查要插在哪一層(middleware / handler / repo filter)? --- ## 3. User Stories(接續既有 US 編號) > 格式對齊 user-stories.md。RICE 的 Effort 欄標「待 Architect 核對」,本檔先給 PM 相對估值。 ### 3.1 模型公開設定(owner 視角) - **US-31(P0)**:作為模型擁有者,我要**在模型 profile 頁設定它的公開對象(私有 / 指定使用者)**,這樣我就能控制誰能用我的模型。 - **US-32(P0)**:作為模型擁有者,我要**把模型分享給指定的一位或多位使用者(用 email 或名稱搜尋)**,這樣特定同事 / 客戶就能直接使用。 - **US-33(P0)**:作為模型擁有者,我要**看到目前這個模型已分享給哪些人,並能移除某個人的存取權**,這樣我能隨時收回授權。 - **US-34(P1)**:作為模型擁有者,我要**把模型設為「同組織可見」或「全公開」**,這樣整個團隊 / 社群不用我逐一授權。 ### 3.2 共享模型庫(被分享者 / 探索者視角) - **US-35(P0)**:作為使用者,我要**在模型庫看到「共享給我」的模型(別人授權給我的)**,並清楚看到它是誰分享的、我的權限是什麼。 - **US-36(P0)**:作為使用者,我要**能對共享模型庫做分頁瀏覽**,這樣模型多時不會一次載入全部、頁面不卡。 - **US-37(P0)**:作為使用者,我要**對共享模型庫做排序(上傳時間 / 名稱 / 檔案大小)**,這樣我能快速找到最新或最相關的模型。 - **US-38(P0)**:作為使用者,我要**對共享模型庫做 filter(依硬體晶片 / 來源 / 可見性 / 分享者)**,這樣我能縮小範圍。 - **US-39(P0)**:作為使用者,我要**用關鍵字搜尋模型(名稱 / 描述)**,這樣我能直接找到目標模型。 - **US-40(P0)**:作為使用者,我要**進入任一可見模型的 profile 頁,看到完整資訊(metadata、支援硬體、擁有者、分享者、我的權限、下載 / 載入按鈕)**,這樣我在使用前能確認它是我要的。 ### 3.3 依身份權限的可見性(貫穿所有 story 的規則) **共享模型庫「我能看到的模型」= 聯集**: ``` 我擁有的(owner) ∪ 明確分享給我的(restricted grant,US-32) ∪ 我所屬 org 的 organization 模型(P1,US-34) ∪ 全公開模型(P1,US-34) ∪ 系統 preset(既有,永遠可見) ``` > **待 Architect 確認 E**:這個「聯集查詢」在現有 `Repository.List(ListFilter)` 介面下無法表達(現在只支援 owner filter)。需擴充 `ListFilter`(加 grantee / visibility / org 維度)或新增 method。請評估對現有 in-memory + postgres 兩個實作的衝擊。 --- ## 4. RICE 排序 / 優先級 | # | Story | Reach | Impact | Conf. | Effort(待 Architect 核對) | RICE | Phase | |---|-------|-------|--------|-------|------|------|-------| | US-32 | 分享給指定使用者 | 70 | 3 | 80% | 2 | 84 | **P0** | | US-35 | 「共享給我」列表 | 70 | 3 | 80% | 1.5 | 112 | **P0** | | US-31 | 公開設定(私有/指定) | 70 | 2 | 80% | 1 | 112 | **P0** | | US-40 | 模型 profile 頁 | 80 | 2 | 90% | 1.5 | 96 | **P0** | | US-39 | 關鍵字搜尋 | 80 | 1 | 90% | 1 | 72 | **P0** | | US-33 | 檢視 / 撤銷授權清單 | 60 | 2 | 80% | 1 | 96 | **P0** | | US-38 | filter(晶片/來源/可見性/分享者)| 80 | 1 | 80% | 1 | 64 | **P0** | | US-37 | 排序 | 80 | 1 | 90% | 0.5 | 144 | **P0** | | US-36 | 分頁 | 80 | 1 | 90% | 0.8 | 90 | **P0** | | US-34 | org 可見 / 全公開 | 50 | 2 | 60% | 3 | 20 | **P1** | > RICE 說明沿用 user-stories.md §5.1(Reach 為 Phase 相對估值、Impact 對北極星 WAD)。Effort 全部標「待 Architect 核對」——尤其 US-32 / US-35 的授權表 + 聯集查詢是技術重點。 ### P0 / P1 切分總結 **P0(MVP,本次做)**: - 可見性兩級:`private`(預設)+ `restricted`(指定 user 分享) - 公開設定 UI(在 profile 頁)+ 授權清單管理(新增 / 移除) - 共享模型庫:「共享給我」維度 + 分頁 + 排序 + filter + 搜尋 - 模型 profile 頁(擴充既有 `/models/[id]`,加分享資訊與權限顯示) **P1(後續)**: - `organization`(同租戶可見)— 依賴租戶 / org 指派機制成熟 - `public`(全公開)— 需內容治理(濫用回報、審核) - 二次分享、edit 權限、分享通知(email / in-app) --- ## 5. 與既有模型功能的關係(擴充 vs 全新) | 元件 / 檔案 | 現況 | 本功能 | 類型 | |------------|------|--------|------| | `Model` domain(model.go) | 無 visibility | 加 `Visibility` 欄位 + 可能的 share 關聯 | **擴充** | | `models` 表(migration 0001) | owner-scoped index | 新 migration:加 visibility 欄 + `model_shares` 表 + 新 index | **擴充 + 新表** | | `Repository.List(ListFilter)` | 只 owner filter | 擴充 filter(grantee / visibility)或新 method | **擴充** | | `GET /api/models`(models.go) | preset + 自己的 | 加「共享給我」聯集 + 分頁 / 排序 / 搜尋 query params | **擴充** | | `GET /api/models/:id`、`download` | 非 owner 403 | 放行被授權者 | **擴充** | | 新 API:設定可見性 / 管理授權 | — | `PUT /api/models/:id/visibility`、`POST/DELETE /api/models/:id/shares` | **全新** | | `/models` 頁(page.tsx) | 按 source 三區 | 加「共享給我」維度 + 分頁 / 排序 / 搜尋列 | **擴充** | | `ModelFilters`(model-filters.tsx) | 只 targetChip | 加來源 / 可見性 / 分享者 filter + 搜尋框 | **擴充** | | `/models/[id]` profile 頁 | 基本資訊 + 下載 / 刪除 | 加:公開設定區、授權清單管理、分享者 / 我的權限顯示 | **擴充** | | 「公開設定」互動 | — | 新 UI(可見性下拉 + user 搜尋授權) | **全新(Design 重點)** | **關鍵**:搜尋 / 排序 / 分頁在既有 code 是被標為「Phase 1 TODO」的(見 model-filters.tsx 註解、feature-model-management.md TODO-3)。本功能把它們正式做出來,且**同時服務「我的模型」與「共享模型」兩個維度**——不是只給共享用。 --- ## 6. 成功指標 | 類別 | 指標 | Baseline | P0 目標 | 追蹤方式 | |------|------|----------|---------|---------| | 採用 | 建立過至少一次分享的 owner 比例 | N/A(新功能,baseline=0) | 內測 FAE 中 ≥ 40% | 埋點:`model_share_created`(待 Architect 確認埋點清單) | | 採用 | 「共享給我」列表被點開的 WAU 比例 | N/A | ≥ 30% | 埋點:`shared_library_viewed` | | 價值 | 用「別人分享的模型」跑過推論的 user 比例 | N/A | ≥ 25% | 埋點:`inference_with_shared_model` | | 效率 | 共享模型庫首屏載入時間(含分頁) | N/A | P95 < 1.5s | 前端 perf(待 Architect / 非功能需求對齊 nonfunctional.md) | | 效率 | 搜尋 → 找到目標模型的操作步數 | 現況需私訊傳檔(不可量測) | ≤ 3 步(搜尋 / filter → profile → 使用) | 可用性測試 | | 護欄 | 未授權存取被正確拒絕率 | 現況 owner-only 403 | 100%(不可退化) | 安全測試(待 Security / Architect) | | 護欄 | 既有「我的模型」列表載入時間不退化 | 現況 P95 | 不劣於現況 | 回歸 perf 測試 | > Baseline 多為 N/A:全新功能、無歷史數據。目標值為內測 FAE 群體的估算門檻,launch 後 2 週校正。護欄指標「未授權存取拒絕率」是**本功能最重要的把關**——分享功能最大的風險是權限漏洞導致模型外洩。 --- ## 7. 待三方確認事項彙總(互審重點) ### 給 Architect(技術可行性) | # | 事項 | 位置 | |---|------|------| | A | `model_shares` 授權關聯表設計是否相容既有 migration 策略(0001~0005 全 owner-scoped index) | §2.2 | | B | `organization` 層級依賴 `users.org_id`(現為未寫入 stub),P1 前需先有租戶指派機制 | §2.2 | | C | `use`(被授權者載入裝置推論)的 download token 簽發 + 授權檢查插入層級(middleware / handler / repo) | §2.3 | | D | `Repository.List` 聯集查詢(owner ∪ granted ∪ org ∪ public)對 in-memory + postgres 兩實作的衝擊 | §3.3 | | E | 分頁 / 排序 / 搜尋在 List 介面的表達(offset/cursor 分頁?搜尋用 LIKE 還是全文索引?) | §3.2 | | F | 各 RICE Effort 欄核對(尤其 US-32 / US-35) | §4 | | G | 成功指標的埋點事件清單可行性 | §6 | ### 給 Design(體驗面) | # | 事項 | 位置 | |---|------|------| | C | 「指定 user 分享」的 UX:怎麼搜尋 user、加入 / 移除、已授權清單呈現 | §2.2 | | — | 可見性層級的 UI(下拉?分段控制?如何讓 owner 一眼看懂「私有 vs 指定 vs 公開」的差異與風險) | §2.2 | | — | 共享模型庫的資訊架構:「我的模型」與「共享給我」怎麼並存(分頁 tab?分區?既有已按 source 分三區,再加維度會不會過載) | §3.2 / §5 | | — | profile 頁如何同時呈現「我是 owner(可管理)」vs「我是被授權者(唯讀)」兩種狀態 | US-40 | | — | 分頁 / 排序 / 搜尋 / filter 控制列的整合設計(既有 filter 只有 targetChip 一個下拉,要擴成完整工具列) | §3.2 | ### 給雙方(需一起拍板) - **P0 是否確認只做 `private` + `restricted` 兩級**?(PM 主張是,理由見 §2.2。若 Design / Architect 認為 org 層級成本可控且需求急,可討論上調。) - **可見性預設值 = `private`**(不主動公開任何東西,安全優先)——三方確認無異議。 --- ## 8. 連結 - 回:[PRD 索引](../PRD.md) - 相依:[模型管理](feature-model-management.md)、[會員系統](feature-auth.md)、[介面契約](../interface-contracts.md) - 待更新:user-stories.md(US-31~US-40 併入主表)、success-metrics.md(分享指標)