本卡屬 FR-182(母卡 FR-182 母案(同清單上一張)),卡 L1,批 1。只改 license_center repo。依賴:無。

這張卡做什麼(白話)

主系統每個租戶要有一張簽過章的授權照才能用,Agent 沒有——拿到註冊 token 就能裝、裝幾台都行。決策者定調 Agent 要比照主系統拿照:License Center(簽發站,獨立 repo 獨立 DB)簽一張「Agent 照」、給客戶一組序號、客戶在 Agent 主控台看到機器碼、把序號+機器碼交回來、員工在 LC 開通簽出綁那台機器的照、寄回給客戶上傳。Agent 照跟主系統的照是不同的一張(記上層主系統照號當對照),沒有模組清單(Agent 不分功能,只分有照/沒照),到期政策只有「到期前幾天提醒、到期後寬限幾天」兩個數字。這張卡是 LC 端的地基:新開一個模組 agent_licensing(自己一張表,不碰主系統照那張表),簽發/開通/換綁/補發/展延六支純函式,照格式用既有簽章引擎加一種型別 agent_license,加五支 CLI 保底。順便把「序號產生/效期」與「私鑰解鎖」這兩段跟主系統照無關的邏輯從 licensing 模組抽到共用層,新模組才不用跨模組 import(LC 鐵律③)。也先把後面兩張卡要用的三個 blueprint 空殼建好、掛進 app.py——app.py 是大家都要往裡加一行的登記檔,由本卡一次掛完,L2/L3 只填自己的檔。

reuse/extend/new

extend:序號三支(ACTIVATION_CODE_TTL/new_activation_code/is_activation_code_expired)從 modules/licensing/service.py 抽到 core/activation_code.py,licensing 改 import(行為不變,既有測試要綠);web/views/issuance.py 的 _resolve_passphrase/_unlock_or_flash_redirect 搬到 web/unlock_helper.py,issuance 改 import;core/crypto/engine.py 加 PAYLOAD_TYPE_AGENT_LICENSE = "agent_license";core/status.py 加 compute_agent_status(expires_at, notify_days_before, grace_days)(四態 valid/notice/grace/expired,不改 compute_status);core/schema.py 加 AgentLicense dataclass(與 License 並列不繼承)。new:modules/agent_licensing/{models,repository,service}.py——AgentLicenseIssuance 表(欄位見 design §4.3)、repo(insert/get_by_id/get_by_activation_code/list_current/list_by_batch/mark_activated/mark_rebind_invalidated/count_by_customer)、service 六支(issue_agent_licenses(count)/activate_agent_license/rebind_agent_license/reissue_agent_license/extend_agent_license/verify),形狀照 licensing;Alembic revision;migrations/env.py 加 import;cli/agent_commands.py 五支(agent-issue/agent-activate/agent-verify/agent-extend/agent-rebind),cli/main.py 一行 cli.add_command。登記型 owner:建空殼 web/views/agent_licenses.py(只有 bp = Blueprint)與 web/views/agent_activation_api.py、web/views/internal_agent_api.py(空 Blueprint+空 schema 不掛路由),web/app.py 三行掛上(機器兩支走 api.register_blueprint+exempt_machine_apis 加進去)——L2/L3 只填檔不碰 app.py。DEV 套 migration(.env 指 license_center_dev)

在哪裡

repo:~/Projects/Billows/Audit-Manager/license_center
改既有:src/license_center/core/crypto/engine.py
改既有:src/license_center/core/schema.py
改既有:src/license_center/core/status.py
改既有:src/license_center/modules/licensing/service.py(改 import 序號三支)
改既有:src/license_center/web/views/issuance.py(改 import 解鎖兩支)
改既有:src/license_center/web/views/activation.py(改 import is_activation_code_expired)
改既有:src/license_center/cli/main.py(add_command 一行)
改既有:src/license_center/web/app.py(掛三個 blueprint)
改既有:src/license_center/web/csrf.py(exempt 加兩個)
改既有:migrations/env.py
新開:src/license_center/core/activation_code.py
新開:src/license_center/web/unlock_helper.py
新開:src/license_center/modules/agent_licensing/__init__.py
新開:src/license_center/modules/agent_licensing/models.py
新開:src/license_center/modules/agent_licensing/repository.py
新開:src/license_center/modules/agent_licensing/service.py
新開:src/license_center/web/views/agent_licenses.py(空殼)
新開:src/license_center/web/views/agent_activation_api.py(空殼)
新開:src/license_center/web/views/internal_agent_api.py(空殼)
新開:src/license_center/cli/agent_commands.py
新開:migrations/versions/<rev>_agent_licensing_agent_license_issuance.py
新開:tests/test_agent_license_service.py
新開:tests/test_agent_status.py
新開:tests/test_activation_code_shared.py

怎麼做