這頁怎麼維護
- 每支套件的即時狀態(已發版/待補殼/退役中)看 design.md §8.3 逐套件狀態表——那裡是維護主體,本頁只記分族不記狀態,避免兩處同一事實漂移。
- 分族有變動時才改這頁:新抽一支套件歸入某族、或某支套件改族(罕見)。
- 第四階段各棒收口後,若該棒的成果推翻了某族的判準(例如 detection 走服務化而非插件),回頭改對應族的「形態」欄並在此註記。
架構手冊 · 套件分類 · living
這頁回答「這支套件屬於哪一類、為什麼跟那支不是同一支」。分類是給判斷用的——新能力要抽套件時照這張表找族群、找同族的先例照抄;但同一族不代表可以合併,那是兩件事(見「同類型≠同疆界」)。決策全文在 FR-069 站的 design.md §3 決策表。
套件到了二十支,光看名字已經看不出關係——jedi-iam、jedi-integrity、jedi-oscal-v2 擺在一起,像是同一層的三個東西,實際上一個是「每個產品都要的身分底座」、一個是「只有落地版才裝的營運元件」、一個是「產品核心價值本身」。三者的發版節奏、誰該裝、壞掉的後果完全不同。
分類要回答的是三個實際問題:
要抽一支新套件時,先找它屬於哪一族,照該族既有的先例抄——不必每次重新想「這個要不要自帶 api 層」「要不要 port 化」。
不是每個產品都要裝二十支。分族之後可以說「新產品至少要身分族+基座」「落地版才要加落地營運服務族」。
同族的套件壞掉的後果相近——基座壞了全停、落地營運服務壞了可降級繼續跑。這決定值不值得為它做高可用。
「這兩支要不要合併」——那是疆界問題不是分類問題,判準完全不同(見下節)。
這是本頁最容易被誤用的一點,先講清楚。
分類看「長得像不像」,疆界看「是不是同一件事」——兩者無關
jedi-integrity(防篡改)與 jedi-license-runtime(授權驗證)同屬落地營運服務族:都只有落地版會裝、都在啟動時把關、壞了都會擋住服務。但它們不是同一個疆界——防篡改管「這包程式有沒有被改過」、授權管「這個客戶有沒有買」,兩件事各自獨立演化,合併只會得到一支「安裝時做很多事」的雜物袋。
反過來也成立:問卷設計(jedi-survey)與作答層(主專案 task_survey)分屬不同層(一個是套件、一個是主專案模組),看起來完全不同類,卻是同一個疆界——兩者之間有跨邊界外鍵、資料同生共死,因此裁定合併(D10)。
判準各自是:
| 問題 | 用什麼判 | 依據 |
|---|---|---|
| 同不同族(本頁) | 誰會裝它、壞了什麼後果、發版節奏跟誰綁 | 本頁分類表 |
| 同不同疆界(該不該合併) | 要不要天天連表查、要不要同生共死——想建外鍵就是同一個疆界 | design.md D17 資料關聯三律 ① |
一句收攏:同族是鄰居,同疆界才是一家人。鄰居再像也不併戶口。
%%{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 TB
subgraph L3["每個產品都可選裝"]
A["① 身分族<br/>jedi-iam"]
B["② 業務平台服務<br/>通知/檔案/公告/設定/選單"]
C["③ 落地營運服務<br/>log-forwarding/license-runtime/integrity"]
end
subgraph L2["本產品的價值所在"]
D["④ 領域核心<br/>OSCAL/module_frame"]
E["⑤ 流程族<br/>flow-engine/flow_control"]
F["⑥ 評估執行族<br/>detection/evidence-classification/問卷"]
G["⑦ 人員指派<br/>participant"]
end
subgraph L1["連到外面世界"]
H["⑧ Edge<br/>remote-agent/cloud_integration"]
end
I["⑨ 基座 jedi-common<br/>(唯一允許被直接依賴)"]
J["⑩ 骨幹 主專案<br/>不抽——聚合層/接線盤/輪次編排"]
L3 --> I
L2 --> I
L1 --> I
J -. 接線注入 .-> L3
J -. 接線注入 .-> L2
J -. 接線注入 .-> L1
| 成員 | jedi-iam(auth+login+mfa+captcha 四合一,D9) |
| 誰會裝 | 每個產品都要——沒有產品不需要登入 |
| 壞了會怎樣 | 全停。沒人進得來 |
| 形態 | 插件(完全體,2.5 階段已達成) |
| 辨識句 | 「你是誰、你能不能進來、你能做什麼」 |
身分是唯一一個「所有產品必裝、且不可能自己不做」的族。四支合併成一支的理由(D9):它們從未獨立演化過——近三次發版五支全部同批 bump。
| 成員 | jedi-notification、jedi-file-upload、jedi-bulletin、jedi-system-config、jedi-system-menu、jedi-information-system、jedi-issue、jedi-device、jedi-log(存活半) |
| 誰會裝 | 選裝——大部分產品會裝其中幾支 |
| 壞了會怎樣 | 該功能不能用,其他照跑(可降級) |
| 形態 | 插件(第三階段已補殼完畢) |
| 辨識句 | 「每個產品都會重寫一次的通用功能」 |
這族最大,也最符合「抽套件」的直覺定義:跟業務無關、換個產品照樣用。jedi-file-upload 是全庫唯一有第二消費者的套件(jedi-issue 在用)。
| 成員 | jedi-log-forwarding、jedi-license-runtime、jedi-integrity |
| 誰會裝 | 接授權體系的產品(見下方判準) |
| 壞了會怎樣 | 視政策——integrity/license 壞了會主動擋住服務(那是它們的工作);log-forwarding 壞了可降級 |
| 形態 | 插件 |
| 辨識句 | 「客戶把產品裝進自己機房之後,我們還需要管的事」 |
🔴 判準是「接不接授權體系」,不是「落地不落地」
族名叫「落地營運」是因為這三支都是為落地版(客戶自建機房)長出來的,但雲端版同樣適用——雲端 SaaS 一樣要驗授權(哪個租戶買了哪些模組)、一樣要轉發稽核 log 到客戶的 SIEM、一樣可能要驗程式包完整性。
正確的判準是:這個產品要不要接入授權/完整性體系? 要,就裝這族;不要(例如純內部工具),就不裝。用「落地與否」判會漏掉雲端版的授權需求。
| 成員 | jedi-oscal-v2 系、module_frame(第四階段 4.3 定形) |
| 誰會裝 | 合規類產品才裝 |
| 壞了會怎樣 | 產品失去核心價值——控制項/框架都讀不到 |
| 形態 | 插件 |
| 辨識句 | 「這是合規產品之所以是合規產品的東西」 |
這族是產品價值本身,不是通用能力。抽它的動機不是「別人也要用」,而是「合規知識該有自己的家、不要散在四十個模組裡」。
| 成員 | jedi-flow-engine(引擎,推流程)、flow_control(控管,掛業務——第四階段 4.2 拆出) |
| 誰會裝 | 有流程需求的產品 |
| 壞了會怎樣 | 任務推不動,但既有資料還在 |
| 形態 | 插件(切分待第二種流程出現時再議) |
| 辨識句 | 「引擎推流程、控管掛業務」 |
兩支成對命名不是巧合(D5):引擎管「下一步是誰」,控管管「這一步要做什麼業務」。稽核只是第一個掛進來的業務,未來問卷審核等都會套同一模式。
| 成員 | jedi-detection(4.4)、jedi-evidence-classification(4.5)、問卷疆界套件(4.6,D10 合併產物) |
| 誰會裝 | 要「實際去查證」的產品 |
| 壞了會怎樣 | 該種查證方式不能用,其他查證照跑 |
| 形態 | detection 開工前先過服務化評估(D7-③);其餘插件 |
| 辨識句 | 「三種問法:機器掃、看文件、問人」 |
這族是同一件事的三種手段——要知道一個控制項到底有沒有落實,可以機器掃(detection)、看證據(evidence-classification)、問人(問卷)。三支同族但各自獨立疆界(同類型≠同疆界的典型)。
| 成員 | jedi-participant(4.1,核心抽取首棒) |
| 誰會裝 | 要「把事指派給人」的產品 |
| 壞了會怎樣 | 任務沒有負責人 |
| 形態 | 插件 |
| 辨識句 | 「誰負責這件事」 |
單獨成族因為它誰都不像——不是身分(身分管「你是誰」,它管「這件事歸你」)、不是流程(流程管「下一步」,它管「這一步歸誰」)。全專案最大 hub(被 60+ 處依賴)但 out-degree 僅 8,是解核心環的鑰匙。
| 成員 | jedi-remote-agent、cloud_integration(Drive 整合,待定序) |
| 誰會裝 | 需要「伸手到系統外面」的產品 |
| 壞了會怎樣 | 外部連線斷,本體照跑(可降級) |
| 形態 | 插件(remote-agent 已發版,migration 隨包首例) |
| 辨識句 | 「跨出這台機器去拿東西/派工」 |
機器身分不併身分族
jedi-remote-agent 管的是機器的身分(mTLS/X-Agent-Uid),jedi-iam 管的是人的身分。兩套認證體系平行、明確不併(D9)——機器不會忘記密碼,人不會用憑證輪替。
| 成員 | jedi-common(層 0) |
| 誰會裝 | 全部——它是所有套件的地基 |
| 壞了會怎樣 | 全停 |
| 形態 | 函式庫(不是插件——它沒有 api 層也不該有) |
| 辨識句 | 「session、查詢基底、例外類、身分脈絡包」 |
唯一允許被直接依賴的套件
架構只有一條實線規則:疆界插件只准直接依賴 jedi-common,插件彼此絕不直接相依(D16)。插件間協作一律經宿主接線盤走 port 注入。jedi-common 是這條規則的唯一例外。
| 成員 | 主專案本體——跨疆界聚合查詢、DI 接線盤、輪次生命週期編排、associations 關聯表 |
| 誰會裝 | 不適用——它是宿主本身 |
| 壞了會怎樣 | 全停 |
| 形態 | 永不成為套件 |
| 辨識句 | 「把各檔口的菜湊成套餐的那個櫃檯」 |
🔴 這族存在的意義是「明文標記不可搬」
第四階段最可能出事的地方,是把骨幹的東西誤判成某支套件的資產一起搬走——尤其跨疆界聚合查詢:它們現在散在 infra/oscal/、infra/flow_control/、infra/detection_tools/ 各模組底下,長得跟該模組的 repository 一模一樣,但 SQL 內部 JOIN 了七個疆界的表。grep 守衛與 standalone harness 都抓不到 SQL 字串裡的跨表依賴——誤搬進套件不會有任何測試變紅,會在客戶端執行時才炸。
骨幹的四類內容:①跨疆界聚合查詢(櫃檯的套餐窗口)②DI 接線盤(哪支 port 接哪個實作)③輪次生命週期編排(產品核心價值,本來就該在宿主)④associations 關聯表(隨「擁有語意的那端」走,過程中逐步溶解)。
%%{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 TB
A{"這個能力<br/>換個產品還要嗎?"} -->|不要,只有合規產品要| B{"是產品核心知識<br/>還是查證手段?"}
B -->|核心知識| C["④ 領域核心"]
B -->|查證手段| D["⑥ 評估執行"]
A -->|要| E{"沒有它<br/>產品就進不去嗎?"}
E -->|是| F["① 身分族"]
E -->|否| G{"是給客戶自建機房<br/>/授權體系用的嗎?"}
G -->|是| H["③ 落地營運服務"]
G -->|否| I{"要連到<br/>系統外面嗎?"}
I -->|是| J["⑧ Edge"]
I -->|否| K["② 業務平台服務"]
A -->|它只是把別人的資料湊起來| L["⑩ 骨幹——不抽"]
找到族之後,照該族既有的先例抄——每一族都已經有至少一支做完的樣板。
現況:只是一個構想,本階段不實作
分完族之後很自然的下一步是:新產品不要一支支列依賴,直接裝一包。構想中兩個 meta-package(本身沒有程式碼,只宣告依賴清單):
| 名稱 | 內含 | 給誰 |
|---|---|---|
jedi-platform-suite |
身分族+業務平台服務族+基座 | 任何新產品的起手式 |
jedi-onprem-suite |
落地營運服務族(log-forwarding/license-runtime/integrity) | 要接授權體系的產品加裝 |
為什麼現在不做:meta-package 的價值是「省下列依賴的力氣」,但代價是多一層版本對版的維護——每支套件發版都要回頭決定 bundle 要不要跟著 bump。在只有一個消費產品的現在,這個代價大於收益。
什麼時候回來做:出現第二個實際要裝的產品時。屆時「新產品該裝哪幾支」會從紙上談兵變成真實問題,bundle 的內容也才有依據定。