test(r2): commit the round's falsifiers as a mutation table; one flag predicate

tests/mutations/r2_flow.toml: 18 falsifiers, each proved RED under its
change by scripts/mutation_check.py (18/18). Its first run found three
vacuous proofs, now resolved:
- landed_at's per-entry skip: the symlink-loop fixture stopped raising
  once the clock moved to lstat. New fixture: a folder that lists but
  cannot be searched.
- the Desk's bench URL guard: the test covered bookmarks only. A
  hand-edited registry bench now rides with it.
- flagged_targets' `error is None`: defence in depth (hydration already
  strips a damaged mark's target), so no single-guard row; named in the
  table header instead.

The rail's flagged filter and the orphan-flag list read flagged_targets
rather than restating it; no reachable behaviour changes.
This commit is contained in:
vh
2026-09-23 10:38:02 -07:00
parent 167f2657c5
commit 39a3cb2262
4 changed files with 203 additions and 5 deletions
+36
View File
@@ -759,6 +759,33 @@ def test_the_content_clock_reads_the_booth_not_what_its_links_point_at(tmp_path)
assert _desk(c.get("/").text).get("rest") == ["g"]
def test_one_unreadable_entry_costs_that_entry_not_the_booth(tmp_path):
"""Nyx (groa): one entry the walk can list but not stat made the whole
booth read as landed NOW on every load, pinned in 'new' forever. A
directory readable but not searchable is that entry: its names list, and
every lstat under it is EACCES. (The symlink loop that first showed this
stopped being a fixture for it once the clock moved to lstat, which reads
a loop without following it.)"""
import os
t0 = time.time() - 10_000
b = _booth(tmp_path, "g", {"a.png": PNG})
sub = b / "d"
sub.mkdir()
(sub / "x.png").write_bytes(PNG)
for p in (b / "a.png", sub / "x.png", sub):
_at(p, t0)
_at(b, t0)
c = _client(tmp_path)
c.get("/b/g/") # look at it
sub.chmod(0o644) # r--: listable, nothing inside stat-able
try:
with pytest.raises(PermissionError):
(sub / "x.png").lstat() # the fixture is live, not assumed
assert _desk(c.get("/").text).get("rest") == ["g"]
finally:
sub.chmod(0o755)
def test_a_nul_in_the_review_path_is_a_404_not_a_500(tmp_path):
"""Nyx (groa, seat-probed): Path raises ValueError on an embedded NUL, and
the route caught only OSError. Every other hostile `f` is a 404."""
@@ -789,11 +816,20 @@ def test_the_desk_never_makes_a_non_web_url_clickable(tmp_path):
"""Nyx (kimi): bookmark and bench URLs are agent-written and land in href.
Autoescape does nothing about a `javascript:` scheme. The Desk links only
http(s) and shows anything else as plain text."""
import json
rows = (_link("evil", "javascript:alert`1`")
+ _link("fine", "https://example.test/"))
board = _booth(tmp_path, "links", {"links.md": rows.encode()})
(board / ".forever").write_bytes(b"")
# The bench WRITE path refuses a non-web URL; a hand-edited registry does
# not pass through it, and the reader takes any text.
(tmp_path / ".benches.json").write_text(json.dumps({
"evil": {"url": "javascript:alert(1)", "name": "evil bench"},
"http://h:1/": {"url": "http://h:1/", "name": "fine bench"}}))
body = _client(tmp_path).get("/").text
panel = re.search(r'data-panel="bookmarks".*?</section>', body, re.S).group(0)
assert 'href="javascript:' not in panel
assert 'href="https://example.test/"' in panel and "evil" in panel
benches = re.search(r'data-panel="benches".*?</section>', body, re.S).group(0)
assert 'href="javascript:' not in benches
assert 'href="http://h:1/"' in benches and "evil bench" in benches