團隊機密治理(Secrets Governance)概念 PRD
這是一份概念型 PRD,不含實作與畫面。 目的是把「問題、範圍、必要能力門檻、驗收標準、營運流程」定清楚, 讓 RD 在不被預設答案綁架的前提下構思技術方案。 工具選型、部署拓撲與存取通道全數由 RD 評估後拍板;本文件只提供問題定義、必要能力門檻與比較框架。 PM 的個人傾向收斂在 §8.3 一個明確標示的「PM 觀點(非決議)」框內,RD 可逕行忽略。
1. 文件資訊
- 文件類型:概念需求規格書(Concept PRD/不含畫面與實作)
- 適用對象:RD(主要收件人)、CEO/PM、行政、未來的資安稽核
- 最後更新:2026/09/01
- 版本:1.2.0
- 對應 Storybook:不適用(本 PRD 不產畫面,見 ADR-010)
- 建立日期:2026/09/01
- PM 單號:
pm_55 - 狀態:待 RD 評估選型;§13.3 問題清單中的待決項需回填後才進入實作
1.1 修訂紀錄
| 版本 | 日期 | 摘要 |
|---|---|---|
| 1.0.0 | 2026/09/01 | 初版。Eric 提出動機(憑證散落於 Obsidian/Google Sheet/git,團隊帳密曝險)與初步構想(自架於辦公室 server + 內網 + VPN)。本版把構想拆成「必要能力門檻(不可談判)」與「部署拓撲(RD 可選)」兩層,並在撰寫過程實查 prd repo 發現一枚已 commit 的有效 Coda API token,列為 P0-1。 |
| 1.1.0 | 2026/09/01 | Eric 回覆 §13.3 兩項待決:Q-3 機密清冊擁有者=Eric;Q-5 預算=0,且「有不用錢的先處理」。預算約束實質收斂選型空間,故新增 §3.3.1(0 預算可行子集,含「三種免費只有兩種真免費」的辨別)、改寫 §8.3(建議自 T3 翻轉為 T2′:辦公室既有硬體 + Cloudflare Tunnel/Access,不自架 VPN)、新增 ADR-015(0 預算之代價:C-10 升為 binding constraint)與 ADR-016(存取通道改用 Zero Trust 取代自架 VPN)、新增 EC-16(免費層 VPS 閒置回收與保管庫流量特徵相衝)、新增 §13.0 階段 R-0(零成本立即可做)。F-8 依實查改為 gitleaks——GitHub push protection 於私有 repo 需付費。修正擴散(Rule 36):同主題另修 §3.3 VPN 列、§8.2 T2/T3/T4 三處標註、EC-3 的過期建議、§3.5 的 1Password 措辭;掃過但確認無需改動者為 EC-2(VPN 憑證循環相依,於 T2′ 下改指 Access 憑據,原文已涵蓋「VPN/Zero Trust 憑證」)、ADR-007(破窗包內容已含 Zero Trust 憑證)、§3.3 benchmark 付費方案表(保留作為預算解禁後的參考,已於 §3.3.1 標示出局)。 |
| 1.2.0 | 2026/09/01 | Eric 收回 v1.1.0 的預算約束:「不處理預算了,只做比較,後續要怎樣做交給工程師決定」。故 ADR-015(預算 0)標記 Superseded、新增 ADR-017(不以預算為選型約束;PRD 只提供比較,執行決策全數交 RD)、ADR-016 自 Accepted 降為 Proposed(Zero Trust vs VPN 屬執行決策,非 PRD 決議)。§3.3.1 自「0 預算可行子集」改寫為中性的費用結構比較(含 7 人年費試算,付費方案全數回到檯面);§8.3 自「選型建議」改寫為選型決策框架,單一建議收斂進一個明確標示的「PM 觀點(非決議)」框內。§13.0 R-0 自「零成本」改為「不需等待任何決策」——其五項本來就與預算無關。F-8 恢復為「掃描工具由 RD 選(gitleaks $0/GitHub Secret Protection 付費)」。修正擴散(Rule 36):同主題全文掃過並連帶修正 12 處——檔頭導讀 blockquote、§3.5 非目標、§8.2 的 T2/T3/T4 三處標題與註記(並拆開「放辦公室」與「走 VPN」兩個可獨立決定的維度)、EC-3、ADR-003/ADR-004 的 Decision、§13.0 R-0 標題與第 2/3/5 項、§13.2 常數表 BUDGET、版本凍結表四列、§13.3 Q-4/Q-5、§13.4 F-8/F-16/F-17、§14 D-2/D-4。掃過但刻意不改者:§1.1 的 1.1.0 修訂列與 ADR-015/ADR-016/ADR-017 的 Context——那是決策沿革,ADR 為 append-only,不得回頭改寫。 |
2. 開發進度與設計來源
開發進度
- RD 評估報告:[TBD — 見 §14 交付清單]
- 選型拍板:[TBD]
- 導入 PR/設定變更:[TBD]
設計來源
- Figma 連結:不適用(無畫面)
- 既有畫面:不適用
事實基礎(實查證據台帳)
本表是本 PRD 的證據台帳(gen-prd Rule 33)。 凡斷言「既有狀態如何」的句子,都必須在此有一列;沒有列的斷言,該句自帶
(推論,未實查)。
Repo 基準(Rule 34 preflight):
| Repo | Branch | Sha | 日期 |
|---|---|---|---|
prd | main / origin/main | 49ba279 | 2026/08/19 |
本 PRD 未讀取
W101-Web/W101-TalentSearchHub/W101-Admin-Web/W101-AMS/wport-cli。 因此所有關於「後端/前端 repo 內機密如何存放」的敘述,一律標記(推論,未實查), 並列為 RD 評估作業第一項(§14 D-1 盤點)。這是刻意的:盤點應由掌握部署的人做,不該由 PRD 猜。
斷言 → 證據:
| 事實 | 來源 |
|---|---|
prd repo 的 .env 被 git 追蹤(非 ignore),內含 CODA_API_TOKEN 等 5 個變數 | prd@49ba279 .env:1-5 |
該 .env 存在於遠端 origin/main,非僅本機 | prd@49ba279 .env(git cat-file -e origin/main:.env 成立) |
該檔案自 2026-03-24 commit 350827e 起入庫,已存在約 5 個月 | prd@350827e(git log -- .env) |
.gitignore 僅排除 **/.env.deploy,未排除 .env | prd@49ba279 .gitignore:22 |
.gitignore 已有「不得 commit 憑證」的既有意識(i18n/.npmrc 被排除並附註解) | prd@49ba279 .gitignore:44-45 |
prd repo 於 GitHub 為 private(hotfire-digital/prd) | gh repo view --json visibility → PRIVATE(2026/09/01 查) |
prd-web 以 Cloudflare Workers 部署(wrangler deploy),團隊既有技術棧已含 Cloudflare | prd@49ba279 prd-web/README.md:24、prd@49ba279 prd-web/package.json:10 |
| CI 部署憑證已存放於 GitHub Actions Secrets、未硬編碼——團隊已具備正確做法,問題是不一致,不是不會做 | prd@49ba279 .github/workflows/prd-web-deploy.yml:43-44 |
Obsidian vault 存在於本機(wport_obsidian,87 份 .md),且 gen-prd 等 skill 會直接讀取其中的 行政/wport_profile.json | /Users/Eric/Documents/obsidian/wport_obsidian(2026/09/01 查;非 git 追蹤,故無 sha) |
| Coda REST API token 為 unscoped bearer token,繼承簽發者的全部權限,非限於單一 doc | Coda API v1 官方文件(2026/09/01 查,Rule 32 廠商能力查證) |
BR-039(API 通道寫入須標記來源以供稽核)存在且為現行規則 | prd@49ba279 business-rules.md:68 |
pm_37 為 Enterprise API v1,涵蓋對外簽發之 API 金鑰 | prd@49ba279 doc/feature/README.md(索引列 pm_37) |
既有 PRD 編號已用至 pm_54(跨全部 ref 與 worktree 掃描),故本案配號 pm_55 | prd 全 ref 掃描 git ls-tree -d refs/heads refs/remotes doc/feature/ + 五個 worktree 工作目錄與未追蹤檔(2026/09/01 二次複查) |
| GitHub secret scanning/push protection 對私有 repo 需付費(GitHub Secret Protection,按 active committer 計價);免費僅及於公開 repo | GitHub 官方文件與 2026 changelog(2026/09/01 查,Rule 32 廠商能力查證) |
| Bitwarden 自架的免費 organization 上限 2 人,且座位數由 license 檔決定 | Bitwarden 官方 licensing 文件與社群 FAQ(2026/09/01 查,Rule 32) |
| Oracle Cloud Always Free 於 2026 年額度減半(約 2 OCPU/12 GB),且對「閒置」實例採回收政策 | Oracle Cloud Free Tier FAQ 與 2026/07 額度變更報導(2026/09/01 查,Rule 32) |
| gitleaks 為 MIT 授權、可作 pre-commit 與 CI 使用,$0 | gitleaks 專案授權(2026/09/01 查,Rule 32) |
⚠️ 上表第 1–4 列合起來說明的事:這不是「將來可能發生」的風險,是已經發生、且持續了 5 個月的事實。 private repo 把嚴重度從「災難」降到「中度」,但沒有降到零——見 §3.1 的爆炸半徑分析。
3. 摘要
3.1 問題陳述
現況:公司的憑證(API key、資料庫連線、SaaS 帳密、共用帳號、憑證檔)散落在至少五種載體:
| 載體 | 典型內容 | 為什麼危險 |
|---|---|---|
| Obsidian vault(純文字 Markdown) | 帳密筆記、API key、設定片段 | vault 通常同步到 iCloud/Dropbox/第三方 sync;純文字無加密;AI agent 讀得到(本 session 的 skill 就會讀 Obsidian) |
| Google Sheet | 共用帳密表、金鑰對照表 | 明文存於 Google Drive;共用連結一旦外流即全表外洩;版本歷史會保留刪除前的內容;第三方 Drive app 授權可讀 |
Git repo(.env、設定檔) | API token、連線字串 | commit 後即進入所有 clone、所有備份、所有 CI 快取;刪除 commit 不等於刪除歷史 |
| 聊天軟體(Slack/LINE/Email) | 臨時傳遞的密碼 | 永久保存、可搜尋、跨裝置同步、退出成員的裝置上仍有 |
| 個人瀏覽器/個人密碼管理器 | 公司共用帳號 | 離職時無法撤銷、無稽核、無人知道誰還握有 |
核心痛點(依嚴重度排序):
- 無法撤銷——成員離職或裝置遺失時,公司不知道他看過哪些憑證,因此不知道該輪替什麼。這是最致命的:沒有清冊,就沒有事故應變。
- 無稽核軌跡——沒有「誰在何時讀了哪一筆」的紀錄。事故發生時無法界定影響範圍。
- 明文靜態儲存——Google Sheet/Obsidian 的內容一旦被讀到就是可直接使用的憑證,沒有第二道防線。
- 爆炸半徑外溢——單一 Google 帳號被接管,等於整份憑證表外洩;單一 laptop 遺失,等於 Obsidian vault 外洩。
- 無輪替節奏——沒人知道哪一把 key 用了多久、還有沒有在用、能不能砍。
一個重要的對照:同一個 repo 裡,
prd-web的 Cloudflare 部署憑證是正確存放於 GitHub Actions Secrets 的(§2 台帳)。 也就是說團隊並非不會做,而是沒有一致的預設路徑——有現成機制的地方就做對了,沒有的地方就落回.env與試算表。 本案要提供的正是那條「預設就對」的路徑。
爆炸半徑範例(§2 台帳第 1 列的實例):prd repo 的 CODA_API_TOKEN 是 Coda 的 user-scoped token——它以「該使用者」的身分行動,可存取該使用者能存取的所有 doc,而非僅限本 repo 用到的那一份。它現在存在於:每一台 clone 過 prd 的機器、每一份 git 備份、每一個讀過該 repo 的 AI agent context、以及 GitHub 的伺服器。private repo 保護的是「外部陌生人讀不到」,不保護「內部任一成員的 GitHub 帳號被接管」,也不保護「離職者的舊 clone」。
3.2 為什麼現在做(策略理由)
不是資安潔癖,有三條具體理由:
- 我們是個資的受託人,不只是自己的。W101 平台上有僑外生的護照、居留證、工作許可、學歷等高敏感個資。一枚外洩的後端憑證=個資法層級的資料外洩事件,不是「重設密碼」等級的麻煩。這條風險與公司規模無關,與資料性質有關。
- 企業客戶會問。年費 94,080 TWD 的企業方案,客戶端(Wistron/Compal/Delta 這類)採購流程常帶資安問卷:憑證管理、存取控制、稽核保留期、離職流程。現在沒有答案;有了之後這是成交加速器,不只是成本。與
BR-039(API 通道寫入須標記來源,供稽核)是同一套治理邏輯的兩端——BR-039 管「客戶動我們的資料要留痕」,本案管「我們自己的鑰匙要留痕」。 - AI agent 已經是團隊成員。團隊日常用 Claude Code/MCP/CLI 讀 repo 與 Obsidian。明文機密放在 agent 讀得到的地方,等於每天都在把憑證送進外部模型的 context。這是傳統資安清單沒有的新風險面,而我們的工作流剛好把它放大到最大。這一條讓「以後再說」不成立。
3.3 SaaS Benchmark(候選方案概覽)
定價為 2026 年 9 月網路公開資訊,採購前必須複查官方定價頁(各家 2026 年初普遍調價)。 本表用途是「界定選項空間」,不是選型結論。選型見 §8 與 ADR-003。
Tier H — 人用憑證(Password Manager)
| 方案 | 授權/費用 | 部署 | 關鍵特性 | 主要疑慮 |
|---|---|---|---|---|
| 1Password Business | 約 USD 7.99/人/月(年繳);Teams Starter 10 人 USD 19.95/月 | 僅廠商雲(不提供自架) | Secret Key + 零知識加密;op CLI 與 op run 可注入環境變數;SCIM/SSO;稽核日誌 | 無自架選項;訂閱費;資料在境外 |
| Bitwarden Teams/Enterprise | 約 USD 4/6 人/月 | 廠商雲 或 自架(自架仍需付授權) | 開源客戶端;官方稽核;相容 Vaultwarden | 自架仍計費,成本優勢有限 |
| Vaultwarden(社群實作) | 免費(AGPL) | 僅自架 | Bitwarden 相容的輕量 Rust 伺服器;可用官方客戶端;資源需求極低 | 非官方、無 SLA、無廠商資安團隊;修補責任 100% 在我們;企業稽核故事較弱 |
| Passbolt CE/Pro | CE 免費(AGPL);Pro 約 USD 4.86–5.4/人/月 | 自架為主,亦有雲 | 為團隊設計;OpenPGP 端到端;活動稽核日誌;官方 Docker/安裝腳本;有獨立滲透測試 | 瀏覽器擴充依賴較重;使用體驗不如商用品 |
| LastPass | — | — | — | ❌ 明確排除,見 ADR-013 |
Tier M — 機器用機密(Secrets Manager)
| 方案 | 授權/費用 | 部署 | 關鍵特性 | 主要疑慮 |
|---|---|---|---|---|
| Infisical | 核心 MIT 開源;雲端免費層約 5 identities/3 projects;Pro 約 USD 18/identity/月 | 自架或雲 | CLI/env 注入 DX 佳;自架僅需 PostgreSQL + Redis | 付費以 identity 計價,CI 身分多時成本跳升快 |
| OpenBao | 完全免費(MPL 2.0,OpenSSF 治理) | 僅自架 | HashiCorp Vault 1.14 分支;動態機密、租約、PKI;Namespaces 等 Vault 企業版功能免費 | 營運負擔最重:unseal、HA、升級、稽核;7 人團隊多半用不到其威力 |
| HashiCorp Vault | BSL 授權(2023 起) | 自架或 HCP | 業界標準、生態最完整 | 授權條款 + 營運負擔;對本團隊規模過重 |
| 平台原生 secret store | 多半含在既有方案內 | 依平台 | Cloudflare Workers Secrets/GitHub Actions Secrets;可搭配 OIDC 短期憑證取代長期 key | 分散於各平台,缺統一清冊與稽核視角 |
部署與存取控制
| 方案 | 費用 | 說明 |
|---|---|---|
| Cloudflare Zero Trust | 免費層涵蓋 50 人;超過為 USD 7/人/月 | ZTNA + Tunnel,可把自架服務暴露為「需身分驗證才能到達」而不開防火牆孔。團隊既有技術棧已使用 Cloudflare,邊際學習成本低 |
| 傳統 VPN(WireGuard/OpenVPN 自架) | 免費 + 維運 | Eric 原始構想的組成部分。v1.1.0 起不建議:ADR-016 改以 Cloudflare Tunnel + Access 取代,理由見 §8.3 與 EC-2 |
3.3.1 費用結構比較(供 RD 權衡,非約束)
預算不設限(ADR-017)。本節只是把「免費」這個詞拆開——因為它在這個領域特別容易誤導。 成本與方案由 RD 於 §14 D-4 一併提出。
「免費」有三種,只有兩種是真的:
| 免費的類型 | 例子 | 對 7 人團隊是否真的 $0 |
|---|---|---|
| 開源自架軟體 | Vaultwarden、Passbolt CE、Infisical 自架、OpenBao | ⭕ 授權 $0;成本轉為維運時間 |
| 廠商免費層(額度內) | Cloudflare Zero Trust(50 人)、各平台原生 secret store、gitleaks | ⭕ 在額度內 $0 |
| 「免費版」但關鍵功能被關掉 | Bitwarden 自架 free org 上限 2 人且需 license 檔;1Password 無免費商用層;GitHub push protection 私有 repo 需付費 | ❌ 不可用 |
第三類是最容易踩到的——特別是 GitHub push protection,常被誤以為全面免費,實際上只有公開 repo 免費。
7 人團隊年費試算(依 §3.3 定價概算,匯率約 32 TWD/USD;採購前須複查官方定價頁):
| 方案 | 計價 | 7 人年費(約) | 備註 |
|---|---|---|---|
| Vaultwarden/Passbolt CE/Infisical 自架/OpenBao | 開源 | NT$0 + 維運工時 | 授權 $0;伺服器若用既有硬體則邊際成本 $0 |
| 1Password Teams Starter Pack | 10 人以下定額 USD 19.95/月 | 約 NT$7,700 | 7 人剛好落在定額內,是付費方案中單位成本最低者 |
| Bitwarden Teams | USD 4/人/月 | 約 NT$10,800 | |
| Passbolt Pro | 約 USD 4.86/人/月 | 約 NT$13,100 | |
| Bitwarden Enterprise | USD 6/人/月 | 約 NT$16,100 | |
| 1Password Business | USD 7.99/人/月 | 約 NT$21,500 | 較 Teams Starter 多出自訂角色、SCIM/AD 佈建等 |
| Infisical Pro | USD 18/identity/月 | 視機器身分數而定 | ⚠️ identity 含 CI 與服務帳號,7 人 + 10 個 CI 身分即約 NT$117,000/年,成長最快 |
| 雲端 VPS(自架用) | 約 USD 5/月起 | 約 NT$1,900 | 免費層 VPS 另有閒置回收問題,見 EC-16 |
兩個值得注意的數字:
- 1Password Teams Starter 的定額結構讓 7 人的付費門檻遠低於直覺(約 NT$7,700/年, 對照公司月 burn 470,000 TWD 約為 0.14%)。「付費 vs 免費」在這個規模下的差距, 可能小於「維運工時」的差距——這正是 RD 該權衡的地方。
- Infisical 以 identity 計價,而機器身分會隨 CI 與服務數量成長。 Tier M 若走這條,成本曲線與 Tier H 完全不同,需分開估。
3.4 範圍界定### 3.4 範圍界定
包含範圍(本 PRD 要定義的)
- 機密的分類與分級架構(哪些算 P0/P1/P2)
- 不論選哪個工具都必須滿足的必要能力門檻(§7)
- 部署拓撲選項與各自的誠實風險(§8.2)
- 生命週期營運流程:入職、離職、輪替、事故應變、破窗(§10)
- 遷移與舊副本銷毀策略(§13.0)——這是本案的重心,不是附錄
- 防回歸機制(避免半年後又回到 Google Sheet)
- 驗收標準與成功指標(§3.6)
排除範圍(明確不做)
- ❌ 不指定最終工具——選型是 RD 的評估產出(ADR-005)
- ❌ 不含任何畫面/Storybook/mockup(ADR-010)
- ❌ 不含實作細節:不定義部署腳本、網路拓撲圖、防火牆規則、DB schema
- ❌ 不自行開發保管庫(ADR-011)
- ❌ 不涵蓋 W101 平台發給客戶的 Enterprise API 金鑰——那是
pm_37的產品功能,兩者是「我們保管自己的鑰匙」vs「我們發鑰匙給客戶」,治理紀律相通但系統不同。本案僅要求:pm_37用來簽發/驗證金鑰的主密鑰(signing key)本身屬於本案的 P0 資產 - ❌ 不涵蓋端點防護(EDR/磁碟加密/MDM)——相鄰但另案
- ❌ 不涵蓋個人私人帳號——公司只管公司資產(ADR-012)
- ❌ 不做 SOC 2/ISO 27001 正式認證——本案是打底,不是送審
3.5 明確的非目標(避免 RD 誤解方向)
- 本案不是「裝一套保管庫就結束」。工具是最容易的一段;難的是 §13.0 的清查與輪替。
- 本案不是要求 RD 蓋一座 Vault 叢集。過度工程會導致沒人用,而沒人用的保管庫比沒有保管庫更危險(會產生「我們已經處理了」的錯覺)。
- 本案不追求零風險,追求的是「風險可見、可撤銷、可稽核」。
3.6 成功條件
| # | 條件 | 量測方式 | 目標 |
|---|---|---|---|
| 1 | P0 機密全數入庫且已輪替 | 對照清冊逐項核對 | 導入後 4 週內 100% |
| 2 | 舊載體零殘留 | 自動掃描 git 歷史 + 人工清查 Google Drive/Obsidian | 有效憑證 0 筆 |
| 3 | 離職撤銷與輪替時效(TTR) | 演練計時 | P0 ≤ 1 小時;全部 ≤ 24 小時 |
| 4 | 備份可還原 | 季度還原演練 | 通過率 100% |
| 5 | 不被繞道 | 新增機密走保管庫的比例 | ≥ 95% |
| 6 | 可回答資安問卷 | 企業客戶問卷的憑證管理段落 | 可據實作答,無「待補」 |
| 7 | 稽核可用 | 能回答「某帳號在某期間讀過哪些機密」 | 查詢時間 ≤ 10 分鐘 |
指標 5 是最容易被忽略、也最能預測失敗的一項。若日常取用比複製 Google Sheet 麻煩,人一定會繞道,而繞道發生時不會有人回報。因此 §7 把「CLI/自動注入」列為必要能力,不是加分項。
4. 商業規則對齊
4.1 本功能使用到的業務規則
| 規則 ID | 規則摘要 | 是否關鍵 | 備註 |
|---|---|---|---|
| BR-039 | 凡經 Enterprise API/CLI/MCP/SDK 之寫入,audit 必須標記呼叫來源 source | ⭕ 相關但非直接 | 同一套「行為必須可稽核」的治理邏輯;本案是其內部對應面 |
4.2 新規則提案
不提案新增 BR。 理由:business-rules.md 的定位是產品商業規則(平台上的使用者行為與資料約束),本案是內部營運治理,寫進去會稀釋該文件的定位。內部政策應以獨立的資安政策文件承載,由本 PRD 拍板後另行產出(§14 D-6)。
4.3 衝突檢查
已比對 business-rules.md(BR-001–BR-041):無衝突。本案不改動任何產品行為、資料模型或使用者流程。
5. 資料實體與語意(What,非 How)
本節描述「必須被追蹤的資訊」與「為什麼」,不規定欄位名、schema 或儲存方式(Rule 31)。 多數工具會自帶其中大部分;缺什麼、怎麼補,是 RD 選型時的評估項。
5.1 實體列表
| 實體 | 用途 | 為什麼需要 |
|---|---|---|
SecretRecord(機密紀錄) | 單一憑證本體 + 其中繼資料 | 保管的最小單位 |
SecretInventory(機密清冊) | 全公司機密的目錄視圖 | 事故應變的前提:不知道有什麼,就無法評估影響 |
AccessGrant(授權) | 誰/哪個身分可存取哪些機密 | 離職撤銷與最小權限的依據 |
AuditEvent(稽核事件) | 存取與變更的軌跡 | 界定外洩影響範圍 |
RotationRecord(輪替紀錄) | 某機密何時被換過、由誰、因何 | 證明「已輪替」,與「已搬家」區分 |
Identity(身分) | 人 + 機器(CI job、服務) | 機器必須有獨立身分,不得共用人的帳號 |
BreakGlassKit(破窗包) | 緊急復原憑據 | 避免「唯一管理員失聯 = 全公司鎖死」 |
5.2 各實體必須被追蹤的資訊(語意層)
SecretRecord
- 機密本體(必須加密靜態儲存,且伺服器管理者不可讀明文——見 §7 C-1)
- 分級:
P0/P1/P2(定義見 §5.3) - 擁有者:必須是具名的人,不得為「RD 部門」這類集合。無主的機密不會被輪替
- 用途說明:這把鑰匙開什麼、砍掉會壞掉什麼(輪替時的第一個問題)
- 生效範圍:正式/測試/開發
- 建立時間、最後輪替時間、下次應輪替時間
- 曾外洩註記:是否曾存在於 Google Sheet/git/聊天軟體。這一欄決定它在遷移時是「搬」還是「換」
- 消費端清單:哪些服務/CI job 正在用它(輪替時要同步更新的對象;漏掉一個就是服務中斷)
SecretInventory
- 需能回答三個問題:(a) 我們總共有幾把鑰匙?(b) 某人能看到哪些?(c) 某把鑰匙誰在用?
- 必須涵蓋不在保管庫裡的機密(例如託管在雲端平台原生 secret store 的)。清冊的價值在完整,不在集中
AccessGrant
- 授予對象(人或機器身分)、範圍、授予者、授予時間、到期時間(若為臨時)
- 臨時授權必須可設到期——承包商與外部合作方的存取若無到期日,實務上等於永久
AuditEvent
- 至少涵蓋:讀取、建立、修改、刪除、分享、授權變更、匯出、登入失敗
- 每筆需有:時間、身分、目標機密、來源(IP/裝置/CLI)、結果
- 保留期見 §13.2 常數表
AUDIT_RETENTION
RotationRecord
- 輪替時間、執行者、原因(定期/離職/疑似外洩/裝置遺失)、涉及的消費端是否已全部更新
- 「已更新全部消費端」是必填的完成條件,否則輪替只完成一半,會表現為隨機的服務中斷
Identity
- 人:一人一帳號,禁止共用登入帳號(否則稽核日誌無意義)
- 機器:CI/部署/runtime 各自獨立身分,可個別撤銷
BreakGlassKit
- 復原所需的憑據組合(主密碼/Secret Key/復原碼/解封金鑰)
- 保管形式與存放位置:實體、離線、雙人(見 ADR-007)
- 最後驗證日期——沒驗證過的破窗包等於不存在
5.3 分級定義(常數,見 §13.2 常數表)
| 分級 | 定義 | 範例 | 輪替週期 | 存取控制 |
|---|---|---|---|---|
| P0 | 外洩即造成個資外洩、金流損失或服務全面失守 | 正式資料庫連線、雲端平台 root/owner、金流閘道、簽章主密鑰、網域註冊商、GitHub org owner | 90 天或事件觸發 | 硬體金鑰 MFA;最小人數;每次存取留痕 |
| P1 | 外洩造成單一系統或第三方服務受損 | 第三方 API key、CI token、監控/通知服務、Coda/Trello token | 180 天或事件觸發 | 一般 MFA;依專案分組 |
| P2 | 外洩造成不便但無實質損害 | 內部工具帳號、共用測試帳號、非敏感 SaaS | 事件觸發即可 | 一般 MFA |
分級的用途是排優先序,不是製造官僚。導入時只要求 P0 在第一週完成,P1/P2 可分批。
6. 介面需求(能力層,非畫面規格)
本 PRD 不含畫面(ADR-010)。工具本身會提供 UI;本節只描述必須存在的能力, 供 RD 在試用候選工具時當作勾稽清單。
| 能力 ID | 能力 | 為什麼是必要 |
|---|---|---|
| UX-1 | 桌面/瀏覽器擴充可自動填入 | 沒有自動填入,人會為了方便而把密碼改成好記的、或複製到別處 |
| UX-2 | 行動裝置可存取 | 外出時拿不到 = 繞道的最大來源 |
| UX-3 | CLI 可讀取並注入環境變數 | RD 若不能 xxx run -- npm start,就會回去用 .env |
| UX-4 | 分享單一機密給指定成員,不必分享整個群組 | 否則權限只能粗放給,最小權限失效 |
| UX-5 | 搜尋與標籤 | 找不到等於不存在 |
| UX-6 | 管理者可一鍵看「某成員可存取的全部機密」 | 離職當下要立刻算出輪替清單 |
| UX-7 | 匯出全部資料為可攜格式 | 出口策略;避免廠商鎖定(§13.0 R-4) |
7. 必要能力門檻(不可談判)
這是本 PRD 對 RD 唯一的硬性約束。 工具與拓撲隨你選,但下列每一條都必須被滿足; 任一條不滿足的方案直接出局,不需進入成本比較。
| 門檻 ID | 要求 | 判定方式 | 不滿足的後果 |
|---|---|---|---|
| C-1 | 零知識/端到端加密:伺服器管理者與廠商皆不可讀明文 | 檢視架構文件與加密模型 | 自架時,取得 server 的人=取得全部機密,等於沒有第二道防線 |
| C-2 | 一人一帳號 + MFA,P0 需支援硬體金鑰或等效強度 | 實測 | 共用帳號會讓稽核日誌變成裝飾 |
| C-3 | 細緻度到「單一機密」的分權 | 實測 | 否則只能全有全無 |
| C-4 | 不可竄改的稽核日誌,含讀取事件 | 實測並匯出樣本 | 只記變更不記讀取,無法界定外洩範圍 |
| C-5 | CLI/API 可供 CI 與本機開發注入 | 實測 | 見 UX-3;這是繞道率的主要決定因素 |
| C-6 | 可即時撤銷單一身分的全部存取 | 實測計時 | 離職流程的核心 |
| C-7 | 破窗機制:管理員全部失聯時仍可復原 | 演練 | bus factor 1 是新創最常見的死法 |
| C-8 | 備份與可驗證還原 | 季度演練 | 未還原過的備份不是備份 |
| C-9 | 可攜匯出(C-1 前提下的明文匯出,需雙人或強驗證) | 實測 | 出口策略 |
| C-10 | 維運負擔與 7 人團隊相稱:無專職 SRE 仍能維持修補節奏 | RD 誠實評估:誰負責看 CVE、多久內上修補 | 這是自架方案最常失守的一條,且失守時沒有告警 |
C-10 沒有客觀判定法,只有一個誠實的問題要回答:「這台機器出現 critical CVE 的那個週五晚上,誰會去升級?」 答不出具體姓名,這條就是不滿足。
8. 部署拓撲選項(RD 拍板)
8.1 兩層分治(本 PRD 的基本架構主張)
人用憑證與機器用機密是兩個不同的問題,硬塞進同一個工具通常兩邊都不好用(ADR-001):
| Tier H — 人用 | Tier M — 機器用 | |
|---|---|---|
| 使用者 | 人(含非技術同仁:行政、業務、行銷) | CI job、部署流程、runtime 服務 |
| 取用方式 | 瀏覽器擴充、桌面 app、手機 | CLI、SDK、平台注入 |
| 主要需求 | 自動填入、易用、跨裝置 | 自動化、無人值守、可審計 |
| 輪替難度 | 低(改密碼即可) | 高(要同步更新所有消費端,否則服務中斷) |
| 適合工具 | Password Manager | Secrets Manager/平台原生 store |
Tier M 的優先策略是「不要有長期憑證」(ADR-006):能用 OIDC 聯邦換短期 token 的路徑(例:GitHub Actions → 雲端供應商),優先改用聯邦,不要把長期 key 存進保管庫再自我感覺良好。保管庫是「無法聯邦化的那些」的歸宿,不是第一選擇。這條的風險削減幅度大於任何工具選型。
8.2 拓撲候選與誠實評估
T1 — 廠商雲(零知識 E2EE)
- 代表:1Password Business、Bitwarden 雲、Passbolt Cloud
- 優點:可用性最高(不受辦公室電力/ISP 影響);修補由廠商負責;有正式稽核報告可回答客戶問卷;導入最快
- 缺點:訂閱費;資料在境外;依賴廠商存續
- 關於「雲端不安全」的反直覺事實:零知識架構下,廠商被入侵不等於保管庫被入侵。1Password 在 2023 年 Okta 事件中內部租戶遭入侵,調查結論為使用者保管庫資料未被存取——因為 Secret Key 只存在使用者裝置上,從未送到伺服器。這是「多一道防線」,不是行銷話術。
T2 — 自架於辦公室 server(Eric 的原始構想)
原始構想把「機器放辦公室」與「對外走 VPN」綁在一起。這兩者是可以分開決定的—— 存取通道另有對照表見 §8.3;下列風險表中的第 1/5 項,主要來自「走自架 VPN」而非「放辦公室」。
-
優點:資料主權完整;無訂閱費;若 VPN 設定正確,對公網攻擊面接近零;對「東西在我看得到的地方」的心理需求最直接
-
誠實風險(這些不是否決理由,是 RD 必須有答案的問題):
# 風險 具體情境 1 循環相依(bootstrap deadlock) VPN 的憑證若存在只能透過 VPN 取得的保管庫裡,第一次設定新裝置或 VPN 壞掉時就完全鎖死。必須有明確的破解方案(見 §10.4 EC-2) 2 辦公室即單點故障 停電、ISP 中斷、路由器故障、颱風、搬家 → 全員拿不到任何憑證。而災難當下正是最需要憑證的時刻(要登入雲端主控台救火) 3 修補節奏 見 C-10。自架不是把風險消除,是把風險從「廠商的資安團隊」換成「我們的週五晚上」 4 備份與異地 磁碟毀損 + 備份未驗證 = 全公司憑證歸零。備份本身也是 P0 資產,需異地且加密 5 可用性摩擦導致繞道 出差、在家、週末要連 VPN 才拿得到密碼 → 有人會「先存一份在本機方便一點」。這會讓整個專案的效果歸零,而且不會有人回報 6 硬體與維運的隱形成本 UPS、備援磁碟、監控、憑證續期、作業系統升級。名目上省下訂閱費,實際上換成人力
T3 — 自架於雲端 VPS + Cloudflare Zero Trust
- 代表:Vaultwarden/Passbolt CE/Infisical 部署於 VPS,以 Cloudflare Tunnel + Access 保護,不開防火牆孔
- 優點:保有自架的資料主權與零授權費;去掉辦公室 SPOF;可用性接近 T1;團隊既有技術棧已使用 Cloudflare(
prd-web以 Workers 部署,見 §2 台帳),Zero Trust 免費層涵蓋 50 人,邊際學習成本低 - 缺點:修補責任仍在我方(C-10 未解除);資料仍在第三方機房(主權介於 T1 與 T2 之間);多一層 Cloudflare 依賴
- 相對 T2 的關鍵差異:T3 保留了 T2 的幾乎全部優點,只換掉「機器放在辦公室」這一個決定,而那正是 T2 風險 1/2/5/6 的共同來源
- 成本註:付費 VPS 約 USD 5/月起(§3.3.1)。若考慮免費層 VPS,須注意閒置回收政策——保管庫的流量特徵正好長得像閒置,是特別糟的組合(EC-16)
T4 — 分層混合
- Tier H 與 Tier M 各自選最合適的承載方式;Tier M 以「OIDC 聯邦優先 + 平台原生 secret store + 統一清冊」承接
- 優點:各層用最合適的工具;導入可分階段;不需要一次到位
- 缺點:兩套系統,需要清冊把它們串成一個可稽核的整體(
SecretInventory的價值就在這裡) - 註:T4 嚴格說是分層原則,不是與 T1/T2/T3 並列的部署地點選項——它的意思是「Tier H 與 Tier M 各自選 T1/T2/T3 之一」。§8.3 的對照表把兩者拆開比較
8.3 選型決策框架(交 RD;本 PRD 不拍板)
依 ADR-017,本 PRD 不指定拓撲、不指定工具、不設預算上限。 本節提供的是權衡用的對照表,讓 RD 的決策有依據、也讓半年後的人看得懂當初為什麼這樣選。
四種拓撲的一頁對照:
| 面向 | T1 廠商雲 | T2 辦公室自架 | T3 雲端 VPS 自架 | T4 分層混合 |
|---|---|---|---|---|
| 授權費 | 付費(見 §3.3.1) | $0 | $0 + 主機費 | 依各層而定 |
| 維運工時 | 最低 | 最高 | 高 | 中 |
| 可用性 | 最高 | 受辦公室電力/ISP/硬體牽制 | 高 | 依各層而定 |
| 資料主權 | 廠商機房(零知識下廠商不可讀) | 完整 | 第三方機房,我方掌控 | 混合 |
| 修補責任(C-10) | 廠商 | 我方 | 我方 | 部分我方 |
| 稽核/合規故事 | 最強(有正式稽核報告) | 需自行說明 | 需自行說明 | 混合 |
| 對外攻擊面 | 廠商承擔 | 視通道設計(見下) | 視通道設計 | 混合 |
存取通道是可以與拓撲分開決定的一個維度——原始構想把「放辦公室」與「走 VPN」綁在一起,但兩者可拆:
| 通道 | 費用 | 循環相依(EC-2) | 遠端可用性摩擦(EC-8) | 維運 |
|---|---|---|---|---|
| 自架 VPN(WireGuard/OpenVPN) | $0 + 維運 | ⚠️ 有——VPN 憑證易被鎖在保管庫內 | ⚠️ 高——需客戶端與設定 | 憑證簽發與續期 |
| Cloudflare Tunnel + Access | 免費層 50 人 | ⭕ 無——以身分驗證,無憑證可鎖 | ⭕ 低——瀏覽器登入即可 | 低;新增 Cloudflare 依賴 |
| 僅限內網、不對外 | $0 | ⭕ 無 | ❌ 最高——出差完全無法取用 | 最低 |
依重視什麼來收斂:
| 若最重視… | 傾向 | 主要代價 |
|---|---|---|
| 最低維運負擔、可用性、可回答客戶資安問卷 | T1 | 年費(7 人約 NT$7,700–21,500,§3.3.1) |
| 資料完全在自己手上、零授權費 | T2 | 辦公室 SPOF + 修補責任在我方 |
| 自架但不想承擔辦公室 SPOF | T3 | 主機費 + 修補責任仍在我方;免費層有 EC-16 |
| 各層用最合適的工具、分階段導入 | T4 | 兩套系統,需清冊串起可稽核性 |
PM 觀點(非決議,RD 可逕行忽略)
若要我押一個,我會押 T4 分層 + Tier H 走 T1,理由是 §3.3.1 那張表裡的一個數字: 7 人用 1Password Teams Starter 約 NT$7,700/年,是月 burn 的 0.14%—— 而它換掉的是 C-10(誰在週五晚上升 CVE)這個沒有客觀判定法、失守時也不會有告警的風險。 這個交換在目前規模下我覺得划算。
若決定自架,我會把「放辦公室」與「走 VPN」分開看:前者合理,後者建議換成 Cloudflare Tunnel + Access——免費、不必開防火牆孔,且剛好解掉原構想中最難補的 兩項風險(EC-2 循環相依、EC-8 可用性摩擦)。這是 ADR-016 的內容,狀態為 Proposed。
以上都不是決議。RD 推翻時只需在對應 ADR 補上理由,不需要說服我。
9. 交付 Map
- 本 PRD:
doc/feature/pm_55/secrets-management-concept-prd.md - Storybook:不適用(ADR-010)
- 後續文件:RD 評估報告 → 選型 ADR 回填 → 資安政策文件(§14 D-6)
- 對應 production 路由:無(非產品功能)
10. 流程圖(Lifecycle / Operations / Edge)
本節畫的是營運流程,不是畫面流程。這些流程與選哪個工具無關, 是 RD 選型時必須確認「這個工具做得到」的清單。
10.1 機密生命週期(主流程)
flowchart TD
S1["產生新機密"] --> S2{"能否改用短期憑證<br/>OIDC 聯邦"}
S2 -->|"可以"| S3["改用聯邦,不入庫<br/>僅在清冊登記來源"]
S2 -->|"不行"| S4["入庫:設定分級、擁有者、用途、消費端"]
S4 --> S5["授權:依最小權限授予"]
S5 --> S6["使用:人由擴充取用 / 機器由 CLI 注入"]
S6 --> S7{"觸發輪替"}
S7 -->|"到期"| S8
S7 -->|"成員離職"| S8
S7 -->|"疑似外洩 / 裝置遺失"| S8
S7 -->|"停用該服務"| S9["撤銷並自清冊除役"]
S8["輪替子流程 SUB-ROT"] --> S6
S3 --> S10["定期複檢:聯邦設定是否仍最小權限"]
S10 --> S10
S9 --> S11["確認舊值已失效,非僅刪除紀錄"]
10.2 輪替子流程(SUB-ROT,被 10.1 / 10.3 / 10.4 共用)
這段是整套機制中最容易做錯的地方:多數人以為輪替=改密碼, 但漏掉任一消費端就是隨機的服務中斷,而中斷會出現在「換完之後的某一天」,很難歸因。
flowchart TD
R1["自清冊取出該機密的消費端清單"] --> R2{"清單是否完整"}
R2 -->|"不確定"| R3["先在非正式環境失效舊值<br/>觀察什麼壞掉,補完清單"]
R3 --> R2
R2 -->|"完整"| R4["產生新值"]
R4 --> R5["逐一更新所有消費端"]
R5 --> R6["驗證各消費端以新值正常運作"]
R6 --> R7{"全部通過"}
R7 -->|"否"| R8["回滾該消費端設定,舊值暫留<br/>記為未完成輪替"]
R8 --> R5
R7 -->|"是"| R9["失效舊值"]
R9 --> R10["驗證舊值確實已無效"]
R10 --> R11["寫入 RotationRecord:時間、執行者、原因、消費端已全數更新"]
10.3 入職 / 離職(人員異動)
sequenceDiagram
participant M as 主管 / PM
participant V as 保管庫
participant P as 平台與第三方服務
participant R as 輪替子流程 SUB-ROT
Note over M,R: 入職
M->>V: 建立個人帳號,強制 MFA
M->>V: 依角色授予群組,最小權限
V-->>M: 產生稽核事件 access.granted
M->>M: 說明禁止事項(見 §13.1)
Note over M,R: 離職 / 裝置遺失
M->>V: 查詢該身分可存取的全部機密(能力 UX-6)
V-->>M: 影響清單
M->>V: 撤銷該身分全部存取
M->>P: 停用該人在各平台的帳號
M->>R: 依分級對影響清單執行輪替
R-->>M: P0 於 1 小時內完成,其餘 24 小時內
Note over M: 撤銷 ≠ 輪替。只撤銷不輪替,<br/>離職者本機仍握有可用的舊值。
這張圖要傳達的唯一重點:離職流程的成本,等於那個人能看到的機密數量。 這是把「最小權限」從教條變成有價格的東西——多給一個人 P0 權限,就是多一筆離職時要在 1 小時內輪替的債。
10.4 Edge Case Coverage(必填)
| 類別 | 情境 | 系統/流程行為 | 事前準備 | 可重試 | 資料一致性策略 | ID |
|---|---|---|---|---|---|---|
| Auth & Lifecycle | 唯一管理員離職或失聯 | 以破窗包復原管理權 | 破窗包雙人保管、每季驗證(ADR-007) | Yes | 復原後立即輪替全部 P0 | EC-1 |
| Auth & Lifecycle | VPN 憑證存在只能經 VPN 取得的保管庫(T2 循環相依) | 以離線副本或獨立通道取得 VPN 憑證 | VPN/Zero Trust 憑證必須存於保管庫之外,列為破窗包內容 | Yes | 該憑證的 SoT 為破窗包,非保管庫 | EC-2 |
| Network & Performance | 辦公室停電/ISP 中斷(僅 T2 適用) | 全員無法取用 → 依破窗包救急 + 客戶端離線唯讀快取 | 此風險是 T1/T3 vs T2 取捨的實質內容之一(§8.3);若選 T2 需明確接受,並以破窗包為底線 | 視方案 | 唯讀離線快取可接受,寫入須待恢復 | EC-3 |
| Network & Performance | 保管庫服務中斷但辦公室正常 | 客戶端離線快取維持唯讀 | 選型時確認客戶端支援離線唯讀 | Yes | 恢復後以伺服器為準 | EC-4 |
| Data & Input | 磁碟毀損 + 備份從未驗證還原 | 全部機密歸零 | 季度還原演練(C-8);備份異地且加密 | No | 無備份即無一致性可言 | EC-5 |
| Logical Inconsistency | 輪替後漏改某個消費端 | 該服務在舊值失效時中斷 | SUB-ROT 的 R2/R6 雙重把關;清冊維護消費端 | Yes | 舊值於全部驗證通過後才失效 | EC-6 |
| Logical Inconsistency | 機密「已搬進保管庫」但舊副本仍在 Google Sheet | 視為未完成,且該機密已外洩 | 遷移完成條件包含「舊副本銷毀 + 已輪替」(§13.0) | Yes | 以清冊的「曾外洩註記」為準 | EC-7 |
| User Interruption | 成員嫌麻煩,私自複製一份到本機/筆記 | 無技術手段可完全阻止 | 降低摩擦是唯一解(UX-1~3);並以指標 5 監測 | N/A | 政策 + 抽查 + 週期性宣導 | EC-8 |
| Auth & Lifecycle | 成員 MFA 裝置遺失 | 依復原碼流程重建 | 復原碼於建立時即存放於保管庫以外 | Yes | 重建後檢視期間稽核日誌 | EC-9 |
| Data & Input | 誤刪機密 | 自軟刪除/版本歷史復原 | 選型時確認支援軟刪除與保留期 | Yes | 保留期見 §13.2 常數表 | EC-10 |
| Logical Inconsistency | 稽核日誌本身外洩 | 洩漏機密名稱、擁有者、使用模式(不含明文) | 日誌存取獨立授權;匯出需留痕 | N/A | 日誌屬 P1 資產 | EC-11 |
| Auth & Lifecycle | 承包商/外部合作方臨時存取 | 授予具到期日的臨時授權 | AccessGrant 支援到期(§5.2) | Yes | 到期自動撤銷,結束後輪替涉及的 P0/P1 | EC-12 |
| Network & Performance | 廠商漲價、終止服務或封鎖我方帳號 | 依可攜匯出遷出(C-9) | 每半年驗證一次匯出可用 | Yes | 匯出檔本身為 P0 資產,處理後銷毀 | EC-13 |
| Data & Input | 機密被貼進 AI agent 的 context 或聊天視窗 | 視為已外洩,立即輪替 | 明文機密不得存於 agent 讀得到的路徑(§13.1) | Yes | 清冊標記曾外洩 | EC-14 |
| Logical Inconsistency | 兩人同時編輯同一筆機密 | 以工具的版本控制解決 | 選型時確認有版本歷史與衝突處理 | Yes | 後寫入為準 + 保留歷史 | EC-15 |
| Network & Performance | 免費層雲端主機因「閒置」被回收或節流 | 保管庫無預警停止服務 | 不要把保管庫放在有閒置回收政策的免費層(§8.3 第 2 點);若不得已,需有保活與監控 | 視情況 | 破窗包為最後防線 | EC-16 |
11. Mock Data Schema
不適用。本 PRD 不含畫面與 mock(ADR-010)。
12. ADR(架構決策紀錄)
Accepted= 本 PRD 拍板,RD 不需再議。Proposed= 交由 RD 評估後拍板,拍板時請回填 Decision 與理由,Status 改為Accepted。
ADR-001: 人用憑證與機器用機密分兩層治理
- Status: Accepted
- Context: 「密碼管理器」與「機密管理器」常被當成同一件事。實際上兩者的使用者、取用方式、輪替難度都不同:人用需要自動填入與行動裝置,機器用需要 CLI 注入與無人值守;機器用機密的輪替要同步更新所有消費端,難度高一個量級。硬用同一個工具,通常是人用層被工程化到非技術同仁不敢用,或機器用層被簡化到 CI 無法自動化。
- Decision: 架構上分為 Tier H(人用)與 Tier M(機器用),兩層可用不同工具,但共用同一份機密清冊以維持稽核完整性。
- Consequences: 需要維護兩套系統與一份跨系統清冊;換得各層都能選到合用的工具,且可分階段導入。清冊若沒人維護,這個決策的價值會歸零——因此清冊擁有者必須具名(§13.3 Q-3)。
- Decision maker: Eric | Date: 2026-09-01
ADR-002: 舊副本一律視為已外洩,遷移必須連帶輪替
- Status: Accepted
- Context: 遷移時最大的誘惑是「把 Google Sheet 的內容複製進保管庫,然後刪掉 Sheet」。這在資安上等於沒做:該憑證曾以明文存在於 Google Drive、存在於版本歷史、存在於任何看過共用連結的人的瀏覽器、存在於任何被授權的第三方 Drive app。無法證明沒有人抄走。
- Decision: 凡曾存在於 Google Sheet/Obsidian/git/聊天軟體/email 的機密,一律視為已外洩,遷移時必須產生新值,不得直接搬移。清冊以「曾外洩註記」欄位追蹤。
- Consequences: 遷移成本顯著提高——這是本案工作量的主要來源,而非工具導入。但不這麼做,整個專案只是把明文換個地方放。此決策不可談判:若因工作量而妥協,請改為「分批完成」而非「降低標準」。
- Decision maker: Eric | Date: 2026-09-01
ADR-003: 部署拓撲
- Status: Proposed — 待 RD 拍板
- Context: Eric 的初步構想是自架於辦公室 server、限內網存取、對外走 VPN(拓撲 T2)。此構想的資料主權與零授權費是真優點,但帶來六項具體風險(§8.2 T2 風險表),其中循環相依(EC-2)與可用性摩擦(EC-8)最難補。候選拓撲共四種:T1 廠商雲、T2 辦公室自架、T3 雲端 VPS + Zero Trust、T4 混合。
- Decision: 待 RD 拍板。本 PRD 不預設答案(ADR-017)。四種拓撲的對照、存取通道的獨立對照、以及「重視什麼 → 傾向哪個」的收斂表,見 §8.3。PM 的個人傾向另置於 §8.3 標示為「非決議」的框內,RD 可逕行忽略。拍板時請在此補上理由與拍板人——特別是若選自架,需具名回答 Q-4(誰負責修補,C-10)。
- 沿革:v1.0.0 曾建議 T3;v1.1.0 因 0 預算改建議 T2′;v1.2.0 依 ADR-017 取消一切預設建議,回到純比較。
- Consequences: 拓撲決定可用性上限與長期維運負擔,是本案最難逆轉的決策,因此交給實際要維運的人拍板,而非由 PRD 預設。
- Decision maker: [待 RD 回填] | Date: [待回填]
ADR-004: 自架時,優先雲端 VPS + Zero Trust,而非辦公室實體機
- Status: Proposed — 待 RD 拍板(附屬於 ADR-003)
- Context: T2 的六項風險中,第 1(循環相依)、2(辦公室 SPOF)、5(可用性摩擦)、6(硬體隱形成本)四項的共同來源都是「機器放在辦公室」這一個決定,而非「自架」本身。T3 保留自架的資料主權與零授權費,同時移除該來源。團隊既有技術棧已使用 Cloudflare(§2 台帳),其 Zero Trust 免費層涵蓋 50 人,可讓自架服務不必開防火牆孔即可安全暴露。
- Decision: 待 RD 拍板(ADR-017)。本 ADR 原本主張「自架時優先雲端 VPS 而非辦公室實體機」;v1.2.0 起不再作為建議,僅保留其分析供權衡:T2 風險 1/2/5/6 的共同來源分別是「走自架 VPN」(風險 1、5)與「機器放辦公室」(風險 2、6),這兩個決定可以分開下——對照表見 §8.3。
- Consequences: 資料改放於第三方機房,主權介於 T1 與 T2 之間;多一層 Cloudflare 依賴。修補責任仍在我方,C-10 未因此解除。
- Decision maker: [待 RD 回填] | Date: [待回填]
ADR-005: 工具選型交 RD;PRD 只定能力門檻
- Status: Accepted
- Context: PM 若直接指定「就用 1Password」,會發生兩件壞事:一是繞過了實際維運者的判斷;二是當該工具在某個門檻上不合用時,沒有人有依據推翻。
- Decision: 本 PRD 定義 §7 的十條必要能力門檻(C-1~C-10)與 §3.6 的成功條件,不指定工具。RD 依門檻篩選候選、實測、提出建議並拍板。§3.3 的候選表僅為界定選項空間,非短名單。
- Consequences: 選型時程延長,換取選型品質與 RD 的擁有感(會用它的人選的,才會被用)。若 RD 評估後認為某條門檻不合理,可提案修改,但需在此 ADR 追加說明——不得默默略過。
- Decision maker: Eric | Date: 2026-09-01
ADR-006: 長期憑證優先改為短期聯邦憑證
- Status: Accepted(方向),實施範圍待 D-1 盤點後界定
- Context: 討論機密管理時的預設框架是「把 key 存到哪裡」,但風險削減幅度最大的動作其實是「讓 key 不存在」。CI 對雲端供應商的存取多半可改用 OIDC 聯邦,換發數分鐘有效的短期憑證,外洩時的價值趨近於零。存進保管庫的長期 key 仍然是長期 key。
- Decision: Tier M 的處理順序為:(1) 能聯邦化的改聯邦;(2) 不能的用平台原生 secret store;(3) 都不行的才進保管庫。三者一律登記於清冊。
- Consequences: 需要逐一改造 CI 設定,短期工作量高於「全部塞進保管庫」;但長期減少輪替負擔(聯邦憑證不需要輪替)。實際可聯邦化的比例待 D-1 盤點後才知道。
- Decision maker: Eric | Date: 2026-09-01
ADR-007: 破窗機制採實體離線 + 雙人保管
- Status: Accepted
- Context: 零知識架構的代價是「廠商也救不了你」。管理員裝置全毀、MFA 全失、唯一知情者失聯時,若無破窗包,全公司憑證即永久歸零。而破窗包若存於數位系統,多半會回到「存在被它保護的那個系統裡」的循環相依。
- Decision: 破窗包(主密碼、Secret Key/解封金鑰、復原碼、VPN/Zero Trust 憑證)以實體紙本形式,由兩位成員分別保管於不同實體位置(至少一份不在辦公室),每季驗證一次有效性並記錄驗證日期。
- Consequences: 有實體遺失與竊取風險,故需雙份、異地、且內容本身不足以單獨解鎖全部(依所選工具的機制設計)。每季驗證是必要成本——未驗證的破窗包等於不存在。
- Decision maker: Eric | Date: 2026-09-01
ADR-008: 稽核日誌保留期
- Status: Proposed — 待 RD 拍板
- Context: 保留期直接決定「事故發生後能回溯多久」。外洩經常在數月後才被發現,保留期太短則發現時已無日誌可查。但長保留期在部分工具屬付費層級,且日誌本身是敏感資產(EC-11)。
- Decision: 建議 12 個月(
AUDIT_RETENTION,§13.2)。RD 依所選工具的實際能力與成本回填,若低於 12 個月需說明補償措施(例如定期匯出至他處)。 - Consequences: 影響工具選型與方案層級;日誌本身需納入 P1 資產管理。
- Decision maker: [待 RD 回填] | Date: [待回填]
ADR-009: 明文機密的禁止載體
- Status: Accepted
- Context: 若不明確列出禁止項,「暫時放一下」會持續發生,且每次都有正當理由。
- Decision: 明文機密禁止存放或傳遞於:Google Sheet/Docs、Obsidian 或任何純文字筆記、git 追蹤的檔案、聊天軟體(Slack/LINE/Discord)、email 內文與附件、AI agent 可讀取的路徑、共用磁碟。完整清單與例外處理見 §13.1。
- Consequences: 需要提供夠方便的替代路徑(保管庫的一次性分享連結),否則禁令會被繞過。禁令與便利性必須同時交付,不得只交付禁令。
- Decision maker: Eric | Date: 2026-09-01
ADR-010: 本 PRD 不產畫面、不產 Storybook
- Status: Accepted
- Context: 本案是採購/導入既有工具與建立營運流程,不是自建產品功能。畫面由所選工具提供。
- Decision: 不產 Storybook、不畫 UI 規格。§6 只列「必須存在的能力」供選型勾稽。
- Consequences: 跳過了 gen-prd Rule 12「先讀 FE 檔案」的觸發條件,因此 Rule 33 的事實查核標準必須提高——本 PRD 的 §2 台帳明確標示未讀取實作 repo,所有相關敘述均標記
(推論,未實查),盤點交由 D-1。 - Decision maker: Eric | Date: 2026-09-01
ADR-011: 不自行開發保管庫
- Status: Accepted
- Context: 加密金鑰管理是極易做錯且錯了不會有告警的領域。7 人團隊自建保管庫的期望結果劣於任何成熟的開源方案。
- Decision: 一律採用既有方案(商用或開源),不自行開發。可以自架、可以客製整合,但核心加密與存取控制不自己寫。
- Consequences: 接受工具的既有限制與可能的廠商依賴(以 C-9 可攜匯出緩解)。
- Decision maker: Eric | Date: 2026-09-01
ADR-012: 公司機密與個人密碼分離
- Status: Accepted
- Context: 若成員把個人帳密也放進公司保管庫,離職時會產生「公司要不要保留/刪除個人資料」的爭議,且降低成員的使用意願(隱私顧慮會導致抗拒)。反之,公司帳密放在個人的私人管理器裡,公司則完全無法撤銷或稽核。
- Decision: 公司保管庫只放公司資產。多數工具提供的個人保管庫(family/personal vault)可視為福利提供,但公司不得存取、不納入稽核、離職時隨帳號一併移交或刪除,且此界線需於入職時明確說明。
- Consequences: 需在導入說明中明確劃線,避免成員誤把個人資料放進公司庫。
- Decision maker: Eric | Date: 2026-09-01
ADR-013: 明確排除 LastPass
- Status: Accepted
- Context: LastPass 於 2022 年遭入侵,攻擊者取得客戶的加密保管庫備份。由於部分帳號的主密碼強度不足且舊帳號的加密迭代次數偏低,離線暴力破解成為可行路徑,該事件的後續影響延續多年。這是「保管庫備份外洩後仍可被破解」的實例,正好是本案要避免的失效模式。
- Decision: 不將 LastPass 納入候選。
- Consequences: 縮小選項空間一項;同時把該事件當作評估其他方案時的檢查角度——要問的是「備份被偷走之後會怎樣」,不是「會不會被偷」。
- Decision maker: Eric | Date: 2026-09-01
ADR-014: prd repo 的 Coda API token 列為 P0-1,先輪替再談導入
- Status: Accepted
- Context: 撰寫本 PRD 時實查
prdrepo,發現.env被 git 追蹤且含有效的CODA_API_TOKEN,自 2026-03-24 起存在於origin/main(證據見 §2 台帳)。Coda 的 API token 為使用者層級,可存取該使用者能存取的全部 doc,範圍大於本 repo 的用途。repo 為 private,故非公開外洩,但已散布至所有 clone、備份與讀過該 repo 的 AI agent context。 - Decision: 此項不等待選型完成,立即依序處理:(1) 於 Coda 撤銷該 token 並簽發新值;(2) 自 git 追蹤移除
.env並補上.gitignore規則;(3) 檢視 Coda 端可得的存取紀錄;(4) 將此筆登記為清冊的第一個項目,標記「曾外洩」。不進行 git 歷史改寫——歷史改寫無法及於已經 clone 的副本,輪替才是有效的補救,改寫只會製造已處理的錯覺並打亂所有人的本機分支。 - Consequences: 需短暫中斷依賴該 token 的自動化(Coda backlog 同步)。此案例同時作為導入時的教材與 §3.6 指標 2 的第一個驗證點。
- Decision maker: Eric | Date: 2026-09-01
ADR-015: 預算為 0,成本改以維運時間計價
- Status: Superseded by ADR-017(2026-09-01 當日由 Eric 收回:「不處理預算了,只做比較」)
- Context: Eric 拍板預算 0,並要求「有不用錢的先處理」。這在現階段是合理的——本案的價值主要來自流程與紀律,而非工具本身,且 §3.6 的七項成功條件沒有一項需要付費功能才能達成。但 0 預算不是沒有成本,它把成本換了計價單位:所有商用託管方案出局,全部落到自架,而自架的帳單是人力。
- Decision: 採用 §3.3.1 的 $0 可行清單。同時明確承認:§7 的 C-10(無專職 SRE 仍能維持修補節奏)自此為本案的 binding constraint——它從「選型檢查項」升格為「決定本案成敗的單一因素」。
- Consequences: (1) 必須具名回答 Q-4「誰在週五晚上升級」,否則整個方案的安全性建立在無人負責的假設上;(2) 接受辦公室 SPOF(§8.3 風險 2),以破窗包(ADR-007)作為底線;(3) 若日後預算解禁,遷移至託管方案的成本很低——機密未曾以明文離開受控環境,依 C-9 匯出即可,不需重新輪替全部機密;(4) 本 ADR 不阻擋未來重議,預算是可變條件,門檻(C-1~C-10)不是。
- Decision maker: Eric | Date: 2026-09-01
- Superseded note: 本 ADR 的分析仍有效(0 預算會把成本換成維運工時,並使 C-10 成為 binding constraint),約束則已解除——預算不再是選型門檻。C-10 回復為 §7 的一般門檻,但仍是自架方案最容易失守的一條。
ADR-016: 存取通道採 Cloudflare Tunnel + Access,取代自架 VPN
- Status: Proposed — 待 RD 拍板(v1.1.0 曾為 Accepted,v1.2.0 依 ADR-017 降為建議:通道選擇屬執行決策)
- Context: 原始構想為「自架於辦公室 + 限內網 + 對外走 VPN」。其中「放辦公室」在 0 預算下是正確的(既有硬體,邊際成本 $0,且不受免費層閒置回收影響,EC-16);但「自架 VPN」帶來兩個最難補的風險:循環相依——VPN 憑證若存於只能經 VPN 取得的保管庫(EC-2);以及可用性摩擦——出差/在家/週末要先連 VPN 才拿得到密碼,而摩擦會導致繞道,繞道不會有人回報(EC-8、§3.6 指標 5)。團隊既有技術棧已使用 Cloudflare(§2 台帳),其 Zero Trust 免費層涵蓋 50 人,遠超 7 人團隊所需。
- Decision: 待 RD 評估。建議:若採自架,保管庫不對公網開放連接埠,改以 Cloudflare Tunnel 出站連線暴露,並以 Cloudflare Access 做身分驗證,不自架 VPN。對照表見 §8.3「存取通道」一節。
- Consequences: (1) 解決 EC-2 循環相依與 EC-8 可用性摩擦;(2) 無需在防火牆開孔,對外攻擊面仍接近零;(3) 新增對 Cloudflare 的依賴——Cloudflare 中斷時無法存取保管庫,以破窗包與客戶端離線唯讀快取(EC-4)緩解;(4) Access 的身分驗證憑據必須列入破窗包,不得存於它所保護的保管庫內(ADR-007、EC-2);(5) 辦公室 SPOF 仍未解決,見 ADR-015。
- Decision maker: Eric | Date: 2026-09-01
ADR-017: 不以預算作為選型約束;PRD 只提供比較,執行決策全數交 RD
- Status: Accepted(Supersedes ADR-015)
- Context: v1.1.0 曾把預算拍板為 0,據此淘汰全部付費方案並收斂出單一建議(T2′)。Eric 隨即收回此約束:「不處理預算了,只做比較,後續要怎樣做交給工程師決定」。這與本案自始的立場一致——
pm_55從第一版起就把執行交給 RD(ADR-005),v1.1.0 的預算約束其實是往回走了一步:它用一個商業條件替 RD 做掉了技術選擇。 - Decision: (1) 不設預算上限,付費與開源方案一律留在檯面,成本作為 RD 方案建議的一部分(§14 D-4)而非篩選前提;(2) PRD 的交付物是比較與門檻,不是結論——§3.3/§3.3.1/§8.2/§8.3 提供對照,§7 的 C-1~C-10 提供淘汰標準,拍板權在 RD;(3) 本 PRD 的單一建議收斂進 §8.3 明確標示的「PM 觀點(非決議)」框內,不散落於各節。
- Consequences: (1) 選型空間回復完整,RD 需自行估算成本,工作量略增(§14 D-4 恢復成本估算);(2) ADR-015 標記 Superseded,其分析保留、約束解除;(3) ADR-016 自 Accepted 降為 Proposed——通道選擇屬執行決策;(4) §13.0 的階段 R-0 不受影響,因其五項本來就與預算無關;(5) 本 ADR 不改變任何門檻:C-1~C-10、ADR-002(必須輪替)、ADR-009(禁止載體)仍為不可談判項——「執行交給 RD」指的是怎麼做,不是要不要做。
- Decision maker: Eric | Date: 2026-09-01
13. 實作備註
13.0 遷移、相容與退場(Rule 23 必填)
本節是本案真正的工作量所在。 工具導入約佔 20%,這裡佔 80%。 若時程壓縮,正確做法是縮減批次範圍(先做 P0),不是降低每一批的完成標準。
階段 R-0:不需等待任何決策,現在就能做
這五項不依賴選型、拓撲或預算——不論 RD 最後選什麼,都得做,而且都是 $0 或近乎 $0。 先做完這一段,風險就已經下降一大截。
- 輪替
prdrepo 的CODA_API_TOKEN,.env移出 git 追蹤並補.gitignore(ADR-014、F-1~F-4)。 - 導入機密掃描作為 pre-commit hook + CI 檢查,並對既有 repo 跑一次歷史掃描。工具由 RD 選:gitleaks(MIT,$0)或 GitHub Secret Protection(私有 repo 需付費,見 §2 台帳)。
- 建立機密清冊初版(D-1)。清冊只放中繼資料、不放機密本體,故可置於私有 repo 的 Markdown(載體由 RD 定,但不得公開——清冊會洩漏「我們有哪些鑰匙、誰持有」,屬 P1 資產)。擁有者:Eric(Q-3 已拍板)。
- 把「顯然沒人在用」的鑰匙砍掉。這是負成本的風險削減——砍掉的鑰匙不必保管、不必輪替、不會外洩。
- 檢視各平台既有的原生 secret store 與可聯邦化的路徑(ADR-006),先把「本來就有、只是沒用」的機制打開。
階段 R-1:盤點與分級
- 列出全部機密:git 歷史掃描、Google Drive 清查、Obsidian vault 全文檢索、各雲端平台既有 secret store、各成員自陳。
- 逐筆標記:分級(§5.3)、擁有者、用途、消費端、是否曾存在於明文載體。
- 標記「疑似已停用」者——盤點時最有價值的副產品是砍掉一批沒人在用卻仍然有效的鑰匙。能砍掉的鑰匙,就不必保管、不必輪替、不會外洩。
- 產出物:機密清冊初版(含 §3.6 指標 1/2 的基準數字)。
階段 R-2:建置與 P0 導入
- 依 ADR-003 拍板結果建置保管庫,完成備份與破窗包(ADR-007)。
- 全員建立帳號並啟用 MFA。
- P0 機密逐筆輪替後入庫(依 ADR-002,不得直接搬移),依 SUB-ROT(§10.2)執行。
- 完成第一次還原演練(C-8)與破窗包驗證。
階段 R-3:全面遷移與舊副本銷毀
-
P1/P2 分批輪替入庫。
-
舊副本銷毀,依載體採不同做法:
載體 正確做法 為什麼不能只做「刪除內容」 Google Sheet/Docs 刪除整份檔案 + 清空垃圾桶 + 撤銷共用連結 + 檢視第三方 app 授權,且該機密已輪替 清空儲存格不會刪除版本歷史;共用連結可能已被轉發;已授權的第三方 Drive app 仍可能保有副本 Obsidian vault 刪除筆記;若 vault 曾同步至第三方服務,一併檢視該服務的版本歷史;該機密已輪替 vault 多為純文字並同步至雲端;且 AI agent 可讀 Git repo 自追蹤移除 + 補 .gitignore;該機密必須輪替;不改寫歷史改寫歷史對已 clone 的副本無效,卻會打亂所有人的分支並製造「已處理」的錯覺 聊天/Email 該機密必須輪替;訊息刪除為輔助動作 訊息已同步至各成員裝置,刪除不可靠 個人密碼管理器 成員自行刪除;該機密必須輪替 無法驗證是否真的刪除 -
產出物:指標 2(舊載體零殘留)的驗證報告。
階段 R-4:防回歸與出口策略
- 導入自動化機密掃描與 push protection,讓「不小心 commit 憑證」在進入歷史前被擋下。
- 建立定期複檢節奏:季度還原演練、季度破窗包驗證、半年一次的權限複檢(誰還需要哪些)。
- 出口策略驗證:每半年執行一次完整匯出(C-9),確認可攜性仍有效。匯出檔本身為 P0 資產,驗證後銷毀。
- 將本節的節奏寫入資安政策文件(§14 D-6)。
Rollback
- 遷移期間舊值不得在新路徑驗證通過前失效(SUB-ROT 的 R7/R9 已強制此順序)。
- 若保管庫方案導入後不合用需更換:以 C-9 匯出 → 匯入新方案 → 驗證 → 銷毀匯出檔。更換工具不需要再次輪替全部機密(機密未曾以明文離開受控環境),這是 C-1 與 C-9 同時被列為門檻的原因。
相容性
- 本案不改動任何產品程式碼、資料模型或使用者流程,與既有 PRD 無功能衝突。
- 唯一的技術性變更是各服務改為自新來源取得憑證(Tier M),屬部署設定調整;影響範圍由 D-1 盤點界定。(推論,未實查——未讀取任何實作 repo,見 §2)
13.1 禁止事項
明文機密禁止存放或傳遞於以下載體(ADR-009):
- ❌ Google Sheet/Docs/Slides 或任何雲端試算表與文件
- ❌ Obsidian、Notion、Apple Notes 或任何純文字筆記系統
- ❌ git 追蹤的檔案(含
.env、設定檔、測試 fixture、註解) - ❌ 聊天軟體(Slack/LINE/Discord/Teams)
- ❌ Email 內文或附件
- ❌ AI agent 可讀取的路徑,或直接貼入 AI 對話視窗
- ❌ 共用磁碟、隨身碟、印出的紙本(破窗包為唯一例外,見 ADR-007)
- ❌ 未加密的截圖、錄影、教學文件
流程上的禁止事項:
- ❌ 共用登入帳號(會使稽核日誌失去意義,C-2)
- ❌ 只撤銷存取而不輪替(離職者本機仍握有可用的舊值,§10.3)
- ❌ 未經驗證消費端即失效舊值(會造成隨機服務中斷,EC-6)
- ❌ 把破窗包存進它所保護的系統(循環相依,EC-2)
- ❌ 以 git 歷史改寫作為外洩補救的主要手段(ADR-014)
例外處理:需臨時傳遞機密時,使用保管庫提供的一次性、有到期時間的分享連結。若所選工具不具此能力,視為 UX-4 不滿足,需在選型時補上替代方案。
13.2 一致性表(Stage 5/6)
(一)語意欄位表
| 語意欄位 | 所屬實體 | 說明 | SoT | 版本 |
|---|---|---|---|---|
| 分級 | SecretRecord | P0/P1/P2,定義見 §5.3 | 本 PRD §5.3 | v1 |
| 擁有者 | SecretRecord | 具名的人,不得為部門 | 機密清冊 | v1 |
| 用途說明 | SecretRecord | 這把鑰匙開什麼、砍掉會壞什麼 | 機密清冊 | v1 |
| 消費端清單 | SecretRecord | 正在使用此機密的服務/CI job | 機密清冊 | v1 |
| 曾外洩註記 | SecretRecord | 是否曾存在於明文載體,決定「搬」或「換」 | 機密清冊 | v1 |
| 下次應輪替時間 | SecretRecord | 依分級推算 | 保管庫工具 | v1 |
| 授權到期時間 | AccessGrant | 臨時授權必填 | 保管庫工具 | v1 |
| 破窗包最後驗證日 | BreakGlassKit | 每季更新 | 資安政策文件 | v1 |
| 輪替原因 | RotationRecord | 定期/離職/疑似外洩/裝置遺失 | 機密清冊 | v1 |
| 消費端已全數更新 | RotationRecord | 輪替的完成條件 | 機密清冊 | v1 |
| 動態機密租約 | — | 依需求動態簽發並自動到期 | 待定 | v2 |
(二)常數表
| 常數 | 值 | 說明 | SoT | 版本 |
|---|---|---|---|---|
ROTATION_P0 | 90 天 | P0 定期輪替週期 | 本 PRD §5.3 | v1 |
ROTATION_P1 | 180 天 | P1 定期輪替週期 | 本 PRD §5.3 | v1 |
ROTATION_P2 | 事件觸發 | P2 無定期要求 | 本 PRD §5.3 | v1 |
TTR_P0 | 1 小時 | 離職/外洩後 P0 完成輪替的時限 | 本 PRD §3.6 | v1 |
TTR_ALL | 24 小時 | 全部機密完成輪替的時限 | 本 PRD §3.6 | v1 |
AUDIT_RETENTION | 12 個月(建議) | 稽核日誌保留期 | ADR-008(待 RD 回填) | v1 |
BREAKGLASS_HOLDERS | 2 人 | 破窗包保管人數 | ADR-007 | v1 |
BREAKGLASS_VERIFY | 每季 | 破窗包驗證頻率 | ADR-007 | v1 |
RESTORE_DRILL | 每季 | 備份還原演練頻率 | C-8 | v1 |
EXPORT_DRILL | 每半年 | 可攜匯出驗證頻率 | §13.0 R-4 | v1 |
PERMISSION_REVIEW | 每半年 | 權限複檢頻率 | §13.0 R-4 | v1 |
SOFT_DELETE_RETENTION | 待 RD 依工具回填 | 誤刪後可復原的期間 | EC-10 | v1 |
MIGRATION_P0_DEADLINE | 導入後 4 週 | P0 全數入庫並輪替的期限 | 本 PRD §3.6 | v1 |
BUDGET | 不設限 | 預算不作為選型門檻;成本由 RD 於方案建議中提出 | ADR-017(Eric,2026-09-01) | v1 |
INVENTORY_OWNER | Eric | 機密清冊的具名維護者 | Q-3(Eric,2026-09-01) | v1 |
(三)稽核事件字典
事件名稱為語意定義,實際名稱依所選工具而定;選型時需確認工具至少涵蓋下列語意。
| 事件語意 | 觸發時機 | 必要欄位 | SoT | 版本 |
|---|---|---|---|---|
secret.read | 任何身分讀取機密明文 | 時間、身分、目標、來源 | 保管庫工具 | v1 |
secret.created | 新增機密 | 時間、身分、目標、分級 | 保管庫工具 | v1 |
secret.updated | 修改機密內容或中繼資料 | 時間、身分、目標、變更項 | 保管庫工具 | v1 |
secret.deleted | 刪除機密 | 時間、身分、目標 | 保管庫工具 | v1 |
secret.rotated | 完成輪替 | 時間、身分、目標、原因、消費端已更新 | 機密清冊 + 工具 | v1 |
secret.shared | 產生分享連結或授予他人 | 時間、身分、目標、對象、到期 | 保管庫工具 | v1 |
secret.exported | 匯出明文 | 時間、身分、範圍 | 保管庫工具 | v1 |
access.granted | 授予存取權 | 時間、授予者、對象、範圍、到期 | 保管庫工具 | v1 |
access.revoked | 撤銷存取權 | 時間、執行者、對象、範圍 | 保管庫工具 | v1 |
auth.failed | 登入失敗 | 時間、身分、來源 | 保管庫工具 | v1 |
breakglass.used | 動用破窗包 | 時間、執行者、原因 | 人工記錄 | v1 |
identity.offboarded | 成員離職流程完成 | 時間、對象、影響清單、輪替完成時間 | 人工記錄 | v1 |
(四)術語字典
| 術語 | 定義 | 常見誤用 | SoT | 版本 |
|---|---|---|---|---|
| 機密(Secret) | 任何可用於取得存取權的憑據 | 只想到密碼,漏掉 token、連線字串、簽章金鑰、憑證檔 | 本 PRD §5.1 | v1 |
| 保管庫(Vault) | 存放機密的加密系統 | 與「機密清冊」混用——清冊涵蓋不在保管庫裡的機密 | 本 PRD §5.1 | v1 |
| 機密清冊(Inventory) | 全公司機密的目錄,含不在保管庫內者 | 誤以為保管庫的列表就是清冊 | 本 PRD §5.1 | v1 |
| 撤銷(Revoke) | 移除某身分的存取權 | 誤以為撤銷等於輪替——這是本案最危險的術語混淆 | 本 PRD §10.3 | v1 |
| 輪替(Rotate) | 產生新值並使舊值失效 | 誤以為改了新值就算完成,忽略消費端更新與舊值失效 | 本 PRD §10.2 | v1 |
| 消費端(Consumer) | 正在使用某機密的服務或流程 | 盤點時漏列,導致輪替後服務中斷 | 本 PRD §5.2 | v1 |
| 破窗(Break-glass) | 管理員全部失效時的緊急復原路徑 | 存進被它保護的系統(EC-2) | ADR-007 | v1 |
| 零知識(Zero-knowledge) | 伺服器持有者無法解密使用者資料 | 誤以為「加密儲存」就是零知識 | 本 PRD §7 C-1 | v1 |
| 聯邦憑證(Federated credential) | 依身分動態換發的短期憑證 | 誤以為存進保管庫的長期 key 具同等安全性 | ADR-006 | v1 |
| 曾外洩(Compromised) | 曾以明文存在於不受控載體 | 誤以為刪掉副本就恢復乾淨 | ADR-002 | v1 |
(五)版本凍結表
| 項目 | v1/v2 | 是否 blocking | 理由 | 拍板人 | 日期 |
|---|---|---|---|---|---|
| 兩層分治架構 | v1 | 否 | ADR-001 已拍板 | Eric | 2026-09-01 |
| 舊副本視為外洩、必須輪替 | v1 | 否 | ADR-002 已拍板,不可談判 | Eric | 2026-09-01 |
| 必要能力門檻 C-1~C-10 | v1 | 否 | 本 PRD 定義完成 | Eric | 2026-09-01 |
| 部署拓撲拍板 | v1 | 是 | ADR-003 待 RD;§8.3 提供決策框架,本 PRD 不拍板(ADR-017) | 待 RD | — |
| 工具選型 | v1 | 是 | ADR-005 待 RD 評估產出;付費與開源方案皆在候選內(ADR-017) | 待 RD | — |
| 預算約束 | v1 | 否 | Eric | 2026-09-01 | |
| 存取通道(VPN vs Zero Trust) | v1 | 否 | ADR-016 降為 Proposed;屬執行決策,交 RD(ADR-017) | 待 RD | — |
| 機密清冊擁有者 | v1 | 否 | Q-3 已拍板為 Eric | Eric | 2026-09-01 |
| P0 盤點與輪替 | v1 | 否 | R-1/R-2 範圍 | Eric | 2026-09-01 |
prd repo Coda token 輪替 | v1 | 是 | ADR-014,不等選型,先行處理 | Eric | 2026-09-01 |
| 稽核保留期數值 | v1 | 否 | 建議 12 個月,RD 依工具回填(ADR-008) | 待 RD | — |
| 破窗機制 | v1 | 否 | ADR-007 已拍板 | Eric | 2026-09-01 |
| 防回歸機密掃描 | v1 | 否 | R-0 第 2 項;必須做,工具(gitleaks/GitHub Secret Protection)交 RD 選 | Eric | 2026-09-01 |
| Tier M 聯邦化改造 | v1 | 否 | 方向已定(ADR-006),範圍待 D-1 | Eric | 2026-09-01 |
| 動態機密/租約機制 | v2 | 否 | 7 人團隊現階段用不到,避免過度工程 | Eric | 2026-09-01 |
| SSO/SCIM 自動化佈建 | v2 | 否 | 團隊規模尚小,人工佈建成本低於導入成本 | Eric | 2026-09-01 |
| 正式資安認證送審 | v2 | 否 | 本案為打底,非送審(§3.4 排除範圍 8) | Eric | 2026-09-01 |
| 端點防護(EDR/MDM) | v2 | 否 | 相鄰議題,另案(§3.4 排除範圍 6) | Eric | 2026-09-01 |
13.3 PRD 問題清單
| # | 對應章節/規則 | 問題 | 建議處理 | 類別 | 影響 | SoT |
|---|---|---|---|---|---|---|
| Q-1 | §8.2、ADR-003 | 部署拓撲未拍板(T1/T2/T3/T4) | RD 評估後回填 ADR-003;本 PRD 建議 T4,自架時選 T3 | 決策 | Blocking:未定無法進入 R-2 | RD |
| Q-2 | §3.3、ADR-005 | 工具未選定,且定價為網路公開資訊 | RD 依 C-1~C-10 篩選、實測;採購前複查官方定價頁 | 決策 | Blocking | RD |
| Q-3 | §5.1、ADR-001 | ✅ 已拍板:擁有者=Eric(2026-09-01)。清冊置於私有 repo Markdown,僅中繼資料(§3.3.1) | 治理 | 已解決 | Eric | |
| Q-4 | §7 C-10 | 「誰在週五晚上升級」未有具名答案 | 若選自架,拍板時必須具名,否則 C-10 判定不成立;選託管則由廠商承擔 | 治理 | 高(自架時)——這條也是 T1/T2 取捨的實質內容 | RD |
| Q-5 | §3.3.1、ADR-017 | ✅ 已結案:不設預算上限(2026-09-01,Eric 收回 v1.1.0 的 0 預算約束)。成本改為 RD 方案建議的一部分(D-4),7 人年費試算見 §3.3.1 | 商業 | 已解決 | Eric | |
| Q-6 | §3.4、EC-12 | 承包商/外部合作方是否納入範圍未定 | 若有外部協作,需納入並確認工具支援到期授權 | 範圍 | 中 | Eric |
| Q-7 | §13.0 R-1 | 機密總量未知,工作量無法估算 | D-1 盤點為所有時程估算的前置 | 規劃 | 高 | RD |
| Q-8 | ADR-008 | 稽核保留期依所選工具可能低於 12 個月 | 若低於,需說明補償措施(定期匯出) | 決策 | 中 | RD |
| Q-9 | §5.2、EC-6 | 消費端清單的準確度無法事前保證 | 以 SUB-ROT 的 R3(非正式環境先失效觀察)補正 | 技術 | 中 | RD |
| Q-10 | §13.0 相容性 | 未讀取任何實作 repo,各服務憑證現況為推論 | 由 D-1 盤點確認;本 PRD 相關敘述已標記「推論,未實查」 | 事實查核 | 中 | RD |
| Q-11 | §3.2 | 非技術同仁(行政/業務/行銷)的導入阻力未評估 | 導入時安排實際操作演練,並以指標 5 監測繞道率 | 營運 | 中 | Eric |
| Q-12 | §3.4 排除範圍 5 | pm_37 簽發客戶 API 金鑰的主密鑰現況未查 | 納入 D-1 盤點,確認其存放位置與分級 | 事實查核 | 高 | RD |
13.4 Sync-fix list
| # | 動作 | 對應決議 | 負責 | 是否 blocking | 狀態 |
|---|---|---|---|---|---|
| F-1 | 於 Coda 撤銷現行 CODA_API_TOKEN 並簽發新值 | ADR-014 | Eric | 是(不等選型) | 待辦 |
| F-2 | prd repo:.env 自 git 追蹤移除,.gitignore 補 .env 規則 | ADR-014 | Eric | 是 | 待辦 |
| F-3 | 更新讀取該 token 的自動化設定為新值 | ADR-014 | Eric | 是 | 待辦 |
| F-4 | 檢視 Coda 端可得的 token 存取紀錄 | ADR-014 | Eric | 否 | 待辦 |
| F-5 | 執行 D-1 全面盤點,產出機密清冊初版 | §13.0 R-1 | RD | 是(阻擋時程估算) | 待辦 |
| F-6 | 完成拓撲與工具選型,回填 ADR-003/ADR-004/ADR-005/ADR-008 | Q-1、Q-2、Q-8 | RD | 是 | 待辦 |
| F-7 | 指定機密清冊具名維護者 | Q-3 | Eric | 否 | ✅ 已完成——擁有者=Eric(2026-09-01) |
| F-8 | 導入機密掃描(pre-commit + CI + 歷史掃描)。做這件事是必須的,工具由 RD 選:gitleaks($0)或 GitHub Secret Protection(私有 repo 付費) | §13.0 R-0 | RD | 否 | 待辦 |
| F-9 | 建立破窗包並完成首次驗證 | ADR-007 | Eric + RD | 是(R-2 完成條件) | 待辦 |
| F-10 | 首次備份還原演練 | C-8 | RD | 是(R-2 完成條件) | 待辦 |
| F-11 | 產出資安政策文件,承載禁止事項與定期節奏 | §14 D-6、ADR-009 | Eric | 否 | 待辦 |
| F-12 | 更新 doc/feature/README.md 索引,加入 pm_55 | 文件慣例 | Eric | 否 | ✅ 已完成(本次) |
| F-13 | 盤點 pm_37 簽發客戶 API 金鑰的主密鑰現況與分級 | Q-12 | RD | 否 | 待辦 |
| F-14 | 評估 Tier M 可聯邦化的範圍(OIDC 取代長期 key) | ADR-006 | RD | 否 | 待辦(D-1 後) |
| F-15 | Coda backlog 未回寫:coda_backlog.json 為產品 backlog 快照,本案屬內部治理,查無對應 row。若要納入追蹤需先於 Coda 建立 row,再回寫 PRD 欄位 | gen-prd Stage 9 | Eric | 否 | 已記錄,暫不回寫 |
| F-16 | 若採自架:確認 Cloudflare Zero Trust 免費層(50 人)可用於既有帳號,並確認 Tunnel 可自部署點出站 | ADR-016(Proposed) | RD | 否 | 待辦(條件性) |
| F-17 | 將存取通道的憑據(VPN 憑證或 Access 身分憑據,視 ADR-016 拍板結果)納入破窗包,不得存於保管庫內 | ADR-016、EC-2 | Eric | 是(R-2 完成條件) | 待辦 |
14. 下一步(交付 RD 的評估作業)
本 PRD 到此為止。以下是交給 RD 的作業清單,D-1 是其餘全部的前置。
| # | 作業 | 產出 | 前置 |
|---|---|---|---|
| D-1 | 全面盤點:git 歷史、Google Drive、Obsidian、各雲端平台 secret store、各成員自陳;逐筆標記分級/擁有者/用途/消費端/曾外洩 | 機密清冊初版 + 總量數字 | 無 |
| D-2 | 依 C-1~C-10 篩選候選,淘汰不滿足門檻者,不需先看價格。付費與開源皆在候選內(ADR-017) | 短名單(建議 2–3 個) | D-1 |
| D-3 | 實測短名單:以 UX-1~7 與 C-5/C-6 逐項實測,特別是 CLI 注入與「一鍵列出某成員可存取的全部機密」 | 實測報告 | D-2 |
| D-4 | 拓撲與成本評估:依 §8.3 決策框架收斂;估算三年總持有成本=授權費 + 維運工時(兩者都要,§3.3.1 有年費試算可用);若建議自架,必須具名回答 Q-4(誰負責修補) | 拓撲建議 + 成本估算 | D-3 |
| D-5 | 回填 ADR:ADR-003/ADR-004/ADR-005/ADR-008 的 Status 改為 Accepted 並補齊理由與拍板人 | 更新後的本 PRD | D-4 |
| D-6 | 產出資安政策文件:承載 §13.1 禁止事項、§13.0 R-4 的定期節奏、入職/離職檢查清單 | 資安政策文件 | D-5 |
時程建議:D-1 是唯一可以馬上開始、且不依賴任何決策的工作,建議先做。盤點本身就會產生價值——通常會找到一批沒人在用卻仍然有效的鑰匙,砍掉它們是零成本的風險削減。
現在就能開始、不需等待任何決策的一段:§13.0 的階段 R-0。其中 F-7(清冊擁有者)已拍板為 Eric,F-1~F-4(Coda token 輪替)可立即執行,F-8(機密掃描)只差選一個工具。
文件結束