Coverage for astrocyte/harness/privacy.py: 90%
29 statements
« prev ^ index » next coverage.py v7.15.0, created at 2026-10-29 22:10 +0000
« prev ^ index » next coverage.py v7.15.0, created at 2026-10-29 22:10 +0000
1"""Owner-only permissions for the local memory store.
3Memories hold conversations, so a store readable by other accounts on a
4shared machine leaks them. New stores are created private (see
5``astrocyte_sqlite``); stores created before that, or by hand, are reported
6by ``astrocyte doctor`` and tightened by ``--fix``.
7"""
9from __future__ import annotations
11import os
12import stat
13from pathlib import Path
15from .paths import data_dir
17_SIDE_FILES = ("", "-wal", "-shm", "-journal")
20def _owned_dir(db: Path) -> Path | None:
21 """The directory too, but only Astrocyte's own: a database placed in a
22 directory of the user's choosing must not change that directory."""
23 parent = db.parent
24 try:
25 return parent if parent.resolve() == data_dir().resolve() else None
26 except OSError:
27 return None
30def exposed(db: Path) -> list[Path]:
31 """Store files (and Astrocyte's data directory) other accounts can read."""
32 if os.name == "nt":
33 return [] # POSIX modes don't describe Windows ACLs
34 out = []
35 for suffix in _SIDE_FILES:
36 f = db.with_name(db.name + suffix)
37 if f.exists() and f.stat().st_mode & (stat.S_IRWXG | stat.S_IRWXO):
38 out.append(f)
39 d = _owned_dir(db)
40 if d is not None and d.exists() and d.stat().st_mode & (stat.S_IRWXG | stat.S_IRWXO):
41 out.append(d)
42 return out
45def make_private(db: Path) -> list[Path]:
46 """chmod what :func:`exposed` reports: files 0600, the directory 0700."""
47 changed = exposed(db)
48 for path in changed:
49 path.chmod(0o700 if path.is_dir() else 0o600)
50 return changed