R-426: decoys for docker-v and the shared reuse-refs, instructions and observations gates

docker-v: an unallowlisted `-v /etc:/x` in a NEW .go file two directories down
under internal/ and under cmd/ convicts; controls: the clean tree and the same
line in a _test.go pass. The three shared felhom.eu scripts run against a
scratch clone of THIS repo in a scratch workspace (siblings symlinked), the
felhom-agent b78a0ff pattern: a missing cited .go/.md path, a version literal
in CLAUDE.md effective text and R-419's prose-only Observations note convict;
the real files, the version inside an HTML comment and both genuine markers
pass. DECOY_SHARED_DIR judges a mutated copy for the red-proof. All four in
COVERS, so their EXEMPT entries in decoy_coverage_gate.py can go.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-10-06 02:00:23 +02:00
parent 2e5ef7e410
commit 7044b11804
+138
View File
@@ -52,6 +52,14 @@ COVERS = {
"gofmt": "R-454: a planted unformatted .go file in internal/ is convicted; the clean tree passes",
"offbox-rename": "R-425: NAS branding in a NEW backups*.html, and in a bundle value an offbox Go file "
"names; control: the same token in the network-storage feature's copy is accepted",
"docker-v": "R-426: an unallowlisted `-v /etc:/x` in a NEW .go file two directories down "
"(internal/ and cmd/) convicts; controls: the clean tree, the same line in a _test.go",
"reuse-refs": "R-426: a cited .go and a cited .md path that do not exist, planted in THIS repo's "
"REUSE.md - vs the real file",
"instructions": "R-426: a component version literal in THIS repo's CLAUDE.md effective text - vs the "
"same sentence inside an HTML comment",
"observations": "R-426: R-419 in THIS repo's REPORT.md - an Observations note SAYING it carries no "
"marker - vs the two genuine markers",
}
fails = []
@@ -344,6 +352,136 @@ if os.path.isdir(os.path.dirname(EV)):
else:
print(" -- %-20s SKIPPED: no felhom.eu sibling clone" % "golden-notice")
# --- docker-v (R-426): a NEW file with an unreviewed host-path mount, anywhere under the roots ------
def _plant_go(rel, body):
path = os.path.join(CTRL, rel)
made = []
d = os.path.dirname(path)
while not os.path.isdir(d):
made.append(d)
d = os.path.dirname(d)
for m in reversed(made):
os.mkdir(m)
io.open(path, "w", encoding="utf-8").write(body)
return path, made
def _unplant(path, made):
os.remove(path)
for m in made:
os.rmdir(m)
DOCKER_V_LINE = u'package decoy\n\nvar args = []string{"run", "-v", "/etc:/x", "alpine"}\n'
for _label, _rel, _expect in (
("docker-v/new-internal-file", os.path.join("internal", "decoydockerv", "deep", "decoy.go"), "convict"),
("docker-v/new-cmd-file", os.path.join("cmd", "decoydockerv", "decoy.go"), "convict"),
("docker-v/_test.go (CONTROL)", os.path.join("internal", "decoydockerv", "decoy_test.go"), "accept")):
ran += 1
_p, _made = _plant_go(_rel, DOCKER_V_LINE)
try:
_rc, _out = gate("docker_run_volume_path_gate.py")
finally:
_unplant(_p, _made)
if (_rc != 0) != (_expect == "convict") or (_expect == "convict" and "/etc:/x" not in _out):
fails.append("%s: rc=%d, expected %s\n%s" % (_label, _rc, _expect, _out[-400:]))
else:
print(" ok %-30s %s" % (_label, "decoy rejected" if _expect == "convict" else "genuine accepted"))
ran += 1
_rc, _out = gate("docker_run_volume_path_gate.py")
if _rc != 0:
fails.append("docker-v/clean tree (CONTROL): rc=%d\n%s" % (_rc, _out[-400:]))
else:
print(" ok %-30s %s" % ("docker-v/clean tree (CONTROL)", "genuine accepted"))
# --- the SHARED felhom.eu gates (R-426), against THIS repo's inputs --------------------------------
# A scratch WORKSPACE: a clone of this repo, named as the main clone, beside symlinks to the siblings,
# because the shared scripts reach across (REUSE.md cites felhom.eu paths; instructions_gate reads the
# workspace CLAUDE.md). The plants go into the clone, never into this tree. Mirrors felhom-agent b78a0ff.
# DECOY_SHARED_DIR exists for ONE purpose, the red-proof: it lets a mutated COPY of the shared scripts be
# judged without editing the felhom.eu clone. Unset, the suite judges the real shared scripts.
import shutil
import tempfile
REPO = os.path.dirname(CTRL)
PARENT = os.path.dirname(REPO)
SHARED = os.environ.get("DECOY_SHARED_DIR") or os.path.join(PARENT, "felhom.eu", "scripts")
def _run(argv, cwd):
p = subprocess.run(argv, cwd=cwd, capture_output=True, text=True, input="")
return p.returncode, p.stdout + p.stderr
def shared_cases():
global ran
for g in ("reuse_refs_check.py", "instructions_gate.py", "observations_gate.py"):
if not os.path.isfile(os.path.join(SHARED, g)):
fails.append("shared gate %s is MISSING beside this clone (tried %s) - a failure, never a skip"
% (g, SHARED))
return
ws = tempfile.mkdtemp(prefix="ctrl-decoy-shared-")
try:
space = os.path.join(ws, "workspace")
os.makedirs(space)
for entry in sorted(os.listdir(PARENT)):
if entry in ("felhom.eu", "felhom-agent", "app-catalog-felhom.eu", "homelab-manifests",
"CLAUDE.md", ".claude-memory"):
os.symlink(os.path.join(PARENT, entry), os.path.join(space, entry))
repo = os.path.join(space, "felhom-controller")
rc, out = _run(["git", "clone", "-q", "--no-tags", "file://" + REPO, repo], ws)
if rc != 0:
fails.append("shared: could not clone this repo into the scratch workspace\n" + out[-400:])
return
# the WORKING-TREE inputs the plants go into, so a case judges today's file
for f in ("REUSE.md", "CLAUDE.md", "REPORT.md"):
shutil.copy(os.path.join(REPO, f), os.path.join(repo, f))
def case(name, script, relpath, extra, expect_rc, must=()):
global ran
ran += 1
p = os.path.join(repo, relpath)
backup = io.open(p, encoding="utf-8").read()
try:
if extra:
io.open(p, "w", encoding="utf-8").write(backup + extra)
rc, out = _run([sys.executable, os.path.join(SHARED, script), repo], repo)
finally:
io.open(p, "w", encoding="utf-8").write(backup)
missing = [m for m in must if m not in out]
if rc == expect_rc and not missing:
print(" ok %-62s rc=%d" % (name, rc))
else:
hole = " - LIVE HOLE" if expect_rc != 0 and rc == 0 else ""
fails.append("%s: rc=%d expected %d%s; missing %s\n%s" % (name, rc, expect_rc, hole, missing,
out[-900:]))
case("reuse-refs: GENUINE: this repo's REUSE.md", "reuse_refs_check.py", "REUSE.md", "", 0, ("FAILED 0",))
case("reuse-refs: FACT: a cited .go path that does not exist", "reuse_refs_check.py", "REUSE.md",
u"\n- see `controller/internal/web/does_not_exist.go`\n", 1, ("does_not_exist.go",))
case("reuse-refs: FACT: a cited .md path that does not exist", "reuse_refs_check.py", "REUSE.md",
u"\n- see `docs/99-does-not-exist.md`\n", 1, ("99-does-not-exist.md",))
case("instructions: GENUINE: this repo's CLAUDE.md", "instructions_gate.py", "CLAUDE.md", "", 0,
("instructions_gate: OK",))
case("instructions: FACT: a version literal in effective text", "instructions_gate.py", "CLAUDE.md",
u"\nThe controller runs v0.298.0 today.\n", 1, ("v0.298.0",))
case("instructions: GENUINE: the same sentence in an HTML comment", "instructions_gate.py", "CLAUDE.md",
u"\n<!--\nThe controller ran v0.298.0 on 2026-10-06.\n-->\n", 0, ("instructions_gate: OK",))
case("observations: FACT: R-419, prose SAYING it has no marker", "observations_gate.py", "REPORT.md",
u"\n## Observations\n\n1. **A real finding.** It carries no `FILED:` marker and no "
u"`NOT-A-FINDING:` marker, deliberately.\n", 1)
case("observations: GENUINE: a FILED marker", "observations_gate.py", "REPORT.md",
u"\n## Observations\n\n1. **A real finding.** Something broke. **FILED: R-419**\n", 0)
case("observations: GENUINE: a NOT-A-FINDING marker", "observations_gate.py", "REPORT.md",
u"\n## Observations\n\n1. **A real finding.** Odd. **NOT-A-FINDING: my own typo, corrected in "
u"the same minute.**\n", 0)
finally:
shutil.rmtree(ws, ignore_errors=True)
shared_cases()
print()
if fails:
for f in fails: