Initial curated RAGcore source from c16667f0c9397e2bfc8dd0255b114fba23c8d05e

This commit is contained in:
Public Source Publisher committed 2026-10-01 01:34:21 +02:00
commit 7ca726caf2
659 files changed
+98171

No files matched your search

@@ -0,0 +1,235 @@
"""Who may point the worker at the server's own filesystem.
The allowlist (``RAGCORE_SOURCE_ROOTS``, tested next door) answers *which*
paths may ever be read. This module answers the separate question of *who* may
choose among them. Both gates are required and neither substitutes for the
other:
* a principal without ``FILESYSTEM_SOURCE_MANAGE`` is refused even for a path
squarely inside an allowed root;
* a principal *with* it is refused for a path outside every root.
The chosen policy is the smallest one that closes the multi-workspace hole:
the allowed roots are a single deployment-wide list, so a path inside them may
belong to another tenant's corpus. Until roots are per-workspace, choosing one
is a deployment decision, and only ``PLATFORM_ADMIN`` holds the permission.
Ordinary content curation (``SOURCE_MANAGE``, held by Editors and Space
Managers) is untouched -- only the filesystem-backed kinds are narrowed.
"""
from __future__ import annotations
from dataclasses import dataclass, field
from pathlib import Path
from uuid import UUID, uuid4
import pytest
from ragcore.application.authorization import AuthorizationService
from ragcore.application.sources import SourceManagementService, SourceRegistryError
from ragcore.domain.authorization import (
ROLE_PERMISSIONS,
Permission,
PermissionDenied,
Principal,
PrincipalType,
)
from ragcore.domain.control import KnowledgeSpace, Role
from ragcore.domain.sources import FILESYSTEM_BACKED_KINDS, ConnectorKind
pytestmark = pytest.mark.security
WORKSPACE_ID = uuid4()
SPACE_ID = uuid4()
_ALLOWED = (Path("/mnt/rag-sources"),)
def _principal(*roles: Role) -> Principal:
return Principal(uuid4(), WORKSPACE_ID, PrincipalType.HUMAN, frozenset(roles))
@dataclass
class FakeRegistry:
created: list[object] = field(default_factory=list)
async def create_source(self, record: object) -> object:
self.created.append(record)
return record
async def update_source(self, record: object) -> object:
self.created.append(record)
return record
async def get_owned_source(
self, source_id: UUID, *, workspace_id: UUID, space_id: UUID | None = None
) -> object | None:
return None
async def list_failed_items(self, source_id: UUID, *, limit: int = 20) -> tuple[object, ...]:
return ()
class FakeControl:
async def list_spaces(self, workspace_id: UUID) -> tuple[KnowledgeSpace, ...]:
return (
KnowledgeSpace(
id=SPACE_ID, workspace_id=WORKSPACE_ID, name="Runbooks", slug="runbooks"
),
)
class FakeDocuments:
async def count_documents_by_source(self, source_ids: tuple[UUID, ...]) -> dict[UUID, int]:
return {}
def _service() -> tuple[SourceManagementService, FakeRegistry]:
registry = FakeRegistry()
return (
SourceManagementService(
registry=registry, # type: ignore[arg-type]
authorization=AuthorizationService(),
control=FakeControl(), # type: ignore[arg-type]
documents=FakeDocuments(), # type: ignore[arg-type]
allowed_roots=_ALLOWED,
),
registry,
)
async def _create(principal: Principal, kind: ConnectorKind) -> object:
service, registry = _service()
values = {
"root": "/mnt/rag-sources/runbooks",
"repository": "https://example.invalid/repo.git",
"ref": "a" * 40,
"checkout_root": "/mnt/rag-sources/checkouts",
}
created = await service.create_source(
principal,
name="Runbooks",
kind=kind,
space_id=SPACE_ID,
config_values=values,
trace_id="trace-fs",
)
assert registry.created
return created
# -- the permission matrix itself -------------------------------------------
def test_only_the_platform_administrator_holds_the_filesystem_permission() -> None:
holders = {
role
for role, permissions in ROLE_PERMISSIONS.items()
if Permission.FILESYSTEM_SOURCE_MANAGE in permissions
}
assert holders == {Role.PLATFORM_ADMIN}
def test_ordinary_source_management_is_not_narrowed() -> None:
"""Only the sensitive kinds are restricted. Curating content -- including
upload sources -- stays exactly as available as it was."""
for role in (Role.EDITOR, Role.SPACE_MANAGER, Role.WORKSPACE_ADMIN):
assert Permission.SOURCE_MANAGE in ROLE_PERMISSIONS[role]
def test_the_filesystem_backed_kinds_are_the_ones_that_read_the_host() -> None:
assert frozenset({ConnectorKind.FOLDER, ConnectorKind.GIT}) == FILESYSTEM_BACKED_KINDS
assert ConnectorKind.FOLDER.reads_server_filesystem
assert ConnectorKind.GIT.reads_server_filesystem
assert not ConnectorKind.UPLOAD.reads_server_filesystem
# -- creation ---------------------------------------------------------------
@pytest.mark.parametrize("role", [Role.EDITOR, Role.SPACE_MANAGER, Role.WORKSPACE_ADMIN])
@pytest.mark.parametrize("kind", sorted(FILESYSTEM_BACKED_KINDS))
async def test_a_role_without_the_permission_cannot_create_a_filesystem_source(
role: Role, kind: ConnectorKind
) -> None:
"""Refused for a path that is *inside* an allowed root, so the refusal can
only be the authorization gate and not the allowlist."""
with pytest.raises(PermissionDenied):
await _create(_principal(role), kind)
@pytest.mark.parametrize("kind", sorted(FILESYSTEM_BACKED_KINDS))
async def test_the_platform_administrator_can_create_a_filesystem_source(
kind: ConnectorKind,
) -> None:
created = await _create(_principal(Role.PLATFORM_ADMIN), kind)
assert created.kind is kind
async def test_a_viewer_cannot_create_any_source_at_all() -> None:
from ragcore.domain.authorization import ResourceNotFound
with pytest.raises((PermissionDenied, ResourceNotFound)):
await _create(_principal(Role.VIEWER), ConnectorKind.FOLDER)
# -- authorization does not replace the sandbox -----------------------------
@pytest.mark.parametrize("root", ["/etc", "/app", "/var/lib/postgresql/data", "/"])
async def test_the_platform_administrator_is_still_bound_by_the_allowed_roots(
root: str,
) -> None:
"""Role and sandbox are independent gates. Holding the strongest
permission in the system does not widen the paths the deployment approved.
"""
service, _ = _service()
with pytest.raises(SourceRegistryError, match="outside every allowed source root"):
await service.create_source(
_principal(Role.PLATFORM_ADMIN),
name="Escape",
kind=ConnectorKind.FOLDER,
space_id=SPACE_ID,
config_values={"root": root},
trace_id="trace-fs",
)
async def test_with_no_configured_roots_even_the_platform_administrator_is_refused() -> None:
service = SourceManagementService(
registry=FakeRegistry(), # type: ignore[arg-type]
authorization=AuthorizationService(),
control=FakeControl(), # type: ignore[arg-type]
documents=FakeDocuments(), # type: ignore[arg-type]
allowed_roots=(),
)
with pytest.raises(SourceRegistryError, match="no allowed source roots"):
await service.create_source(
_principal(Role.PLATFORM_ADMIN),
name="Runbooks",
kind=ConnectorKind.FOLDER,
space_id=SPACE_ID,
config_values={"root": "/mnt/rag-sources/runbooks"},
trace_id="trace-fs",
)
# -- the capability probe the screens use -----------------------------------
def test_can_manage_filesystem_sources_matches_the_permission() -> None:
service, _ = _service()
assert service.can_manage_filesystem_sources(_principal(Role.PLATFORM_ADMIN))
for role in (Role.WORKSPACE_ADMIN, Role.SPACE_MANAGER, Role.EDITOR, Role.VIEWER):
assert not service.can_manage_filesystem_sources(_principal(role))
# ...while ordinary source management is untouched for the roles that
# legitimately curate content.
assert service.can_manage(_principal(Role.EDITOR))
assert service.can_manage(_principal(Role.WORKSPACE_ADMIN))
@@ -0,0 +1,235 @@
"""The filesystem-source policy, proven at the HTTP boundary.
The unit-level tests next door prove the service refuses. This one proves the
refusal survives the route: the Control Plane form is posted directly, with no
button to click and nothing hidden, against the *real*
``SourceManagementService`` and the real authorization service. Only the
persistence ports are fakes.
That distinction is the point of the test. Hiding "Add source" from a role is
courtesy; the boundary is that posting the form anyway is refused, and that no
source row is written when it is.
"""
from __future__ import annotations
from dataclasses import dataclass, field, replace
from datetime import datetime
from pathlib import Path
from uuid import UUID, uuid4
import pytest
from fastapi.testclient import TestClient
from ragcore.api.v1.control.dependencies import get_principal
from ragcore.application.authorization import AuthorizationService
from ragcore.application.documents import DocumentListPage
from ragcore.application.sources import (
SourceListPage,
SourceManagementService,
SourceRecord,
SourceStatus,
)
from ragcore.domain.authorization import Principal, PrincipalType
from ragcore.domain.control import KnowledgeSpace, Role
from ragcore.domain.sources import ConnectorKind
from ragcore.main import create_app
from ragcore.web.sources import get_source_management
pytestmark = pytest.mark.security
WORKSPACE_ID = uuid4()
SPACE_ID = uuid4()
FOLDER_SOURCE_ID = uuid4()
_ALLOWED = (Path("/mnt/rag-sources"),)
_INSIDE = "/mnt/rag-sources/runbooks"
_OUTSIDE = "/etc"
def _principal(role: Role) -> Principal:
return Principal(uuid4(), WORKSPACE_ID, PrincipalType.HUMAN, frozenset({role}))
@dataclass
class FakeRegistry:
sources: dict[UUID, SourceRecord] = field(default_factory=dict)
writes: list[SourceRecord] = field(default_factory=list)
async def create_source(self, record: SourceRecord) -> SourceRecord:
self.writes.append(record)
self.sources[record.id] = record
return record
async def update_source(self, record: SourceRecord) -> SourceRecord:
self.writes.append(record)
self.sources[record.id] = record
return record
async def get_owned_source(
self, source_id: UUID, *, workspace_id: UUID, space_id: UUID | None = None
) -> SourceRecord | None:
source = self.sources.get(source_id)
if source is None or source.workspace_id != workspace_id:
return None
return source
async def list_sources(self, workspace_id: UUID, filters: object) -> SourceListPage:
items = tuple(
source for source in self.sources.values() if source.workspace_id == workspace_id
)
return SourceListPage(items=items, total=len(items), limit=50, offset=0)
async def list_sync_runs(self, source_id: UUID, *, limit: int = 20) -> tuple[object, ...]:
return ()
async def list_failed_items(self, source_id: UUID, *, limit: int = 20) -> tuple[object, ...]:
return ()
async def set_status(
self, source_id: UUID, status: SourceStatus, *, now: datetime
) -> SourceRecord | None:
source = self.sources.get(source_id)
if source is None:
return None
self.sources[source_id] = replace(source, status=status)
return self.sources[source_id]
class FakeControl:
async def list_spaces(self, workspace_id: UUID) -> tuple[KnowledgeSpace, ...]:
return (
KnowledgeSpace(
id=SPACE_ID, workspace_id=WORKSPACE_ID, name="Runbooks", slug="runbooks"
),
)
class FakeDocuments:
async def count_documents_by_source(self, source_ids: tuple[UUID, ...]) -> dict[UUID, int]:
return {}
async def list_documents(self, workspace_id: UUID, filters: object) -> DocumentListPage:
return DocumentListPage(items=(), total=0, limit=25, offset=0)
def _client(role: Role) -> tuple[TestClient, FakeRegistry]:
registry = FakeRegistry()
registry.sources[FOLDER_SOURCE_ID] = SourceRecord(
id=FOLDER_SOURCE_ID,
workspace_id=WORKSPACE_ID,
space_id=SPACE_ID,
name="Runbooks",
kind=ConnectorKind.FOLDER,
config={"root": _INSIDE, "include": [], "exclude": [], "trust_level": "trusted_internal"},
)
service = SourceManagementService(
registry=registry, # type: ignore[arg-type]
authorization=AuthorizationService(),
control=FakeControl(), # type: ignore[arg-type]
documents=FakeDocuments(), # type: ignore[arg-type]
allowed_roots=_ALLOWED,
)
app = create_app()
app.dependency_overrides[get_principal] = lambda: _principal(role)
app.dependency_overrides[get_source_management] = lambda: service
app.state.session_factory = None
return TestClient(app), registry
def _form(root: str = _INSIDE) -> dict[str, str]:
return {
"name": "Runbooks",
"kind": "folder",
"space_id": str(SPACE_ID),
"root": root,
"include": "",
"exclude": "",
"trust_level": "trusted_internal",
}
# -- creation ---------------------------------------------------------------
@pytest.mark.parametrize("role", [Role.EDITOR, Role.SPACE_MANAGER, Role.WORKSPACE_ADMIN])
def test_posting_the_create_form_is_refused_without_the_filesystem_permission(
role: Role,
) -> None:
client, registry = _client(role)
response = client.post("/admin/sources", data=_form(), follow_redirects=False)
assert response.status_code == 403
assert registry.writes == []
assert _INSIDE not in response.text
@pytest.mark.parametrize("role", [Role.EDITOR, Role.SPACE_MANAGER, Role.WORKSPACE_ADMIN])
def test_the_create_form_itself_is_not_served_without_the_permission(role: Role) -> None:
client, _ = _client(role)
assert client.get("/admin/sources/new").status_code == 403
@pytest.mark.parametrize("role", [Role.EDITOR, Role.SPACE_MANAGER, Role.WORKSPACE_ADMIN])
def test_editing_an_existing_folder_source_is_refused_too(role: Role) -> None:
"""Editing is how an approved source gets repointed at a different
directory, so it is the same capability as creating one."""
client, registry = _client(role)
# 403 for a role that may read the source but not repoint it; 404 for one
# that may not see it at all (an Editor has no SPACE_READ). Both are
# denials that reveal nothing -- what matters is that neither writes.
assert client.get(f"/admin/sources/{FOLDER_SOURCE_ID}/edit").status_code in (403, 404)
posted = client.post(
f"/admin/sources/{FOLDER_SOURCE_ID}/edit",
data={
"name": "Runbooks",
"root": "/mnt/rag-sources/elsewhere",
"trust_level": "unverified",
},
follow_redirects=False,
)
assert posted.status_code in (403, 404)
assert registry.writes == []
assert registry.sources[FOLDER_SOURCE_ID].config["root"] == _INSIDE
def test_the_platform_administrator_may_create_a_filesystem_source() -> None:
client, registry = _client(Role.PLATFORM_ADMIN)
response = client.post("/admin/sources", data=_form(), follow_redirects=False)
assert response.status_code == 303
assert [record.kind for record in registry.writes] == [ConnectorKind.FOLDER]
assert str(registry.writes[0].config["root"]).replace("\\", "/") == _INSIDE
# -- role permission and path sandbox are both required ---------------------
def test_a_path_outside_the_allowed_roots_is_refused_for_the_platform_administrator() -> None:
client, registry = _client(Role.PLATFORM_ADMIN)
response = client.post("/admin/sources", data=_form(root=_OUTSIDE), follow_redirects=False)
assert response.status_code == 400
assert "outside every allowed source root" in response.text
assert registry.writes == []
def test_a_hidden_button_is_never_the_boundary() -> None:
"""The Sources list omits the Add-source affordance for a role that may
not use it -- and posting the form anyway is still refused. The second
assertion is the security property; the first is only the UI telling the
truth about it."""
client, registry = _client(Role.WORKSPACE_ADMIN)
listing = client.get("/admin/sources")
assert listing.status_code == 200
assert '/admin/sources/new"' not in listing.text
assert client.post("/admin/sources", data=_form(), follow_redirects=False).status_code == 403
assert registry.writes == []
@@ -0,0 +1,132 @@
"""The allowlist at the two boundaries that surround the connectors.
The connectors enforce it against the real filesystem before every read; these
are the two places that decide a path may be *stored* and *built into a
connector* at all. Both must fail closed on their own -- neither is allowed to
rely on the other having checked.
"""
from __future__ import annotations
from pathlib import Path
from uuid import uuid4
import pytest
from ragcore.application.jobs import TerminalJobError
from ragcore.application.sources import (
SourceRecord,
SourceRegistryError,
SourceStatus,
build_source_config,
)
from ragcore.domain.sources import ConnectorKind
from ragcore.infrastructure.ingestion.sync_handler import build_connector
pytestmark = pytest.mark.security
_ALLOWED = (Path("/mnt/rag-sources"),)
# -- the Control Plane boundary: what may be stored --------------------------
def test_a_folder_root_inside_an_allowed_root_is_accepted() -> None:
config = build_source_config(
ConnectorKind.FOLDER, {"root": "/mnt/rag-sources/runbooks"}, allowed_roots=_ALLOWED
)
assert str(config["root"]).replace("\\", "/") == "/mnt/rag-sources/runbooks"
@pytest.mark.parametrize("root", ["/etc", "/app", "/var/lib/postgresql/data"])
def test_a_folder_root_outside_every_allowed_root_is_refused(root: str) -> None:
with pytest.raises(SourceRegistryError, match="outside every allowed source root"):
build_source_config(ConnectorKind.FOLDER, {"root": root}, allowed_roots=_ALLOWED)
def test_no_configured_roots_means_no_folder_source_can_be_created() -> None:
"""The default is fail closed: a deployment that never named a root does
not get an implicit one, least of all ``/``."""
with pytest.raises(SourceRegistryError, match="no allowed source roots"):
build_source_config(
ConnectorKind.FOLDER, {"root": "/mnt/rag-sources/runbooks"}, allowed_roots=()
)
def test_a_git_checkout_root_answers_to_the_same_allowlist() -> None:
"""The checkout root is an operator-supplied server-side path the worker
runs git against -- the same exposure a folder root is."""
with pytest.raises(SourceRegistryError, match="outside every allowed source root"):
build_source_config(
ConnectorKind.GIT,
{"repository": "local", "ref": "main", "checkout_root": "/app"},
allowed_roots=_ALLOWED,
)
def test_an_upload_source_needs_no_root() -> None:
"""Uploads are fed by callers, never read from the server's filesystem, so
the allowlist has nothing to say about them."""
assert build_source_config(ConnectorKind.UPLOAD, {}, allowed_roots=()) == {
"origin": "control-plane",
"trust_level": "trusted_internal",
}
# -- the worker boundary: what may be built into a connector -----------------
def _record(kind: ConnectorKind, config: dict[str, object]) -> SourceRecord:
return SourceRecord(
id=uuid4(),
workspace_id=uuid4(),
space_id=uuid4(),
name="Runbooks",
kind=kind,
status=SourceStatus.ACTIVE,
config=config,
)
def test_a_stored_source_outside_the_allowlist_fails_terminally() -> None:
"""A record stored before the allowlist was tightened must not be retried
forever: no number of attempts turns a path an operator disallowed into
one they allowed."""
source = _record(ConnectorKind.FOLDER, {"root": "/etc"})
with pytest.raises(TerminalJobError, match="outside every allowed source root"):
build_connector(source, allowed_roots=_ALLOWED)
def test_a_stored_source_inside_the_allowlist_builds_a_connector() -> None:
source = _record(ConnectorKind.FOLDER, {"root": "/mnt/rag-sources/runbooks"})
connector = build_connector(source, allowed_roots=_ALLOWED)
assert connector.allowed_roots == _ALLOWED # type: ignore[attr-defined]
def test_the_worker_fails_closed_when_no_roots_are_configured() -> None:
source = _record(ConnectorKind.FOLDER, {"root": "/mnt/rag-sources/runbooks"})
with pytest.raises(TerminalJobError, match="outside every allowed source root"):
build_connector(source, allowed_roots=())
def test_a_pattern_filtered_connector_still_carries_the_allowlist() -> None:
"""Wrapping must not lose the check: the inner connector is the one that
reads, and it is the one that has to hold the roots."""
source = _record(
ConnectorKind.FOLDER,
{"root": "/mnt/rag-sources/runbooks", "include": ["*.md"]},
)
connector = build_connector(source, allowed_roots=_ALLOWED)
assert connector._inner.allowed_roots == _ALLOWED # type: ignore[attr-defined]
+176
View File
@@ -0,0 +1,176 @@
"""The filesystem allowlist: which server-side paths a source may ever read.
Rejecting traversal, symlinks and relative paths only proves a path is well
formed. These tests are about the separate question the allowlist answers --
whether a well-formed path is one an operator ever intended RAGcore to read.
"""
from __future__ import annotations
from pathlib import Path
import pytest
from ragcore.domain.sources import (
SourceRootError,
assert_within_allowed_roots,
normalize_allowed_roots,
resolve_within_allowed_roots,
)
pytestmark = pytest.mark.security
_ROOTS = (Path("/mnt/rag-sources"), Path("/srv/corpora"))
def test_no_configured_roots_allows_nothing() -> None:
"""Fail closed. An empty allowlist is a real answer -- "this deployment
reads no server-side paths" -- not a missing one to be defaulted away."""
with pytest.raises(SourceRootError, match="no allowed source roots"):
assert_within_allowed_roots("/mnt/rag-sources/runbooks", ())
@pytest.mark.parametrize(
"requested",
[
"/mnt/rag-sources",
"/mnt/rag-sources/runbooks",
"/mnt/rag-sources/runbooks/fleet",
"/srv/corpora/handbook",
],
)
def test_a_root_and_anything_below_it_is_allowed(requested: str) -> None:
assert assert_within_allowed_roots(requested, _ROOTS) == Path(requested)
@pytest.mark.parametrize(
"requested",
[
"/etc",
"/etc/shadow",
"/app/src/ragcore/config.py",
"/var/lib/postgresql/data",
"/mnt",
"/",
],
)
def test_a_path_outside_every_root_is_refused(requested: str) -> None:
with pytest.raises(SourceRootError, match="outside every allowed source root"):
assert_within_allowed_roots(requested, _ROOTS)
@pytest.mark.parametrize(
"requested",
[
"/mnt/rag-sources-secret",
"/mnt/rag-sources-secret/keys",
"/srv/corpora-backup",
],
)
def test_a_sibling_sharing_a_string_prefix_is_not_contained(requested: str) -> None:
"""Containment is decided on path *components*, never on string prefixes.
``/mnt/rag-sources`` does not contain ``/mnt/rag-sources-secret``, however
much the two look alike to ``startswith``."""
with pytest.raises(SourceRootError, match="outside every allowed source root"):
assert_within_allowed_roots(requested, _ROOTS)
@pytest.mark.parametrize(
"requested",
["relative/path", "", "rag-sources", "C:x"],
)
def test_a_path_that_is_not_absolute_is_refused(requested: str) -> None:
with pytest.raises(SourceRootError):
assert_within_allowed_roots(requested, _ROOTS)
def test_traversal_is_refused_before_containment_is_even_considered() -> None:
"""``/mnt/rag-sources/../../etc`` normalises to ``/etc``, so a check that
normalised first and compared second would be fine either way -- but the
path is rejected outright, so a root that happens to be near the top of
the tree cannot be walked out of."""
with pytest.raises(SourceRootError, match="must not traverse"):
assert_within_allowed_roots("/mnt/rag-sources/../../etc", _ROOTS)
def test_a_nul_byte_is_refused() -> None:
with pytest.raises(SourceRootError, match="NUL-free"):
assert_within_allowed_roots("/mnt/rag-sources/x\x00.txt", _ROOTS)
def test_the_stored_spelling_survives_validation() -> None:
"""The API host validating a POSIX deployment path must hand back exactly
what the operator wrote: a Windows-side ``normpath`` would rewrite it into
something the Linux worker could never open."""
assert str(assert_within_allowed_roots("/mnt/rag-sources/docs", _ROOTS)).replace(
"\\", "/"
) == "/mnt/rag-sources/docs"
# -- operator-configured roots ----------------------------------------------
def test_a_filesystem_root_may_not_be_an_allowed_root() -> None:
"""Allowing ``/`` would make the allowlist meaningless."""
with pytest.raises(SourceRootError, match="must not be a filesystem root"):
normalize_allowed_roots(["/"])
def test_a_relative_or_traversing_root_is_refused_at_startup() -> None:
with pytest.raises(SourceRootError, match="absolute"):
normalize_allowed_roots(["mnt/rag-sources"])
with pytest.raises(SourceRootError, match="traverse"):
normalize_allowed_roots(["/mnt/rag-sources/../.."])
def test_duplicate_roots_collapse() -> None:
assert normalize_allowed_roots(["/mnt/rag", "/mnt/rag"]) == (Path("/mnt/rag"),)
# -- filesystem truth --------------------------------------------------------
def test_resolution_rejects_a_path_that_does_not_exist(tmp_path: Path) -> None:
"""The worker's check is about the filesystem as it is: a lexically fine
path that cannot be resolved is not a path it may read."""
with pytest.raises(SourceRootError, match="cannot be resolved"):
resolve_within_allowed_roots(tmp_path / "absent", (tmp_path,))
def test_resolution_accepts_a_real_directory_inside_an_allowed_root(tmp_path: Path) -> None:
allowed = tmp_path / "corpora"
inside = allowed / "runbooks"
inside.mkdir(parents=True)
assert resolve_within_allowed_roots(inside, (allowed,)) == inside.resolve(strict=True)
def test_resolution_refuses_a_real_directory_outside_every_allowed_root(tmp_path: Path) -> None:
allowed = tmp_path / "corpora"
allowed.mkdir()
elsewhere = tmp_path / "secrets"
elsewhere.mkdir()
with pytest.raises(SourceRootError, match="outside every allowed source root"):
resolve_within_allowed_roots(elsewhere, (allowed,))
def test_an_unmounted_root_contains_nothing_but_does_not_break_the_others(
tmp_path: Path,
) -> None:
"""A deployment may configure roots that only some containers mount. One
that is absent here simply cannot contain anything; the roots that are
present still get their chance."""
allowed = tmp_path / "corpora"
allowed.mkdir()
assert resolve_within_allowed_roots(
allowed, (tmp_path / "never-mounted", allowed)
) == allowed.resolve(strict=True)