Files
aios/tests/v2r1/test_memory_scope.py
T

54 lines
2.5 KiB
Python

"""Executable completeness contract for memory namespaces and access."""
from __future__ import annotations
import pytest
from aios_v2r1.memory_scope import MemoryScope, qualify_memory_key
from aios_v2r1.tenant_context import ScopeError, ValidationError
def scope(kind: str = "session", **changes: object) -> MemoryScope:
values: dict[str, object] = {
"tenant_id": "tenant-a", "cell_id": "cell-a", "profile_id": "profile-a",
"session_id": "session-a", "kind": kind}
values.update(changes)
return MemoryScope(**values) # type: ignore[arg-type]
@pytest.mark.parametrize(("kind", "session_id", "expected"), [
("session", "session-a", "tenant/tenant-a/cell/cell-a/profile/profile-a/session/session-a/memory/session"),
("profile", None, "tenant/tenant-a/cell/cell-a/profile/profile-a/memory/profile"),
("cell", None, "tenant/tenant-a/cell/cell-a/memory/cell"),
("tenant", None, "tenant/tenant-a/cell/cell-a/memory/tenant"),
("shared_artifact", None, "tenant/tenant-a/cell/cell-a/memory/shared_artifact")])
def test_every_namespace_is_explicit(kind: str, session_id: str | None, expected: str) -> None:
assert scope(kind, session_id=session_id).namespace == expected
@pytest.mark.parametrize("requested", [
scope(tenant_id="tenant-b"), scope(cell_id="cell-b"),
scope(profile_id="profile-b"), scope(session_id="session-b")])
def test_cross_scope_access_is_denied(requested: MemoryScope) -> None:
with pytest.raises(ScopeError):
scope().assert_access(requested)
def test_cross_kind_access_is_denied() -> None:
with pytest.raises(ScopeError, match="cross-kind"):
scope("session").assert_access(scope("profile", session_id=None))
def test_shared_artifacts_are_read_only() -> None:
owner = scope()
shared = scope("shared_artifact", session_id=None)
owner.assert_access(shared)
with pytest.raises(ScopeError, match="immutable"):
owner.assert_access(shared, write=True)
def test_qualified_key_contains_the_full_namespace() -> None:
assert qualify_memory_key(scope(), "facts.v1") == (
"tenant/tenant-a/cell/cell-a/profile/profile-a/session/session-a/"
"memory/session/facts.v1")
@pytest.mark.parametrize("key", ["../escape", "a/b", ".", "..", " space ", "x?query"])
def test_memory_key_traversal_and_malformed_keys_are_rejected(key: str) -> None:
with pytest.raises(ValidationError):
qualify_memory_key(scope(), key)
def test_memory_search_surface_is_disabled() -> None:
assert not hasattr(scope(), "search")
assert not hasattr(scope(), "search_all")