本卡屬 FR-182(母卡 CM-3609 https://app.notion.com/p/FR-182-Agent-Agent-P1-License-Center-4-3-410346da4cd0816ea5e2c4757ebc4fbb),P3 主系統端,卡 P3-3,Stage 6(P1 LC 端已 Done 上 188/189;P2 Agent 端 CM-3621~3623 Stage 4)。只改 evidence-agent。依賴:P2-1、P2-2。
P2 做好的 Agent 授權模組,這張卡接上主系統:①status_fields() 從空 dict 改成回授權狀態與到期日兩鍵(白名單 P3-1 已加,主系統 P3-2 已會收);②線上開通:新一支 activate_online(序號)——帶註冊 token+序號+機器碼打主系統 P3-2 的端點,拿回照後走 P2-1 同一條 install()(驗章、核機器碼、落地、開閘門),主系統回的各 error code 對映成 Agent 主控台看得懂的原因;③主控台 API 多一支 POST /api/license/activate-online(P2-2 的檔)。畫面在 P3-3b。
extend(接 P2 的檔):guidant_agent/license/__init__.py status_fields() 回 {"license_status": state.status, "license_expires_at": state.expires_at}(P2-1 留的空 dict 填上;agent_status 元件「有變才送」靠既有 snapshot diff,不另加邏輯);guidant_agent/license/app/online_activate.py(new)activate_online(cfg, code) -> LicenseState:POST {cloud_url}/api/1.0/agents/license/activate body {enroll_token: cfg.registration_token, activation_code, machine_fingerprint: device_uuid}(TLS 驗證走 cloud_trust.cloud_tls_verify 既有;逾時 15 秒)→ 回的 license 丟 P2-1 install()(同一條驗章+落地)→ 回狀態;主系統各 GRC 碼對映成 LicenseRejected(reason):CODE_NOT_FOUND/CODE_USED/LOCKED/LC_UNREACHABLE/LC_UNAVAILABLE/其餘 remote_error;console/api/license_routes.py 加 POST /activate-online @require_session("configure") body {activation_code}(P2-2 的檔,P2 已合回才能動)。FE 畫面在 P3-3b(同批、FE repo)。🔴 registration_token 註冊完 FR-179 A3 會不再留在 .env——本卡先照現況讀 cfg.registration_token,A3 合回後要改成「主控台首次設定頁輸入的 token 暫存」,回寫標明。
repo:~/Projects/Billows/Audit-Manager/evidence-agent
改既有:guidant_agent/license/__init__.py
改既有:guidant_agent/console/api/license_routes.py(加一支)
新開:guidant_agent/license/app/online_activate.py
新開:test/test_license_online_activate.py
guidant_agent/license/(gate.install、LicenseRejected、status_fields)、P2-2 的 console/api/license_routes.py;guidant_agent/sync/app/cloud_trust.py(cloud_tls_verify、describe_tls_failure)、sync/adapters/cloud_http.py(對主系統 POST 的既有寫法——reuse,不自己 httpx.post);config/config.py:137 registration_token;jedi-agent-protocol events.py AGENT_LICENSE_STATUSES(P3-1);P3-2 回寫的五個 GRC 碼。guidant_agent/license/__init__.py status_fields():s = gate.state → {"license_status": s.status, "license_expires_at": s.expires_at}(gate 沒掛回 {})。agent_status 元件的 snapshot diff 自然處理「有變才送」。guidant_agent/license/app/online_activate.py:activate_online(cfg, gate, device_uuid, activation_code) -> LicenseState:用 cloud_http 既有的 POST(TLS 驗證同心跳)打 /api/1.0/agents/license/activate body {enroll_token: cfg.registration_token, activation_code, machine_fingerprint: device_uuid},逾時 15 秒;status 200 → gate.install(json.dumps(body["data"]["license"]).encode());非 200 → 讀 error_code 對映 LicenseRejected(reason):GRC_AGENT_LICENSE_CODE_NOT_FOUND→code_not_found、_CODE_USED→code_used、_LOCKED→locked、_LC_UNREACHABLE→lc_unreachable、_LC_UNAVAILABLE→lc_unavailable、_REJECTED→remote_error(帶 msg)、FILE_AGENT_TOKEN_INVALID→token_invalid、連不上主系統→cloud_unreachable。cfg.registration_token 空 → token_missing(FR-179 A3 之後 .env 不留 token,屆時改讀首次設定頁暫存——本卡回寫標明)。console/api/license_routes.py 加 POST /activate-online @require_session("configure"),body {activation_code} 上限 1 KB,回 GET 同形狀;失敗 400 {error_code: AGENT_LICENSE_REJECTED, reason};稽核同上傳。cloud_http 各回應 → reason;成功 → gate.install 被叫一次;status_fields 兩鍵。守衛綠。curl -k --http1.1 -b cookie -XPOST …/api/license/activate-online -d '{"activation_code":"<LC DEV>"}' → 200 valid;主系統 remote_agents.license_status 變 valid(狀態事件送達)。pytest:mock 主系統各 GRC 碼 → 對應 reason;成功 → install 被叫且狀態 valid;status_fields() 回兩鍵;守衛綠。本機 Agent(P2 合回版)對 DEV 主系統(P3-2 版):主控台輸入 LC DEV 簽的序號 → 10 秒內「已授權」、sync 起來、主系統 remote_agents.license_status=valid
~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/features/FR-182-2611-agent-license/design.md(D6 不擋啟動但不起 sync、D8 用既有 integrity 驗章、§4.2 照 payload、§4.8 Agent 端);討論稿 ~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/features/FR-182-2611-agent-license/discussion.md §2.2 Agent 端盤點、§2.4 與 FR-181/FR-179 接點、§3.7 狀態表~/Projects/Billows/Audit-Manager/compliance-manager-be/docs/features/FR-182-2611-agent-license/prototype/agent-console-license.html(七場景;P2-3 對照刻,P2-1/P2-2 看資料要長什麼樣)~/Projects/Billows/Audit-Manager/evidence-agent/CLAUDE.md、docs/ARCHITECTURE.md(模組分工、依賴方向、守衛)