Files
writer-work-flow/apps/api/tests/test_credentials_crypto.py
Yaojia Wang b523b4fd21 feat: M1 — 立项→写章草稿(SSE)→自动保存;连一家 provider
- 薄自建 LLM 网关:OpenAI 兼容适配器(DeepSeek) + instructor 结构化输出 + usage_ledger 记账 + 档位路由
- 记忆服务 assemble:确定性选择(显式+主角+近况) + 渲染卡 + 缓存断点(中性文本)
- LangGraph 写章节点 + Postgres checkpointer + SSE 归一(token/done/error)
- API:立项 + 写章 draft(SSE) + PUT 自动保存 + 提供商凭据(Fernet 加密/测试连接)
- 前端:AppShell + 作品库 + 5 步立项向导 + 写作工作台(流式打字机+自动保存) + 设置页
- M1 E2E:真实 DB + mock 网关零 token 走通闭环
2026-06-18 11:38:28 +02:00

60 lines
1.6 KiB
Python
Raw Permalink 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.

"""T1.7 凭据加密工具单测——Fernet 往返 + 掩码ARCH §4.7)。
绝不在响应/日志回显明文 Key。
"""
from __future__ import annotations
import pytest
from cryptography.fernet import Fernet
from ww_api.security.credentials import (
CredentialKeyError,
decrypt_api_key,
encrypt_api_key,
mask_api_key,
)
KEY = Fernet.generate_key().decode()
def test_encrypt_decrypt_round_trip() -> None:
# Arrange
plaintext = "sk-abc123def456"
# Act
blob = encrypt_api_key(plaintext, key=KEY)
# Assert
assert isinstance(blob, bytes)
assert plaintext.encode() not in blob # 密文不含明文
assert decrypt_api_key(blob, key=KEY) == plaintext
def test_encrypt_is_non_deterministic() -> None:
# Fernet 含随机 IV——两次加密产物不同但都能解回
a = encrypt_api_key("sk-secret", key=KEY)
b = encrypt_api_key("sk-secret", key=KEY)
assert a != b
assert decrypt_api_key(a, key=KEY) == decrypt_api_key(b, key=KEY) == "sk-secret"
def test_missing_key_fails_fast() -> None:
with pytest.raises(CredentialKeyError):
encrypt_api_key("sk-x", key="")
def test_invalid_key_fails_fast() -> None:
with pytest.raises(CredentialKeyError):
encrypt_api_key("sk-x", key="not-a-valid-fernet-key")
def test_mask_shows_only_last_four() -> None:
assert mask_api_key("sk-abcdefgh1234") == "sk-…1234"
def test_mask_short_key_fully_hidden() -> None:
# 极短 key 不泄露任何字符
assert mask_api_key("ab") == "sk-…••••"
def test_mask_empty_key() -> None:
assert mask_api_key("") == "sk-…••••"