本卡屬 FR-101(母卡見建卡後補號),第 1 棒:意見回饋全鏈(app/domain/infra 三層)+
api/整層(route 表、守門、7 條 route、序列化)。31 檔,全部是 FR-099 新搬進套件的,只掃不修。
使用者送意見回饋、改回饋、刪回饋、刪附件、匯出、看標籤選單、查成員名單——這七個對外功能現在全在套件裡。看的是:誰能做哪件事(現況是只要登入幾乎都能做)、能不能改刪別人的、內容流到 GitLab/GitHub 時帶了什麼、守門是怎麼從主專案注入進來的。
這 31 支是 FR-081 I2 那 5 條發現(含 CM-1630)的新落點,也是使用者最直接碰得到的面。守門殼與宿主注入的接縫是新形狀,FR-098 A1 證明這種地方最值得看。
api/routes/feedback_route.py:35/52/59/74/91/102 七條只有 @auth_required,:116 匯出多掛 capability_required;app/feedback/service/feedback_service.py:240 update_feedback/:279 delete_feedback 用 uid 撈出就改就刪,user_login_name 只拿去寫 updated_user 與關單紀錄)。要驗:有沒有任何一層比對 created_user;get_feedbacks_and_pager(:151)任何登入者是否看得到全租戶所有人的回饋;跨租戶靠 feedback_issues 的 RLS,但它 join 的 issues 表零隔離——_attach_issues(:131)用 issue_uid 撈內容時會不會撈到別租戶的 issue 內容。標「重複 CM-1630,位置更新」,但新細節(跨租戶 join)若成立要單獨寫。api/guards.py、api/routing.py、plugin/assembly.py:88-105 _assert_api_wiring)。守門殼只驗 auth_required/capability_required 兩項必填,current_user_login_name 缺了回 None(docstring 自稱「不是安全的門」)。要問:current_user_login_name 為 None 時 add_feedback 的 created_user 是空——之後誰都算不上主人;宿主 core/plugins/issue.py 用 host_defaults() 給的 auth_required 是 jwt_required() decorator 本身(其他套件用 lambda 每次建),兩種寫法在 flask_restful MethodResource 上行為一不一樣;_guard 有沒有漏 method。feedback_route.py:60-70 request.files['json'] 直接 json.loads;app/feedback/service/feedback_issue_service.py 把 title/description/labels/files 交給 Local/GitLab/GitHub 三個 provider)。要驗:request.files['json'] 不存在時炸什麼;description 是 HTML(html_to_text 只在匯出用)——存進 issues 與送到 GitHub 時有沒有清;labels 清單是 uid 還是名字、能不能塞不存在的;檔名/大小限制在哪一層。feedback_service.py:337 export_feedbacks)。唯一有能力點的端點。get_feedbacks() 撈全部後寫 Excel/CSV——FR-097 第 78 項同款:公式注入(title/description 由使用者填,開頭 =/+/-/@ 有沒有處理);export_type 從 URL 來,有沒有白名單。api/routes/issue_member_route.py)。只驗登入、直接回 member_service.get_members() 結果不包信封。要驗:回的是哪張表(members 零隔離)、有沒有租戶條件、任何登入者是否拿到全站名冊(守門殼錯誤訊息自己寫「回傳全站使用者名冊」)。feedback_service.py:93-125 _translate_display_name_filters 與哨兵值)。宿主 IssueUserNameSearcher 上限 200;要驗:哨兵字串的「永遠不成立」論證在 ILIKE 下是否真的成立;created_user filter 合併時有沒有讓使用者用 filter 直接指定別人帳號撈他的回饋(這在①的脈絡下等於列舉)。api/serializers/feedback.py)。回饋回應有沒有夾帶 gitlab_issue_uid/github_issue_uid/內部 id 這類可拿去打第三方的識別。verify=False 兩處/CM-1633 附件刪除檢查半套/CM-1634 Nexus 明文。撞到標「重複 CM-16xx,位置更新」不另計——CM-1630 與 CM-1632 首腦已開檔確認搬家沒修(新位置見各棒重點)。issues、labels、issue_*_mapping 皆 RLS 關、0 規則;只有新的 feedback_issues 開 RLS、4 規則、不強制)。撞到標「第 7 項」。RootIntegrateConfigProvider 從 ROOT 租戶讀設定;不要被任何「沒在用」的殘留註解說服。第一步:驗 scope 檔數,對上 31 才啟動: