本卡屬 FR-182(母卡 FR-182 母案(同清單上一張)),卡 L2,批 2。只改 license_center repo。依賴:L1。
L1 把 Agent 照的資料與六支函式做好了,這張卡給員工畫面:LC 後台導覽列多一項「Agent 授權」,底下五個頁——清單(一台一列:客戶、照號、上層主系統照、型態、到期日、推算狀態、機器碼前段、開通狀態;搜尋與篩選;列尾操作下拉)、簽發表單(跟主系統簽發表單長一樣,多「數量」與「上層主系統照」兩欄;填 3 就一次簽 3 張各自獨立的照與序號,共一個批號)、簽發結果頁(這批 N 張列出照號+序號,可打包下載)、離線開通受理(輸入客戶交回的序號+機器碼,簽出綁機的照,結果頁下載)、詳情(明文欄位、事件歷史、操作)。另外客戶時間軸頁加一張小卡「Agent 照 N 台」連到清單。全部照既有 Tabler 樣式與既有頁的寫法(CSRF、CSP nonce、log 規範)。對照雛形做:docs/features/FR-182-2611-agent-license/prototype/lc-agent-license.html 七個場景,雛形是結構不是像素。
new:填 L1 建的空殼 web/views/agent_licenses.py——/agent-licenses/(清單:搜尋客戶代碼/名稱/訂單、篩狀態/開通/型態,列尾下拉詳情/下載/展延/補發/換綁,只列現行照)、/agent-licenses/issue(表單:客戶代碼、客戶名稱、訂單、上層主系統照下拉(呼叫 modules/licensing/service 查該客戶現行照——鐵律③只叫 service)、型態、天數、數量、提醒天數、寬限天數、發照人)、/agent-licenses/batch/<batch_id>(這批 N 張:照號+序號+下載未綁機照;zip 全部下載)、/agent-licenses/activate(序號+機器碼+發照人)、/agent-licenses/activate/<id>/result、/agent-licenses/<id>(明文、事件歷史、操作下拉;非現行照標「已被取代」不給下載)、/agent-licenses/<id>/{download,extend,reissue,rebind}。五支模板照 issue_form.html/activate_form.html/overview.html/license_detail 的樣子。extend:base.html 導覽列加「Agent 授權」;customer_timeline.py+模板加「Agent 照 N 台(已開通 x/待開通 y)→ 看清單」一張卡+事件混進時間軸前綴「Agent」。解鎖走 web/unlock_helper.py。log:簽發/開通/換綁/補發/展延/下載六種 INFO 帶 agent_license_id、customer_code、actor;序號只記摘要(activation_code_digest)
repo:~/Projects/Billows/Audit-Manager/license_center
改既有:src/license_center/web/views/agent_licenses.py(填空殼)
改既有:src/license_center/web/templates/base.html
改既有:src/license_center/web/views/customer_timeline.py
改既有:src/license_center/web/templates/customer_timeline.html
新開:src/license_center/web/templates/agent_licenses_index.html
新開:src/license_center/web/templates/agent_license_issue_form.html
新開:src/license_center/web/templates/agent_license_batch.html
新開:src/license_center/web/templates/agent_license_activate_form.html
新開:src/license_center/web/templates/agent_license_detail.html
新開:tests/test_agent_license_views.py
web/views/issuance.py(表單→service→結果頁→下載的完整形狀、log 怎麼記)、web/views/overview.py(清單、get_if_current 下載守門)、web/views/license_detail.py、web/views/customer_timeline.py、五支對應模板、LC CLAUDE.md「Web 應用層防護」「Logging」兩段。web/views/agent_licenses.py(填 L1 的空殼):index(GET;list_current(customer_code);每列算 compute_agent_status;搜尋/篩選照 overview.html 的 listjs 寫法,data-* 欄位:status rank/activated/type)、issue(GET/POST;POST 讀表單 → unlock_helper.unlock_or_flash_redirect → issue_agent_licenses → redirect batch;「上層主系統照」下拉的選項:from license_center.modules.licensing.service import … 若 licensing service 沒有「列某客戶現行照」的函式就在 licensing service 加一支 list_current_licenses(repo, customer_code)(薄,呼叫既有 repo),不直接 import licensing 的 repository)、batch(GET /batch/<batch_id>;列表+每張「下載未綁機照」+「全部下載 zip」用 io.BytesIO+zipfile,檔名 <id>.license armor)、activate(GET/POST → activate_agent_license → redirect activate_result)、activate_result(GET /activate/<id>/result)、detail(GET /<id>;list_events;非現行照顯示「已被取代」+接替照連結、不給下載)、download(get_if_current 守門,armor)、extend/reissue/rebind(GET 表單 + POST,照 issuance 的 extend/reissue_confirm/rebind)。全部 login_required。agent_licenses_index.html/agent_license_issue_form.html/agent_license_batch.html/agent_license_activate_form.html/agent_license_detail.html)照對應既有模板複製改;base.html 導覽列在「離線開通受理」後加 <a href="{{ url_for('agent_licenses.index') }}"><i class="ti ti-device-desktop me-1"></i>Agent 授權</a>。表單 csrf_token hidden;inline script 帶 nonce;不用 onclick=。customer_timeline.py+模板:呼叫 agent_licensing service(不是 repo)拿 count_by_customer 與事件列;加一張卡「Agent 照 N 台(已開通 x/待開通 y)→ 看清單」;事件混進既有時間軸、badge 前綴「Agent」。issue(agent_license_batch=… count=… customer_code=… actor=…)、activate/rebind/reissue/extend(agent_license_id)、download(兩個下載入口都記,稽核「誰把照拿走」);序號只記 activation_code_digest();失敗(序號查無/已用/逾期)WARNING。tests/test_agent_license_views.py:用既有 conftest 的 app fixture——未登入 302;簽發表單 POST count=2 → 302 到 batch 頁且 DB 兩筆;batch 頁 zip 回 application/zip 含兩檔;離線開通 POST → 結果頁含 alic-;詳情非現行照無下載鈕(突變:拿掉 get_if_current 守門 → 紅);log 捕捉不含完整序號。對照雛形 docs/features/FR-182-2611-agent-license/prototype/lc-agent-license.html 七個場景逐頁核:登入後台 → 導覽「Agent 授權」→ 簽發(數量 3)→ 結果頁 3 組序號+zip → 離線開通(序號+64 碼)→ 結果頁下載 .license → CLI agent-verify 過 → 詳情頁事件歷史兩筆(簽發、開通)→ 清單該列「已開通」、另兩列「待開通(序號 N 天後逾期)」→ 客戶時間軸看到「Agent 照 3 台」;tests/test_security_headers.py 掃模板綠(inline script 帶 nonce、無 onclick);tests/test_csrf.py 既有綠;journalctl/stderr 看到六種事件各一條且序號只有摘要;grep -rn border-left templates/ 為 0
~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/features/FR-182-2611-agent-license/design.md(關鍵決策 D1~D8、§4.2 照 payload、§4.3 表、§4.4 六支 service、§4.5 五頁、§4.6 機器 API、§4.7 CLI、拆卡表本卡那列);討論稿 ~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/features/FR-182-2611-agent-license/discussion.md §2 現況盤點(哪些 reuse/extend)~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/features/FR-182-2611-agent-license/prototype/lc-agent-license.html(七場景,L2 對照用;L1/L3 看一眼知道資料要長什麼樣)