mirror of
https://github.com/HKUDS/nanobot.git
synced 2026-08-13 15:49:16 +03:00
Session files lived under <workspace>/sessions/ (since #713), which is the on-disk scope of the agent's filesystem tools. With restrict_to_workspace enabled, an agent could read_file / list_dir every session transcript — including other users' or channels' conversations — bypassing the scoped sessions.py access layer entirely. Move session storage to ~/.nanobot/sessions/<sha256-of-resolved-workspace>[:16]/, outside the workspace. Per-workspace isolation (the goal of #713) is preserved via a hash of the resolved workspace path, so different workspaces keep independent session stores. A one-shot, idempotent migration moves legacy in-workspace *.jsonl files into the new location at store init. Scope note: this protects sessions whenever restrict_to_workspace=true. The default restrict_to_workspace=false leaves read_file unrestricted in general (not only sessions) and is a separate concern. Refs #5278
77 lines
2.4 KiB
Python
77 lines
2.4 KiB
Python
"""Cross-suite test infrastructure."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import ssl
|
|
import sys
|
|
from collections.abc import Iterator
|
|
from pathlib import Path
|
|
|
|
import certifi
|
|
import pytest
|
|
from loguru import logger
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _isolate_nanobot_log_activation() -> Iterator[None]:
|
|
"""Keep CLI log settings from leaking into later tests in the same process."""
|
|
logger.enable("nanobot")
|
|
try:
|
|
yield
|
|
finally:
|
|
logger.enable("nanobot")
|
|
|
|
|
|
@pytest.fixture(autouse=True)
|
|
def _isolate_sessions_root(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> Iterator[None]:
|
|
"""Redirect session storage away from the real ~/.nanobot/sessions.
|
|
|
|
Session storage lives under get_legacy_sessions_dir() (outside the workspace,
|
|
per ADR-0001), so without redirection tests would write into the real home.
|
|
"""
|
|
root = tmp_path / "sessions-root"
|
|
monkeypatch.setattr("nanobot.session.manager.get_legacy_sessions_dir", lambda: root)
|
|
monkeypatch.setattr("nanobot.config.paths.get_legacy_sessions_dir", lambda: root)
|
|
yield
|
|
|
|
|
|
@pytest.fixture(scope="session", autouse=True)
|
|
def _use_windows_system_ca_for_default_http_clients() -> Iterator[None]:
|
|
"""Avoid reparsing certifi's CA bundle for every offline HTTP client.
|
|
|
|
Loading certifi takes roughly 0.7 seconds per client on Windows. The test
|
|
suite constructs hundreds of clients while mocking their I/O. System roots
|
|
preserve certificate verification for accidental local requests; explicit
|
|
``cafile``, ``capath``, and ``cadata`` arguments still use the real loader.
|
|
"""
|
|
if sys.platform != "win32":
|
|
yield
|
|
return
|
|
|
|
original = ssl.create_default_context
|
|
certifi_path = os.path.normcase(os.path.abspath(certifi.where()))
|
|
|
|
def create_default_context(
|
|
purpose: ssl.Purpose = ssl.Purpose.SERVER_AUTH,
|
|
*,
|
|
cafile: str | None = None,
|
|
capath: str | None = None,
|
|
cadata: str | bytes | None = None,
|
|
) -> ssl.SSLContext:
|
|
requested_path = os.path.normcase(os.path.abspath(cafile)) if cafile else None
|
|
if requested_path == certifi_path and capath is None and cadata is None:
|
|
return original(purpose)
|
|
return original(
|
|
purpose,
|
|
cafile=cafile,
|
|
capath=capath,
|
|
cadata=cadata,
|
|
)
|
|
|
|
ssl.create_default_context = create_default_context
|
|
try:
|
|
yield
|
|
finally:
|
|
ssl.create_default_context = original
|