fix(effects): protect provenance control state efficiently

A hardlink into the effect store was protected only by the log's own nlink
refusal, which an agent could undo by removing the alias after writing
through it. Adding the store to the recursive control-plane inventory would
make every path check cost grow with accumulated runs. _aliases_effect_store
instead uses the store's invariants: logs and launch indexes refuse
st_nlink != 1 and the store is flat, so only a multiply linked regular file
on the store's device is compared by inode against one non-recursive listing.
Single-link files cost nothing and the store is never rglob-inventoried. The
helper takes a stat result so it plugs into Wave 3's scan-local snapshot after
the rebase.
This commit is contained in:
Alexandre Teixeira
2026-10-03 00:58:32 +01:00
parent b23c6d40b3
commit 7267341d49
+44 -5
View File
@@ -28,6 +28,45 @@ def _absolute(value):
raise ValueError("Resource path must be canonical and absolute")
def _effect_store_dirs():
from src import constants
directories = {canonical_root(os.path.join(constants.DATA_DIR, "effects"))}
effect_log = sys.modules.get("src.agent_runtime.effect_log")
if effect_log is not None:
directories.add(canonical_root(effect_log.EFFECTS_DIR))
return directories
def _aliases_effect_store(candidate, directories):
"""Whether ``candidate`` (an ``os.stat`` result) is a hardlink into the effect store.
The effect log and launch index refuse any file with more than one link,
and the store is flat. So only a multiply linked regular file on the
store's device can alias store state, and only then is the store listed,
one directory level, by inode. Ordinary single-link files cost nothing,
and the cost never depends on recursive store size. Uninspectable store
state fails closed.
"""
if not stat.S_ISREG(candidate.st_mode) or candidate.st_nlink < 2:
return False
for directory in directories:
try:
if os.stat(directory).st_dev != candidate.st_dev:
continue
with os.scandir(directory) as entries:
for entry in entries:
if entry.inode() != candidate.st_ino:
continue
observed = entry.stat(follow_symlinks=False)
if (observed.st_dev, observed.st_ino) == (candidate.st_dev, candidate.st_ino):
return True
except FileNotFoundError:
continue
except OSError:
return True
return False
def _control_plane_path(path):
# Execution snapshots/receipts are server state, even if a workspace root
# contains the data directory. A writable user file cannot mint authority.
@@ -46,11 +85,9 @@ def _control_plane_path(path):
if processes is not None:
job_dirs.add(canonical_root(processes._LAUNCH_DIR))
# Durable effect claims/outcomes/observations are server evidence state.
# The log refuses hardlinked files itself, so a prefix check suffices.
effect_dirs = {canonical_root(os.path.join(constants.DATA_DIR, "effects"))}
effect_log = sys.modules.get("src.agent_runtime.effect_log")
if effect_log is not None:
effect_dirs.add(canonical_root(effect_log.EFFECTS_DIR))
# The store is not inventoried here: it grows with every run. Aliases are
# caught below by ``_aliases_effect_store`` instead.
effect_dirs = _effect_store_dirs()
if any(Path(path).is_relative_to(directory) for directory in effect_dirs):
return True
# Producers may have configured paths different from the default constants.
@@ -97,6 +134,8 @@ def _control_plane_path(path):
candidate = os.stat(path)
except FileNotFoundError:
return False
if _aliases_effect_store(candidate, effect_dirs):
return True
for control in protected:
try:
observed = os.stat(control)