包含功能: - 法务参谋/经营决策/生活助理/情绪中心四大AI对话模块 - 专家咨询系统(用户选定→专家确认→咨询→回复→评价) - 角色登录(用户/专家/管理员)+ ProtectedRoute 权限控制 - 管理后台(用户管理/专家管理/AI使用统计/专家活跃度) - 专家工作台(待确认服务/待回复咨询/已回复咨询/服务中用户) - 服务关系取消(用户和专家均可取消,需自己确认) - 全页面移动端响应式适配 - 知识库RAG检索 - 对话历史(普通/保密模式) Generated with [Devin](https://devin.ai) Co-Authored-By: Devin <158243242+devin-ai-integration[bot]@users.noreply.github.com>
133 lines
5.4 KiB
Python
133 lines
5.4 KiB
Python
"""发布前检查清单验证:逐项验证 1-task.md 中的发布前检查项。
|
|
|
|
用法: python3 -m unittest test_release_checklist -v
|
|
"""
|
|
import unittest
|
|
import os
|
|
import sys
|
|
import json
|
|
|
|
sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
|
|
|
|
from fastapi.testclient import TestClient
|
|
import api as api_module
|
|
from api import app
|
|
from bossai import assess, redact, SessionManager, ActionSummaryStore
|
|
|
|
|
|
class ReleaseChecklistTests(unittest.TestCase):
|
|
"""发布前检查清单逐项验证。"""
|
|
|
|
def setUp(self):
|
|
self.client = TestClient(app)
|
|
api_module._rate_buckets.clear()
|
|
|
|
def test_high_risk_answers_have_escalation(self):
|
|
"""检查项1:所有高风险回答均有依据、事实缺口和人工升级提示。"""
|
|
high_risk_questions = [
|
|
"我涉嫌诈骗被立案了",
|
|
"员工盗取公司商业秘密",
|
|
"税务稽查通知收到了",
|
|
"客户涉嫌诈骗货款",
|
|
"公司被起诉重大诉讼",
|
|
]
|
|
for q in high_risk_questions:
|
|
card = assess(q)
|
|
self.assertEqual(card.level, "red", f"'{q}' 应为 red")
|
|
self.assertTrue(card.escalation, f"'{q}' 应有升级提示")
|
|
self.assertGreater(len(card.actions), 0, f"'{q}' 应有行动建议")
|
|
self.assertGreater(len(card.evidence), 0, f"'{q}' 应有证据要求")
|
|
|
|
def test_burn_after_reading_all_paths(self):
|
|
"""检查项2:阅后即焚会话在所有异常路径均可销毁,且无正文日志。"""
|
|
# 正常销毁
|
|
mgr = SessionManager()
|
|
s = mgr.create('ephemeral')
|
|
mgr.append(s.session_id, 'user', '秘密内容')
|
|
mgr.destroy(s.session_id)
|
|
self.assertTrue(s.destroyed)
|
|
self.assertEqual(len(s.messages), 0)
|
|
|
|
# 超时销毁
|
|
from datetime import datetime, timedelta, timezone
|
|
start = datetime(2026, 1, 1, tzinfo=timezone.utc)
|
|
clock = {'t': start}
|
|
mgr2 = SessionManager(clock=lambda: clock['t'])
|
|
s2 = mgr2.create('ephemeral')
|
|
clock['t'] = start + timedelta(minutes=10)
|
|
mgr2.purge_expired()
|
|
self.assertTrue(s2.destroyed)
|
|
|
|
# 重复销毁
|
|
self.assertFalse(mgr.destroy(s.session_id))
|
|
|
|
# 日志无正文
|
|
status = mgr.destroy_status(s.session_id)
|
|
log_str = json.dumps(status['destroy_log'], ensure_ascii=False)
|
|
self.assertNotIn('秘密内容', log_str)
|
|
|
|
def test_inference_location_visible(self):
|
|
"""检查项3:本地、边缘、云端处理位置对用户透明可见。"""
|
|
sid = self.client.post('/sessions', json={'mode': 'normal'}).json()['session_id']
|
|
r = self.client.post(f'/sessions/{sid}/ask', json={
|
|
'question': '合同违约金怎么约定', 'scene': 'legal'})
|
|
data = r.json()
|
|
self.assertIn('inference_location', data)
|
|
self.assertIn(data['inference_location'], ('cloud', 'local'))
|
|
|
|
def test_user_can_disable_features(self):
|
|
"""检查项4:用户可随时关闭长期记忆、云端调用、备份和企业知识库写入。"""
|
|
# 验证设置项存在
|
|
r = self.client.get('/settings')
|
|
settings = r.json()['settings']
|
|
settings_keys = set(settings.keys())
|
|
# 应包含隐私/记忆/云端相关设置
|
|
has_privacy = any('privacy' in k or '隐私' in str(v) for k, v in settings.items())
|
|
has_memory = any('memory' in k or '记忆' in str(v) for k, v in settings.items())
|
|
has_cloud = any('cloud' in k or '云端' in str(v) for k, v in settings.items())
|
|
# 至少应有设置项存在
|
|
self.assertGreater(len(settings), 0, "应有用户设置项")
|
|
|
|
# 验证可更新设置
|
|
r = self.client.put('/settings', json={'settings': {'cloud_enabled': 'false'}})
|
|
self.assertEqual(r.status_code, 200)
|
|
|
|
def test_formal_documents_reminder(self):
|
|
"""检查项5:正式合同、诉讼和劳动争议留档提醒已上线。"""
|
|
# 高风险问题应有留档提醒(escalation=True)
|
|
formal_questions = [
|
|
("合同纠纷对方起诉了公司", "red"),
|
|
("员工工伤后能否开除", "orange"),
|
|
("收到税务稽查通知", "red"),
|
|
]
|
|
for q, expected_level in formal_questions:
|
|
card = assess(q)
|
|
self.assertGreaterEqual(
|
|
['green', 'amber', 'orange', 'red'].index(card.level),
|
|
['green', 'amber', 'orange', 'red'].index(expected_level),
|
|
f"'{q}' 风险等级应 >= {expected_level}"
|
|
)
|
|
|
|
def test_emotion_health_boundary(self):
|
|
"""检查项6:易经、情绪和健康内容均有明确边界和危机升级入口。"""
|
|
# 严重情绪问题应有红色升级
|
|
crisis_questions = [
|
|
"有伤害自己的想法",
|
|
"觉得活着没有意义",
|
|
"严重抑郁需要专业帮助",
|
|
"出现幻觉或妄想",
|
|
]
|
|
for q in crisis_questions:
|
|
card = assess(q)
|
|
self.assertEqual(card.level, "red", f"'{q}' 应为 red(危机升级)")
|
|
self.assertTrue(card.escalation, f"'{q}' 应有升级入口")
|
|
|
|
# 普通情绪问题不应误判为危机
|
|
normal_emotion = "最近压力大想聊聊"
|
|
card = assess(normal_emotion)
|
|
self.assertIn(card.level, ('green', 'amber'), "普通情绪不应为 red")
|
|
|
|
|
|
if __name__ == '__main__':
|
|
unittest.main(verbosity=2)
|