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

1"""Owner-only permissions for the local memory store. 

2 

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""" 

8 

9from __future__ import annotations 

10 

11import os 

12import stat 

13from pathlib import Path 

14 

15from .paths import data_dir 

16 

17_SIDE_FILES = ("", "-wal", "-shm", "-journal") 

18 

19 

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 

28 

29 

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 

43 

44 

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