fix(u6): fold the cold contract panel — the import selection gap, and a document arguing with itself
/heid-contract-review panel 01M35BWCJ806MT75NA630Y4WFH. The headline arrived from all four arms independently and it is a missing feature, not a wording problem. `bench import --apply` registered every candidate, while the same contract says roughly 14 of 35 are reference bookmarks that must stay on the board. There was no selection mechanism between the dry-run report and the write -- so the write path did the exact thing this unit's rationale calls impossible, tell a bench from a bookmark by its URL, silently, to rows that belong where they are. The report existed precisely because the decision is not mechanizable. `--apply` now takes the ids the operator names; a bare `--apply` is refused and an unknown id is refused, both writing nothing. Two solo findings, both real: - A successful registration could push the registry past the size its own reader refuses, so the LAST bench added would make every other bench invisible while reporting success. The writer now respects the reader's cap. - The credential ban covered bench URLs and not `booth link`, the door this unit did not touch -- and the board renders on an unauthenticated LAN surface. A password can no longer reach it through either door. A small deliberate widening, named rather than smuggled. Cap semantics were readable three ways (refuse / clip-for-display / truncate-and-store) with a different build behind each, 4-of-4. Now stated per field: name and owner truncate, url and state are refused at the write and are DAMAGE at the read. url is not a display budget -- INV-7 promises the click goes to the posted address byte for byte, and a clipped URL keeps that promise in the type system while breaking it in the browser. The code had been clipping it; fixed. Two passages disagreed about one character: INV-7's specimen named "a trailing slash on a non-empty path" as something normalization changes, while the rule list keeps it and INV-6 makes the two spellings two benches. The rule list is right; the specimen was wrong. Found by 3-of-4. Also: INV-6's component list was illustrative where it had to be exhaustive and was short scheme and port; "writes nothing" appeared twice with different lists; the dead marker's predicate was readable two ways with 221 rows riding on it; and INV-2's falsifier read as though three callers agreeing pinned something, when three callers of one wrong predicate agree perfectly -- the table's expected values are the real check and now say so. 597 -> 604 tests.
This commit is contained in:
+78
-6
@@ -440,11 +440,28 @@ def test_bench_verbs_round_trip(booth):
|
||||
|
||||
|
||||
def test_bench_state_and_rm_take_an_id_or_a_url(booth):
|
||||
"""`bench ls` prints ids; the operator has the URL. Both must address."""
|
||||
"""`bench ls` prints ids; the operator has the URL. BOTH must address.
|
||||
|
||||
This used to invoke both verbs with the URL only, twice, while its docstring
|
||||
claimed it covered the id — the same claim-not-evidence shape as the `ls`
|
||||
docstring. A raw URL whose normalization DIFFERS from it is used, so the two
|
||||
columns are genuinely distinct inputs. Cold panel, regin F8.
|
||||
"""
|
||||
data, _ = booth
|
||||
run(data, "bench", "add", "http://x.test/p/", "ex")
|
||||
assert run(data, "bench", "state", "http://x.test/p/", "retired").returncode == OK
|
||||
assert run(data, "bench", "rm", "http://x.test/p/").returncode == OK
|
||||
raw = "HTTP://X.Test:80/p/?b=2&a=1#frag"
|
||||
bid = normalize_bench_url_cli(raw)
|
||||
assert bid != raw, "pick a URL whose normalization actually differs"
|
||||
run(data, "bench", "add", raw, "ex")
|
||||
# by the ID the registry stores
|
||||
assert run(data, "bench", "state", bid, "retired").returncode == OK
|
||||
assert "retired" in run(data, "bench", "ls").stdout
|
||||
# and by the RAW URL the operator has in their scrollback
|
||||
assert run(data, "bench", "state", raw, "live").returncode == OK
|
||||
assert "live" in run(data, "bench", "ls").stdout
|
||||
assert run(data, "bench", "rm", raw).returncode == OK
|
||||
run(data, "bench", "add", raw, "ex again")
|
||||
assert run(data, "bench", "rm", bid).returncode == OK
|
||||
assert "ex" not in run(data, "bench", "ls").stdout
|
||||
|
||||
|
||||
def test_bench_add_refuses_a_bad_url_with_the_reason(booth):
|
||||
@@ -502,10 +519,51 @@ def test_import_classifies_into_three_groups(booth):
|
||||
assert out.count("https://talk.nh3.phasefinal.com:8092/") >= 2, out
|
||||
|
||||
|
||||
def test_bare_apply_refuses_and_writes_nothing(booth):
|
||||
"""THE SELECTION GAP — all four cold contract-review arms, independently.
|
||||
|
||||
`--apply` used to register every candidate, while the same contract says
|
||||
roughly 14 of 35 are reference bookmarks that must STAY on the board. That
|
||||
made the write path do the exact thing the unit's own rationale calls
|
||||
impossible — tell a bench from a bookmark by its URL — silently, to rows
|
||||
that belong where they are. The dry-run prints ids; `--apply` takes the
|
||||
ones the operator names, and refuses without them.
|
||||
|
||||
Defeating change: restoring the register-everything branch."""
|
||||
data, _ = booth
|
||||
_seed_board(data)
|
||||
r = run(data, "bench", "import", "--apply")
|
||||
assert r.returncode == REFUSED
|
||||
assert "needs the ids" in r.stderr
|
||||
assert not (data / ".benches.json").exists(), "a bare --apply wrote the registry"
|
||||
|
||||
|
||||
def test_apply_refuses_an_id_that_is_not_a_candidate(booth):
|
||||
data, _ = booth
|
||||
_seed_board(data)
|
||||
r = run(data, "bench", "import", "--apply", "http://not-on-the-board/")
|
||||
assert r.returncode == REFUSED
|
||||
assert "not a candidate id" in r.stderr
|
||||
assert not (data / ".benches.json").exists()
|
||||
|
||||
|
||||
def test_apply_registers_ONLY_the_named_ids(booth):
|
||||
"""The bookmark stays a bookmark unless the operator says otherwise."""
|
||||
data, _ = booth
|
||||
_seed_board(data)
|
||||
talk = normalize_bench_url_cli("https://talk.nh3.phasefinal.com:8092/")
|
||||
assert run(data, "bench", "import", "--apply", talk).returncode == OK
|
||||
ls = run(data, "bench", "ls").stdout
|
||||
assert "peedlar" not in ls, "an unnamed candidate was registered anyway"
|
||||
assert len([l for l in ls.splitlines() if "talk" in l]) == 1
|
||||
|
||||
|
||||
def test_import_apply_collapses_the_repost(booth):
|
||||
data, _ = booth
|
||||
_seed_board(data)
|
||||
assert run(data, "bench", "import", "--apply").returncode == OK
|
||||
talk = normalize_bench_url_cli("https://talk.nh3.phasefinal.com:8092/")
|
||||
repo = normalize_bench_url_cli("https://gitea.phasefinal.com/vh/peedlar")
|
||||
assert run(data, "bench", "import", "--apply", talk, repo).returncode == OK
|
||||
ls = run(data, "bench", "ls").stdout
|
||||
# ONE ROW, counted by line: "talk" appears in both the name and the
|
||||
# hostname, so a substring count would read 2 for a correctly collapsed row.
|
||||
@@ -524,7 +582,9 @@ def test_nothing_in_the_unit_touches_links_md(booth):
|
||||
before = hashlib.sha256((board / "links.md").read_bytes()).hexdigest()
|
||||
run(data, "link", "http://10.100.10.50:8090/b/x/", "refused")
|
||||
run(data, "bench", "import")
|
||||
run(data, "bench", "import", "--apply")
|
||||
run(data, "bench", "import", "--apply") # refused, writes nothing
|
||||
run(data, "bench", "import", "--apply",
|
||||
normalize_bench_url_cli("https://talk.nh3.phasefinal.com:8092/"))
|
||||
run(data, "bench", "add", "http://new.test/", "new")
|
||||
run(data, "bench", "state", "http://new.test/", "retired")
|
||||
run(data, "bench", "ls") # a read verb can truncate too
|
||||
@@ -553,3 +613,15 @@ def test_link_fails_CLOSED_when_the_booth_check_cannot_run(booth, tmp_path):
|
||||
assert r.returncode != OK
|
||||
assert "could not check" in r.stderr, r.stderr
|
||||
assert not (data / "links" / "links.md").exists(), "a row landed despite an unusable check"
|
||||
|
||||
|
||||
def test_a_credential_never_reaches_the_board(booth):
|
||||
"""`normalize_bench_url` refuses userinfo for a bench; `booth link` was the
|
||||
door this unit did not touch, and the board renders on an unauthenticated
|
||||
LAN surface. Cold contract panel, groa solo. A deliberate small widening of
|
||||
the unit, named rather than smuggled."""
|
||||
data, _ = booth
|
||||
r = run(data, "link", "https://user:hunter2@x.test/p", "leaky")
|
||||
assert r.returncode != OK
|
||||
assert "credentials" in r.stderr
|
||||
assert not (data / "links").exists(), "a credentialed URL created the board"
|
||||
|
||||
Reference in New Issue
Block a user