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:
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user