feat: complete customer service safety and handover flow
This commit is contained in:
@@ -51,6 +51,48 @@ async def test_accept_is_idempotent_and_persists_outbox() -> None:
|
||||
await session.commit()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_customer_service_accept_redacts_sensitive_message_before_persistence() -> None:
|
||||
"""客服原始凭据只能存在于请求瞬间,数据库会话中必须是脱敏文本。"""
|
||||
session_id = f"privacy-{uuid4()}"
|
||||
key = f"privacy-key-{uuid4()}"
|
||||
raw_message = "验证码 123456,银行卡 6222021234567890123,登录密码: Secret123"
|
||||
context = RequestContext(
|
||||
user_id="1", trace_id=str(uuid4()), roles=("customer",), permissions=("agent:run",)
|
||||
)
|
||||
request = AgentRequest(
|
||||
agent_type="customer_service", message=raw_message, session_id=session_id,
|
||||
idempotency_key=key,
|
||||
)
|
||||
run_id = ""
|
||||
async with SessionFactory() as session:
|
||||
try:
|
||||
accepted = await AgentRunApplicationService(session).accept(request, context)
|
||||
run_id = accepted.run_id
|
||||
message = await session.scalar(select(ConversationMessage).where(
|
||||
ConversationMessage.session_id == session_id,
|
||||
ConversationMessage.role == "user",
|
||||
))
|
||||
assert message is not None
|
||||
assert "123456" not in message.content
|
||||
assert "6222021234567890123" not in message.content
|
||||
assert "Secret123" not in message.content
|
||||
assert "验证码" in message.content
|
||||
assert "银行卡号已隐藏" in message.content
|
||||
finally:
|
||||
if run_id:
|
||||
run = await session.scalar(select(AgentRun).where(AgentRun.run_id == run_id))
|
||||
if run is not None:
|
||||
await session.execute(delete(AgentRun).where(AgentRun.id == run.id))
|
||||
await session.execute(delete(RequestIdempotency).where(
|
||||
RequestIdempotency.id == run.idempotency_id
|
||||
))
|
||||
await session.execute(delete(ConversationMessage).where(
|
||||
ConversationMessage.session_id == session_id
|
||||
))
|
||||
await session.commit()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_concurrent_same_key_creates_at_most_one_run() -> None:
|
||||
session_id = f"concurrent-{uuid4()}"
|
||||
|
||||
Reference in New Issue
Block a user