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
7 changes: 7 additions & 0 deletions services/api/tests/memory_stack.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,13 @@ def stored_text(self) -> str:
return "\n".join(found)


def holds_word(text_dump: str, word: str) -> bool:
"""Whether `word` appears in `text_dump` as a whole word, ignoring case. A dump of every
stored value also holds random key hashes and ids, whose letters can spell a short word
("bus" in "...GdGbusxe..."); a stored sentence or token still has a boundary around it."""
return re.search(rf"(?<![^\W_]){re.escape(word)}(?![^\W_])", text_dump, re.IGNORECASE) is not None


@pytest.fixture
def stack(tmp_path, monkeypatch):
engine = create_engine(
Expand Down
6 changes: 3 additions & 3 deletions services/api/tests/test_boundary_forget.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import json

import pytest
from memory_stack import OWNER, request_id
from memory_stack import OWNER, holds_word, request_id
from memory_stack import stack as stack

SECRET = "My spare house key hides under the blue flowerpot by the gate"
Expand Down Expand Up @@ -214,7 +214,7 @@ def test_a_memory_from_chat_stays_forgotten_and_its_message_can_be_forgotten_too
# words too (Pi keeps the transcript). Pi can still forget the message afterwards,
# and then nothing of it is left anywhere.
assert "gym" not in json.dumps(stack.library(object_type="evidence"))
assert "gym" not in stack.stored_text()
assert not holds_word(stack.stored_text(), "gym")
assert stack.unsay("msg_bike")["state"] == "deleted"
assert "gym" not in json.dumps(stack.library())
assert "gym" not in stack.stored_text() and "gym" not in stack.backup()
assert not holds_word(stack.stored_text(), "gym") and not holds_word(stack.backup(), "gym")
4 changes: 2 additions & 2 deletions services/api/tests/test_boundary_scope.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import json

import pytest
from memory_stack import READ_KEY
from memory_stack import READ_KEY, holds_word
from memory_stack import stack as stack

TEA = "I prefer green tea in the afternoon"
Expand Down Expand Up @@ -147,7 +147,7 @@ def test_a_read_key_cannot_switch_namespace(seeded):
assert (
stack.http.put("/runtime/conversation/msg_x", headers=read, json=ingest).status_code == 401
)
assert "chess" not in stack.stored_text()
assert not holds_word(stack.stored_text(), "chess")


def test_all_scope_stays_inside_the_keys_namespace(seeded):
Expand Down
10 changes: 8 additions & 2 deletions services/api/tests/test_boundary_supersede.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
from concurrent.futures import ThreadPoolExecutor

from app.routes import memory as memory_routes
from memory_stack import request_id
from memory_stack import holds_word, request_id
from memory_stack import stack as stack

OLD = "I always study physics in the library after school"
Expand Down Expand Up @@ -90,7 +90,7 @@ def test_a_correction_is_what_every_read_returns_and_history_keeps_the_old_text(
assert stale.status_code == 409
assert set(returned_texts(stack, memory_id)) == {NEWER}
assert stack.index.holds(memory_id, NEWER)
assert "bus" not in stack.stored_text()
assert not holds_word(stack.stored_text(), "bus")


def test_concurrent_corrections_one_wins_and_the_rest_leave_no_trace(stack):
Expand Down Expand Up @@ -222,3 +222,9 @@ def resolve(winner):
json.loads(responses[[r.status_code for r in responses].index(409)].text)["detail"]["code"]
== "revision_conflict"
)


def test_the_leak_check_ignores_letters_inside_a_random_hash():
# The check above once failed on a stored key hash that happened to spell "bus".
assert not holds_word("zI7eP5gQdGbusxeJu9C9KN5iuaFtieMX4=", "bus")
assert holds_word('["bus"]', "bus") and holds_word("study physics on the BUS", "bus")
3 changes: 2 additions & 1 deletion services/api/tests/test_refusal_and_pending_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import json

from memory_stack import holds_word
from memory_stack import stack as stack

GREY = "The weather was grey on the walk home" # below the default value threshold
Expand All @@ -31,7 +32,7 @@ def test_a_refused_write_keeps_only_the_refusal(stack):
payload = json.loads(refusal["payload_json"])
assert payload["reason"] == "low_value" and payload["text_length"] == len(GREY)
assert set(payload) == {"agent_id", "reason", "text_length", "value_score"}
assert "grey" not in stack.stored_text().lower() # nor anywhere else
assert not holds_word(stack.stored_text(), "grey") # nor anywhere else


def test_search_finds_a_memory_still_queued_for_the_index_by_its_words(stack):
Expand Down
Loading