◆ wport | pm_41

wport CLI v2(Enterprise 完整 parity + Personal 預留)PRD

wport CLI v2(Enterprise parity)

來源 doc/feature/pm_41/wport-cli-v2-mockup.md

wport CLI v2(Enterprise 完整 parity + Personal 預留)PRD

PRD 代號pm_41
延續pm_37(Enterprise REST API + wpk_live_ 認證)、pm_38(公司資訊編輯欄位語義)
CLI 套件@wport/cli(現況見 exec-wport-cli SKILL
產品原則(Eric 確認)GUI 能做什麼,CLI 就做什麼;僅 法遵級、核彈行為(刪除公司、帳號) 永久排除。
個人線認證(Eric 2026/06/24 裁決):個人 CLI 改用 OAuth(wport login,device-code flow)不再發個人 API 金鑰wpk_personal_ 廢止)。金鑰自助頁僅核發公司金鑰


1. 文件資訊

  • 文件類型:CLI + REST API 擴充需求規格書
  • 適用對象:CLI 工程師、後端、產品、QA、AI Agent 整合(Cursor / Claude)
  • 最後更新:2026/07/15
  • 版本:1.3.0(2026/07/15:職缺 close(關閉)全面撤銷——職缺狀態只有上下架;見 §3 DR-10。全文件 close 引用已同步移除)
  • 版本(前):1.2.2(2026/06/25:①企業 API 金鑰雙軌制(自助申請 + 我方 AMS 代管)正式回寫;見 §3.4 DR-9 / §4.2 BR-API-CLI-010 / §7.3)
  • 建立日期:2026/06/22
  • 對應 Coda rowIdi-wportCliV241x(新建列,見 §16)
  • 對應 Storybook
    • API 金鑰自助申請(軌道 A,使用者端)storybook/src/stories/mockups/company/ApiKeySelfService.stories.ts
    • 企業 API Key 管理(軌道 B,我方 AMS)storybook/src/stories/mockups/siteadmin/EnterpriseApiKeyAdmin.stories.ts
    • 公司編輯(欄位 SoT):storybook/src/stories/mockups/company/CompanyEditRegisterV2.stories.ts
    • 人才庫(行為參考):storybook/src/stories/mockups/recruitment/ 相關 mockup
  • Storybook 連結
  • 代號對照pm_37 = Enterprise REST API;本 PRD = pm_41(CLI v2,延續 pm_37);pm_39 = 第三方登入(Apple 等,見 doc/feature/pm_39/third-party-auth-mockup.md

2. 開發進度與設計來源

開發進度

  • CLI PR #:[TBD](hotfire-digital/wport-agents 或獨立 @wport/cli repo)
  • 後端 PR #:[TBD](REST 擴充,依賴 pm_37 落地)
  • 前端 PR #:[TBD](本版已含使用者端 API 金鑰自助申請 UI 設計與 mockup,見 §3.4 DR-8;前端實作待排程,personal key 開放依賴此 UI 上線)

設計來源

  • 現行 CLI 行為exec-wport-cli SKILL.md
  • 競品對標:Stripe CLI、GitHub CLI (gh)、Heroku CLI、Shopify CLI
  • 內部 SoTpm_37 OpenAPI、pm_38 公司欄位語義

3. 功能摘要(Feature Summary)

3.1 功能概述

  • 功能名稱:wport CLI v2
  • 主要使用者角色
    • 企業端:Owner / Admin / Manager(wpk_live_ + wport enterprise
    • 求職者(預留):個人 user(wport personal,認證走 OAuth wport login,非金鑰;延後實作
    • AI Agent:透過 JSON 輸出與 --minimal / --fields 整合
  • 核心目標
    • 補齊 @wport/cli 企業線:從現況僅 jobs list/view 擴展至 與 GUI 等價 的職缺、人才庫、召募活動、公司資訊操作
    • 統一終端機體驗(exit code、--output json、Idempotency、quota 可見性)
    • 為 MCP / Agent skill 提供穩定命令面(延續 pm_37 OpenAPI 策略)

3.2 範圍界定

包含範圍(pm_41 交付)

A. 企業線 CLI(wport enterprise,需 wpk_live_

模組CLI 能力對應 GUI / REST
認證login / whoami / logout(已有,維持)pm_37
職缺create / update / publish / unpublish / delete / copy / batch createclose 已撤銷,DR-10)職缺管理 dashboard
職缺list 強化:點擊、來訪、應徵、狀態、名稱、更新時間、上架時間、上架者職缺列表欄位
職缺view(已有,維持 + --fields職缺詳情
營運usage(月 quota、rate limit 剩餘)pm_37 ApiUsage
公司company view / company update完整對齊 pm_38 v1 編輯欄位公司編輯頁
人才庫talents list(filter + 分頁讀取)、talents view人才庫應徵/來訪 Tab
人才庫talents respond(發信/回應,對齊 GUI)人才庫回訊
召募campaigns list / view / create / update / publish / unpublish召募活動管理

B. 公開線(已有,維持)

  • wport jobs search / wport jobs view(無 key)

C. 全域(已有,維持)

  • wport config / wport doctor

排除範圍(明確不做)

項目理由
Personal API Key(wpk_personal_廢止(Eric 2026/06/24);個人 CLI 改 OAuth wport login,不發個人金鑰
核彈 deny list(見 §3.5)法遵;即使 GUI 有入口亦不得經 CLI/API 暴露
人才庫 bulk export / 無分頁全量 dump防爬蟲與個資外洩
刪除個人帳號 / 刪除公司 / 轉移所有權BR-012、BR-016 核彈行為
管理公司成員(邀請/移除/改角色)高風險治理;維持 GUI
Test/Live key 分離沿用 pm_37 v2 規劃
Webhook / MCP server 實作獨立專案;本 PRD 僅維護命令與 OpenAPI 對齊

Personal 線(規格預留,延後實作;認證走 OAuth)

待 OAuth 整合後交付:

  • wport login|whoami|logoutOAuth device-code flow,user-scoped,不綁公司,不發金鑰)
  • wport personal resumes list|view|create|update|copy|delete
  • wport personal apply(投遞職缺,對齊 BR-011 72h 冷卻)

3.3 成功條件(KPI,CLI 上線後 3 個月)

KPI目標
@wport/cli 月活躍安裝用戶(unique machine)≥ 30
企業線命令執行次數 / 月≥ 5,000
透過 CLI 建立或更新的職缺≥ 200 筆
CLI 相關 support ticket< 10 件 / 月
Agent skill(exec-wport-cli)文件與 CLI 版本漂移0 次 major 未同步

3.4 設計決策依據(Design Rationale)

DR-1:CLI = thin wrapper over REST

  • 採用:所有企業寫入走 pm_37 namespace REST;新增模組(talents/campaigns/company)擴充同一 Enterprise API namespace
  • 理由:單一 OpenAPI SoT;CLI 不直連 DB

DR-2:GUI parity,核彈除外

  • 採用:職缺刪除、履歷刪除(personal 線)允許,但需 --confirm;帳號/公司刪除永不開放
  • 理由:Eric 產品哲學;降低 HR 自動化摩擦,保留法遵底線

DR-3:人才庫讀取 = filter + 分頁,禁止 bulk dump

  • 採用talents list 必須 page + page_size(max 100);不提供 --all 或無上限 stdin batch
  • 理由:B1 確認;個資保護

DR-4:公司 update 對齊 pm_38 v1

  • 採用company update payload 語義 = pm_38 §5 公司擴充欄位(含 BR-024/025 建議規則)
  • 權限:Owner / Admin only(BR-016;Manager 不可編輯公司)

DR-5:個人線改 OAuth(不發個人金鑰,Eric 2026/06/24 裁決)

  • 採用:個人 CLI 以 OAuth device-code flowwport login)認證,wpk_personal_ 廢止
  • 理由:個人使用者非整合自動化場景,OAuth 體驗更佳(無需自管金鑰、可隨時於帳號撤銷授權),且免去 C 端金鑰外洩風險
  • SaaS benchmarkgh auth loginstripe loginvercel login 皆以 OAuth/device-code 處理「人」的登入,API key 留給「機器對機器」(公司整合)

DR-6:沿用 pm_37 認證與 quota

  • 採用wpk_live_Idempotency-Key(寫操作)、company-level 月 quota 5000
  • 新增:人才庫讀取建議獨立子 quota(見 §8.5)

DR-7:破壞性操作護欄

  • 採用delete / batch 寫入需 --confirm 或互動確認;batch ≤ 100(繼承 pm_37)(close 已撤銷,DR-10)

DR-8:公司 API 金鑰自助申請 UI(Eric 2026/06/24 裁決・改採 GitHub fine-grained PAT 流派)

本頁只核發公司金鑰 wpk_live_(綁公司,企業線);個人線改 OAuth(DR-5),不再有個人金鑰。原 v1.1.0 的「每公司限一把 / scope 固定不可選 / 永久」三項裁決已被推翻,改採下表多把具名 key 模型。mockup:Mockups/公司/API 金鑰自助申請

決策採用理由
多把具名 key每公司可建多把有名稱的 active 金鑰,治理上限 ≤ 10 把(BR-API-CLI-004 改寫)不同整合(職缺同步 / 人才庫 Agent / 批次腳本)應各自一把,便於分別撤銷與用量歸因;輪替/撤銷單把不影響其他整合。對標 GitHub PAT、Stripe restricted keys
scope 可勾選申請時以 checkbox 勾選範圍(職缺 / 人才庫 / 召募 / 公司資訊),至少一項(BR-API-CLI-006 改寫)最小權限原則;一把只讀人才庫的 key 不該能改公司資訊
公司資訊 scope 限 O/A「公司資訊」scope 僅 Owner/Admin 可勾;Manager 建 key 時該項 disabled(灰階 + 鎖頭),不隱藏(BR-API-CLI-006)公司資訊編輯本就限 O/A(BR-016 / pm_38 DR-4);若 Manager 可建含此 scope 的 key 等於經 key 放大權限,必須堵住;灰階可讓 Manager 知悉能力存在但不可授權
角色 vs 導航Owner / Admin / Manager:企業後台可進入 API 金鑰頁;Member:無權(403 / 無權頁)mockup 用 recruitment header + role Controls;Member 不應有治理入口(BR-016)
強制到期 30/60/90每把金鑰必須設定到期日,選 30 / 60 / 90 天無「永不過期」;逾期一般 API → 401(BR-API-CLI-008)「避免 key 外洩就完蛋」(Eric)——到期窗即外洩風險上限;對標 GitHub fine-grained PAT(強制最長 1 年)、AWS 金鑰輪替最佳實務
過期 key-for-key 換新金鑰 expired 後,rotate endpoint 仍接受該把過期金鑰作授權(rotate-only 例外);換發新明文、重設到期、scope/名稱不變;舊 key 立即失效(BR-API-CLI-009)RD 回饋常見 M2M 實務:整合腳本在 key 過期後仍可「用舊 key 換新 key」,無需人工登入 GUI;CLI wport enterprise keys rotate 支援自動化輪替
每把獨立用量key 卡片顯示本月呼叫數 + 最後使用;公司月配額 5000 為所有金鑰共用可快速辨識哪把 key 在被使用 / 異常爆量,便於撤銷
撤銷免理由撤銷僅需二次確認,不要求填理由(BR-API-CLI-005)使用者端自助操作;理由欄屬後台治理(pm_37 AMS)需求,C 端徒增摩擦
角色閘門公司金鑰僅 Owner/Admin/Manager 可建立,Member 無權(BR-016)沿用既有角色矩陣
一次性明文建立 / 輪替後完整明文僅在畫面顯示一次金鑰明文絕不以 Email 或任何管道傳送(BR-API-CLI-007)信箱外洩即金鑰外洩;對標 Stripe / GitHub / OpenAI 鐵則
CLI 套件連結UI 提供 @wport/cli npm 超連結降低上手摩擦
  • 雙軌治理(見 DR-9):軌道 A(本頁自助)與軌道 B(AMS EnterpriseApiKeyAdmin並存,共用同一 ApiKey 服務與 wpk_live_ 資料模型;RD 落地時兩入口須呼叫同一核發 / 輪替 / 撤銷 API。
  • 導航 / IA(見 §9):mockup 採企業後台 recruitment header單一公司情境(無頁內切換公司);頁內提示框沿用 wb-alert
  • 狀態:UI mockup 已更新Mockups/公司/API 金鑰自助申請),含 role Controls、多把金鑰 / 含過期換新 / 申請(scope checkbox + 到期)/ 一次性揭露 / Member 選單隱藏等情境;前端正式實作待排程(§2)。軌道 B 沿用 pm_37 EnterpriseApiKeyAdmin mockup(見 §3.4 DR-9)。

DR-9:企業 API 金鑰雙軌治理(自助申請 + 我方代管,並存)

pm_37 v1 僅有 ops 人工核發;pm_41 上線企業自助後,兩軌並存、共用同一 ApiKey 資料模型與核發 / 輪替 / 撤銷服務——差別在操作者、可見範圍與治理欄位,不是兩套 key 機制。

維度軌道 A:企業自助申請(C 端)軌道 B:我方幫忙申請(AMS / ops)
入口企業後台 → 公司設定 → API 金鑰(mockup:recruitment header)W101-AMS → 企業 API Key 管理(EnterpriseApiKeyAdmin
StorybookMockups/公司/API 金鑰自助申請Mockups/Siteadmin/EnterpriseApiKeyAdmin
操作者公司 Owner / Admin / Managerwport 平台管理員(我方管理者;非企業角色)
列表可見範圍僅該使用者所屬公司的金鑰全平台所有公司、所有金鑰(跨公司全域列表 + 篩選)
核發使用者自行申請多把具名 key我方代指定公司 + 指定帳號核發(onboarding / support 場景)
scope 勾選職缺 / 人才庫 / 召募 / 公司資訊(至少一項);「公司資訊」僅 O/A 可勾(BR-API-CLI-006)四項皆可勾(含公司資訊);不受企業 BR-016 角色限制——平台管理員代客核發
到期強制 30 / 60 / 90 天(BR-API-CLI-008)同左;與軌道 A 同一欄位
輪替 / 過期換新UI「輪替」/「換新金鑰」;CLI keys rotate(BR-API-CLI-009)AMS 可對任意 key 輪替;過期 key-for-key 規則同源
撤銷(刪除 key)公司 O/A/M 可撤銷自家 key;免填理由、二次確認(BR-API-CLI-005)平台管理員可撤銷任意公司任意 key建議填理由(稽核 / support 追溯,pm_37 OPS 治理)
配額 override❌(沿用公司月配額 5000)✅ ops 可調企業專屬 quota(繼承 pm_37 OPS-2)
明文揭露建立 / 輪替後僅畫面一次性不入信(BR-API-CLI-007)同左;代核發時由 ops 於 AMS 畫面一次性複製交予客戶,不得經 Email 傳明文
CLI`wport enterprise keys listrotate`(企業自動化)
  • 列表合一(實作):不論軌道 A 或 B 核發,同一 wpk_live_ 出現在(1)該公司 C 端自助列表、(2)AMS 全域列表——單一 SoT,雙入口讀寫
  • 與 pm_37 關係:軌道 B = pm_37 OPS-2 / admin/enterprise-api-keys 的延續;pm_41 將資料模型升級為多把具名 + 可勾 scope + 強制到期後,AMS 須同步對齊(非舊版「每公司每帳號限一把」)。
  • 產品原則:早期 onboarding / 大客戶可由我方代核發;成熟後企業以自助為主,兩軌不互斥

DR-10:職缺 close(關閉)全面撤銷(2026/07/15 裁決)

  • 裁決職缺狀態只有上下架(published / unpublished),無「暫停」、無「關閉」jobs close 與後端 PATCH /enterprise/jobs/:enc_id/close 全面撤銷(backend PR #118;@wport/cli 0.7.0 命令改隱藏 stub:印遷移訊息、exit 2、不發請求)。
  • 緣由:close 產生的 CLOSED(10) 是 GUI 從不存在的第三狀態。本 PRD §2 對照表原宣稱「職缺管理 dashboard」具備 close,未經 GUI 現況驗證即依「GUI parity」原則納入 CLI;實際 GUI 只有上下架 toggle,被 CLI 關閉的職缺在企業後台成為無法再上架、無法操作的殭屍列(error.job.closed),卡死管理流程。
  • 資料補救:存量 status=10 已以 contract migration(V20260715024448__tsh-pm_41-jobs-close-revoke-restore.sql)復原為未刊登;staging / prod 實查歸零(2026/07/15)。
  • 流程教訓:「GUI 能做什麼,CLI 就做什麼」的 parity 對照表,逐項須以 GUI 現況實證(截圖 / 前端 code),不得以 PRD 自身表格自證。
  • 本文件其餘章節之 close 引用已同步移除;歷史語境見版本 1.2.x。

3.5 核彈 Deny List(永久禁止,CLI + Enterprise API 皆不得實作)

行為相關規則說明
刪除個人帳號BR-012不可逆、GDPR;僅 GUI 多步驟流程
刪除公司BR-007、BR-016僅 Owner;需強互動
轉移公司所有權BR-016資產級操作
管理成員(邀請/移除/改角色)BR-007治理風險
人才庫全量匯出BR-017爬蟲/個資
GDPR 級個資打包匯出BR-020與 Enterprise API 無關

4. 商業規則對齊(Business Rules Alignment)

4.1 本功能使用到的業務規則

規則 ID規則摘要是否關鍵在本 PRD 的對應
BR-001email 驗證後才能登入key 申請者須已驗證(pm_37)
BR-005公司未驗證可建職缺但無法上架publish 回 403;CLI 透傳
BR-008職缺發布必填欄位create/update/publish 驗證
BR-009職缺狀態機非法轉換 → 409
BR-010履歷最多 6 份personal resumes copy(延後)
BR-01172h 投遞冷卻personal apply(延後)
BR-012Owner 不可刪帳號核彈 deny
BR-016角色權限矩陣企業命令依角色;公司 edit 僅 O/A
BR-017資料存取控制僅自家公司資源;人才庫欄位白名單
BR-022每帳號最多 10 間公司key 為 company-scoped
pm_38 BR-024統編驗證後不可變company update 拒絕改 tax_id
pm_38 BR-025欄位顯示偏好company update 含 visibility flags

4.2 補充說明 / 新規則提案

  • BR-API-CLI-001(建議新增):CLI 破壞性企業寫入(jobs delete、batch)須顯式 --confirm 或互動輸入職缺標題確認
  • BR-API-CLI-002(建議新增):人才庫 API/CLI 回傳欄位不得超過 GUI 單筆詳情可見範圍;禁止 export endpoint
  • BR-API-CLI-003(建議新增)talents respond 每日每公司發信上限對齊 GUI([RD 決定具體數字])
  • BR-API-CLI-004(改寫,Eric 2026/06/24):API 金鑰僅有公司金鑰 wpk_live_(個人金鑰廢止,個人線改 OAuth)。每公司可建多把具名 active 金鑰,治理上限 ≤ 10 把/公司;達上限須先撤銷再申請。每把獨立 scope、到期日與用量。
  • BR-API-CLI-005(建議新增,Eric 裁決):使用者端金鑰撤銷免填理由,二次確認即可(理由欄為 pm_37 後台治理需求,C 端不沿用)。
  • BR-API-CLI-006(改寫,Eric 2026/06/24):金鑰權限範圍由使用者於申請時勾選(公司=職缺/人才庫/召募/公司資訊,至少一項);其中**「公司資訊」scope 僅 Owner/Admin 可勾**,Manager 建 key 時該選項 disabled(對齊 BR-016 / pm_38 DR-4,防止經 key 放大權限)。
  • BR-API-CLI-007(建議新增,Eric 裁決・資安):金鑰明文絕不以 Email 或任何管道傳送,只在建立/輪替當下的畫面顯示一次。系統可選擇寄送不含金鑰的安全提醒信(「你的公司剛建立了一把 API 金鑰,若非本人請立即撤銷」)——此提醒信為選配,內容嚴禁含金鑰明文或可還原片段
  • BR-API-CLI-008(建議新增,Eric 2026/06/24・資安):公司金鑰強制設定到期日,選項 30 / 60 / 90 天不提供「永不過期」;逾期後一般 Enterprise API → 401;需透過輪替或重新核發延續。輪替(rotate)會換新明文並重設到期。理由:到期窗 = 金鑰外洩風險上限;對標 GitHub fine-grained PAT 強制到期。
  • BR-API-CLI-009(建議新增,2026/06/25・RD 回饋)過期金鑰 key-for-key 換新——金鑰狀態為 expired 時,除一般 API 外,POST .../api-keys/{enc_id}/rotate 仍接受該把過期金鑰作為 Bearer 授權(rotate-only 例外);成功後產生新 wpk_live_ 明文(僅揭露一次)、重設到期日(沿用申請時 30/60/90 選項或預設 90)、scope 與名稱不變;舊金鑰立即失效。GUI 過期卡片顯示「換新金鑰」;CLI 提供 wport enterprise keys rotate <enc_id>(優先 credential store 內該 key,或 --api-key 顯式帶入過期 key)。不得以過期 key 呼叫其他 enterprise endpoint。
  • BR-API-CLI-010(建議新增,2026/06/25)企業 API 金鑰雙軌制——軌道 A(企業自助)軌道 B(我方 AMS 代管)並存,共用同一 ApiKey 實體與 wpk_live_ 前綴。軌道 A:公司 O/A/M 僅能看/管自家金鑰;scope 勾選受 BR-API-CLI-006;撤銷免理由。軌道 Bwport 平台管理員於 AMS 可見全平台所有公司所有金鑰;可代指定公司核發、四 scope 皆可勾(不受企業 BR-016)、可輪替 / 撤銷(刪除)任意 key(建議填理由供稽核)、可調 quota override(pm_37 OPS)。兩軌核發之 key 須同時出現在該公司 C 端列表與 AMS 全域列表。AMS 治理不經 CLI

5. 資料實體與欄位(Data Entities & Fields)

Rule 30:描述需追蹤的資訊與業務目的;JSON 命名由 OpenAPI 決定。

5.1 實體列表

實體用途CLI 模組
ApiKey(enterprise)wpk_live_ 認證;軌道 A 自助 + 軌道 B AMS 共用(DR-9)wport enterprise
OAuthSession(personal,預留)OAuth user-scoped token(廢 wpk_personal_wport personal(延後)
Job職缺 CRUD + 統計enterprise jobs
JobListStats列表聚合指標enterprise jobs list 擴充欄位
Company(pm_38 擴充)公司資訊讀寫enterprise company
TalentPoolEntry應徵/來訪紀錄enterprise talents
Campaign召募活動enterprise campaigns
ApiUsagequota 可見性enterprise usage

5.2 實體資料需求說明

ApiKey(enterprise,雙軌共用)

為什麼需要:M2M 認證;軌道 A(C 端自助)與軌道 B(AMS 代管)同一資料列(BR-API-CLI-010)
必須追蹤

  • 綁定公司、核發對象帳號、具名稱稱、遮罩後 key 前綴
  • scopes(職缺 / 人才庫 / 召募 / 公司資訊)
  • 狀態:active / expired / revoked
  • expires_at、本月用量、最後使用時間
  • 核發來源:self_service | ams_ops(稽核區分,[RD 命名])

JobListStats(列表必須可選輸出)

為什麼需要:對齊 GUI 職缺管理表;HR 用 CLI/Agent 監控成效
必須可追蹤 / 回傳

  • 職缺識別與名稱
  • 狀態(對齊 BR-009)
  • 近 7 日點擊數、來訪數(與 GUI dashboard 一致)
  • 應徵數(可選欄位)
  • 最後更新時間
  • 上架時間(published_at)
  • 上架者(acting user email 或 display name)

Company(對齊 pm_38 v1)

必須支援讀寫的資訊類別(語義層,細項見 pm_38 §5):

  • 基本資料:名稱、統編/登記號、國家、地址、產業、資本額等
  • 品牌:Logo、Banner
  • 介紹:公司介紹、3 組照片/URL、3 個介紹影片 URL
  • 擴充敘述:痛點、得獎、里程碑、QA(free text)
  • 敏感欄位與顯示偏好:設立日期、負責人、董監事、電話 + 各欄位「對外是否顯示」
  • 統編鎖定後不可變更(BR-024)

TalentPoolEntry

必須追蹤

  • 履歷識別、候選人顯示名稱、摘要欄位(對齊 GUI 列表)
  • 來源類型:應徵 vs 來訪
  • 關聯職缺、關聯召募活動/頁面來源
  • 時間戳(應徵時間 / 來訪時間)
  • 篩選維度:job_id、campaign/source_id、keyword、date_range

禁止

  • 一次回傳全公司所有履歷全文
  • 超出 GUI 詳情頁的 PII 欄位

Campaign

必須追蹤:名稱、狀態、上架時間、關聯落地頁設定、權限檢查


6. CLI 命令面與資料需求(Command Surface & Data Needs)

本節取代傳統 UI 區塊;為 @wport/cliexec-wport-cli skill 的 SoT。

6.1 命令樹(pm_41 目標)

wport
├── doctor
├── config
├── jobs                    # 公開(已有)
│   ├── search
│   └── view
├── enterprise              # 企業 key
│   ├── login | whoami | logout
│   ├── usage
│   ├── keys                    # 金鑰治理(輪替;GUI 為主,CLI 補自動化)
│   │   ├── list
│   │   └── rotate <enc_id>     # 含過期 key-for-key(BR-API-CLI-009)
│   ├── jobs
│   │   ├── list
│   │   ├── view
│   │   ├── create
│   │   ├── update
│   │   ├── copy
│   │   ├── publish | unpublish | delete
│   │   └── batch create
│   ├── company
│   │   ├── view
│   │   └── update
│   ├── talents
│   │   ├── list
│   │   ├── view
│   │   └── respond
│   └── campaigns
│       ├── list | view
│       ├── create | update
│       └── publish | unpublish
└── personal                # 延後實作(規格預留)
    ├── login | whoami | logout
    ├── resumes ...
    └── apply

6.2 全域 CLI 契約(繼承現行 + 擴充)

項目規範
全域 flags--lang--api--output table|json--timeout--no-color
企業認證--api-key > WPORT_API_KEY > credential store(mode 0600)
寫入 headersIdempotency-Key(自動產生 UUID 或 --idempotency-key
Exit codes0 成功;2 參數;3 4xx;4 5xx/網路;5 設定檔損壞
Agent 友善--minimal--fields(逗號分隔 dotted path)
破壞性操作--confirm 必填(delete / batch delete)

6.3 企業職缺命令資料需求

wport enterprise jobs list

Flag說明
--statusdraft / published / unpublished / deleted
--updated-afterISO 日期篩選
-p, --page / -s, --page-size分頁(max 100)
--fields預設含:enc_id,title,status,clicks_7d,visits_7d,applications,updated_at,published_at,publisher_display
--minimalenc_id,title,status,clicks_7d,visits_7d

wport enterprise jobs create|update

輸入說明
--file <json>Job payload;update 支援 partial
--publishcreate 時若公司已驗證可直接上架
--if-matchoptimistic lock(updated_at / version)

wport enterprise jobs delete

護欄說明
--confirm必填;或互動輸入職缺 title 子字串

wport enterprise jobs batch create

限制說明
--file≤ 100 筆;partial success 回應

6.4 公司命令(pm_38 對齊)

wport enterprise company view

  • 輸出完整公司物件(JSON)或 table 摘要
  • --fields 支援子路徑(如 field_visibility.is_phone_visible

wport enterprise company update

  • --file company.json:payload 語義對齊 pm_38 Company 擴充實體
  • 權限:403 forbidden(Manager/Member)
  • 統編已鎖:嘗試修改 tax_id → 422 tax_id_locked
  • Logo/Banner:支援 URL 或 --logo-file / --banner-file([RD 決定 multipart vs 先上傳媒體 API])

6.5 人才庫命令

wport enterprise talents list

Flag說明
--tabapplied(應徵)/ visit(來訪)
--job職缺 enc_id
--source召募活動或頁面來源 enc_id 暫不做(需後端擴功能,另行評估)
-k, --keyword姓名/職稱/公司關鍵字
--from / --to時間區間
-p, --page / -s, --page-size必填語意(預設 page=1, size=20, max 100)
--fields / --minimalAgent token 節省

刻意不提供--allexport--batch(stdin 無上限)

wport enterprise talents view <enc_resume_id>

  • 單筆詳情;欄位範圍 = GUI 人才庫詳情

wport enterprise talents respond <enc_resume_id>

Flag說明
--subject / --body郵件內容
--template可選模板 ID(對齊 GUI) 暫不做(需後端擴功能,另行評估)
--job關聯職缺(若 GUI 需要)
  • 繼承 GUI 發信規則與日限額(BR-API-CLI-003)

6.6 召募活動命令

命令說明
campaigns list分頁列表 + status 篩選
campaigns view單活動詳情
campaigns create / update--file JSON
campaigns publish / unpublish狀態轉換;權限對齊 GUI(B5:有權限即可)

6.7 金鑰治理命令(輪替 / 過期換新)

金鑰申請 / 撤銷以 GUI 自助頁為主(§3.4 DR-8);CLI 補 自動化輪替,尤其整合腳本在 key 過期後的 key-for-key 換新(BR-API-CLI-009)。

wport enterprise keys list

Flag說明
--company公司 enc_id(多公司帳號時必填)
--statusactive / expired / revoked
--output jsonAgent 友善

wport enterprise keys rotate <enc_id>

項目說明
用途以舊金鑰換新金鑰(key-for-key);active 與 expired 皆可
認證--api-key > WPORT_API_KEY > credential store;過期 key 僅此命令可過
--expiry-days可選 30 / 60 / 90;預設沿用原 key 建立時選項,或 90
輸出新明文(--output jsonapi_key 欄位);終端機預設遮罩,需 --reveal 顯示全文(寫入後建議立即更新整合)
副作用舊 key 立即失效;新 key 繼承 scope + 名稱;重設 expires_at
權限申請者角色須為 Owner/Admin/Manager(BR-016);過期 rotate 不另要求 GUI 登入

典型腳本流程(cron / CI)

# credential store 已存即將過期或剛過期的 key
wport enterprise keys rotate ck_abc123 --expiry-days 90 --output json --reveal
# → 更新環境變數 / secret manager 後,舊 key 自動失效

7. 使用者動作與後端需求(User Actions & Backend Needs)

7.1 企業 CLI

動作 ID動作類型需要後端涉及實體
ENT-1職缺 createWriteJob
ENT-2職缺 batch createWriteJob
ENT-3職缺 updateWriteJob
ENT-4職缺 publish/unpublish/deleteWriteJob
ENT-5職缺 copyWriteJob
ENT-6職缺 list(含統計)ReadJob, JobListStats
ENT-7職缺 viewReadJob
ENT-8usage 查詢ReadApiUsage
ENT-9company viewReadCompany
ENT-10company updateWriteCompany
ENT-11talents listReadTalentPoolEntry
ENT-12talents viewReadTalentPoolEntry
ENT-13talents respondWriteTalentPoolEntry, Email
ENT-14campaigns CRUD + publishWrite/ReadCampaign

7.2 Personal CLI(延後,規格預留)

動作 ID動作類型需要後端備註
PER-1~6resumes CRUD + copyWrite/ReadBR-010 上限
PER-7apply 投遞WriteBR-011 冷卻

7.3 企業 API 金鑰治理(雙軌 UI,見 DR-9)

軌道 A:企業自助(C 端 Account Settings)

動作 ID動作類型需要後端備註
KEY-A-1列出本公司金鑰ReadApiKey;O/A/M
KEY-A-2申請新金鑰(名稱 + scope + 到期)Write≤10 把 active;BR-API-CLI-004~008
KEY-A-3輪替 / 過期換新Write一次性明文;BR-API-CLI-009
KEY-A-4撤銷金鑰Write免理由;BR-API-CLI-005

軌道 B:我方 AMS 代管(admin/enterprise-api-keys

動作 ID動作類型需要後端備註
KEY-B-1列出全平台金鑰Read跨公司篩選;平台管理員
KEY-B-2代客核發(公司 + 帳號 + scope + 到期)Write四 scope 皆可;BR-API-CLI-010
KEY-B-3詳情(用量 / 稽核 log)Readpm_37 OPS
KEY-B-4改名Write
KEY-B-5輪替Write含 expired key-for-key
KEY-B-6撤銷(刪除 key)Write建議理由;任意公司
KEY-B-7調整配額 overrideWritepm_37 OPS-2

8. API Hints(提示用,非最終 API 設計)

企業職缺寫入端點繼承 pm_37 §8;以下為 pm_41 新增 REST 需求(由 RD 併入 OpenAPI)。

8.1 認證(繼承 pm_37)

  • Enterprise(公司):Authorization: Bearer wpk_live_<32>(強制到期,逾期 401)
  • Personal(延後):OAuth bearer token(device-code flow),user-scoped;不發 wpk_personal_ 金鑰

8.2 新增讀取需求

  • HINT-GET-ENT-1:職缺列表含統計(ENT-6)
  • HINT-GET-ENT-2:公司詳情(ENT-9)
  • HINT-GET-ENT-3:人才庫列表(ENT-11)— tab、job、source、keyword、date_range、分頁
  • HINT-GET-ENT-4:人才庫單筆(ENT-12)
  • HINT-GET-ENT-5:召募活動列表/詳情(ENT-14)
  • HINT-GET-ENT-6:ApiUsage 摘要(ENT-8)

8.3 新增寫入需求

  • HINT-MUT-ENT-1:公司更新(ENT-10)— payload 語義 = pm_38
  • HINT-MUT-ENT-2:人才回應/發信(ENT-13)
  • HINT-MUT-ENT-3:召募活動 CRUD + publish/unpublish(ENT-14)
  • HINT-MUT-ENT-4:職缺 copy(ENT-5)
  • HINT-MUT-ENT-5:金鑰輪替 POST .../api-keys/{enc_id}/rotate接受 active 與 expired key 作 Bearer(expired 僅此 endpoint);回新明文 + expires_at(BR-API-CLI-009)
  • HINT-ADM-KEY-1(軌道 B):GET /admin/enterprise-api-keys全平台金鑰列表(公司 / 狀態 / 帳號篩選)
  • HINT-ADM-KEY-2(軌道 B):POST /admin/enterprise-api-keys — 代客核發(公司 + 帳號 + scopes + expiry_days);四 scope 皆可
  • HINT-ADM-KEY-3(軌道 B):DELETEPOST .../revoke — 平台管理員撤銷任意 key(建議理由欄)

8.4 Personal API(延後)

  • Namespace 建議:/api/v1/personal/*
  • 履歷 CRUD、copy、apply;認證為 user-scoped key

8.5 Quota / Rate Limit(建議值)

維度預設值備註
企業月 quota5000 calls/company繼承 pm_37
分鐘 rate limit60 calls/min/key繼承 pm_37
人才庫讀取300 calls/company/day新增子限額,防爬蟲
talents respond100 sends/company/day對齊 GUI 發信限制 [RD 核對]
Batch 上限100繼承 pm_37
Idempotency TTL24h繼承 pm_37

9. 導航 / Storybook Map

9.1 企業 API 金鑰雙軌(DR-9)

軌道參考 UIStorybook用途
A 自助企業後台 → API 金鑰Mockups/公司/API 金鑰自助申請mockups-company-apikeyselfservicerecruitment header;Controls:role;單一公司、無切換;Manager「公司資訊」scope 灰階
B 我方代管W101-AMS 企業 API Key 管理Mockups/Siteadmin/EnterpriseApiKeyAdminmockups-siteadmin-enterprise-api-key-admin-demo全平台所有公司所有 key;代客核發 + 四 scope 可勾 + 撤銷 / 輪替 / 配額;平台管理員專用

9.2 其他參考 mockup

參考 UIStorybook用途
職缺列表統計recruitment dashboard mockuplist 欄位對齊
人才庫MockupTalentPoolPagefilter/tab 行為
公司編輯CompanyEditRegisterV2company update 欄位

導航 / IA — 軌道 A(mockup 裁決)

導航 / IA — 軌道 B(AMS,pm_37 延續)

  • 位置:W101-AMS 後台 → 企業 API Key 管理(非 C 端帳號設定)。
  • 操作者:僅 wport 平台管理員;可跨公司檢視與治理所有 wpk_live_ 金鑰(列表、核發、scope 勾選、撤銷刪除、輪替、配額 override)。
  • 契約 SoTdoc/feature/pm_37/enterprise-api-v1-mockup.md(AMS Key 管理 UI 見 Storybook mockups-siteadmin-enterpriseapikeyadmin);資料模型對齊 pm_41 多把 / scope / 強制到期(DR-9)。

10. Flowcharts

10.1 User Flow(企業 HR 使用 CLI)

flowchart TD
    Start([HR 安裝 @wport/cli]) --> Doctor[wport doctor]
    Doctor --> Login[wport enterprise login]
    Login --> Cmd{選擇模組}
    Cmd --> Jobs[職缺 CRUD / 上下架]
    Cmd --> Talents[人才庫 list → view → respond]
    Cmd --> Campaigns[召募活動管理]
    Cmd --> Company[公司 view / update]
    Jobs --> Check{權限 + 公司狀態}
    Check -- publish 且未驗證 --> E403[403 company_not_verified]
    Check -- OK --> OK[輸出 JSON / table]
    Talents --> Page[分頁讀取]
    Page --> NoDump[禁止 bulk export]
    Company --> Role{Owner/Admin?}
    Role -- 否 --> E403b[403 forbidden]
    Role -- 是 --> OK

10.2 System Flow(CLI 呼叫鏈)

sequenceDiagram
    participant U as User/Agent
    participant CLI as @wport/cli
    participant API as Enterprise API
    participant S as Domain Services

    U->>CLI: wport enterprise jobs publish <id> --confirm
    CLI->>CLI: 解析 key + 產生 Idempotency-Key
    CLI->>API: PATCH .../jobs/{id}/publish
    API->>API: auth + quota + idempotency
    API->>S: BR-005/008/009 檢查
    S-->>API: result
    API-->>CLI: 200 + body + rate limit headers
    CLI-->>U: table 或 JSON(exit 0)

10.3 Personal 線(延後;認證走 OAuth)

stateDiagram-v2
    [*] --> EnterpriseCLI: pm_41 交付(公司金鑰多把)
    EnterpriseCLI --> OAuthIntegration: 個人 OAuth(wport login)整合
    OAuthIntegration --> PersonalCLI: 開放 wport personal(resumes / apply)

10.4 Edge Case Coverage

類別情境系統行為CLI 回饋可重試資料一致性備註
Network逾時 > timeout中止請求exit 4 + 訊息Yes寫入未確認則重送 Idempotency
Network重複執行 writeIdempotency 去重原響應N/A無雙寫pm_37
Data缺少 —confirmCLI 本地拒絕exit 2N/A不發請求delete
Data人才庫 page_size > 100CLI 本地拒絕exit 2N/A
Authkey expired(一般 API)API 401exit 3需 rotateBR-API-CLI-008
Authexpired key 呼叫 rotateAPI 200 + 新明文exit 0N/A舊 key 失效BR-API-CLI-009
Authkey revokedAPI 401exit 3No
AuthMember 使用 enterpriseAPI 403exit 3NoBR-016
Logicalpublish 未驗證公司API 403exit 3Yes(驗證後)草稿保留BR-005
Logical統編 locked 仍 updateAPI 422exit 3Nopm_38
Logicalbatch partial successAPI 200 mixedJSON succeeded/failed失敗項 Yes成功已落地pm_37
Logicaltalents respond 超限API 429exit 3次日BR-API-CLI-003
Interruption腳本 Ctrl+C進行中請求可能完成Idempotency

11. Mock Data Schema

  • CLI 套件:對接真實 API;本地僅 credential store 與 config(mode 0600)
  • Storybook:人才庫/公司/職缺 mock 為欄位對齊參考,非 CLI runtime mock

12. 實作備註(Implementation Notes)

12.1 CLI 必做

  • 企業寫入命令自動附 Idempotency-Key(可 --idempotency-key 覆寫)
  • delete / batch--confirm 時 exit 2,不呼叫 API
  • 更新 exec-wport-cli SKILL 與 CLI 版本同步(CI check 建議)
  • 企業 key 永不 echo 全文;whoami 僅顯示尾 4 碼
  • wport enterprise keys rotate 支援 active / expired key-for-key(BR-API-CLI-009);輪替後提示更新 credential store
  • company update 檔案上傳路徑與 pm_38 媒體限制一致

12.2 後端必做(pm_41 增量)

  • 擴充 OpenAPI:talents、campaigns、company(pm_38)、jobs stats、jobs copy
  • 人才庫 endpoint 強制分頁;拒絕無 limit 查詢
  • talents respond 接入既有郵件服務 + 日限額
  • Audit log 覆蓋新 endpoint(繼承 pm_37)

12.3 禁止事項

  • ❌ 核彈 deny list 任何命令
  • talents export / 全量 dump
  • ❌ CLI 繞過 pm_37/pm_38 驗證規則
  • ❌ 在 log 明文記錄 API key

12.4 相依性

相依說明Blocking
pm_37 REST 落地職缺寫入 API 必須先存在
pm_38 公司 APIcompany update 欄位
人才庫/召募既有服務後端 domain service 重用
個人 OAuth 整合personal CLI 認證Personal 線

13. 四大一致性表格

13.1 欄位對照表

欄位語義用途SoT版本
職缺列表點擊/來訪(7d)list 統計GUI dashboard / PRD pm_41v2
publisher_display上架者GUI 刊登帳號欄v2
company.* 擴充欄位company updatepm_38v2
talent tab applied/visit人才庫MockupTalentPoolPagev2
wpk_live_ 前綴企業認證pm_37v1
個人認證OAuth(wport login,廢 wpk_personal_)pm_41 v1.2personal

13.2 常數表

常數來源版本
企業月 quota5000pm_37v1
人才庫日讀取上限300/company/daypm_41 建議v2
respond 日上限100/company/daypm_41 建議v2
履歷上限6BR-010personal
投遞冷卻72hBR-011personal
batch 上限100pm_37v1
page_size max100CLI 全域v2
破壞性操作需 —confirmpm_41v2
金鑰上限/公司≤ 10 把 active(多把具名)BR-API-CLI-004v2
金鑰到期選項30 / 60 / 90 天(強制,無永久)BR-API-CLI-008v2

13.3 事件字典

事件名觸發訂閱者
enterprise_api_call_completed各 enterprise endpointAudit(pm_37)
talent_respond_senttalents respond 成功Email + Audit
campaign_publishedcampaigns publish既有活動服務
company_api_key_issued自助 UI 核發 / 輪替公司 keyAudit(不寄金鑰明文;選配寄不含金鑰之安全提醒信,BR-API-CLI-007)
company_api_key_expired金鑰到期自動失效(BR-API-CLI-008)Audit;選配寄到期提醒(不含金鑰)

13.4 術語字典

定義
GUI parityCLI 能力邊界 = 同角色 GUI 可執行動作
核彈行為刪帳號、刪公司、轉移所有權、全量個資匯出
Enterprise CLIwport enterprise 子命令樹
Personal CLIwport personal(延後)
軌道 A企業自助 API 金鑰(C 端 Account Settings)
軌道 B我方 AMS 代管 API 金鑰(全平台列表;平台管理員)

14. 版本凍結表

項目版本Blocking?決策者日期
企業職缺 full CRUD CLIpm_41 v2Eric2026/06/22
職缺 list 統計欄位pm_41 v2Eric2026/06/22
company update(pm_38)pm_41 v2Eric2026/06/22
人才庫 list/view/respondpm_41 v2Eric2026/06/22
召募活動 CRUDpm_41 v2Eric2026/06/22
核彈 deny listpm_41 v2Eric2026/06/22
公司金鑰多把 + scope 勾選 + 強制到期 30/60/90pm_41 v1.2Eric2026/06/24
過期 key-for-key 換新(UI + CLI rotate)pm_41 v1.2.1Eric2026/06/25
企業 API 金鑰雙軌(自助 + AMS 代管)pm_41 v1.2.2Eric2026/06/25
個人金鑰廢止,個人 CLI 改 OAuthpm_41 v1.2Eric2026/06/24
Personal CLI(OAuth)personal v1❌ 延後Eric2026/06/24
talents bulk export❌ 永不Eric2026/06/22
成員管理 CLI❌ 永不Eric2026/06/22

15. Token / API 契約完整性

項目規範
雙軌治理軌道 A 自助 + 軌道 B AMS 代管並存;同一 ApiKey SoT(BR-API-CLI-010 / DR-9)
公司 key TTL強制到期 30/60/90 天(逾期 401,BR-API-CLI-008);兩軌同源
個人 key廢止;個人 CLI 改 OAuth(DR-5)
金鑰數量上限每公司 ≤ 10 把 active 具名金鑰(BR-API-CLI-004)
Rotate 輪替產生新明文(僅顯示一次)+舊金鑰立即失效+重設到期;expired key 僅 rotate endpoint 可授權(BR-API-CLI-009);單把操作不影響其他金鑰
Revoke下一請求 401;軌道 A 免填理由;軌道 B 建議填理由(稽核)
權限範圍軌道 A:申請時勾選,公司資訊 scope 限 O/A(BR-API-CLI-006);軌道 B:平台管理員四 scope 皆可勾
列表可見性軌道 A:僅本公司;軌道 B:全平台所有公司所有 key
金鑰明文傳遞僅一次性畫面顯示,絕不入信 / 不經任何管道再傳(BR-API-CLI-007)
Idempotency企業寫入必填;TTL 24h
即時權限重檢每次請求驗 key + role + company.status
人才庫 PII欄位白名單 = GUI 詳情

16. Sync-Fix List

動作OwnerBlocking?
新建 Coda 列 wport CLI v2 → PRD=pm_41PM
更新 exec-wport-cli SKILL 命令樹CLI
pm_37 OpenAPI 擴充 talents/campaigns/companyRD
pm_38 公司 API 與 CLI payload 對齊測試RD + CLI
BR-API-CLI-001~010 提案回寫 business-rules(含雙軌/多把/scope/過期換新)PM上線後
AMS EnterpriseApiKeyAdmin 對齊 pm_41 多把+scope+到期(軌道 B)RD / FE
公司 API 金鑰自助申請 UI(多把/scope/到期/role,mockup 已更新)→ 前端實作排程PM / FE
npm @wport/cli 發版與 changelogCLI

16.1 Coda 管理建議(Q4)

建議:新建獨立列,不併入 i-uL6dSrzo8o(pm_37)。

做法優點
新列 wport CLI v2交付物清楚(npm 套件 vs REST);排程獨立;相依性欄位寫 pm_37, pm_38
舊列 pm_37 不變REST API 規格不被 CLI 範圍污染

相依性 建議填:pm_37(Enterprise REST), pm_38(公司欄位), @wport/cli npm


17. Email Template

資安鐵則(BR-API-CLI-007):任何信件一律不含金鑰明文或可還原片段。金鑰明文只在建立/輪替當下的畫面顯示一次。

  • 企業 key:沿用 pm_37 §17(issued/revoked/rotated)——皆為不含金鑰之治理通知。
  • talents respond:沿用既有「企業回覆求職者」模板([RD 對齊 BR-018 既有類型])。
  • 公司 key 自助申請 / 輪替 / 撤銷 / 到期不寄含金鑰之信。可選配寄送不含金鑰的安全提醒信(「你的公司剛建立/輪替了一把 API 金鑰,若非本人請立即撤銷」「金鑰即將於 X 天後到期」)——此提醒信為選配,預設可不寄(Eric:資安考量,避免多餘信件面)。

18. PRD 問題清單

#IssueSuggested fixImpact
1BR-017 人才庫 API 細節仍待確認RD spec 階段補齊並回寫
2talents respond 日限額具體數字RD 核對 GUI 實際限制後更新 §8.5
3company 媒體上傳 CLI 介面(file vs URL)RD 決定 multipart 流程
4pm_37 尚未落地時 pm_41 排程建議 pm_37 BE 與 pm_41 CLI 並行,CLI 可先 mock server

19. 下一步(Next Steps)

  1. RD:在 pm_37 OpenAPI 新增 talents / campaigns / company / job-stats / job-copy
  2. CLI:實作 wport enterprise 命令樹並發版 @wport/cli
  3. 更新 exec-wport-cli SKILL 與版本 pin 說明
  4. QA:以「GUI parity 矩陣」驗收(同角色同動作)
  5. 個人 OAuth(wport login)整合完成後,啟動 Personal CLI 實作

附錄 A:現況 vs 目標(工程師痛點對照)

現況(exec-wport-cli)pm_41 目標
enterprise jobs list+ 統計欄位 + 完整篩選
enterprise jobs view維持
create / update / publish / unpublish / delete / copy / batch
company view / update(pm_38)
talents list / view / respond
campaigns 全套
usage
personal *規格預留,閘門後實作

文件結束