"""Startup and error-surface guards in `create_app` (NIST SI-11, AU-11).""" from __future__ import annotations import pytest from fastapi.testclient import TestClient import ypms.main from ypms.main import create_app def test_unhandled_exception_is_opaque_and_carries_request_id() -> None: app = create_app() @app.get("/_boom") def boom() -> None: raise RuntimeError("DETAIL: Key (email)=(kid@example.org) already exists") with TestClient(app, raise_server_exceptions=False) as c: r = c.get("/_boom", headers={"X-Request-ID": "req-abc123"}) assert r.status_code == 500 assert r.json() == {"error": "internal_error", "request_id": "req-abc123"} assert r.headers["X-Request-ID"] == "req-abc123" assert "kid@example.org" not in r.text assert "Traceback" not in r.text def test_unhandled_exception_log_omits_message(caplog: pytest.LogCaptureFixture) -> None: app = create_app() @app.get("/_boom") def boom() -> None: raise RuntimeError("parameters: ('123456789', 'kid@example.org')") with TestClient(app, raise_server_exceptions=False) as c: c.get("/_boom") logged = "\n".join(r.getMessage() for r in caplog.records) assert "request.unhandled_exception" in logged assert "RuntimeError" in logged assert "kid@example.org" not in logged and "123456789" not in logged def test_app_refuses_to_start_without_retention_policies( monkeypatch: pytest.MonkeyPatch, ) -> None: monkeypatch.setattr(ypms.main, "missing_policies", lambda: ["orphans"]) with pytest.raises(RuntimeError, match="orphans"): create_app()