FR-062 · License Management — 需求討論稿 · 2026-08-08(v2)

產品上線前的最後一塊地基:License 控管機制

Guidant AI 即將以「雲端 SaaS」與「落地部署」兩種模式對外銷售。本文件提出完整的 License 控管設計:公司內部離線簽發、產品端驗章執法、按功能模組授權、可組態到期管線、序號開通與機器綁定。十五項核心決策(D1–D15)已全數拍板,並於 v2 套入九項修訂:到期政策改為可組態管線(出廠預設「到期 → 14 天寬限 → 永久唯讀」)、簽發端初版即做極簡 Web 後台、金鑰生命週期管理、Plan 套餐範本、補發換綁流程,以及依程式碼相依實證完成的「基礎包/加值包」模組分層。

D1–D15 全數拍板(v2 含九項修訂) 出廠預設:到期 → 寬限 → 永久唯讀 基礎包+4 加值包(程式碼實證) 待確認:Plan 套餐組合與命名 待確認:分層最終圈選
§1

實作後記

本節為 2026-08-08~09 開發實作期(.1~.7 全七階段落地)後補記,記錄五項討論稿定案之後、實作過程中發生的演進,格式一律「當時討論版 → 實作後 → 為什麼變」。既有討論內容一字不動,本節純附加。

1. 照檔格式三次演進

當時討論版:只定案「Ed25519 離線簽章 license 檔」,格式為明文 JSON(v1)。

實作後:連續改了三次——

  • v2 payload 打包(T-1.3):user 驗收時提出「不想讓客戶隨手打開文字編輯器就看到照的內容」,改為信封 {format_version, kid, payload, signature}payload 為原文 zlib 壓縮+base64。
  • v3 .license armor 外皮(T-1.5):user 認為裸 .json 交付不夠專業,對齊業界(JetBrains/GitLab/Keygen)慣例改用自有副檔名+PEM 風格文字塊包裝。
  • v2.1 send_email 補旗標(T-7.3):grace/readonly 兩段到期通知信要接線時發現格式只預留了 notify 段的 send_email,順勢把 grace/readonly 也補齊同一旗標,from_dict 對舊照容忍缺鍵。

為什麼變:三次都不是推翻決策,是把「防翻閱」的產品體感做扎實——簽章防竄改(安全)跟打包防翻閱(體感)從頭到尾是兩件獨立的事,文件不可把打包/armor 誤寫成「加密」。三次都趕在下一階段消費格式之前改完,沒有留下需要回溯相容多套格式的技術債。

2. Passphrase 環境變數化

當時討論版:私鑰以 passphrase 加密保存,簽發時人工輸入 passphrase 解密。

實作後:簽發站私鑰解密改優先讀 .envLICENSE_CENTER_KEY_PASSPHRASE 環境變數,設定後簽發/展延/補發表單免手動輸入;表單欄位僅在未設環境變數時才顯示(保留 air-gapped 備援路徑)。

為什麼變:開發期簽發站部署在同一台機器,每次簽照都要手動貼 passphrase 太不順手,而且沒有增加真實風險——私鑰檔與 .env 本來就同機。這是開發/內部部署階段的權宜做法,不是正式對外簽發的保管方式——正式簽發仍須密碼管理器+兩處站外加密備份,design.md §4.9 已明確標註此界線。

3. T-5.2 線上開通提前落地(不等雲端)

當時討論版:線上開通伺服器「掛雲端環境」,雲端仍在開發中,此任務排在後面、等雲端就緒才做。

實作後:user 點破「線上開通本體就是一條 HTTP 流程(產品端 ↔︎ 開通伺服器),local 模擬(localhost 對 localhost)跟真雲端唯一差別是網址」,裁定本任務現在做、不等雲端——把「開發+全流程驗證」跟「公網部署」拆成兩件事,前者本棒完成,後者(TLS、網域、防火牆)留到雲端環境就緒後補驗。

為什麼變:機制本身不依賴雲端環境是否存在,只依賴「有個 HTTP 端點可以打」。硬把整個任務排到雲端就緒之後,等於把一個可以獨立驗證的功能無謂延後,錯失提前抓 bug 的機會。

4. 到期通知信收件人判定:三者聯集

當時討論版:到期通知信「通知租戶管理員」,未細寫怎麼判定誰是管理員。

實作後:DB 實查發現單一候選欄位(is_super_adminis_admin 角色成員/tenant.update capability 持有者)任一單獨拿來判都有覆蓋殘缺(例如某租戶只有 capability 持有者收得到),改為三者聯集;聯集結果為空的租戶 fallback 寄到 root 管理員並記警告 log。

為什麼變:討論階段「通知管理員」聽起來是單一明確概念,實作時一查 DB 才發現租戶管理員的認定在系統裡本來就有三條平行路徑、彼此覆蓋不完整——不改成聯集會有租戶到期了但沒有任何人收到通知。

5. TENANT_ADMIN_EXCLUDED_RESOURCE_TYPES 不退役(推翻原定案)

當時討論版(D12):此硬編租戶停用清單「將被 license 機制取代」,定案要退役。

實作後:T-4.3 實作者查證後拒絕退役,覆核 DB 實況後 user 接受——這份清單管的是開通租戶當下要不要預設給某個 UI 入口能力點(provisioning-time),license 管的是這個租戶商務上有沒有買某個模組(request-time)。兩個維度看起來像同一件事,實際各自獨立,license 取代不了這份清單的作用。改為兩者並存,design.md §3/§8 已同步(裁決見 CM-1126)。

為什麼變:這是本案唯一一項「討論階段的定案被實作查證推翻」的項目,值得記一筆——設計文件的判斷仰賴的是討論當下的認知,實作時對著真實程式碼與真實資料查證,才發現原本以為的「同一件事」其實是兩件事。


§2

需求背景

Guidant AI(GRC 合規管理平台)即將正式上線銷售,銷售模式有兩種:

雲端 SaaS

客戶使用公司自營的雲端環境,多租戶共用同一套系統。授權由公司在系統管理後台直接指派,客戶無感、即改即生效。

落地部署(Host 版)

整套系統部署在客戶自己的機房或私有雲。產品離開公司掌控範圍,授權必須以「不可竄改的憑證檔」形式隨產品交付,並能離線驗證。

兩種模式都需要一套 License 控管機制,核心需求為:

  1. 功能管控——root tenant(總公司/維運租戶)以外的所有租戶,其可用功能均受 license 管控;未授權的模組不出現在選單、API 拒絕存取。
  2. 簽發能力——公司能產生 license 交付客戶,客戶註冊開通後生效。
  3. 有效期管理——支援授權起訖日與訂閱制到期,到期後有明確、漸進、可預期的降級行為,而非直接鎖死。

本文件的定位

License 機制是「產品能不能收錢」的商業基礎設施,牽動簽發流程、合約條款、客服話術與續約營運。本文件將市場調查、十五項設計決策、安全信任模型、資料模型、系統接入點與階段拆分完整攤開,供決策層審閱。文中所有決策(D1–D15)均已於前期討論拍板;本版(v2)另套入九項後續拍板修訂,並將可販售模組清單依後端程式碼相依盤點改版為「基礎包/加值包」分層。

§3

市場調查摘要:業界怎麼做

在定案前,我們調查了主流商用軟體的授權機制,重點結論如下。

廠商/產品 授權機制 對本案的啟示
GitLab EE 雙軌制:線上 activation code+離線 signed license file(供 air-gapped 環境) 落地部署必須支援離線授權檔;線上與離線是同一套驗證引擎的兩種交付方式
Elastic 簽章 JSON license;到期後自動降級至免費功能層,不鎖資料 到期不直接鎖死是業界共識,避免客戶資料被扣押的觀感與合約糾紛
Atlassian Data Center 到期後擋「新增」,既有內容仍可使用 「唯讀降級」是成熟的到期緩衝設計
商用授權服務(Keygen、Cryptlex 等) 提供現成 license server、機器指紋綁定、floating seat 等 機器指紋與序號開通已是標準做法;但引入第三方服務會讓授權鏈依賴外部廠商,本案自建

業界共識可歸納為四點:

簽發私鑰絕不進產品

產品端只放公鑰做驗證。私鑰留在公司內部,客戶拿到的產品裡沒有任何可以簽發授權的材料。

到期不直接鎖死

提醒 → 寬限 → 唯讀,漸進式收斂。直接鎖死會製造合約糾紛與惡劣的續約體驗;本案出廠預設的終態即為「永久唯讀」,不鎖登入。

防護分層

簽章防竄改 → 公鑰編譯進執行檔防替換 → 時鐘回撥偵測防倒轉系統時間 → 蓄意破解(直接改產品程式碼)靠合約與稽核約束。

管理平台可以很小

簽發端與產品端分離是必要的,但簽發端不必是完整網站——一個包在 CLI 簽發引擎之上的極簡 Web 後台(客戶總覽+簽發表單)即可滿足營運,等經銷商等需求出現再演化。

§4

決策定案表(D1–D15)

以下十五項決策已全數拍板,為本案設計的權威依據。標示「v2 修訂」者為初稿後由決策者再拍板的修訂內容。

編號 決策 內容 理由
D1(v2 修訂) 簽發端與管理端分工 簽發端=公司內部簽發工具:底層為 CLI 簽發引擎(Ed25519 私鑰簽章+發照紀錄表),初版即在其上做一個極簡 Web 後台(客戶總覽頁+簽發/換發表單頁,詳見〈簽發端形態〉節);管理端=產品內 root tenant 系統管理後台(上傳、驗章、指派、各租戶授權狀態總覽)。不另建獨立管理網站 Web 後台讓非工程師(業務、維運)可自行發照與掌握客戶到期全貌;CLI 保留為底層引擎,air-gapped 簽發或緊急狀況仍可命令列操作。管理功能放主站的理由見 D15
D2 授權對象 License 綁「頂層客戶租戶」,不限使用者人數(seat);但格式預留 quota 欄位(max_users、max_projects 等),初版一律填不限 現階段以模組計價,seat 計價留為未來商業槓桿;格式先預留可免日後換版
D3 授權粒度 功能模組授權,模組粒度沿用既有權限系統的 capability.resource_type;模組的商業打包採「基礎包+加值包」分層(見〈附表:模組分層表〉),簽發端另以 Plan 套餐範本組合(見〈Plan 套餐範本〉節) 直接複用權限系統既有的資源分類,執法時 license 與 capability 兩層守門對齊同一套語彙,無需另建對照
D4 簽章與驗證 Ed25519 離線簽章 license 檔,公鑰編譯進後端程式(不放設定檔、不放資料庫),並採 kid+公鑰列表機制支援金鑰輪替(見〈金鑰生命週期管理〉節)。SaaS 與 Host 版共用同一驗證引擎:SaaS 由 root tenant 後台線上指派(內部同樣產照,客戶無感、即改即生效);Host 版的照=合約,出貨定案,續約換新照 公鑰放設定檔或資料庫等於讓落地客戶可自行替換;編譯進執行檔是業界標準防線。單一驗證引擎確保兩種銷售模式行為一致
D5(v2 修訂) 到期政策 可組態到期管線:提醒(notify)→ 寬限(grace)→ 唯讀(readonly)→ 鎖定(lockout)四段,每段各帶 {enabled, days} 開關與天數,整組 expiry_policy 簽進照內,橫幅與 email 通知也是每段的旗標。出廠預設:notify 30 天、grace 14 天、readonly 啟用且為終態、lockout 預設關閉——即預設行為是「到期 → 14 天寬限 → 永久唯讀(可登入、可看、可下載匯出檔案,擋全部寫入)」,不鎖登入。產品端無任何天數設定 天數放產品端=落地版客戶可竄改設定拉長寬限,且形成雙真相衝突。簽進照裡=單一真相來源,改預設值只影響之後簽的新照。lockout 段格式保留、預設停用:未來政策變嚴時發照打開即可,不必改版
D6 換發模式 Replace 換發制:一個租戶任一時刻只有一張現行照;續約、加購、展延一律重簽整張新照替換,舊照留歷史紀錄(稽核可查)。不採 append 疊加 多張照疊加會出現「模組 A 三月到期、模組 B 六月到期」的混合到期日,狀態機被迫 per-module 化,客服話術與客戶理解成本都會失控
D7 簽發權集中 只有公司內部能簽發(私鑰不出門);未來經銷商也透過公司簽發,需計算抽佣——發照紀錄表預留經銷商與抽佣欄位 私鑰外流等於授權體系瓦解;經銷商模式的商業結構(抽佣)先在資料上預留,流程日後再議
D8(v2 修訂) 租戶樹效力 照綁頂層客戶租戶,效力涵蓋其下全部子孫租戶;照內帶 max_sub_tenants 子租戶數上限(商業計價槓桿),預設值定為 5。平行頂層租戶只有 root tenant 能開;客戶可在額度內自行開設子租戶 客戶內部組織(子公司、部門)自然映射為子租戶,授權隨樹繼承最直覺;子租戶上限提供「集團版 vs 單公司版」的計價空間
D9 機器綁定 機器指紋:開通時取得並綁定該部署主機;續約換照時機器不變即不必重跑開通。照檔遺失與換機另有補發/換綁流程(見〈補發與換綁流程〉節) 防止一張照複製到多套部署;續約免重開通降低客戶摩擦
D10 開通方式 序號開通制,線上與離線雙路都做(實作各開 case):簽發產出「license 檔+開通序號(短碼)」→ 客戶系統首次登入偵測無照,導向開通頁 → 線上開通:輸入序號打公司開通伺服器(部署位置已定:掛雲端環境),自動下載照並回傳機器指紋;離線開通:開通頁顯示本機機器碼,客戶把序號+機器碼交給公司,公司簽出綁定該機的照回寄,客戶上傳 → 開通成功回寫發照紀錄。序號/機器碼開通流程僅 Host 版適用;SaaS 的送照管道是 root tenant 後台指派,零客戶動作(見〈開通流程〉節的兩模式對照) 線上開通體驗最好,但落地客戶常在封閉網路,離線路徑不可省。雙路共用同一張照與同一套驗證,只差交付方式
D11 照型分類 License 帶 type 欄位:formal(正式)/trial(試用)/extension(臨時展延)/transitional(過渡)。extension 應對「訂單行政流程未回簽但服務不可中斷」——抓原照只改到期日快速簽發。紀錄表標記型態,試用與展延不混入營收認列 實務上續約回簽常晚於服務到期日,沒有展延機制就會出現「合約在走流程、客戶系統先鎖住」的事故;型態標記讓財務端能區分正式營收與行政性簽發
D12(v2 修訂) 可販售模組分層 以 BE 程式碼相依盤點為據,模組分為基礎包(隨基本授權附)與四個加值包(問卷/檢測工具/雲端整合/AI 儀表板),死模組與舊架構殘留自販售清單移除,平台級模組不販售(見〈附表:模組分層表〉)。現行硬編的租戶停用清單 TENANT_ADMIN_EXCLUDED_RESOURCE_TYPES 將被 license 機制取代 逐模組圈選在工程上不成立——多數模組彼此 hard 相依,拆開賣會得到不能動的系統。分層邊界以程式碼實證劃定,加值包挑的是「關掉之後系統仍完整」的模組
D13 到期通知 系統內橫幅+email 通知租戶管理員,兩者都做;v2 修訂後兩者均為 expiry_policy 各段的旗標,簽進照內 橫幅保證登入必見,email 覆蓋不常登入的管理員;到期是收入事件,通知不嫌多
D14 既有租戶過渡 本功能上線的 migration 自動為所有既有頂層租戶(root 除外)產生過渡照:全模組、效期=上版日+90 天、type: transitional;內部環境(DEV/STG)發長效內部照。執法邏輯第一天即全量生效,無任何特例分支 「既有租戶暫時豁免」的特例分支是技術債溫床且測不到執法路徑;發過渡照讓所有租戶第一天就走同一條授權管線,90 天內完成正式照替換
D15(併入 D1) 管理功能放主站 License 管理頁放在產品內 root tenant 系統管理後台,不另建站 三個理由:①Host 版客戶機器上只有產品本身,別無他處可放;②SaaS 復用同一批頁面,成本最低;③root tenant 後台(platform-admin 權限軸)本就是特權維運功能的家
§5

整體架構

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
flowchart LR
  subgraph issuer["公司簽發端(內部,持有私鑰)"]
    WEB["極簡 Web 後台<br/>客戶總覽頁+簽發/換發表單<br/>Plan 套餐一鍵帶入"]
    CLI["簽發引擎 CLI<br/>(Ed25519 私鑰簽章)"]
    LEDGER[("發照紀錄表<br/>license_issuance<br/>訂單編號/客戶代碼/序號/型態<br/>經銷商·抽佣欄位預留")]
    ACT["線上開通伺服器<br/>(掛雲端環境)"]
    WEB --> CLI
    CLI --> LEDGER
    ACT --> LEDGER
  end

  subgraph deliver["交付物"]
    LIC["license 檔<br/>(簽章 JSON)"]
    SN["開通序號<br/>(短碼,Host 版)"]
  end

  subgraph product["產品端(SaaS / Host 版共用)"]
    ADMIN["root tenant 系統管理後台<br/>上傳/驗章/指派/狀態總覽"]
    ENGINE["License 驗證引擎<br/>公鑰列表(kid 查表)編譯進後端"]
    STORE[("tenant_licenses<br/>現行照+歷史照")]
    GUARD["授權守門<br/>common/authz 第六軸<br/>+唯讀 gate+選單/任務型態過濾"]
    CRON["每日排程<br/>到期狀態機檢查"]
    ADMIN --> ENGINE
    ENGINE --> STORE
    STORE --> GUARD
    CRON --> STORE
  end

  CLI --> LIC
  CLI --> SN
  LIC --> ADMIN
  SN -->|"線上開通(Host)"| ACT
  ACT -->|"自動下載照+回傳機器指紋"| ADMIN
圖 1 — 整體架構:公司簽發端(Web 後台+CLI 引擎)與產品端的分工與交付物

要點:

  • 私鑰只存在於左側。產品端(右側)只有公鑰列表與驗證邏輯,沒有任何簽發能力。
  • SaaS 與 Host 版是同一個右側:SaaS 的「指派」動作在公司自營環境的 root tenant 後台完成(內部同樣走簽發產照),Host 版則由客戶自行上傳照——驗證引擎、守門、狀態機完全共用。
  • 發照紀錄表是簽發端唯一的持久資料,含訂單編號與客戶代碼,供財務對帳與稽核。

簽發端形態:極簡 Web 後台(初版即做,D1 修訂)

初版即做一個公司內部小型 Web 應用,包在 CLI 簽發引擎之上(Web 是殼、CLI 是引擎),兩個頁面:

客戶總覽頁

每個客戶一列:客戶代碼/名稱/訂單編號/照型態/Plan/模組集/到期日/推算狀態/開通狀態。依臨期排序並上色,維運與業務打開就知道「誰快到期了」。

簽發/換發表單頁

選 Plan 套餐一鍵帶入模組集,可再逐模組微調;填效期產照+序號;展延(extension)一鍵完成——抓原照只改到期日。

三點誠實揭露:

  • Host 版客戶顯示的是「按合約推算」狀態,不是即時實況——照在客戶機房裡跑,簽發端只能按到期日與 expiry_policy 推算目前應處階段。有網路的 Host 客戶可經回報端點回心跳,補一欄「實際狀態」;SaaS 租戶則為真即時(照就在自家平台 DB)。
  • CLI 保留為底層引擎:air-gapped 簽發、緊急搶修時仍可純命令列操作,Web 掛了不影響簽發能力。
  • 成本影響:相較純 CLI,簽發端(階段 6)工時約 2–3 倍,換取的是非工程師可自行操作發照與續約營運,並成為未來經銷商後台的地基。
§6

信任模型與安全設計

License 機制的價值取決於「客戶繞不繞得過去」。本節誠實攤開防線與殘餘風險。

防線一:竄改照內容——驗章失敗即鎖定

客戶若直接編輯 license 檔(改到期日、開模組),Ed25519 驗章立即失敗,整張照無效,系統進入鎖定狀態(無有效照=無授權,與到期管線的可組態終態無關),並且:

  • 本地留證:記錄事件時間與檔案指紋,air-gapped 環境由維運進場時查看。
  • 有網路則回報公司端點。

原則:能通知就通知,不能通知就鎖——鎖了客戶自然會回來找

防線二:破解管理員帳號也無法自行簽發

產品內沒有私鑰、沒有簽發程式碼,只有「收照櫃台」(上傳與驗證)。即使客戶取得產品最高權限帳號,能做的也只是上傳一張照——而照必須由公司私鑰簽出。SaaS 的線上指派功能只存在於公司自營環境的 root tenant,不隨 Host 版出貨。

防線三:時鐘回撥偵測

落地客戶可能把系統時間倒轉來延長效期。對策:

  • 系統持續記錄「見過的最大時間戳」,偵測到時間倒退即判定異常。
  • license 的簽發時間不可在未來(簽發時間晚於當下系統時間即拒收)。

殘餘風險揭露

蓄意破解防不完,這是所有落地軟體的共同事實

客戶若直接修改產品程式碼(patch 掉驗證邏輯),任何技術防線都擋不住——GitLab、Atlassian 等一線廠商的落地版同樣如此。這一層的約束手段是合約與稽核:授權合約明訂禁止反向工程與規避授權,技術上留存的竄改證據(防線一)作為舉證材料。本案的技術防線目標是「讓正常客戶不會誤觸、讓一般管理員無法繞過」,不是「數學上不可破解」。

§7

金鑰生命週期管理

私鑰是整套授權體系的根,本節定義保管、輪替與應變。

私鑰保管與備份紀律

  • 私鑰檔以 passphrase 加密保存,加密備份至少兩處:公司密碼管理器/保險庫一份+離線媒介(如保險櫃內的隨身碟)一份。
  • 發照紀錄表 license_issuance 同步備份——它是「發過哪些照」的唯一權威紀錄,遺失等於失去對帳與補發依據。

簽發機器壞了怎麼辦

私鑰是檔案,不綁機器。簽發機器故障時,換一台機器裝上簽發工具、還原私鑰備份即恢復簽發能力;照的驗證完全不看簽發機器,已交付客戶的照不受任何影響。

kid+公鑰列表機制(初版就做)

為什麼初版就要做金鑰輪替的地基

若產品端只編譯一把公鑰,日後換鑰=逼全部客戶同時升級產品版本,商業上不可行。因此初版即採:

  • 產品端編譯進公鑰列表 [{kid, pubkey}](不是單一把)。
  • 照內帶 kid 欄位,驗章時按 kid 查表取對應公鑰。

輪替時:新版產品帶新舊雙鑰過渡,新照用新鑰簽、存量舊照仍能驗,客戶按自己的升級節奏走,無需同步換照。

輪替劇本與洩漏應變

情境 處置
計畫性輪替(例如每 2–3 年) 產鑰新 kid → 新版產品公鑰列表加入新鑰(保留舊鑰)→ 之後新照改用新鑰簽 → 存量照到期換發時自然轉到新鑰 → 舊鑰無存量照後,下一版移除
私鑰洩漏(急件) 立即產新鑰;緊急出版只帶新鑰的產品版本(=吊銷舊鑰);換發全部現行照(新鑰重簽)並通知客戶升級。發照紀錄表就是「哪些照要換發」的清單

誠實揭露:備份紀律是必須品

私鑰遺失且無任何備份=無法再簽發新照與續約

已發出去的照不受影響(各自跑到到期日),但公司將無法簽新照、無法續約、無法展延——等同授權營運中斷,只能換新鑰並要求全部客戶換照升級。這不是可以事後補救的風險,上述兩處備份紀律是本案的營運前提,不是建議

§8

License 檔欄位定義

License 檔為簽章 JSON,欄位分五組:

分組 欄位 說明
識別 license_id 照的唯一識別碼
customer_code 客戶代碼(對齊發照紀錄表)
order_no 訂單編號(財務對帳鏈結)
issued_to 客戶名稱
tenant 綁定 綁定的頂層客戶租戶識別
type formaltrialextensiontransitional
issuer 發照人
時間 issued_at 簽發時間(不可在未來)
starts_atexpires_at 效期起訖
expiry_policy.notify {enabled, days_before, show_banner, send_email}——到期前提醒段(出廠預設:啟用、30 天、橫幅+email)
expiry_policy.grace {enabled, days, show_banner}——寬限段(出廠預設:啟用、14 天)
expiry_policy.readonly {enabled, days?}——唯讀段;days 省略或 readonly 為終態時無期限(出廠預設:啟用、終態)
expiry_policy.lockout {enabled}——鎖定段(出廠預設:停用;格式保留,未來政策變嚴時發照打開)
功能 modules {resource_type: bool} 對映,展開後的模組清單(產品端只認這個)
plan Plan 套餐名稱標籤(如 professional);純標示用,產品端不據此執法
limits {max_sub_tenants(預設 5), max_users(預留), max_projects(預留)}
綁定 machine_fingerprint 機器指紋(開通後綁定;SaaS 不綁,留空)
deployment_mode saashost——同一 schema 同一引擎,僅以此欄位區分(host 有指紋+序號、saas 空)
完整性 kid 簽章金鑰識別碼,驗章時按 kid 查產品端公鑰列表
signaturealg Ed25519 簽章與演算法標記
§9

Plan 套餐範本(簽發端概念)

Plan 是簽發端的範本,不是產品端的概念:發照時選 Plan 一鍵帶入模組集,可再逐模組微調後簽出。

  • 照內存的是展開後的模組清單plan 名稱標籤欄;產品端只認模組清單、不認 Plan
  • 因此套餐內容日後調整只影響未來發的照,已發照完全不受影響——與 expiry_policy 天數預設值同一哲學:範本改動不回溯存量。

Plan 草案(供決策者與業務修改的起點):

Plan 內容
Basic 基礎包
Professional 基礎包+問卷包+雲端整合包
Enterprise 全模組(基礎包+全部四個加值包)
§10

開通流程

SaaS 與 Host 版的送照管道對照

序號/機器碼開通流程僅 Host 版適用。兩種模式對照如下:

SaaS Host 版
送照管道 root tenant 後台指派:簽發引擎內部產照直接寫入租戶,客戶零動作、即改即生效 交付 license 檔+開通序號,客戶走線上或離線開通
機器綁定 不綁機器指紋(照存平台 DB) 開通時綁定機器指紋(D9)
照格式 同一 schema、同一簽發引擎deployment_mode: saas(指紋與序號留空) 同一 schema,deployment_mode: host(含指紋+序號)
照的存放 簽發端紀錄表存全部(以 deployment_mode 篩選);SaaS 平台 DB 只有 SaaS 租戶的照 各 Host 環境只有自己那一張——存放天然分離,無互見風險
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
sequenceDiagram
    participant C as 客戶(管理員)
    participant P as 產品端(開通頁)
    participant S as 公司開通伺服器
    participant I as 公司簽發端(Web 後台+CLI)

    rect rgb(226, 240, 241)
    Note over I,P: 路徑 0 — SaaS:後台指派(客戶零動作)
    I->>I: root tenant 後台指派 → 簽發引擎內部產照
    I->>P: 直接寫入該租戶(不綁機器指紋)
    P->>P: 驗章 → 即改即生效
    end

    Note over I: Host 版:簽約後簽發產出 license 檔+開通序號
    I->>C: 交付開通序號(短碼)

    rect rgb(238, 242, 243)
    Note over C,S: 路徑 A — Host 線上開通
    C->>P: 首次登入,系統偵測無照 → 導向開通頁
    C->>P: 輸入開通序號
    P->>S: 序號+本機機器指紋
    S->>I: 核對序號 → 簽出綁定該機的照
    S-->>P: 回傳 license 檔(自動下載安裝)
    P->>P: 驗章 → 生效
    S->>I: 回寫紀錄:已開通+機器指紋+時間
    end

    rect rgb(251, 252, 252)
    Note over C,I: 路徑 B — Host 離線開通(封閉網路)
    C->>P: 首次登入 → 開通頁顯示本機機器碼
    C->>I: 將序號+機器碼交付公司(郵件等既有管道)
    I->>I: 簽出綁定該機器碼的照
    I->>C: 回寄 license 檔
    C->>P: 上傳 license 檔
    P->>P: 驗章+核對機器指紋 → 生效
    Note over I: 人工回寫紀錄:已開通+機器指紋+時間
    end
圖 2 — 送照時序:SaaS 內部指派+Host 版線上/離線開通(D10)

Host 兩路共用同一張照格式與同一套驗證引擎,差別只在交付方式。機器綁定(D9)在開通當下完成;日後續約換照,機器不變即不必重跑開通。線上開通伺服器掛雲端環境(決策者已定;雲端環境仍在開發中,不擋本案——離線路徑先行,見階段拆分)。

§11

SaaS 後台管理操作

root tenant 後台對 SaaS 租戶可執行的授權操作:

操作 說明
指派/變更方案 選 Plan 或逐模組調整,內部產照直接寫入,即改即生效
展延/縮短效期 重簽新照替換(D6 replace 制)
手動立即停權 SaaS 獨有能力——欠費等情況直接把租戶切唯讀或停用,不等到期日。Host 版做不到此事(照在客戶手上,只能等它到期)
檢視單一租戶狀態 現處階段、下一階段時點、模組集
§12

補發與換綁流程

Host 版照檔與機器綁定的兩種例外情境(SaaS 無此問題,照存平台 DB):

情境 A:照檔弄丟(機器沒變)

發照紀錄表存有完整照內容,一鍵重出同一張照(同內容、同機器指紋)交付客戶。紀錄表記「補發」事件,不影響營收報表(不是新簽)。

情境 B:換機(機器指紋變了)

客戶新機走一次開通流程取得新機器碼 → 公司簽出同內容、改綁新機的照 → 紀錄表記「換綁」事件,舊指紋留歷史並作廢

防複製政策:

  • 換綁人工受理——受理時確認舊機已停用,不提供自助換綁。
  • 同一客戶頻繁換綁是警訊(可能在複製部署),簽發端總覽頁對高頻換綁客戶標記提示。
§13

到期狀態機(可組態管線)

到期後的行為不再是寫死的四段,而是一條可組態管線:notify → grace → readonly → lockout 四段各自可獨立開關、各帶天數,整組 expiry_policy 簽進照內(D5 修訂)。

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
stateDiagram-v2
    [*] --> valid: 照生效
    valid --> notice: 距到期 ≤ notify.days_before(預設 30)
    notice --> grace: 到期日過(grace 啟用)
    notice --> readonly: 到期日過(grace 停用時直接唯讀)
    grace --> readonly: 寬限天數用盡(預設 14)
    readonly --> locked: lockout 啟用且 readonly.days 用盡<br/>(出廠預設 lockout 停用,此轉換不會發生)

    notice --> valid: 換發新照
    grace --> valid: 換發新照
    readonly --> valid: 換發新照
    locked --> valid: 管理員上傳新照

    valid: valid — 正常服務
    notice: notice — 全功能+到期提醒(橫幅/email 依照內旗標)
    grace: grace — 全功能+醒目警告
    readonly: readonly — 可登入·可看·可下載匯出,擋全部寫入(預設為終態)
    locked: locked — 鎖登入,僅管理員可進上傳頁(預設停用,可組態)
圖 3 — 可組態到期管線(D5 修訂):實線為出廠預設路徑(終態=永久唯讀),lockout 段預設停用

各段開關的語意

組態 行為語意
關閉 grace 到期日一過直接進唯讀,無寬限
關閉 lockout出廠預設 唯讀為終態——客戶永遠可登入、查看、下載匯出資料,只是不能寫
關閉 readonly(且 lockout 開) 寬限用盡直接鎖定(嚴格政策組合)
readonly.days 省略 唯讀無期限(readonly 為終態時的自然寫法)
全部關閉 形同永久照——簽發工具會警示(防誤簽),但不禁止(內部長效照即為此組態)
各段 show_banner / notify 的 send_email UI 橫幅與 email 通知逐段可控,一樣簽進照內

設計要點:

  • 出廠預設(決策者已定):notify 30 天 → grace 14 天 → readonly 啟用且為終態、lockout 停用。即預設行為是「到期 → 14 天寬限 → 永久唯讀(可登入、可看、可下載匯出檔案,擋全部寫入)」,不鎖登入。lockout 段格式保留、預設停用——未來政策變嚴,發照時打開即可,不必改版
  • 整組 expiry_policy 簽在照裡,產品端沒有任何可調設定。簽發端維護全系統統一預設值,改預設值只影響之後簽的新照,舊照按自己照裡的政策跑完自然收斂——不存在「改一個設定影響所有存量客戶」的風險,也杜絕落地版被客戶竄改天數。
  • locked(若啟用)不是死路:管理員永遠可以進 License 上傳頁上傳新照(防死鎖),登入端點與上傳端點在唯讀與鎖定狀態下均豁免。
  • 狀態轉換由每日排程檢查驅動(複用既有 APScheduler 機制),任何狀態換發新照即回到 valid。
§14

端到端流程

%%{init: {'theme':'base','themeVariables':{'primaryColor':'#E2F0F1','primaryTextColor':'#14201F','primaryBorderColor':'#0E7C86','secondaryColor':'#EEF2F3','secondaryTextColor':'#14201F','tertiaryColor':'#FBFCFC','tertiaryTextColor':'#14201F','lineColor':'#4A5A5C','textColor':'#14201F','mainBkg':'#E2F0F1','nodeBorder':'#0E7C86','nodeTextColor':'#14201F','edgeLabelBackground':'#FBFCFC','titleColor':'#14201F','clusterBkg':'#FBFCFC','clusterBorder':'#E4EAEB','actorBkg':'#E2F0F1','actorTextColor':'#14201F','actorBorder':'#0E7C86','actorLineColor':'#C7D1D2','signalColor':'#4A5A5C','signalTextColor':'#14201F','labelBoxBkgColor':'#EEF2F3','labelBoxBorderColor':'#C7D1D2','labelTextColor':'#14201F','loopTextColor':'#14201F','noteBkgColor':'#F6EBD5','noteTextColor':'#14201F','noteBorderColor':'#9C6B12','activationBkgColor':'#EEF2F3','activationBorderColor':'#C7D1D2','sequenceNumberColor':'#FFFFFF'}}}%%
flowchart LR
  A["① 簽約<br/>訂單成立<br/>(訂單編號·客戶代碼)"] --> B["② 簽發<br/>Web 後台選 Plan 產照+序號<br/>寫入發照紀錄表"]
  B --> C["③ 交付<br/>Host:照=合約隨貨<br/>SaaS:後台直接指派"]
  C --> D["④ 開通(Host)<br/>線上或離線<br/>綁定機器指紋"]
  D --> E["⑤ 使用<br/>模組守門·子租戶額度<br/>每日狀態檢查"]
  E --> F["⑥ 到期<br/>notice → grace → readonly<br/>(出廠預設終態=永久唯讀)"]
  F --> G["⑦ 續約換發<br/>重簽整張新照替換<br/>舊照留歷史"]
  G --> E
  F -.->|"訂單未回簽<br/>但服務不可中斷"| H["臨時展延照<br/>type: extension<br/>只改到期日"]
  H --> E
圖 4 — 端到端:簽約 → 簽發 → 交付 → 開通 → 使用 → 到期 → 續約換發(D6 replace 制;到期段依出廠預設,終態=永久唯讀)
§15

資料模型草案

兩端各一張表起步,刻意極簡:

簽發端:發照紀錄表 license_issuance

公司內部持有,是財務對帳與稽核的權威紀錄,也是 Web 後台客戶總覽頁的資料源。

欄位群 欄位 說明
商務識別 order_no(訂單編號)customer_code(客戶代碼)、客戶名 決策層明確要求必含前兩欄,對帳鏈結
授權內容 tenant 識別、開通序號、typedeployment_mode、Plan 標籤、模組集、expiry_policy、到期日 簽進照裡的內容留檔;補發(情境 A)即據此重出同一張照
開通狀態 機器指紋(開通後回寫)、開通時間、換綁歷史(舊指紋作廢紀錄) 線上路徑自動回寫、離線路徑人工回寫;頻繁換綁於總覽頁標記
通路(預留) 經銷商欄位、抽佣欄位 D7:未來經銷商模式的資料先留位
稽核 發照人、時間戳、事件類別(新簽/換發/展延/補發/換綁)

產品端:tenant_licenses

欄位群 欄位 說明
綁定 tenant_id 頂層客戶租戶
照本體 license 原文 逐次驗章的依據(不信任解析快取)
快取 解析後欄位快取 模組集、到期日、expiry_policy 等,供守門快速讀取
狀態 validnoticegracereadonlylocked 每日排程更新;哪些狀態可達由照內 expiry_policy 決定
歷史 is_current 旗標(或歷史表) D6:舊照留存供稽核
稽核 上傳人、上傳時間

產品端狀態機由每日排程檢查(複用 core/scheduler.py 既有 APScheduler cron 樣板,比照 framework_parse_job_cleanup 的寫法)。

§16

系統接入點盤點

本案不是從零長出一套機制,而是掛進既有骨架。逐點盤點如下:

元件 現況 本案動作
common/authz/ FR-048 建立的統一授權守門,現有五軸(platform-admin / super-admin / project-role / capability / signed-token) 新增第六軸 license.py:照抄 capability.py 的 guard+decorator+flask.g memoize 樣板;root tenant 經 viewer_is_platform_admin() 無條件豁免
capability.resource_type 權限系統的資源分類(見附表分層盤點) 作為 license 模組粒度來源(D3);現行硬編停用清單 TENANT_ADMIN_EXCLUDED_RESOURCE_TYPESapp/auth/service/tenant_provisioning_service.py將被 license 機制取代
api/grcapi/project capability 守門 目前零 capability 守門(技術債,見附表 callout) license 執法前必須補守門,否則「沒買 project」API 層擋不住
任務型態選單 GrcJobType enum 寫死(common/enum/grc_job_type_enum.pyapi/grc/serializers/job.py 任務型態下拉按租戶授權動態過濾——沒買問卷包的租戶不可選到問卷任務
ui_route 選單過濾 選單項由 ui_routes 動態組出(api/auth/routes/ui_route_route.py 為樣板) 未授權模組的選單項直接隱藏,使用者不會看到點了才報錯的按鈕
core/scheduler.py 既有 APScheduler,已有每日 cron 前例(framework_parse_job_cleanup 新增每日 cron 檢查各租戶照的到期狀態轉換
唯讀執法 readonly 狀態下全域攔截 POST/PUT/PATCH/DELETE 回 403;License 上傳端點與登入端點豁免(防死鎖);下載匯出類 GET 不受影響
config 現有 ENV class 只有基礎設施參數,無部署形態語意 新增 DEPLOYMENT_MODEsaashost)概念,供驗證引擎區分行為(如機器指紋是否必綁)
§17

使用情境

以下以虛構客戶「宏遠科技」(customer_code:HY-001)走五個情境,說明機制在真實營運中的樣貌。

情境一:落地版發照與開通

宏遠採購 Host 版 Professional 方案,訂單編號 SO-2026-0142。業務結單後,維運在簽發 Web 後台的簽發表單選 Plan「Professional」(自動帶入基礎包+問卷包+雲端整合包)、填效期一年,產出:license 檔(綁宏遠頂層租戶、展開後的模組集與出廠預設 expiry_policy 簽入照內)+開通序號,發照紀錄表自動新增一筆(含訂單編號與客戶代碼)。宏遠機房是封閉網路,走離線開通:IT 人員首次登入被導向開通頁,抄下畫面上的機器碼,連同序號寄回公司;公司簽出綁定該機的照回寄;IT 上傳,驗章通過即全功能生效。發照紀錄表回寫「已開通+機器指紋+時間」。

情境二:到期全過程(出廠預設政策)

宏遠的照 2027-08-31 到期,假設未續約,依出廠預設 expiry_policy(notify 30/grace 14/readonly 終態/lockout 停用),時間軸如下:

日期 狀態 系統行為
2027-08-01 notice(到期前 30 天) 橫幅出現「授權將於 8/31 到期」+email 通知租戶管理員
2027-09-01 grace(寬限 14 天) 全功能照常,橫幅升級為醒目警告「授權已到期,9/14 後進入唯讀」
2027-09-15 起 readonly終態 可登入、可查看、可下載匯出資料;所有寫入操作被擋(403)。lockout 段預設停用,不會進一步鎖登入

過程中任一天完成續約、上傳新照,立即回到 valid。客戶資料自始至終可登入查看與匯出,不存在「資料被扣押」的爭議空間;若未來對特定客群需要更嚴格的政策,發照時啟用 lockout 段即可。

情境三:公司調整到期政策預設值

2027 年公司決定把寬限期從 14 天改為 7 天。維運只改簽發端的 expiry_policy 預設值——之後簽的新照帶 grace 7 天;宏遠等存量客戶手上的照仍是 14 天,按原條件跑到換照為止。沒有任何存量客戶的行為在無預警下改變,也沒有產品端設定要同步。

情境四:臨時展延(訂單未回簽)

宏遠 2027 年續約,採購流程卡在用印,回簽日眼看晚於 8/31 到期日。業務向維運申請展延照:Web 後台展延一鍵——抓原照內容、只把到期日改為 9/30、type: extension 簽出。宏遠上傳後服務不中斷;紀錄表標記為展延、不計入營收。正式訂單回簽後,再簽正式新照替換。

情境五:客戶偷改照被鎖

宏遠某工程師嘗試直接編輯 license 檔,把到期日改成 2099 年。下一次驗證時 Ed25519 簽章比對失敗,整張照判定無效,系統進入鎖定並在本地記錄事件(時間、檔案指紋);該環境若可連外即回報公司端點。宏遠管理員發現系統鎖定後聯繫公司,維運調出竄改留證,依合約處理,重新提供正確的照恢復服務。(此為「無有效照」的鎖定,與到期管線的可組態終態無關。)

§18

階段拆分(可獨立驗證、隨時可中斷)

拆分原則(決策者明確要求)

每階段自帶可觀察產出與人工測試素材——測試資料由前一階段產出,不依賴任何未完成的後續階段;階段 1–3 對現有系統零侵入,中途暫停不留任何風險;執法最後才進場,且帶環境開關可整體關閉。任何一個階段結束都是一個安全的暫停點。

階段 內容 人工測法 依賴
階段 1 簽發端獨立先行:Ed25519 產鑰/簽章引擎+CLI 產照+發照紀錄表 跑 CLI 產照、驗簽章、查紀錄表。完全不碰主產品
階段 2 產品端驗照與狀態顯示(只讀不執法):tenant_licenses 表+上傳/驗章+狀態頁 拿階段 1 的照上傳,看解析與狀態顯示。不影響既有任何功能 階段 1(要有照可上傳)
階段 3 狀態機排程與橫幅(仍不擋操作):每日 cron+階段推算+橫幅顯示 發一張短效照(2 天)觀察狀態轉換與橫幅變化 階段 1+2
階段 4 執法進場(帶環境開關可整體關閉):authz 第六軸守門+api/grcapi/project 補 capability 守門+唯讀 gate+任務型態動態過濾+選單過濾 測試租戶驗「擋/不擋」、開關切換前後行為對照 階段 1–3
階段 5 開通流程:離線開通先行(case A)、線上開通後續(case B——開通伺服器掛雲端環境,決策者已定;雲端仍在開發中,不擋本案) 走一輪機器碼→簽照→上傳→綁定;線上路徑待雲端就緒後補測 階段 1+2(要有照與序號可開通)
階段 6 簽發 Web 後台(包在階段 1 的 CLI 引擎上):客戶總覽頁+簽發/換發表單頁 用總覽頁核對既有發照紀錄、走表單簽一張照與 CLI 結果比對 階段 1(引擎與紀錄表)
階段 7 email 通知+過渡照 migration(D14,上版前最後執行 短效照觸發通知信;DEV 先跑 migration 驗過渡照產出 階段 3(狀態機事件);migration 為上版動作
§19

附表:模組分層表(D12 修訂)

v1 的逐模組圈選表已廢止。本次依 BE 程式碼相依盤點(2026-08-08,唯讀分析)改為「基礎包/加值包」分層——分層邊界不是商業直覺,而是程式碼實證:基礎包缺一系統不成立,加值包關掉系統仍完整

基礎包(隨基本授權附)

缺一系統不成立、或屬支撐資料/一般營運的模組,共 21 個:

projectmodule-framecompliance-frameworkworkflowflow_templateauditdeviceinformation-systemdashboardreportproject-summary-reportuserroledepartmenttenantbulletinbulletin-listfeedbackfeedback-viewnotify_configstorage-config

關鍵相依證據(為何不能拆開賣):

相依事實 程式碼座標
開專案 hard 依賴 module-frame 三件組 clone——沒有 module-frame 就開不了專案 app/project/service/project_start_app_service.py:335-344
flow engine(workflow/flow_template)是任務執行骨幹,缺了專案是空殼 app/grc/service/prep_job_generation_service.py
device/information-system 是 SSP 受評範圍的支撐資料 app/grc/service/project_service.py:299-316
dashboard SQL 串 6 個模組的資料,缺一歸零 infra/grc/repository/grc_dashboard_repo_impl.py:185-201

加值模組(4 包,邊界經程式碼實證)

加值包 內含 resource_type 邊界實證
問卷包 survey 解鎖專案的問卷型任務。job_service 對 survey 為 hard 相依但方向單純——未授權時把任務型態選單過濾掉即可,不影響其他任務型態
檢測工具包 remote-agent-managedetection-profileplugin三合一,不拆賣 detection 任務鏈三者 hard 綁定(app/grc/service/job_service.py:131-135detection_orchestration_service.py),拆開任一都是壞的半套
雲端整合包 cloud_integration 全系統邊界最乾淨:Drive 為 best-effort 同步層,證據上傳有本地保底(app/flow_engine/service/job_evidence_service.py:85-88),關掉零影響
AI 儀表板包 ai-dashboard 技術獨立,registry 為靜態表;未授權時模組呈空圖表,需在選單/入口過濾

自販售清單移除

resource_type 移除理由
resource 死模組——無任何程式引用、已停用、報告腳本已標記刪除
cruise-project 舊架構殘留,非現行產品功能

平台級(維持不販售)

issue-integrate-configldap-configsmtp-configlogsystem-menusystem_config 共 6 個,is_platform 全標記,僅 root tenant 使用。

販售前必補技術債

🔴 以下四項是 license 執法的前置工程,屬本案工程範圍的一部分

  1. api/grcapi/project 目前零 capability 守門——意即「沒買 project」在 API 層根本擋不住,只是選單看不到。license 執法必須先把守門補齊(納入階段 4)。
  2. GrcJobType enum 寫死common/enum/grc_job_type_enum.pyapi/grc/serializers/job.py:173-177,209-213)——任務型態下拉需按租戶授權動態過濾,否則沒買問卷包的租戶選得到問卷任務,選了會卡死在 SURVEY_INCOMPLETE 永遠完成不了。
  3. job_import_service.py:31VALID_JOB_TYPES 與 enum 不同步(缺 detection_tool)——既有小 bug,本案順手修。
  4. workflow resource_type 語意釐清:現行租戶停用清單停掉的是舊 UI 入口的能力點,flow engine 引擎本身照常運作——license 切分時不可誤把引擎關掉(引擎屬基礎包骨幹)。
§20

待確認事項

留待決策的三件事

  1. Plan 套餐組合與命名:Basic/Professional/Enterprise 草案(見〈Plan 套餐範本〉節)為工程端起點,組合內容與命名請決策者與業務最終確認。
  2. 基礎包/加值包分層最終圈選:分層邊界已依程式碼相依實證劃定(見附表),商業面是否照此打包、加值包是否再合併或拆分,待最終確認。
  3. 過渡照效期:現定上版日+90 天(D14),數字可調,於階段 7 migration 前定案即可。

已定案、自待確認清單移除:子租戶上限預設值=5(D8);lockout 段預設關閉、唯讀為出廠終態(D5);線上開通伺服器掛雲端環境(D10)。

FR-062 · License 控管機制 — 需求討論稿 · 2026-08-08 v2(套入九項拍板修訂+BE 模組相依盤點)· v1 2026-08-08 初稿 · 模組盤點自 DEV 資料庫 public.capabilities 與 BE 程式碼相依分析(唯讀查詢,2026-08-08)