Finish the wonderland: System told truthfully, in eight tabs instead of ten

Claude-Session: https://claude.ai/code/session_01Ms2FbjQy31TVf3CEvQhGM8
This commit is contained in:
Gabriel Brown
2026-08-24 23:31:52 -04:00
parent 9ffaf45a4d
commit be0e55214b
57 changed files with 5040 additions and 925 deletions
+96
View File
@@ -198,6 +198,102 @@ jq -e 'has("pwned") | not' "$settings" >/dev/null || fail 'a file outside the ba
# ── A snapshot that is not listed is refused ─────────────────────────────────
run restore "settings-20000101-000000000.json" >/dev/null 2>&1 && fail 'a missing snapshot was reported restored'
# ── A snapshot can be given a name, and the name cannot be a path ────────────
#
# Fifteen rows reading "2026-08-24 11:03:07" are fifteen rows nobody can choose
# between, which is the same as having no backups: the one you want is the one
# you took before the thing you are undoing, and the timestamp does not say
# what that was. So `create` takes a name.
#
# A name typed by a person then reaches a filename, which is the oldest way a
# helper gets talked into writing outside its own directory. The charset is the
# snapshot charset -- letters, digits, dot, dash, underscore -- and everything
# else is either sanitized out or refused; either is fine, writing outside
# BACKUP_DIR is not.
rm -f "$backups"/*.json
printf '{"gapsOut":24}' >"$settings"
printf '{"initialized":true,"favorites":[]}' >"$home"
run create >/dev/null || fail 'create without a name failed'
[[ "$(run list | jq 'length')" == "1" ]] || fail 'an unnamed create did not produce one snapshot'
run create "Before the theme experiment" >/dev/null || fail 'create with a name failed'
named="$(run list | jq -r '.[0]')"
jq -e '.label == "Before the theme experiment"' <<<"$named" >/dev/null \
|| fail "a named snapshot did not carry its name back: $named"
named_file="$(jq -r .name <<<"$named")"
[[ "$named_file" =~ ^[A-Za-z0-9_.-]+$ ]] \
|| fail "a named snapshot produced the filename \"$named_file\", which is outside the snapshot charset"
# Every one of these either fails or produces a file inside the backup
# directory. None of them may produce a file anywhere else, and none may
# remove or overwrite something that is not a snapshot.
outside="$work/state/panama/NOT-A-BACKUP"
printf 'untouched\n' >"$outside"
for hostile in \
'../../../NOT-A-BACKUP' \
'/etc/panama-owned' \
'a/b' \
'..' \
'.' \
$'tab\there' \
'-rf'; do
run create "$hostile" >/dev/null 2>&1 || true
[[ "$(<"$outside")" == 'untouched' ]] \
|| fail "the snapshot name \"$hostile\" wrote outside the backup directory"
done
while read -r listed; do
[[ -n "$listed" ]] || continue
[[ "$listed" =~ ^[A-Za-z0-9_.-]+$ ]] \
|| fail "a hostile snapshot name produced the listed filename \"$listed\""
done < <(run list | jq -r '.[].name')
# ── A snapshot can be deleted, and only a snapshot ───────────────────────────
#
# Same boundary as restore, in the other direction, and with a worse failure:
# restore reading the wrong file overwrites settings, delete resolving the
# wrong name destroys something that is not a backup at all.
before_delete="$(run list | jq 'length')"
(( before_delete >= 2 )) || fail 'not enough snapshots to exercise delete'
victim="$(run list | jq -r '.[0].name')"
run delete "$victim" >/dev/null || fail 'deleting a listed snapshot failed'
[[ ! -e "$backups/$victim" ]] || fail 'a deleted snapshot is still on disk'
[[ "$(run list | jq 'length')" == "$((before_delete - 1))" ]] \
|| fail 'delete removed a different number of snapshots than one'
printf '{"pwned":false}' >"$work/delete-target.json"
for hostile in \
'../../delete-target.json' \
'/etc/passwd' \
"$victim" \
'settings-20000101-000000000.json' \
'' ; do
run delete "$hostile" >/dev/null 2>&1 \
&& fail "delete accepted \"$hostile\", which is not a snapshot in the backup directory"
done
[[ -f "$work/delete-target.json" ]] || fail 'delete followed a traversing name out of the backup directory'
escape="settings-20000101-000000009.json"
ln -s "$work/delete-target.json" "$backups/$escape"
run delete "$escape" >/dev/null 2>&1 \
&& fail 'delete accepted a symlink escaping the backup directory'
[[ -f "$work/delete-target.json" ]] || fail 'delete removed the target of an escaping symlink'
rm -f "$backups/$escape"
# ── The list says how much room a snapshot takes ─────────────────────────────
#
# Fifteen snapshots of a settings file are nothing; fifteen of a settings file
# somebody grew are not, and the page offers a Delete button now, which is a
# decision nobody can make without the size.
run list | jq -e 'all(.[]; (.bytes | type == "number") and .bytes > 0)' >/dev/null \
|| fail 'the snapshot list does not report each snapshots size'
listed_bytes="$(run list | jq -r '.[0].bytes')"
actual_bytes="$(stat -c %s "$backups/$(run list | jq -r '.[0].name')")"
[[ "$listed_bytes" == "$actual_bytes" ]] \
|| fail "the list reports $listed_bytes bytes for a snapshot that is $actual_bytes on disk"
# ── Snapshots are capped ─────────────────────────────────────────────────────
for _ in $(seq 1 20); do
printf '{"n":%s}' "$RANDOM" >"$settings"