FR-101 · 需求索引 · 本頁由 build 掃資料夾生成

FR-101 jedi-issue 大整理後重掃

✅ 三棒掃完並驗收收尾(2026-09-16);發現已全數處理(2026-10-01 同步)——淨新增 3 條(匯出公式注入、無部門送回饋被擋、全站成員名冊入口):2 條已修、1 條死程式已刪除(均隨 1.21.0 出貨);FR-081 四張舊卡回歸確認當時一張都沒修,現已全數處理(三件已修、版控殘留已清)。工具重掃同一批檔結論與 FR-081 高度一致但 CM-1633 兩次都沒報。

狀態:✅ 已完成 文件 3 份

這是資安掃描系列的一個 arc。 跨 arc 的結論、修正卡狀態、還沒開卡的待辦與覆蓋率,在跨 arc 總表:security-scan-consolidated/。本頁只講這一支。

🔴 一頁看完

三棒全部掃完。J1/J2 已驗收,J3 等驗收。三棒合計淨新增 2 條(J1 一條、J2 一條),J3 零新增。

J1 找到 4 條發現、全部中等、無高風險:兩條是 CM-1630 搬家後的新落點(誰都能改刪別人的回饋、誰都讀得到全部回饋),一條是 CM-1632 的重複(GitHub 連線關掉憑證驗證),淨新增只有 1 條——匯出檔的 Excel 公式注入。另有 1 條工具沒報、人工查出的:任何登入者都拿得到全站使用者名冊(成員清單端點,根因歸總表第 7 項)。詳見 J1 報告。

J2 的結果形狀完全不同:掃描工具在指定的 37 個檔裡一條都沒報,它報的 4 條全部越界到 J1/J3 的檔案,而且就是 J1 已報過驗收過的同 4 條(檔名行號都一樣),淨新增為零。真正的產出來自人工查證卡片六個重點:查出 1 條新缺口——沒有被分配部門的使用者送不出意見回饋,且畫面看不出原因(資料庫隔離規則與欄位可為空的組合,三個檔交叉比對才看得出來);另判定總表第 7 項對 labels 表是誤判——標籤是全站共用的選項字典(碼表),整張表沒有任何「這筆屬於誰」的欄位,回全表是正確行為。這 37 個檔不能算「掃過且乾淨」,詳見 J2 報告。

J3 的價值不在找到新東西,而在確認了兩件事。第一,FR-081 的舊結論一條都沒被修掉——GitHub 連線關掉憑證驗證的兩處(CM-1632)還在、刪除附件守門只做一半(CM-1633)一行未改、意見回饋不驗權限(CM-1630)照舊、版控歷史的舊密碼(CM-1607)仍可撈出。第二,同一批檔重掃會給出幾乎逐字相同的結論——這對工具穩定性是好消息,但也意味著重掃挖不出新東西:CM-1633 那個「算了過濾結果卻只用一半」的錯誤擺在那裡,工具第二次一樣沒報(檢查員的推論停在「現在打得到嗎」,答案是打不到所以判定不成立)。淨新增 0 條,工具報的 5 條裡 4 條越界到 J1,詳見 J3 報告。

意見回饋功能(使用者回報問題、可轉成 GitLab/GitHub 問題單、可夾附件)原本一半在主專案、一半在套件。FR-099 把主專案那一半整組搬進套件 jedi-issue,主專案刪掉五個目錄。搬完後套件的樣子變了,FR-081 在 2026-09-10 掃的是搬家前的版本。

§1

變了多少

變動 檔數 內容
新增 38 意見回饋四層+7 條對外 route、守門殼、route 表、插件骨架五檔、4 支隨包 migration
刪除 18 舊 plugin.py、頂層 ports/ 目錄(併進 domain/ports.py)
既有檔有改 25 GitLab/GitHub 整合、附件、成員那批。邏輯改動約 120 行,其中 GitHub 附件那支刪 34 行改 15 行
沒動 57 整合底層與成員、附件的多數檔——沿用 FR-081 結論,不重掃

主專案那側整個變形:FR-081 I2 掃的 31 檔宿主接線(api/feedback/、app/feedback/ 等五個目錄)已全部刪除,只剩 core/plugins/issue.py 一支接線檔。當年 I2 那 5 條發現(含唯一一條次嚴重的 CM-1630)現在的落點在套件裡。

§2

首腦開卡時已開檔核出的(未經三位檢查員投票,寫進卡當錨點)

  • 🔴 CM-1630 搬家沒修:套件版 feedback_route.py 七條 route 仍只有匯出掛能力點;feedback_service.py 的修改與刪除用 uid 撈出就改就刪,呼叫者帳號只拿去寫審計欄位與關單紀錄,沒有比對是不是本人。
  • CM-1632 verify=False 兩處仍在(infra/github.py:22、github_issue_adapter.py:40)。
  • 六張舊表零隔離仍在(2026-09-16 DEV 唯讀實查):新搬進來的 feedback_issues 開了 RLS(4 條規則、不強制),但它關聯的 issues/labels/三張 mapping 沒有——門上了鎖、牆是空的。
  • 守門殼 _assert_api_wiring 只驗登入與能力點兩項必填;10 顆能力點有 6 顆自陳後端不守(與 FR-098 第 80 項同一種產品決策題)。
  • 隨包 migration 002 用 SET LOCAL app.is_super_admin='t' 寫 ui_routes。

總進度表

棒 卡 範圍 檔數 狀態 首腦驗收
J1 CM-1826 意見回饋全鏈(app/domain/infra)+ api/ 整層 31 ✅ 已掃完(報告):4 條發現全中等,淨新增 1 條;驗證章 verified、12 票全投 ✅ 已驗(2026-09-16):四條屬實無改判;F1/F2 併 CM-1630(位置更新)、F3 併 CM-1632(越界屬 J3)、F4 新登記總表第 82 項;runner 補查的成員名冊端點屬實歸第 7 項;交付四件齊全(第十二次做滿)
J2 CM-1827 plugin/、domain/ports.py、common/、標籤三層、4 支 SQL 37 ⚠️ 已掃完(報告):工具範圍內 0 條,4 條全越界重複 J1;驗證章 verified、12 票全投、2h33m;六個重點全靠 runner 人工+DEV 實查 ✅ 已驗(2026-09-16):四條越界判定正確不另計;N1 新登記總表 §3.2 第 18 項(首腦 DEV 重查三項事實全對);第 7 項對 labels 剔除(碼表判斷正確);①與第 80 項同款產品決策題入 §7 第 16 項;交付四件齊全(第十三次做滿)
J3 CM-1828 有改動的 25 支整合/附件/成員檔(回歸) 25 ✅ 已掃完(報告):淨新增 0;18 票全投、4 通過皆中等(1 範圍內=CM-1632、3 越界重複 J1)、1 條退件(歷史檔);七個重點工具碰兩個、其餘人工 ✅ 已驗(2026-09-16):回歸確認四張舊卡一張沒修(CM-1632 兩處/CM-1630/CM-1633 一行未改/CM-1607);重掃結論與 FR-081 高度一致;GitLab 側無同款;附件靜默跳過入 §7 待裁;交付四件齊全(第十四次做滿)。FR-101 三棒收尾

一次只派一棒,每棒獨立驗收完才派下一棒。掃描版本基準:jedi 套件 repo 4c208d4(branch feature/review);J3 掃的是 3cc966f,兩者之間 jedi-issue 零差異(中間的 commit 只動 jedi-iam)。

⚠️ 主專案接線 core/plugins/issue.py+2 支小檔不在本案,併進之後「日誌+資產+議題三支套件的主專案接線」那棒(BE repo,約 21 檔),等三棒跑完再開卡。

J1 驗收(首腦,2026-09-16)

結論:四條全屬實、無改判;淨新增一條中等(第 82 項,匯出公式注入)。CM-1630 與 CM-1632 搬家沒修,位置更新。

§3

工具的驗證章

項目 結果
驗證章狀態 verified,無拒收原因
候選 → 去重後 4 → 4
投票 12(4 × 3),四條全 3:0;F1 面板由高降中
未審/中斷 0/0
研究員派出/回收 1/1
耗時 3,302 秒(55 分)
掃描版本 jedi 4c208d4,branch feature/review,工作區乾淨
範圍 31 檔,與工單逐檔對上
§4

四條判定

# 白話 首腦判定
F1 任何登入者能改掉/刪掉別人的回饋 屬實。feedback_service.py:240/:279 用 uid 撈出就改就刪,呼叫者帳號只寫審計欄位。併 CM-1630,位置更新
F2 清單/明細誰都讀得到全租戶 屬實。同屬 CM-1630
F3 GitHub 連線 verify=False 屬實。重複 CM-1632,檔案屬 J3 範圍(越界)
F4 匯出 Excel/CSV 公式注入 屬實,新登記第 82 項(中)。首腦開檔:export_rows 六欄裡標題/描述/標籤名/建立者暱稱四欄使用者可控,html_to_text 只拔標籤不處理開頭等號;:389 ws.append 與 :378 writer.writerow 直接寫。與第 78 項同病,建議共用一支中和函式
§5

runner 人工補查(工具七個重點只碰三個)

  • 🔴 成員名冊端點:issue_member_route.py 只驗登入,member_repostiory.py:23 query(Members).all(),members 表無租戶欄、RLS 關(首腦 DEV 唯讀重查 15:50:0 筆;model 含 email 欄)。屬實,歸總表第 7 項;建議 CM-1630 描述補上這條(原卡只講六個回饋操作)。
  • 跨租戶 join:_attach_issues 先撈受隔離的 feedback_issues 再比對 issues,方向上不會多出別租戶回饋;但 issues 表無租戶欄(DEV 28 筆)、零隔離,「門鎖了牆是空的」。歸第 7 項,不另計。runner 的判斷正確。
  • 三項查證不成立(守門殼兩種注入寫法等價/哨兵值論證成立/回應夾帶的第三方 id 無存取權杖打不進去)——首腦覆核同意。
  • 順手記兩個非資安小坑:零筆時匯出 500;描述是 HTML 未清洗,前端現在不用 v-html 所以不成立。
§6

可信度

  • 「這四條是真的嗎」→ 可信:12 票全投,首腦逐條開檔。
  • 「只有這四條嗎」→ 不可信:快篩一位研究員,七個重點碰三個,其餘靠人工。
§7

交付狀況

項目 狀況
報告 ✅ runner 自行交付 scan-J1-feedback-chain.md
commit ✅ runner 自行 commit(cad9d94b)
Notion 回寫+狀態 ✅ runner 自行完成
修正卡 ✅ 已修(CM-2055,1.21.0 出貨;與第 78 項合修)

✅ 交付四件齊全——本計畫第十二次做滿。

J2 驗收(首腦,2026-09-16)

結論:工具對這 37 個檔零產出——報的四條全越界、與 J1 那四條連行號都一樣,判定正確不另計。真正的產出是 runner 人工六個重點:查出一條真 bug(§3.2 第 18 項)、更正一條總表誤判(第 7 項剔除標籤表)。

§8

工具的驗證章

項目 結果
驗證章狀態 verified
候選 → 去重後 4 → 4,四條的檔案都不在 37 檔 scope 內(首腦逐檔比對)
投票 12 全投、全 3:0
耗時 9,175 秒(2 小時 33 分);第一位研究員被砍掉重派
掃描版本 jedi 589d034(該 commit 只動 jedi-iam,J2 範圍與 4c208d4 零差異)
§9

首腦親核三件

  1. N1 屬實。DEV 唯讀重查(18:40):feedback_issues_insert policy 原文為 app_tenant_allowed_for_session(tenant_id) AND (can_read_all_orgs OR app_org_allowed_for_session(org_unit_id)),無超管旁路(另三條有);app_org_allowed_for_session(NULL) 回 f;users 中 org_unit_id IS NULL 且非超管的帳號 1 個。三件事合起來=沒部門的人送回饋必被擋且無錯誤訊息。登記 §3.2 第 18 項,修法三選一入 §7 第 17 項待裁。
  2. 標籤表是碼表,runner 判斷正確。DEV 查 labels:七欄(id/uid/name/color/description/scope/is_deleted),無租戶、部門、建立者欄;內容 FUNCTION 16 筆、FEEDBACK_TYPE 3 筆等下拉選項。依 §5「有沒有主人」判準回全表正確。總表第 7 項由六張改五張(issues/members/三張 mapping 仍零隔離)。
  3. 能力點宣告 vs 執法:runner 核出宿主 system_core.py:69 對照表真擋整合設定四顆,回饋五顆只前端認。與第 80 項同一種產品決策題,入 §7 第 16 項,建議與第 80 項一起裁。

其餘:守門殼正面案例(缺必填拒絕掛載)、SET LOCAL 在 --single-transaction 內安全、四支 migration 冪等、錯誤碼乾淨、整合金鑰套件內不落 log——首腦抽核 ②④ 兩項屬實,其餘採信。

§10

可信度

  • 「N1 是真的嗎」→ 可信,首腦 DEV 重查三項事實。
  • 「這 37 檔乾淨嗎」→ 不可信。工具等於沒掃,只能說「六個重點查過」。runner 問要不要重掃:首腦建議不重掃——這 37 檔是骨架、碼表、SQL 與介面定義,六個重點已涵蓋它的全部攻擊面,重掃一輪面板換不到新東西;若日後套件骨架再大改再排。
§11

交付狀況

項目 狀況
報告 ✅ runner 自行交付 scan-J2-plugin-label-migration.md
commit ✅ runner 自行 commit(22bb4dba)
Notion 回寫+狀態 ✅ runner 自行完成,含四題待裁(現均已裁)
修正卡 ✅ 已處理(見 security-report M21 問題表;1.21.0 出貨)

✅ 交付四件齊全——本計畫第十三次做滿。

J3 驗收(首腦,2026-09-16)

結論:淨新增 0。這棒的價值不在找新洞,在兩件事——回歸確認 FR-081 四張舊卡一張都沒修,以及證明工具重掃同一批檔會給出幾乎相同的結論。

§12

工具的驗證章

項目 結果
驗證章狀態 unverified,reason_kind: findings-refused(F5 的 .env 在 git 歷史、不在樹裡,被渲染器退件)——面板完整跑完、18 票全投,第三種型態不算失敗
候選 → 去重後 6 → 6;通過 4 皆中等、退件 1、駁回 1
研究員 2 派 2 回
耗時 8,093 秒(2 小時 15 分)
掃描版本 jedi 3cc966f8;掃描期間平行線 commit 651e33c(jedi-file-upload),首腦確認對 jedi-issue 零差異
範圍內產出 1 條(F1=CM-1632 行號 43→40),其餘 3 條越界到 J1 範圍(首腦逐檔比對)
§13

首腦親核

  • CM-1633 一行未改:開檔 local_issue_attachment.py:87 算出過濾後集合、:91 刪對應關係用過濾後的、:98 刪實體檔用回未過濾的 file_uids。與 FR-081 I3 描述一致。工具兩次都沒報——它只問「現在打得到嗎」(單一呼叫點只傳一個編號),程式寫錯這件事它不會說。
  • GitLab 側無同款:infra/gitlab.py:27、gitlab_issue_adapter.py:44 的 gitlab.Gitlab( 建構都沒傳 ssl_verify,套件預設驗證。CM-1632 只在 GitHub 這半。
  • GitHub 附件降級:github_issue_attachment.py:103-108 只記檔名進 WARNING、回空清單;使用者端無提示。產品決策題入總表 §7。
  • runner 其餘四項(範圍內零 except Exception、本地路徑只用 issue 編號、CM-1807 已修、entity 必填未變選填)抽核 ①④ 屬實,其餘採信。
§14

可信度

  • 「報出來的是真的嗎」→ 可信,四條 3:0,首腦逐條開檔。
  • 「這 25 檔乾淨嗎」→ 不可信,工具範圍內只產出 1 條;但這棒本來就是回歸確認,目的達成。runner 問要不要重掃:不重掃——本棒已證明重掃給出相同結論,要提高覆蓋該換方法。
§15

交付狀況

項目 狀況
報告 ✅ runner 自行交付 scan-J3-integration-regression.md
commit ✅ runner 自行 commit(ad70978f)
Notion 回寫+狀態 ✅ runner 自行完成,含三題待裁(現均已裁)
修正卡 ✅ 已處理(見 security-report M21 問題表;1.21.0 出貨)

✅ 交付四件齊全——本計畫第十四次做滿。FR-101 三棒收尾。

§16

三棒收尾:總表怎麼變

項目 變動
§3.1 新增第 82 項(J1);第 7 項六張改五張(J2)
§3.2 新增第 18 項(J2)
§7 待裁(現均已處理) 回饋五顆權限點要不要守(第 16)/無部門送回饋修法(第 17)/附件靜默跳過要不要告知(第 18)
已開卡未修 CM-1630/1632/1633/1607 位置更新(當時全部未修;09-21 作廢、改照問題總表派工,現已全數處理:三件已修、版控殘留已清)
掃描方法 工具對同一批檔重掃結論一致;對骨架、碼表、SQL 類的檔零產出(J2);對「程式寫錯但現在打不到」的錯誤兩次都不報(CM-1633)

需求討論紀錄

§17

為什麼開新 FR 不續 FR-081

範圍、切法、動機都不同:FR-081 按「攻擊面」切六棒、面板六棒全部投完票,是本專案最乾淨的一批紀錄。續在底下會把「130 檔舊版全掃完」與「151 檔新版只掃變動」混在同一份進度表。FR-081 README 加一段指向本 FR。

§18

為什麼只掃 93 支不掃 151 支

57 支內容與 2026-09-10 掃過的版本逐字相同(git diff ed62d8a..HEAD 零差異),工具產物與六份報告仍有效。重掃只多燒一輪面板,換不到新資訊。

§19

為什麼 J3 要掃(決策者 2026-09-16 裁)

25 支邏輯改動只有約 120 行,本可省。掃的理由兩個:GitHub 附件那支是唯一實質行為變更(從「拋例外導致整張 issue 沒建」改成「靜默跳過附件只記 warning」,對不對要驗);以及這是第一次有機會驗「工具對同一批檔重掃,結論一不一致」,成本一棒。

§20

共同設定

項目 值
主 session 模型 Opus 5 (1M context),不要用 Sonnet
effort low
scanRoot ~/Projects/Jedicogy/module/jedi-python-package/jedi-issue
派工節奏 一次只派一棒,驗收完才派下一棒
§21

🔴 前幾個 arc 換來的紀律(本系列必照做)

掃完要逐項回頭核工單的「重點看什麼」——快篩模式下工具常只咬住一個最顯眼的攻擊模式(FR-097 L1 最嚴重那條工具完全沒碰、FR-098 A1/A2 五六個重點只碰一個)。工具沒答的自己開檔查了再寫,標「(工具未報,人工查證)」。報告格式抄 FR-098 A2。

§22

相關座標

§23

文件

以下全部由 build 掃資料夾產生,新增檔案重 build 即自動出現。標題連結指向渲染後的 HTML,md 連向源檔。

證據與盤點

文件 類型 標題 最後更新
scan-J1-feedback-chain / md 盤點證據 J1 檢查結果:意見回饋全鏈+對外 route 與守門殼(jedi-issue) 2026-09-16
scan-J2-plugin-label-migration / md 盤點證據 J2 檢查結果:插件骨架+標籤鏈+隨包 migration+共用(jedi-issue) 2026-09-16
scan-J3-integration-regression / md 盤點證據 J3 檢查結果:有改動的整合與附件層(回歸重掃) 2026-09-16
§24

Notion 卡

卡片內容(決策紀錄、驗收條件)以 Notion 為準,本頁只記座標。

關係 卡號 標題 狀態
母案 CM-1825 FR-101 jedi-issue 大整理後重掃(三棒 93 檔,只掃不修) —
子卡 CM-1826 J1 意見回饋全鏈+對外 route 與守門殼(31 檔) 修正待驗證
子卡 CM-1827 J2 插件骨架+標籤鏈+隨包 migration+共用(37 檔) 修正待驗證
子卡 CM-1828 J3 有改動的整合與附件層(25 檔) 修正待驗證