Shortcuts you invent, rules you write, gestures you own - all still just data

Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
Gabriel Brown
2026-08-25 01:51:59 -04:00
parent f9e5d3f470
commit 06c53d6c21
48 changed files with 4749 additions and 140 deletions
+249 -2
View File
@@ -71,6 +71,7 @@ readonly WIFI_PSK='psk-must-never-leave-9c1f'
readonly VPN_SECRET='vpn-secret-must-never-leave-7b20'
readonly ENTERPRISE_PW='enterprise-pw-must-never-leave-4e88'
readonly HOTSPOT_PW='hotspot-pw-must-never-leave-3a55'
readonly HIDDEN_PW='hidden-pw-must-never-leave-8d13'
# ── Static: the helper cannot walk past the stubs ────────────────────────────
#
@@ -134,6 +135,58 @@ PY
grep -q -- '--show-secrets' "$helper" \
&& fail 'the helper asks NetworkManager to print secrets; the details view has no use for them'
# ── Static: the address validators exist, and every verb has a shape ─────────
#
# A static address that NetworkManager refuses is a connection that comes up
# with no address at all, which is a worse failure than being told to retype it
# -- so the refusal has to happen here, before nmcli is called. Named rather
# than only exercised, because the dynamic half below can only ever prove that
# SOME check ran, not that the right family's check did.
for pattern in IPV4 IPV6 IPV4_PREFIX IPV6_PREFIX; do
grep -qE "^${pattern} = re\.compile" "$helper" \
|| fail "no $pattern pattern, so a static address is whatever NetworkManager will take"
done
# Every verb has to be in shape_for AND in FALLBACKS, or a refusal comes back
# in a shape the page cannot read -- the reason a page never has to branch on
# whether the reply is an error.
python3 - "$helper" <<'PY' || fail 'a verb has no reply shape, or a shape has no fallback'
import ast
import sys
source = open(sys.argv[1], encoding="utf-8").read()
tree = ast.parse(source)
shapes = {}
for node in ast.walk(tree):
if isinstance(node, ast.FunctionDef) and node.name == "shape_for":
for inner in ast.walk(node):
if isinstance(inner, ast.Dict):
shapes = {key.value: value.value for key, value in
zip(inner.keys, inner.values)
if isinstance(key, ast.Constant) and isinstance(value, ast.Constant)}
fallbacks = set()
for node in tree.body:
target = getattr(node.targets[0], "id", "") if isinstance(node, ast.Assign) else ""
if target == "FALLBACKS" and isinstance(node.value, ast.Dict):
fallbacks = {key.value for key in node.value.keys if isinstance(key, ast.Constant)}
required = {"details", "forget", "saved", "set-autoconnect", "set-mac-random",
"set-metered", "set-ip", "join-enterprise", "join-hidden",
"import-vpn", "hotspot", "proxy", "airplane"}
missing = sorted(required - set(shapes))
if missing:
print(f"shape_for does not know: {missing}", file=sys.stderr)
raise SystemExit(1)
orphans = sorted(set(shapes.values()) - fallbacks)
if orphans:
print(f"shapes with no FALLBACKS entry: {orphans}", file=sys.stderr)
raise SystemExit(1)
raise SystemExit(0)
PY
# ── Static: the enterprise password is read, not passed ──────────────────────
#
# The mechanism is a choice (libnm's GObject bindings when they are installed, a
@@ -222,6 +275,13 @@ command -v jq >/dev/null 2>&1 || { printf 'network tools contract: SKIP (no jq)\
command -v python3 >/dev/null 2>&1 || { printf 'network tools contract: SKIP (no python3)\n'; exit 0; }
# ── The fake machine ─────────────────────────────────────────────────────────
#
# The field list the saved-profile stub answers to, read from the helper rather
# than retyped: a stub that answered a list the helper no longer asks for would
# quietly stop being consulted, and the in-range assertions below would pass on
# an empty table.
SAVED_FIELDS="$(sed -nE 's/^SAVED_FIELDS = "([^"]+)"$/\1/p' "$helper")"
[[ -n "$SAVED_FIELDS" ]] || fail 'the helper names no field list for the saved profiles'
work="$(mktemp -d /tmp/panama-network-contract.XXXXXX)"
stub_dir="$work/bin"
@@ -280,12 +340,37 @@ detail() {
printf 'IP4.GATEWAY:192.168.7.1\n'
printf 'IP4.DNS[1]:192.168.7.1\n'
printf 'IP4.DNS[2]:1.1.1.1\n'
# What the PROFILE asks for, as distinct from what is on the wire above.
# The editor reads these; a helper that reported only the active state
# would show an empty form over a static address.
printf 'connection.metered:unknown\n'
printf 'ipv4.method:auto\n'
printf 'ipv4.addresses:--\n'
printf 'ipv4.gateway:--\n'
printf 'ipv4.dns:--\n'
printf 'ipv6.method:auto\n'
printf 'ipv6.addresses:--\n'
printf 'ipv6.gateway:--\n'
printf 'ipv6.dns:--\n'
printf '802-11-wireless-security.psk:$WIFI_PSK\n'
printf '802-1x.password:$ENTERPRISE_PW\n'
printf 'vpn.secrets.password:$VPN_SECRET\n'
}
case "\$joined" in
*"-f $SAVED_FIELDS"*)
# The saved-profile table: NAME last, so a network called "Cafe: Guest"
# survives the field separator.
printf '22222222-0000-0000-0000-000000000002:802-11-wireless:yes:yes:1700000000:Home Wi-Fi\n'
printf '44444444-0000-0000-0000-000000000004:802-11-wireless:yes:no:1600000000:Office-Corp\n'
printf '55555555-0000-0000-0000-000000000005:802-11-wireless:no:no:1500000000:Cafe: Guest\n'
printf '66666666-0000-0000-0000-000000000006:802-3-ethernet:yes:no:1400000000:Wired connection 1\n'
exit 0 ;;
*"-f SSID device wifi list"*)
# Only one of the saved networks is anywhere near this machine, which is
# the whole point of the in-range flag.
printf 'Home Wi-Fi\nCoffeeHaus_Guest\n'
exit 0 ;;
*"connection edit"*)
# The only invocation that is fed anything, and it is drained under a
# timeout: every other one inherits whatever stdin the test runner had,
@@ -446,6 +531,168 @@ runh set-mac-random 'Home Wi-Fi' false >/dev/null 2>&1
grep -Eq 'cloned-mac-address +permanent' "$state_dir/argv" \
|| fail "turning randomization off did not restore the permanent address: $(log)"
# ── details reports the profile, not only the wire ───────────────────────────
#
# The editor writes the profile's addressing, so it has to be able to read it.
# The four fields at the top of `details` are what the connection currently
# holds, which is a different question: a static address that has not been
# applied yet is in the profile and not on the wire, and an editor bound to the
# wire would show an empty form over a setting somebody just typed.
: >"$state_dir/argv"
profile="$(runh details 'Home Wi-Fi' 2>/dev/null)"
jq -e 'has("metered") and has("ip4Method") and has("ip4Addresses")
and has("ip4Gateway") and has("ip4Dns") and has("ip6Method")' \
<<<"$profile" >/dev/null || fail "details does not report the profile's own addressing: $profile"
jq -e '.metered == "auto"' <<<"$profile" >/dev/null \
|| fail "NetworkManager's 'unknown' metered flag is not reported as automatic: $profile"
# "--" is nmcli for "unset", and a page that rendered it would show two dashes
# in the gateway box.
jq -e '.ip4Gateway == "" and (.ip4Dns | length) == 0' <<<"$profile" >/dev/null \
|| fail "an unset profile property came through as nmcli's placeholder: $profile"
# ── set-metered is three states, not two ─────────────────────────────────────
: >"$state_dir/argv"
runh set-metered 'Home Wi-Fi' yes >/dev/null 2>&1
grep -Eq 'connection\.metered +yes' "$state_dir/argv" \
|| fail "marking a connection metered did not reach nmcli: $(log)"
: >"$state_dir/argv"
runh set-metered 'Home Wi-Fi' auto >/dev/null 2>&1
# "automatic" is NetworkManager deciding, which it spells "unknown". Sending it
# "auto" would be refused, and sending it "no" would report a guess as a fact.
grep -Eq 'connection\.metered +unknown' "$state_dir/argv" \
|| fail "leaving metered to NetworkManager did not send its own spelling: $(log)"
: >"$state_dir/argv"
[[ -n "$(error_of set-metered 'Home Wi-Fi' sometimes)" ]] \
|| fail 'an unknown metered state was accepted'
[[ ! -s "$state_dir/argv" ]] || fail 'an unknown metered state still reached nmcli'
# ── set-ip writes a whole stack, and validates before it does ────────────────
: >"$state_dir/argv"
runh set-ip 'Home Wi-Fi' 4 manual 192.168.7.50/24 192.168.7.1 '1.1.1.1,9.9.9.9' >/dev/null 2>&1
for setting in 'ipv4\.method +manual' 'ipv4\.addresses +192\.168\.7\.50/24' \
'ipv4\.gateway +192\.168\.7\.1' 'ipv4\.dns +1\.1\.1\.1,9\.9\.9\.9'; do
grep -Eq "$setting" "$state_dir/argv" \
|| fail "a manual IPv4 address did not set $setting: $(log)"
done
# Without this NetworkManager appends DHCP's nameservers to the ones just
# typed, so "manual DNS" silently becomes "manual DNS and whatever else".
grep -Eq 'ipv4\.ignore-auto-dns +yes' "$state_dir/argv" \
|| fail "manual DNS does not ignore the ones DHCP hands out: $(log)"
# It was active in the listing, so it has to come back up or the change is
# saved and invisible.
grep -Eq 'connection up Home Wi-Fi' "$state_dir/argv" \
|| fail "an active connection was not reactivated after its address changed: $(log)"
: >"$state_dir/argv"
runh set-ip 'Home Wi-Fi' 6 manual 'fd00::42/64' 'fd00::1' 'fd00::1' >/dev/null 2>&1
grep -Eq 'ipv6\.method +manual' "$state_dir/argv" \
|| fail "a manual IPv6 address did not set the IPv6 method: $(log)"
grep -Fq 'fd00::42/64' "$state_dir/argv" \
|| fail "the IPv6 address never reached nmcli: $(log)"
# Going back to automatic has to CLEAR what manual left behind, or the
# connection comes up holding both.
: >"$state_dir/argv"
runh set-ip 'Home Wi-Fi' 4 auto >/dev/null 2>&1
grep -Eq 'ipv4\.method +auto' "$state_dir/argv" \
|| fail "returning to DHCP did not set the method: $(log)"
grep -Eq 'ipv4\.addresses' "$state_dir/argv" \
|| fail "returning to DHCP left the static address in place: $(log)"
grep -Eq 'ipv4\.ignore-auto-dns +no' "$state_dir/argv" \
|| fail "returning to DHCP kept ignoring the nameservers it hands out: $(log)"
# Each of these must be refused BEFORE nmcli, for the reason at the top of the
# name-validation block: nmcli refuses them too, so a check that only asks "did
# something error" passes with the validation deleted.
while IFS='|' read -r family address gateway dns why; do
: >"$state_dir/argv"
[[ -n "$(error_of set-ip 'Home Wi-Fi' "$family" manual "$address" "$gateway" "$dns")" ]] \
|| fail "$why was accepted"
[[ ! -s "$state_dir/argv" ]] || fail "$why reached nmcli before being refused"
done <<'BAD'
4|192.168.7.50|192.168.7.1|1.1.1.1|an address with no prefix
4|999.1.1.1/24|192.168.7.1|1.1.1.1|an address whose octets are not octets
4|192.168.7.50/33|192.168.7.1|1.1.1.1|an IPv4 prefix past 32
6|fd00::42/129|fd00::1|fd00::1|an IPv6 prefix past 128
4|192.168.7.50/24|not-a-gateway|1.1.1.1|a gateway that is not an address
4|192.168.7.50/24|192.168.7.1|nameserver|a nameserver that is not an address
6|192.168.7.50/24|fd00::1|fd00::1|an IPv4 address typed into the IPv6 stack
BAD
: >"$state_dir/argv"
[[ -n "$(error_of set-ip 'Home Wi-Fi' 5 auto)" ]] || fail 'a third IP family was accepted'
[[ -n "$(error_of set-ip 'Home Wi-Fi' 4 sideways)" ]] \
|| fail 'an addressing mode that is neither automatic nor manual was accepted'
# ── saved: the profiles this machine holds, in range or not ─────────────────
: >"$state_dir/argv"
saved="$(runh saved 2>/dev/null)"
jq -e '(.connections | length) == 4' <<<"$saved" >/dev/null \
|| fail "the saved listing did not parse four profiles: $saved"
# NAME is read last precisely so this one survives: nothing else in the row can
# contain a colon.
jq -e '[.connections[].name] | index("Cafe: Guest") != null' <<<"$saved" >/dev/null \
|| fail "a network name containing a colon was cut in half: $saved"
jq -e '.connections[] | select(.name == "Home Wi-Fi")
| .active == true and .autoconnect == true and .inRange == true' <<<"$saved" >/dev/null \
|| fail "the connected profile is not reported as connected and in range: $saved"
# The whole reason for the scan cross-reference: a saved network you are
# nowhere near is otherwise invisible until you stand next to it.
jq -e '.connections[] | select(.name == "Office-Corp") | .inRange == false' <<<"$saved" >/dev/null \
|| fail "a saved network that the scan did not see is not reported as out of range: $saved"
# A wired profile is not somewhere else; it is a cable. Saying "out of range"
# about one would be inventing a fact.
jq -e '.connections[] | select(.name == "Wired connection 1") | .inRange == null' <<<"$saved" >/dev/null \
|| fail "a wired profile was given an in-range answer, which it cannot have: $saved"
grep -Fq -- '--rescan no' "$state_dir/argv" \
|| fail "listing saved profiles made the radio go looking: $(log)"
offenders="$(jq -r '[paths | map(tostring) | join(".")]
| map(select(test("(password|secret|psk|passphrase)$";"i"))) | join(", ")' <<<"$saved")"
[[ -z "$offenders" ]] || fail "the saved listing carries credential-shaped fields: $offenders"
# ── join-hidden: the same stdin rule as the enterprise join ─────────────────
: >"$state_dir/argv"
: >"$state_dir/stdin"
hidden_out="$(printf '%s\n' "$HIDDEN_PW" \
| runh join-hidden 'office-private' 'office-private' wpa-psk 2>"$work/hidden.err")"
grep -Fq "$HIDDEN_PW" "$state_dir/argv" \
&& fail 'the hidden network passphrase was passed as a command argument'
grep -Fq "$HIDDEN_PW" <<<"$hidden_out" \
&& fail 'the hidden network passphrase is echoed back in the helper output'
grep -Fq "$HIDDEN_PW" "$work/hidden.err" \
&& fail 'the hidden network passphrase was written to stderr'
leaked="$(leak_in_scratch "$HIDDEN_PW")"
[[ -z "$leaked" ]] || fail "the hidden network passphrase was written to $leaked"
grep -Fq "$HIDDEN_PW" "$state_dir/stdin" \
|| fail 'the hidden network passphrase never reached nmcli at all, on stdin or otherwise'
# Without this the profile saves and never connects: NetworkManager only probes
# for a network by name when it is told the name is not broadcast.
grep -Fq '802-11-wireless.hidden yes' "$state_dir/stdin" \
|| fail 'the profile is not marked hidden, so NetworkManager will never look for it'
grep -Fq 'connection up office-private' "$state_dir/argv" \
|| fail "join-hidden saved a profile and never brought it up: $(log)"
# An open hidden network is a real thing, and it has no passphrase to wait for.
: >"$state_dir/argv"
: >"$state_dir/stdin"
runh join-hidden 'open-hidden' 'open-hidden' none </dev/null >/dev/null 2>&1
grep -Fq 'connection edit' "$state_dir/argv" \
|| fail "an open hidden network was not created: $(log)"
grep -Fq 'wireless-security' "$state_dir/stdin" \
&& fail 'an open network was given a key-management setting'
: >"$state_dir/argv"
[[ -n "$(runh join-hidden 'office-private' 'office-private' wep </dev/null 2>/dev/null \
| jq -r '.error // ""')" ]] || fail 'an unknown hidden-network security was accepted'
[[ ! -s "$state_dir/argv" ]] \
|| fail 'an unknown hidden-network security still reached nmcli'
[[ -n "$(runh join-hidden 'office-private' 'office-private' wpa-psk </dev/null 2>/dev/null \
| jq -r '.error // ""')" ]] || fail 'a secured hidden network with no password was accepted'
# ── import-vpn picks its plugin from the extension ───────────────────────────
printf '[Interface]\n' >"$work/tunnel.conf"
@@ -606,9 +853,9 @@ done
[[ -n "$(error_of bogus-verb)" ]] || fail 'an unknown command was accepted'
# ── Nothing anywhere left a secret behind ───────────────────────────────────
for secret in "$WIFI_PSK" "$VPN_SECRET" "$ENTERPRISE_PW" "$HOTSPOT_PW"; do
for secret in "$WIFI_PSK" "$VPN_SECRET" "$ENTERPRISE_PW" "$HOTSPOT_PW" "$HIDDEN_PW"; do
leaked="$(leak_in_scratch "$secret")"
[[ -z "$leaked" ]] || fail "a secret was left behind in $leaked"
done
printf 'network tools contract: PASS (details, forget, autoconnect, MAC, import, hotspot, enterprise, proxy, airplane)\n'
printf 'network tools contract: PASS (details, forget, saved, autoconnect, MAC, metered, static IP, import, hotspot, enterprise, hidden, proxy, airplane)\n'