diff --git a/src/openjarvis/server/session_store.py b/src/openjarvis/server/session_store.py index 107f0052..7dd829cd 100644 --- a/src/openjarvis/server/session_store.py +++ b/src/openjarvis/server/session_store.py @@ -25,9 +25,11 @@ class SessionStore: def __init__(self, db_path: str = "") -> None: if not db_path: db_path = str(get_config_dir() / "sessions.db") - from openjarvis.security.file_utils import secure_create + # Ensure the parent directory exists (skip for :memory:) + if db_path != ":memory:": + from openjarvis.security.file_utils import secure_create - secure_create(Path(db_path)) + secure_create(Path(db_path)) self._db = sqlite3.connect(db_path, check_same_thread=False) self._db.row_factory = sqlite3.Row self._create_tables() diff --git a/tests/server/test_session_store.py b/tests/server/test_session_store.py index c078b25e..6f637035 100644 --- a/tests/server/test_session_store.py +++ b/tests/server/test_session_store.py @@ -115,3 +115,29 @@ class TestLastActiveChannel: def test_returns_none_for_unknown_user(self, store): assert store.get_last_active_channel("nobody") is None + + +class TestInMemoryDatabase: + """``:memory:`` is a SQLite sentinel, not a path — it must not be created. + + ``secure_create`` treats it as a filename, which fails outright on Windows + (``:`` is illegal there) and litters the working directory elsewhere. + """ + + def test_in_memory_store_is_usable(self): + s = SessionStore(db_path=":memory:") + try: + session = s.get_or_create("user1", "twilio") + assert session["sender_id"] == "user1" + finally: + s.close() + + def test_in_memory_store_creates_no_file(self, tmp_path, monkeypatch): + monkeypatch.chdir(tmp_path) + before = set(tmp_path.iterdir()) + s = SessionStore(db_path=":memory:") + try: + assert set(tmp_path.iterdir()) == before + assert not (tmp_path / ":memory:").exists() + finally: + s.close()