feat(errors): incident-key safe error envelopes (v1.7.2)
This commit is contained in:
72
tests/test_error_envelopes.py
Normal file
72
tests/test_error_envelopes.py
Normal file
@@ -0,0 +1,72 @@
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi.testclient import TestClient
|
||||
|
||||
import app as app_module
|
||||
|
||||
|
||||
def make_client(tmp_path: Path) -> TestClient:
|
||||
os.environ["JARVISCHAT_ADMIN_PIN"] = "1234"
|
||||
app_module.DB_PATH = tmp_path / "jarvischat-errors.db"
|
||||
app_module.SESSIONS.clear()
|
||||
app_module.PIN_ATTEMPTS.clear()
|
||||
app_module.RATE_EVENTS.clear()
|
||||
app_module.init_db()
|
||||
return TestClient(app_module.app, raise_server_exceptions=False)
|
||||
|
||||
|
||||
def test_unhandled_api_exception_returns_friendly_error_with_incident_key(
|
||||
tmp_path: Path, monkeypatch
|
||||
):
|
||||
with make_client(tmp_path) as client:
|
||||
sid = client.post("/api/auth/guest", headers={"Origin": "http://testserver"}).json()[
|
||||
"session_id"
|
||||
]
|
||||
headers = {"X-Session-ID": sid}
|
||||
|
||||
def boom(_topic=None):
|
||||
raise RuntimeError("super secret db internals")
|
||||
|
||||
monkeypatch.setattr(app_module, "get_all_memories", boom)
|
||||
|
||||
resp = client.get("/api/memories", headers=headers)
|
||||
assert resp.status_code == 500
|
||||
payload = resp.json()
|
||||
assert payload.get("error_key", "").startswith("INC-")
|
||||
assert "support lookup" in payload.get("detail", "").lower()
|
||||
assert "super secret db internals" not in resp.text
|
||||
|
||||
|
||||
def test_chat_stream_error_hides_internal_exception_and_emits_incident_key(
|
||||
tmp_path: Path, monkeypatch
|
||||
):
|
||||
with make_client(tmp_path) as client:
|
||||
sid = client.post("/api/auth/guest", headers={"Origin": "http://testserver"}).json()[
|
||||
"session_id"
|
||||
]
|
||||
headers = {"X-Session-ID": sid, "Origin": "http://testserver"}
|
||||
|
||||
class BrokenStreamContext:
|
||||
async def __aenter__(self):
|
||||
raise RuntimeError("ultra secret model transport failure")
|
||||
|
||||
async def __aexit__(self, exc_type, exc, tb):
|
||||
return False
|
||||
|
||||
def broken_stream(*args, **kwargs):
|
||||
return BrokenStreamContext()
|
||||
|
||||
monkeypatch.setattr(app_module.httpx.AsyncClient, "stream", broken_stream)
|
||||
|
||||
resp = client.post(
|
||||
"/api/chat",
|
||||
json={"message": "hello", "model": app_module.DEFAULT_MODEL},
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
assert resp.status_code == 200
|
||||
body = resp.text
|
||||
assert "ultra secret model transport failure" not in body
|
||||
assert "error_key" in body
|
||||
assert "support lookup" in body.lower()
|
||||
Reference in New Issue
Block a user