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",
|
"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 "
|
"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",
|
"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 = []
|
fails = []
|
||||||
@@ -344,6 +352,136 @@ if os.path.isdir(os.path.dirname(EV)):
|
|||||||
else:
|
else:
|
||||||
print(" -- %-20s SKIPPED: no felhom.eu sibling clone" % "golden-notice")
|
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()
|
print()
|
||||||
if fails:
|
if fails:
|
||||||
for f in fails:
|
for f in fails:
|
||||||
|
|||||||
Reference in New Issue
Block a user