fix(evidence): validate ownership before all searches

This commit is contained in:
2026-07-12 06:04:00 +02:00
parent c6966f3d15
commit d21aac9151
4 changed files with 68 additions and 15 deletions
+33 -3
View File
@@ -257,7 +257,10 @@ def test_active_searcher_splits_default_and_mixed_kinds_before_global_limit(tmp_
from tht.search.evidence import ActiveEvidenceSearcher
store = CorpusStore(tmp_path / "corpus")
generation = store.stage(CorpusManifest(), {}, generation="gen:" + "a" * 32)
generation = store.stage(
CorpusManifest(metadata={"workspace_id": "default"}), {},
generation="gen:" + "a" * 32,
)
store.publish(generation)
calls = []
@@ -368,7 +371,8 @@ def test_gc_rejects_workspace_mismatch_without_deleting(tmp_path):
assert wrong.store.list_generations() == generations
def test_active_search_rejects_workspace_mismatch_before_delegate(tmp_path):
@pytest.mark.parametrize("kinds", [None, ["evidence", "memory"], ["memory"]])
def test_active_search_rejects_workspace_mismatch_before_delegate(tmp_path, kinds):
from tht.search.evidence import ActiveEvidenceSearcher, CorpusWorkspaceMismatchError
vectors = Vectors()
@@ -386,7 +390,33 @@ def test_active_search_rejects_workspace_mismatch_before_delegate(tmp_path):
with pytest.raises(CorpusWorkspaceMismatchError, match="different workspace"):
ActiveEvidenceSearcher(
owner.store, Delegate(), expected_workspace_id="workspace-b",
).search([1.0], kinds=["evidence"])
).search([1.0], kinds=kinds)
def test_unscoped_active_manifest_is_never_adopted_by_direct_run_or_gc(tmp_path):
store = CorpusStore(tmp_path / "corpus")
generation = store.stage(CorpusManifest(), {})
store.publish(generation)
class ForbiddenSource:
def discover(self):
raise AssertionError("invalid corpus reached source discovery")
class ForbiddenVectors:
def __getattr__(self, name):
raise AssertionError(f"invalid corpus reached vector operation {name}")
candidate = CorpusPipeline(
store=store, sources=[ForbiddenSource()], embedder=Embedder(),
vector_store=ForbiddenVectors(), embedding_model="model", embedding_dimensions=3,
chunk_policy=ChunkPolicy(version="chunk-v1", max_chars=100),
pipeline_version="evidence-v1",
)
with pytest.raises(PipelineError, match="missing or invalid"):
candidate.run()
with pytest.raises(PipelineError, match="missing or invalid"):
candidate.gc(workspace_root=tmp_path)
assert store.active_generation() == generation
def test_unchanged_documents_skip_acquire_normalize_chunk_and_embed(tmp_path):