feat!: require explicit user on every tenant-data endpoint

Remove the implicit jpmschweitzer default tenant (DEFAULT_USER) from
src/core/multi_tenancy.py and every endpoint and request model that
inherited it (~40 endpoints across /query, /wiki, /vector, /graph,
/ingest, /volatile, /documents, /stats, /rag).

- Add validate_required_user() + RequiredUser pydantic type in
  multi_tenancy and a shared require_user FastAPI dependency
  (RequiredUserQuery) that rejects missing, empty, and whitespace-only
  users with 422, following the /maintenance/* pattern.
- Wiki page create / smart-create / dossier request models now require
  user (no fallback in wiki_service).
- /maintenance/cleanup/test-data derives the tenant from the page path
  instead of using the production tenant collection.
- Wiki.js change listener skips changes when no tenant user can be
  derived from the notification email instead of defaulting to the
  production tenant.
- Consolidation service internal helpers no longer default to the
  production tenant.
- Tool catalog marks user as required with honest descriptions.
- OpenAPI descriptions updated honestly; CHANGELOG notes that callers
  (tatlock, Scheduler ingest tasks) must now send explicit user.
- Offline tests: 422 coverage for query/body endpoints, required-user
  validator tests; updated legacy tests that assumed a default tenant.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 11:06:11 +02:00
co-authored by Claude Fable 5
parent a66d801abd
commit 84e9185371
27 changed files with 481 additions and 153 deletions
+20 -10
View File
@@ -26,15 +26,20 @@ class TestWikiSmartCreateRequest:
"""Tests for WikiSmartCreateRequest model validation."""
def test_minimal_request(self):
"""Test request with only required field."""
request = WikiSmartCreateRequest(topic="Docker containers")
"""Test request with only required fields (topic AND user)."""
request = WikiSmartCreateRequest(topic="Docker containers", user="llm_tester")
assert request.topic == "Docker containers"
assert request.path is None
assert request.tags == []
assert request.user is None
assert request.user == "llm_tester"
assert request.include_web_research is True
assert request.include_wiki_search is True
def test_user_is_required(self):
"""A request without an explicit user must be rejected."""
with pytest.raises(ValueError):
WikiSmartCreateRequest(topic="Docker containers")
def test_full_request(self):
"""Test request with all fields."""
request = WikiSmartCreateRequest(
@@ -68,7 +73,8 @@ class TestWikiSmartCreateRequest:
"""Test that path without leading slash gets one added."""
request = WikiSmartCreateRequest(
topic="Test",
path="technology/test"
path="technology/test",
user="llm_tester"
)
assert request.path == "/technology/test"
@@ -76,7 +82,8 @@ class TestWikiSmartCreateRequest:
"""Test that trailing slash is removed."""
request = WikiSmartCreateRequest(
topic="Test",
path="/technology/test/"
path="/technology/test/",
user="llm_tester"
)
assert request.path == "/technology/test"
@@ -84,7 +91,8 @@ class TestWikiSmartCreateRequest:
"""Test that duplicate tags are removed."""
request = WikiSmartCreateRequest(
topic="Test",
tags=["devops", "devops", "containers", "devops"]
tags=["devops", "devops", "containers", "devops"],
user="llm_tester"
)
assert len(request.tags) == 2
assert "devops" in request.tags
@@ -94,7 +102,8 @@ class TestWikiSmartCreateRequest:
"""Test that tag whitespace is cleaned."""
request = WikiSmartCreateRequest(
topic="Test",
tags=[" devops ", "containers", " ", ""]
tags=[" devops ", "containers", " ", ""],
user="llm_tester"
)
assert "devops" in request.tags
assert "containers" in request.tags
@@ -536,7 +545,8 @@ class TestSmartCreateEndpoint:
# For now, we test the model validation
request = WikiSmartCreateRequest(
topic="Test Topic",
tags=["test"]
tags=["test"],
user="llm_tester"
)
assert request.topic == "Test Topic"
@@ -546,8 +556,8 @@ class TestSmartCreateEndpoint:
WikiSmartCreateRequest(topic="")
def test_request_accepts_minimal_input(self):
"""Test that only topic is required."""
request = WikiSmartCreateRequest(topic="Minimal test")
"""Test that topic and user are the only required fields."""
request = WikiSmartCreateRequest(topic="Minimal test", user="llm_tester")
assert request.topic == "Minimal test"
assert request.include_web_research is True # default
assert request.include_wiki_search is True # default