Skip to content

Commit dcd5c43

Browse files
committed
copilot suggestions
1 parent 9375923 commit dcd5c43

2 files changed

Lines changed: 45 additions & 7 deletions

File tree

src/ai_agent/utils/cache_db.py

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,10 +27,26 @@
2727

2828
log = logging.getLogger("cache_db")
2929

30-
_DEFAULT_DB_PATH = os.getenv(
31-
"CACHE_DB_PATH",
32-
str(Path(tempfile.gettempdir()) / "ai_agent_cache.db"),
33-
)
30+
31+
def _default_db_path() -> str:
32+
"""Return a per-user cache DB path so different OS users cannot share data.
33+
34+
On POSIX systems the current UID is embedded in the filename, ensuring
35+
each user gets an isolated file under the system temp directory. The
36+
caller can override the path entirely via ``CACHE_DB_PATH``.
37+
"""
38+
env = os.getenv("CACHE_DB_PATH")
39+
if env:
40+
return env
41+
uid_suffix = ""
42+
try:
43+
uid_suffix = f"_{os.getuid()}"
44+
except AttributeError:
45+
pass # Windows — no getuid(); fall back to a single shared filename
46+
return str(Path(tempfile.gettempdir()) / f"ai_agent_cache{uid_suffix}.db")
47+
48+
49+
_DEFAULT_DB_PATH = _default_db_path()
3450

3551

3652
class CacheDB:
@@ -52,6 +68,13 @@ def __init__(self, db_path: str | Path | None = None) -> None:
5268
self._conn = sqlite3.connect(path, check_same_thread=False)
5369
self._lock = threading.Lock()
5470

71+
# Restrict the DB file to the owner only so other OS users cannot
72+
# read cached data. The chmod is best-effort (no-op on Windows).
73+
if path != ":memory:":
74+
try:
75+
os.chmod(path, 0o600)
76+
except Exception:
77+
log.warning("Could not set owner-only permissions on cache DB: %s", path)
5578
self._conn.execute("PRAGMA journal_mode=WAL")
5679
self._conn.execute("PRAGMA synchronous=NORMAL")
5780
self._conn.executescript(

src/ai_agent/utils/image_meta.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,18 +10,33 @@
1010
from PIL import Image
1111
import tifffile as tiff
1212

13-
from ai_agent.utils.cache_db import get_cache_db
13+
from ai_agent.utils.cache_db import CacheDB, get_cache_db
1414

1515
# ---------------------------------------------------------------------------
1616
# SQLite-backed metadata cache (keyed by resolved-path + mtime + size)
1717
# Avoids re-reading large files (e.g. TIFF stacks) on every retrieval call.
18+
#
19+
# PRIVACY NOTE: DICOM-derived metadata can contain sensitive identifying
20+
# fields (Study/Series descriptions, institution names, patient context).
21+
# By default the metadata namespace uses an in-memory-only CacheDB so
22+
# nothing is written to disk. Set IMAGE_META_CACHE_PERSIST=1 to opt into
23+
# on-disk persistence (e.g. for long-running servers with large TIFF stacks).
1824
# ---------------------------------------------------------------------------
1925
_META_CACHE_MAX = int(os.getenv("IMAGE_META_CACHE_MAX", "128"))
26+
_META_CACHE_PERSIST = os.getenv("IMAGE_META_CACHE_PERSIST", "0").strip() == "1"
2027

2128
_META_NS = "meta"
2229

2330
_meta_log = __import__("logging").getLogger("cache_db.meta")
2431

32+
# In-memory-only DB used when persistence is disabled (the default).
33+
_meta_mem_db: CacheDB | None = None if _META_CACHE_PERSIST else CacheDB(":memory:")
34+
35+
36+
def _get_meta_db() -> CacheDB:
37+
"""Return the CacheDB instance to use for image metadata."""
38+
return get_cache_db() if _META_CACHE_PERSIST else _meta_mem_db # type: ignore[return-value]
39+
2540

2641
def _meta_cache_key(p: Path) -> str:
2742
"""Stable cache key derived from resolved path, mtime, and size."""
@@ -34,15 +49,15 @@ def _meta_cache_key(p: Path) -> str:
3449

3550
def _meta_cache_get(key: str) -> Optional[str]:
3651
try:
37-
return get_cache_db().get(_META_NS, key)
52+
return _get_meta_db().get(_META_NS, key)
3853
except Exception:
3954
_meta_log.warning("Metadata cache get failed; skipping cache.", exc_info=True)
4055
return None
4156

4257

4358
def _meta_cache_set(key: str, value: str) -> None:
4459
try:
45-
get_cache_db().set(_META_NS, key, value, max_entries=_META_CACHE_MAX)
60+
_get_meta_db().set(_META_NS, key, value, max_entries=_META_CACHE_MAX)
4661
except Exception:
4762
_meta_log.warning("Metadata cache set failed; continuing without caching.", exc_info=True)
4863

0 commit comments

Comments
 (0)