Files
group_xinghuo_jinrong/docs/course/jinrong-module-risk/modules/03-tools-rest.html
T
zhanghongyu_0626 793c0307f8 feat(risk): Enhance risk management functionality and access control
- Updated `RiskListAccess` and `ThresholdWriteAccess` to enforce access control in the risk repository and threshold repository, ensuring only authorized roles can perform sensitive operations.
- Introduced new methods in `RiskRepository` for counting pending alerts and listing alerts with access checks, improving data security and compliance.
- Enhanced the `chat.py` and `deps.py` files to integrate compliance roles into the risk management matrix, allowing for more granular access control.
- Updated documentation to reflect the new testing baseline of 825 passed tests, indicating improved stability and functionality across the application.

This update significantly strengthens the risk management capabilities, ensuring robust access control and compliance with organizational policies.
2026-09-11 17:07:22 +08:00

136 lines
7.6 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<section class="module" id="module-3">
<div class="module-inner">
<p class="eyebrow animate-in">模块 3 · REST 与对话 Tool</p>
<h1 class="module-title animate-in">台账 REST 要带 risk 头<br>对话靠六只 Tool</h1>
<p class="module-lead animate-in">
风控<span class="term" data-definition="REST:用 URL + HTTP 方法(GET/POST)访问的后端接口,浏览器和脚本都能调。">REST</span>
走模块鉴权工厂(<code>deps.py</code> 的 <code>get_auth_context</code>),前端必须带 <code>X-Agent-Type: risk</code>。
风控对话走顾问通用编排(<code>agent_service.py</code>)的 risk 分支 + SSE;Tool 由风控对话 Tool 注册表(<code>chat_tools.py</code>)注册 <strong>六只</strong>只读 Tool,经对话 Tool 编排(<code>tool_service.py</code>)分发。
</p>
<div class="screen animate-in">
<h2>预警 REST 两端点</h2>
<div class="pattern-cards">
<div class="pattern-card">
<h3>GET /api/risk/alerts</h3>
<p>risk_officer / risk_manager 全量;compliance 强制只看 aml;响应含 <code>disclaimer</code></p>
</div>
<div class="pattern-card">
<h3>POST /api/risk/alerts/{id}/handle</h3>
<p>仅 risk_officer;handler_result 三枚举 + 审计;409 状态冲突</p>
</div>
</div>
<div class="callout callout-warning">
<strong>曾踩过的坑:</strong> <code>web/src/api/risk.ts</code> 若漏 <code>X-Agent-Type: risk</code>,JWT 正确也 401。
问数 API 则相反——不要带这个头。
</div>
</div>
<div class="screen animate-in">
<h2>风控对话 Tool(chat_tools.py)注册表(C1 + 扩展)</h2>
<div class="file-tree animate-in">
<div class="tree-item tree-folder">风控对话 Tool(app/service/risk/chat_tools.py)</div>
<div class="tree-item tree-indent">alert_query — 客户或全量待审预警</div>
<div class="tree-item tree-indent">customer_context — L0 + L3 + 待审预警</div>
<div class="tree-item tree-indent">suitability_check — 只读校验 + 审计落库</div>
<div class="tree-item tree-indent">aml_lookup — 名单匹配</div>
<div class="tree-item tree-indent">query_overdue_alerts — 超期未处置(FR-9)</div>
<div class="tree-item tree-indent">query_agent_behavior — 代理人行为链(FR-10)</div>
</div>
<p>红线:Tool 只读,不生成预警单、不处置、不改正式风险等级。</p>
</div>
<div class="screen animate-in">
<h2>群聊:风控问「今天多少待审预警」</h2>
<div class="chat-window" id="chat-risk-m3">
<div class="chat-messages">
<div class="chat-message" data-msg="0" data-sender="browser" style="display:none">
<div class="chat-avatar" style="background:#D94F30">前</div>
<div class="chat-bubble">
<span class="chat-sender" style="color:#D94F30">RiskChatPage</span>
<p>POST /api/chat/stream · X-Agent-Type: risk</p>
</div>
</div>
<div class="chat-message" data-msg="1" data-sender="chat" style="display:none">
<div class="chat-avatar" style="background:#E87A62">API</div>
<div class="chat-bubble">
<span class="chat-sender" style="color:#E87A62">tool_service</span>
<p>意图命中「待审预警」→ alert_query(customer_id 空缺=全量)</p>
</div>
</div>
<div class="chat-message" data-msg="2" data-sender="tool" style="display:none">
<div class="chat-avatar" style="background:#B83D24">Tool</div>
<div class="chat-bubble">
<span class="chat-sender" style="color:#B83D24">alert_query</span>
<p>RiskRepository.list_alerts → 今日新增口径 + alert_id 列表</p>
</div>
</div>
<div class="chat-message" data-msg="3" data-sender="llm" style="display:none">
<div class="chat-avatar" style="background:#D4A843">AI</div>
<div class="chat-bubble">
<span class="chat-sender" style="color:#D4A843">DeepSeek</span>
<p>组织自然语言;可追问 query_agent_behavior 查 STAFF 行为链</p>
</div>
</div>
</div>
<div class="chat-typing" id="chat-risk-m3-typing" style="display:none">
<div class="chat-avatar" id="chat-risk-m3-typing-avatar">…</div>
<div class="chat-typing-dots"><span class="typing-dot"></span><span class="typing-dot"></span><span class="typing-dot"></span></div>
</div>
<div class="chat-controls">
<button class="btn chat-next-btn">下一条</button>
<button class="btn chat-all-btn">全部播放</button>
<button class="btn chat-reset-btn">重播</button>
<span class="chat-progress"></span>
</div>
</div>
</div>
<div class="screen animate-in">
<div class="translation-block">
<div class="translation-code">
<span class="translation-label">前端 · risk.ts + simulate</span>
<pre><code><span class="code-line">apiFetch(<span class="code-string">'/api/risk/alerts'</span>, {</span>
<span class="code-line"> token, agentType: <span class="code-string">'risk'</span>, <span class="code-comment">// 必须</span></span>
<span class="code-line">})</span>
<span class="code-line"><span class="code-comment">// RiskSimulatePage → /api/simulate/trade 同样带 risk</span></span></code></pre>
</div>
<div class="translation-english">
<span class="translation-label">白话</span>
<div class="translation-lines">
<p class="tl">台账页、模拟交易页、风控对话——凡走 get_auth_context 的都要声明 risk 线。</p>
<p class="tl">处置预警用 handle REST;日常问数用对话 Tool,两者不要混接口。</p>
</div>
</div>
</div>
<div class="quiz-container" id="quiz-risk-m3">
<div class="quiz-question-block"
data-correct="option-a"
data-explanation-right="query_agent_behavior 查 audit/行为链,支持 agent_id 过滤;是 FR-10 专用 Tool。"
data-explanation-wrong="customer_context 是客户档案+L3;行为链是独立 Tool。">
<h3 class="quiz-question">风控对话里问「代理人 STAFF-Q 有没有越权记录」,应触发哪个 Tool?</h3>
<div class="quiz-options">
<button class="quiz-option" data-value="option-a" onclick="selectOption(this)">
<div class="quiz-option-radio"></div><span>query_agent_behavior</span>
</button>
<button class="quiz-option" data-value="option-b" onclick="selectOption(this)">
<div class="quiz-option-radio"></div><span>customer_context</span>
</button>
<button class="quiz-option" data-value="option-c" onclick="selectOption(this)">
<div class="quiz-option-radio"></div><span>aml_lookup</span>
</button>
</div>
<div class="quiz-feedback"></div>
</div>
<button class="quiz-check-btn" onclick="checkQuiz('quiz-risk-m3')">检查答案</button>
<button class="quiz-reset-btn" onclick="resetQuiz('quiz-risk-m3')">重做</button>
</div>
<p style="margin-top:2rem; font-size:0.9rem; color: var(--color-text-muted);">
仓库现状(2026-09-10):STAFF-30001 含 risk_demo;<code>python -m pytest</code> → <strong>825 passed</strong>。
</p>
</div>
</div>
</section>