本卡屬 FR-182(母卡 CM-3609 https://app.notion.com/p/FR-182-Agent-Agent-P1-License-Center-4-3-410346da4cd0816ea5e2c4757ebc4fbb),P2 Agent 端,卡 P2-2,Stage 4(P2 第一批,接在 P1 的批 1~3 之後;P1 LC 端 CM-3610~3613 已 Done 並上 189)。只改 evidence-agent。依賴:無(同批 P2-1/P2-2/P2-3 平行;P2-2 的 gate 介面以 P2-1 為準,合回後對一次)。

這張卡做什麼(白話)

P2-1 讓 Agent 認得照、沒照就不起 sync;這張卡給主控台兩支 API,畫面(P2-3)靠它們:①看授權狀態+本機機器碼(任何登入者都能看——客戶要抄機器碼給原廠);②上傳照(只有「設定」權限能傳)。上傳走 P2-1 的 install:先驗新檔、通過才覆蓋,驗不過原檔不動、回明確原因(型別不對/簽章不對/綁的是別台/已過期/檔壞了),畫面照原因顯示一句人話。順便在總覽 API 多帶授權狀態與到期日兩個值,總覽頁頂端要顯示「N 天後到期」提醒。全部照 keys_routes.py 的形狀(薄殼、require_session、body 上限、稽核)。

reuse/extend/new

new:guidant_agent/console/api/license_routes.py(license_bp,url_prefix="/api/license")——GET "" @require_session(None)(任何登入者)回 {status, reason, license_id, customer_code, issued_to, type, starts_at, expires_at, days_to_expiry, grace_days_left, machine_fingerprint(本機 device_uuid 完整 64 碼), bound_fingerprint_prefix, expiry_policy};POST /upload @require_session("configure"),body_limit.read_limited(64 KB)、multipart 或 raw body 都收 → license.app.install.install(bytes) → 成功回新狀態 200、失敗 400 帶 reason(wrong_type/bad_signature/mismatch/expired/malformed);兩支都 page_viewed/audit(事件碼用既有 Code 裡最接近的,不加新事件碼——event_code.py 是登記型檔,P3 統一加)。extend:console/api/__init__.py 檔尾加一行 from ...license_routes import license_bp 與 SUB_BLUEPRINTS 加一項(登記型,本卡 owner);console/api/pages.py _SPA_PAGES 加 "license";console/app/overview.py 回應加 license: {status, expires_at} 兩鍵(總覽頁頂端要顯示提醒)。禁:不碰 console/api/__init__.py 的 create_session/require_session(FR-179 A1 的範圍)。

在哪裡

repo:~/Projects/Billows/Audit-Manager/evidence-agent
改既有:guidant_agent/console/api/__init__.py(檔尾 import 一行+SUB_BLUEPRINTS 一項)
改既有:guidant_agent/console/api/pages.py(_SPA_PAGES 加 license)
改既有:guidant_agent/console/app/overview.py(加 license 兩鍵)
新開:guidant_agent/console/api/license_routes.py
新開:test/test_license_routes.py

怎麼做

驗收(首腦照這個驗)

pytest:未登入 401;files scope 的票 GET 200、POST 403;上傳主系統照 400 wrong_type;上傳壞簽章 400 bad_signature;上傳別台的照 400 mismatch 且回 bound_fingerprint_prefix;上傳對的照 200 且 GET 變 valid;65 KB body 413;_SPA_PAGES 含 license(GET /console/license 回 SPA 殼 200);守衛三支綠。本機 curl -k --http1.1 走一遍(本機管理員登入拿 cookie)

必讀