diff --git a/emrg/sandbox/fence.py b/emrg/sandbox/fence.py index 0b47963b..0b82b0d5 100644 --- a/emrg/sandbox/fence.py +++ b/emrg/sandbox/fence.py @@ -88,7 +88,10 @@ def file_refusal(file_path: str, policy: SandboxPolicy) -> str | None: # is the one place the in-process fence is **stricter** than the kernel # profile rather than identical to it: it can refuse a write bash would # be allowed to make, never the reverse. The list stays in - # ``emrg/tools/file_policy.py`` because the legacy scanner reads it too. + # ``emrg/tools/file_policy.py`` because this module and + # ``emrg/sandbox/roots.py`` are its two readers — the in-process fence + # and the kernel profile refuse the same five paths because they ask the + # same derivation, not because two lists happen to agree. return f"{policy.mode} sandbox: blocked write to protected daemon file {file_path!r}" try: # The enforcement question is asked here rather than left to diff --git a/emrg/tools/command_scan.py b/emrg/tools/command_scan.py index fe1b995b..3cfe56d3 100644 --- a/emrg/tools/command_scan.py +++ b/emrg/tools/command_scan.py @@ -28,11 +28,15 @@ so the rules are enforced on the path a command really takes rather than on the one the switch retired. -**What is shared with the legacy file.** The tokenizer and its helpers -(``tokenize_command``, ``nested_command_texts``, ``basename``, the Windows -backslash protection) — the legacy scanner keeps private aliases to these for its -own ~30 call sites, and those aliases are the *same function objects*, so the two -readers cannot drift into two spellings of one command. +**The mechanics have one home.** The tokenizer and its helpers +(``_tokenize_command``, ``_nested_command_texts``, ``_basename``, the Windows +backslash protection) are defined here and nowhere else, so the guards below and +the executors that call them read one implementation of a command's text rather +than two that could drift into two spellings of one command. +``emrg/tools/bash_tool.py`` once re-bound these names as private aliases for its +own ~30 call sites; P7 (issue #1675) deleted that file, and the aliases went with +it — ``tests/test_file_policy_has_one_home.py`` holds that no module re-binds +them. """ from __future__ import annotations @@ -121,7 +125,8 @@ def _windows_shell() -> bool: #: A shell parameter expansion — `$X`, `${X}`, `$1`, `$@` … — as one pattern, because #: the rules below ask "does a value spelling name a variable?" rather than "which -#: variable?". `_UNRESOLVED_ROOT_RE` stays with the legacy scanner and imports this. +#: variable?". It stays a string rather than a compiled pattern because +#: `_UNRESOLVED_VAR_RE` below is the only reader, and it wants the repetition. _PARAM_EXPANSION = r"\$(?:\{[^}]*\}|[A-Za-z_0-9@*#?$!-][A-Za-z0-9_]*)" _UNRESOLVED_VAR_RE = re.compile(rf"(?:{_PARAM_EXPANSION})+")