FR-099 · 需求索引 · 本頁由 build 掃資料夾生成
🟢 三棒程式全部完成,待驗收(2026-09-16)。母卡 CM-1816、子卡 CM-1817~1819。主專案五個目錄已刪、對外 URL 一字不變。套件版號已升 1.2.0。發版(推 Nexus)、升主專案 pin、push 三件都等決策者指示——在那之前這個 branch 不可交付(乾淨環境會啟動失敗)。
意見回饋與標籤是模組化的漏網,不是欠債。 主專案那兩個目錄整條鏈都在呼叫 jedi-issue,本身只是轉發殼,但歷次模組化是按目錄名掃的——api/issue/ 搬走了,另外命名的 api/feedback//api/label/ 沒被認出是同一件事。
會被漏掉的原因之一是套件 README 曾經寫錯。 它聲明「Issue 本體產品目前未使用」「GitHub/GitLab 產品目前沒在用」,兩條都與事實不符,而緊接著的下一句是「不要順手清死碼」——於是每一輪盤點的人讀了都會跳過這一塊。文件寫錯會讓錯誤自我延續,這是本案最值得記住的一點。
決策者已拍板三件:GitLab/GitHub 外部整合保留、整組搬進套件(連同 FE 設定頁視為正式功能,python-gitlab/PyGithub 兩支相依留著);開成獨立 FR 母卡+子卡;對外 URL 一字不變(FE 零改動)。
主專案少掉五個目錄:api/feedback/、api/label/、app/feedback/、domain/feedback/、infra/feedback/ 全刪,兩顆 DI 容器收掉,模組註冊表移除兩列,只剩 core/plugins/issue.py 一個接線檔。對外網址一個字都沒變、前端零改動,使用者完全感覺不到差別。
主專案用到套件的三個新東西(兩張 port 介面 + issue_project_name 設定欄位),這三個在 Nexus 上那版 jedi-issue 1.1.1 都不存在。所以在發版之前,拿這個 branch 到一台乾淨的機器上裝起來,服務會在啟動時就因為找不到東西而掛掉。
套件原始碼已經備妥、版號也已經升到 1.2.0,缺的只有「推上去」這個動作本身。
| 步 | 做什麼 | 備註 |
|---|---|---|
| 1 | 三個 repo push | push 一律等指示 |
| 2 | 套件目錄下 poetry publish -r nexus |
不可逆,推之前再確認一次版號是 1.2.0 |
| 3 | 主專案 pyproject.toml 的 pin 改成 jedi-issue==1.2.0 |
現在故意還沒改:版本鎖定檔需要 Nexus 上的檔案指紋,而那要等推上去才存在。先改會讓鎖定檔對不上,連裝都裝不起來 |
| 4 | 主專案 poetry update jedi-issue + 重啟服務驗七條網址 |
不要用 poetry lock,這個專案跑起來會卡很久 |
把 GitLab 整合真的打開、看它在 GitLab 長出一則 issue ——這條沒驗,因為沒有可用的測試專案與金鑰(開發庫裡兩組設定的金鑰欄位都是空的)。
驗過的是它的前半段:設定存得進去也讀得回來、開關的值真的會決定走不走外部整合(打開=走、關掉或設定缺漏=只建在本地)。沒驗的是後半段——真的連出去開 issue 那一步。
| 查什麼 | 結果 |
|---|---|
| 主專案那份是不是殼 | 是。搬遷前 24 處呼叫全都轉手給套件的 IssueService,且全帶「本地」這個來源參數——實體早就在套件裡 |
feedback_issues 是什麼 |
只有四欄(issue_uid + gitlab/github id + 審計欄)的純關聯表,標題內容靠 relationship 從套件 issues 表撈 |
| 資料量(DEV) | issues 25 筆/labels 35 筆/feedback_issues 14 筆(前兩棒的驗證資料計入,issues 刪回饋時只標為關閉、不刪列) |
| 表歸屬 | 套件六張表 owner 是 ammgr,feedback_issues 是 cmmgr |
| label 是獨立功能嗎 | 不是。FE 三處打 /labels/menu 全在 views/feedback/ 底下,抓 FEEDBACK_TYPE/FUNCTION 兩個 scope |
| 外部整合啟用了嗎 | DEV system_configs 的 ISSUE_INTEGRATE_CONFIG:GITLAB 與 GITHUB 兩筆 enable 皆 false(功能在、未啟用) |
| 能力點 | 十個(feedback.* 五個 + feedback-view.read + issue-integrate-config.* 四個)。開發、基線、STG、POC 四個庫與出貨 seed 都是完整的十個,沒有缺漏 |
意見回饋要搬進通用套件,就得先把「只有 Guidant AI 才知道的事」跟「任何產品都適用的事」分開。這四件是分界線上的:
| 東西 | 為什麼不能直接搬 | 現在怎麼做 |
|---|---|---|
專案代號 "CM" |
CM 是 Guidant AI 的代號,是產品知識 | 變成套件的一個設定欄位 issue_project_name,預設留空,由主專案填 |
| 「該讀哪一列設定」 | 讀最上層租戶那一列並繞過隔離,是本產品的多租戶規則 | 開一張門(port)問宿主,主專案在 core/plugins/issue.py 回答 |
| 用暱稱搜尋回饋 | 回饋這張表直接去 JOIN 使用者表,會讓套件裝不進沒有身分模組的產品 | 方向倒過來:先問身分名冊「暱稱含這個字的是哪些帳號」,再拿帳號清單篩本表。篩選仍在資料庫裡做,分頁總數才不會變成假的 |
| 建表與權限腳本放哪 | 表隨模組走,不能留在主專案 | 進套件自己的 migrations/(001~004),由宿主決定何時套 |
issue_project_name 為什麼預設留空:預設若寫 "CM",別的產品裝了這支套件、忘了填,不會有任何錯誤訊息——資料會靜靜落進 Guidant AI 的命名空間,直到同一個庫出現兩個產品的資料才發現。
| 問題 | 裁示 | 理由 |
|---|---|---|
feedback-view.read 命名與其他五個不同,要統一嗎 |
不改 | 它對應「唯讀檢視」頁、與「管理」頁是兩張不同的頁。名字不一致反而正確反映了它們是不同資源;統一會失去「只能看不能管」的區分能力 |
| 意見回饋三條 route 只守登入、沒守能力點,要補嗎 | 不補,且此時不決定 | 補了之後沒被授予的角色會當場被擋掉,而系統裡不只那 14 個角色。POC 交付前動權限可能讓客戶有人不能用。日後要補的前置是先查「現在實際在用的人是什麼角色」 |
feedback_issues 要併進 issues 表嗎 |
不併 | 兩張表不是一對一(11 筆 issue 沒有對應的回饋,是刪回饋後留下的),且只有 feedback_issues 有租戶隔離。併表要寫資料遷移、處理孤兒、重設隔離規則,換來省一張表 |
這塊容易誤判,寫下來免得下一個人重查:
設定不走意見回饋自己的端點,走的是通用的系統設定端點。所以 issue-integrate-config 這四顆能力點不在 jedi-issue 的 route 上,而是由 core/plugins/system_core.py 的對照表把 ISSUE_INTEGRATE_CONFIG 這個群組分流過去守。
四顆都真的在擋人:新增、修改、刪除三個動作,沒有這些點的帳號實打會收到 403;讀取沒掛能力點,但設定存在最上層租戶那一列,其他租戶受資料庫層隔離看不到,實打回 404。
所以套件那份四顆的宣告清單必須完整——少列哪一顆,通用端點對應的動作就會退回一顆沒人持有的能力點,症狀是設定頁按下去永遠 403。
core/plugins/<pkg>.py 一支一檔三段),本案照它做。migrations/。