Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 29 additions & 1 deletion tests/test_acl.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

import pytest

from vaultrag.retrieval import resolve_principal, search
from vaultrag.retrieval import Principal, resolve_principal, search

pytestmark = pytest.mark.asyncio

Expand All @@ -31,6 +31,34 @@ async def _search_as(conn, embedder, user_id: str, question: str = QUESTION, lim
return {h.doc_id for h in hits}


class _NoDatabaseAccess:
def cursor(self, **kwargs):
raise AssertionError("search opened a database cursor before validating arguments")


@pytest.mark.parametrize(
("limit", "candidates", "message"),
[
(0, 50, "limit"),
(-1, 50, "limit"),
(5, 0, "candidates"),
(5, -1, "candidates"),
],
)
async def test_search_rejects_non_positive_counts_before_database_access(
limit, candidates, message
):
with pytest.raises(ValueError, match=message):
await search(
_NoDatabaseAccess(),
Principal(user_id="alice", groups=()),
QUESTION,
[0.0],
limit=limit,
candidates=candidates,
)


async def test_group_isolation_alice_cannot_see_sales_or_hr(conn, corpus, embedder):
docs = await _search_as(conn, embedder, "alice")
assert "eng-handbook" in docs, "alice is in engineering and must see the eng handbook"
Expand Down
5 changes: 5 additions & 0 deletions vaultrag/retrieval.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,11 @@ async def search(
Returns:
Up to `limit` chunks the user is allowed to see, best first.
"""
if limit <= 0:
raise ValueError("limit must be greater than 0")
if candidates <= 0:
raise ValueError("candidates must be greater than 0")

# A chunk is visible iff its document has an ACL row whose principal is one of ours.
# EXISTS rather than JOIN so a document with several matching ACL rows yields one chunk, not N.
#
Expand Down
Loading