M41: harden trust boundaries and delivery
This commit is contained in:
@@ -7,6 +7,7 @@ import httpx
|
||||
|
||||
from app.api.routers import knowledge as knowledge_router
|
||||
from app.core.config import get_settings
|
||||
from app.core.ratelimit import SlidingWindowLimiter
|
||||
from app.services.knowledge import KnowledgeHealth
|
||||
from app.services.knowledge.demo import DemoKnowledgeProvider
|
||||
from app.services.knowledge.procedures import iter_procedure_documents
|
||||
@@ -140,6 +141,16 @@ def test_ask_question_requires_authentication(client):
|
||||
assert response.status_code == 401
|
||||
|
||||
|
||||
def test_knowledge_questions_are_bounded_per_session_and_client(ops_client, monkeypatch):
|
||||
limiter = SlidingWindowLimiter(max_requests=1, window_seconds=60)
|
||||
monkeypatch.setattr(knowledge_router, "_question_limiter", limiter)
|
||||
body = {"question": "What is the vehicle return procedure?"}
|
||||
assert ops_client.post("/api/v1/knowledge/questions", json=body).status_code == 200
|
||||
blocked = ops_client.post("/api/v1/knowledge/questions", json=body)
|
||||
assert blocked.status_code == 429
|
||||
assert int(blocked.headers["retry-after"]) >= 1
|
||||
|
||||
|
||||
def test_ask_question_is_audited_without_leaking_full_text(ops_client):
|
||||
ops_client.post(
|
||||
"/api/v1/knowledge/questions",
|
||||
@@ -695,5 +706,38 @@ def test_ragcore_search_fallback_prefers_damage_procedure(monkeypatch):
|
||||
),
|
||||
)
|
||||
answer = provider.ask("Wat moet ik doen bij schade?", "test-correlation-damage", "nl-BE")
|
||||
assert answer.evidence_state == "insufficient"
|
||||
assert answer.answer == ""
|
||||
assert any(source.document_id == "damage-procedure" for source in answer.sources)
|
||||
|
||||
|
||||
def test_ragcore_search_fallback_accepts_relevant_damage_evidence_above_threshold(monkeypatch):
|
||||
provider = RAGcoreKnowledgeProvider()
|
||||
monkeypatch.setattr(provider._settings, "ragcore_space_id", "space-1")
|
||||
search = _search_body()
|
||||
search["results"].append(
|
||||
{
|
||||
"citation": {
|
||||
"document_id": "damage-procedure",
|
||||
"document_version_id": "version-2",
|
||||
"title": "damage-procedure.md",
|
||||
"section": "Damage",
|
||||
"excerpt": "Record damage and keep the vehicle blocked.",
|
||||
},
|
||||
"rank": 1,
|
||||
"scores": {"fused": 0.5},
|
||||
}
|
||||
)
|
||||
monkeypatch.setattr(
|
||||
provider,
|
||||
"_client",
|
||||
lambda: _FakeClient(
|
||||
post_responses={
|
||||
"/v1/answers": _FakeResponse(503, {}),
|
||||
"/v1/search": _FakeResponse(200, search),
|
||||
}
|
||||
),
|
||||
)
|
||||
answer = provider.ask("Wat moet ik doen bij schade?", "strong-damage", "nl-BE")
|
||||
assert answer.evidence_state == "grounded"
|
||||
assert answer.sources[0].document_id == "damage-procedure"
|
||||
|
||||
Reference in New Issue
Block a user