diff options
| author | Craig Jennings <c@cjennings.net> | 2026-07-24 12:58:03 -0500 |
|---|---|---|
| committer | Craig Jennings <c@cjennings.net> | 2026-07-24 12:58:03 -0500 |
| commit | c388c25dcbdea4f8dc6ca2a7cca1c50786195f0d (patch) | |
| tree | 6bec0994938cf57f444ceac45e62b9f3fb77832c /todo.org | |
| parent | 249bb93b29ef471a6529d2d5bb96df87e1ac1a8a (diff) | |
| download | archsetup-c388c25dcbdea4f8dc6ca2a7cca1c50786195f0d.tar.gz archsetup-c388c25dcbdea4f8dc6ca2a7cca1c50786195f0d.zip | |
docs(todo): close the seven speedrun tasks, one of them disproved
Diffstat (limited to 'todo.org')
| -rw-r--r-- | todo.org | 35 |
1 files changed, 26 insertions, 9 deletions
@@ -202,10 +202,12 @@ Same class as three bugs already fixed this session — =_restore_dot= claiming Grading: Critical severity (a backup system that reports success while backing nothing up; the failure surfaces only when the backup is needed — graded on the harm once in the failure state, not on how rarely it is entered) × rare edge case (needs a ZFS root, a reachable TrueNAS, and the user enabling the timer by hand — archsetup deliberately does not enable it, and =findmnt -n -o FSTYPE /= on this machine says btrfs, so it is latent here) = P2 = [#B]. Left alone: =BACKUP_PATH="backups" # TODO: Configure actual path= is still an unresolved TODO in the destination, and single-dataset mode relies on =set -e= to propagate a syncoid failure rather than reporting it. Neither is a defect in the sense above; the TODO is Craig's call. -** TODO [#D] Wireless regdom is silently unset for a three-letter-language locale :bug:installer:solo: +** DONE [#D] Wireless regdom is silently unset for a three-letter-language locale :bug:installer:solo: +CLOSED: [2026-07-24 Fri] :PROPERTIES: :LAST_REVIEWED: 2026-07-24 :END: +Fixed as archsetup =249bb93=. =locale_country= matches the =_CC= group instead of counting characters, and =set_wireless_regdom= verifies the substitution landed rather than trusting sed's exit code. 16 tests. =configure_networking= derives the wireless regulatory domain by fixed offset: =wireless_region="${current_lang:3:2}"=, with a comment reading "extract country code (positions 3-4)". That is correct only for a two-letter language code. =validate_config= accepts =^[a-z]{2,3}(_[A-Z]{2})?...=, so a three-letter language is a legal =LOCALE=, and glibc ships 75 of them (=agr_PE=, =ast_ES=, =ber_DZ=, =ayc_PE=, ...). Verified by running the expansion: =ber_DZ.UTF-8= yields =_D=, =ayc_PE.UTF-8= yields =_P=, =C= yields the empty string, =POSIX= yields =IX=. @@ -239,10 +241,12 @@ The sibling asymmetry: =is_encrypted_root()= already exists in this script and = Grading: Critical severity (the machine will not boot and recovery needs external media — graded on the harm once in the failure state, not on how rarely it is entered) × some users, sometimes (LUKS-encrypted non-ZFS root using the busybox =encrypt= hook; deterministic for those machines, absent everywhere else) = P2 = [#B]. Deliberately not attempted: migrating =encrypt= to =sd-encrypt=. That means rewriting the kernel cmdline from =cryptdevice== to =rd.luks.name== against the volume's UUID, which is a real migration and not a mechanical edit. Refusing the cosmetic swap keeps a working machine working, which is the right trade against quieter fsck output. -** TODO [#D] keymap and consolefont hooks are inert under the systemd initramfs :bug:installer:solo: +** DONE [#D] keymap and consolefont hooks are inert under the systemd initramfs :bug:installer:solo: +CLOSED: [2026-07-24 Fri] :PROPERTIES: :LAST_REVIEWED: 2026-07-24 :END: +Fixed as archsetup =249bb93=. The swap rewrites both to =sd-vconsole=, collapsing them into one entry and never duplicating an existing one. The open question is answered: this machine is KEYMAP=us with no encrypt hook, but the function runs on LUKS machines where a non-US layout at the passphrase prompt is exactly what sd-vconsole restores. 7 tests. Same class as the =encrypt= bug above, but cosmetic rather than boot-critical, so it was filed rather than bundled into that fix. Enumerating the busybox-only hooks on this machine (every hook under =/usr/lib/initcpio/hooks/= defining =run_hook=/=run_earlyhook=/=run_latehook=) gives: btrfs, consolefont, encrypt, grub-btrfs-overlayfs, keymap, memdisk, resume, sleep, udev, usr. All go inert once =/init= is systemd. Of those, =encrypt= is the only boot-critical one — =resume= is handled natively by systemd's hibernate-resume generator, and =btrfs= by udev rules (this machine runs =btrfs= alongside =systemd= and boots fine). @@ -393,10 +397,12 @@ This is the round-3 finding one layer out, and the asymmetry is the tell: =018c0 Grading: graded on severity alone under the privacy carve-out, exactly as the round-3 sibling. Same exposure (cleartext DNS to an untrusted venue resolver), same bound (=net diagnose='s =encrypted-dns= step catches the stranded state), and the same affirmative promise removing the reason to look. Major severity = P2 = [#B]. Fixed as dotfiles =601c5b4= (committed locally, deliberately NOT pushed — held for Craig's morning review). The watcher now returns the outcome, appends a =portal-restore-watch= event with it, and fires a persistent =notify security= alert on each of the three failing outcomes, each naming the command to run by hand. A clean restore stays silent. Five tests: one per failing outcome, one pinning the silence on a clean restore, and one on the event-log line. The whole =TestPortalLogin= class now shadows =notify= with a logging fake, so no future watcher test can fire a real desktop notification mid-suite. -** TODO [#D] dns-override failure path says "reverted" without checking :bug:net:quick:solo: +** DONE [#D] dns-override failure path says "reverted" without checking :bug:net:quick:solo: +CLOSED: [2026-07-24 Fri] :PROPERTIES: :LAST_REVIEWED: 2026-07-24 :END: +Fixed as dotfiles =2cf3fb3=. The revert is checked; a declined one now says 1.1.1.1 is still set and names =resolvectl revert <iface>=. Found in the 2026-07-24 sentry bug-hunt, round 3, sweeping for siblings of the portal-restore finding above. =net/src/net/repair.py=, =repair_dns_override()= failure path: when the 1.1.1.1 override doesn't restore resolution, it calls =priv.run("dns-revert", iface)=, discards the result, and returns evidence reading "override didn't restore resolution — reverted". A failed revert leaves 1.1.1.1 set on the link while the step says it was removed. Same defect class as the portal-restore bug, three hundred lines up in the same file, and it survived the sweep only because the consequence is much smaller. Every other mutating repair in this file verifies by re-measuring afterwards rather than by reading an exit code, which is the stronger pattern and is why the sweep otherwise came back dry. @@ -531,10 +537,12 @@ What's off is the *grouping* for multi-line messages. Thirteen =systemd-coredump Consequence is modest: the digest's top-N rows get eaten by near-duplicates, so genuinely distinct errors fall off the evidence list sooner. It doesn't affect the metric's value or severity. The question is what you'd want: group coredumps by the binary named in the first line (a special case for =systemd-coredump=), signature only the *first line* of any multi-line message (a general rule, and arguably the right one — the first line is the error, the rest is context), or leave it alone. The middle option is the smallest general change and I'd lean that way, but it changes grouping for every multi-line error, so it's yours to call. -** TODO [#D] a failed wallpaper apply reports "nothing to apply" :bug:settings:quick:solo: +** DONE [#D] a failed wallpaper apply reports "nothing to apply" :bug:settings:quick:solo: +CLOSED: [2026-07-24 Fri] :PROPERTIES: :LAST_REVIEWED: 2026-07-24 :END: +Fixed as dotfiles =2cf3fb3=. The decision moved to =gui.wallpaper_apply_toast=, a module-level pure helper, because the callback lives inside a GTK widget where no test can reach it. 5 tests. Found in the 2026-07-24 sentry bug-hunt, round 7, sweeping the settings panel's worker callbacks. =settings/gui.py='s =_async= passes an exception through as the *result* rather than as a separate error argument, so every =done= callback has to test =isinstance(res, Exception)=. Five do — =_mx_pin=, =_mx_letter=, =_after_matrix=, =_set_pointer=, the drum/dial/gallery/refresh callbacks. =_wp_apply= is the one that doesn't: @@ -552,10 +560,12 @@ def _wp_apply(self, note="Wallpaper set"): Grading: Minor severity (wrong text on an error path, correctly marked as a failure, nothing corrupted) × rare edge case (needs =store.save= or =wallpaper.apply= to raise rather than return False) = P4 = [#D]. Fix: give it the same =isinstance(res, Exception)= arm its five siblings have — toast =str(res)= on an exception, keep the current two-way message otherwise. One callback, three lines. -** TODO [#D] two manage.py nmcli reads sit outside their own error conversion :bug:net:quick:solo: +** DONE [#D] two manage.py nmcli reads sit outside their own error conversion :bug:net:quick:solo: +CLOSED: [2026-07-24 Fri] :PROPERTIES: :LAST_REVIEWED: 2026-07-24 :END: +Fixed as dotfiles =2cf3fb3=. =_key_mgmt= converts both nmcli exceptions to "", which both call sites already treat as neither wpa-eap nor sae. 2 tests, including one driving =_classify_up_failure= end to end. Found in the 2026-07-24 sentry bug-hunt, round 4, reading =net/src/net/manage.py=. =nmcli.run()= raises =NmcliTimeout= on timeout and =NmcliError= on a missing binary, and every mutation in this module is written to convert both into a result envelope. Two calls escape that conversion because they run through =_key_mgmt()=, which wraps =nmcli.get_value= and catches nothing: - =edit()= line 243 calls =_key_mgmt(uuid)= for the enterprise-profile refusal *before* its own =try=, while the next four lines catch exactly those two exceptions around =nmcli.run=. @@ -566,10 +576,12 @@ Consequence is a leaked exception where the caller expected an envelope. The pan Grading: Minor severity (the operation fails either way; what's lost is the classified message, and only the CLI path shows a traceback) × rare edge case (=connection show= has a 2s timeout and nmcli's presence is already established by the time either site runs) = P4 = [#D]. Fix: give =_key_mgmt= the same conversion its callers use — catch =(nmcli.NmcliError, nmcli.NmcliTimeout)= and return "", which both call sites already handle correctly (neither "wpa-eap" nor "sae"). One =try= in one helper covers both sites. -** TODO [#D] three atomic writers share one fixed .tmp name :bug:quick:solo: +** DONE [#D] three atomic writers share one fixed .tmp name :bug:quick:solo: +CLOSED: [2026-07-24 Fri] :PROPERTIES: :LAST_REVIEWED: 2026-07-24 :END: +Fixed as dotfiles =2cf3fb3=. All three carry =.tmp.$(getpid)=, matching the six writers that already did. 6 tests across audio and maint. Found in the 2026-07-24 sentry bug-hunt, round 4, sweeping both repos for the temp-file half of the atomic-write idiom. The tree writes state atomically in nine places, and six of them make the temp path unique per writer: =net/cache.py= and =timer/engine.py= both use =f"{path}.tmp.{os.getpid()}"=, and =settings/store.py=, =settings/idle.py=, =bt/repair.py=, =net/probe.py= all use =tempfile.mkstemp=/=NamedTemporaryFile=. Three use a bare =path + ".tmp"=: - =audio/src/audio/ptt.py= =write_state= (the lead carried over from round 3's Next Steps) @@ -583,15 +595,20 @@ Real concurrent-writer pairs exist for two of the three. =maint/cache.py= =updat Grading: Minor severity (every reader degrades rather than crashes — =cache.get= catches =ValueError= and reports no data, =read_state= reads a torn file as disarmed, and both recover on the next write; the sharpest edge is the loser's =FileNotFoundError= aborting the rest of =scan_net=, which the next hourly run repairs) × rare edge case (the write window is a millisecond or two, and the overlapping writers are an hourly timer against a human keypress) = P4 = [#D]. Fix: give all three the =f"{path}.tmp.{os.getpid()}"= form the two careful siblings already use. It is three one-line changes and needs no new abstraction. Note this closes the torn-file half only — the read-modify-write in =ptt.toggle_plan= and =curation.set_preference= can still lose an update between two writers, which wants a lock rather than a temp-name change and should stay a separate decision. -** TODO [#C] dmenuexitmenu word-splits its menu so no entry matches :bug:dwm:solo: +** DONE [#C] dmenuexitmenu word-splits its menu so no entry matches :bug:dwm:solo: +CLOSED: [2026-07-24 Fri] :PROPERTIES: :LAST_REVIEWED: 2026-07-24 :END: Found in the 2026-07-24 sentry bug-hunt (shellcheck SC2128). =dwm/.local/bin/dmenuexitmenu= line 4 expands the menu unquoted: =choice=$(echo -e $menuitems | dmenu ...)=. Word-splitting collapses the runs of spaces the labels carry, so dmenu shows =Lock= where the =case= arm expects =Lock = (two spaces) and =Logout = where the arm expects a trailing space. No arm matches, so choosing an entry does nothing at all. -Grading: Major severity (every menu action is inert) × rare edge case (dwm is not stowed on this machine — =~/.local/bin/dmenuexitmenu= does not exist, so the script is currently dead code) = P3 = [#C]. +CORRECTION (2026-07-24): THE BUG AS FILED DOES NOT EXIST. Ran it. =echo= rejoins the words split off the unquoted expansion with single spaces, and no label carries two spaces, so quoted and unquoted produce byte-identical output — verified against the exact literals from git rather than a retyped copy. Every =case= arm matches and every menu action works. + +What is real is latent. An unquoted expansion collapses a double space and glob-expands a =*=; the second was demonstrated turning a label into a directory listing. No current label triggers either. + +Hardened anyway in dotfiles =2cf3fb3= as robustness, not as a bug fix: the expansion is quoted and the bogus one-element array is now a plain string. Output confirmed unchanged byte-for-byte. New =tests/dmenuexitmenu/= (10 tests) pins the working behaviour, and shellcheck on the file drops from three findings to one. -Fix: quote the expansion (=echo -e "$menuitems"=) and index the array element explicitly. Left unfixed for now because dwm is inactive; raise to [#B] if the dwm tier is ever restowed. +SECOND SENTRY FILING DISPROVED BY RUNNING IT, after =a57c443= (mkplaylist). Both came from a shellcheck hit plus reasoning, neither was executed. A static-analysis finding says a construct is unsafe, not that it currently misbehaves, and both filings treated the first as the second. ** VERIFY [#B] Two agent sessions sharing one git repo :chore:tooling: SCHEDULED: <2026-07-27 Mon> Twice on 2026-07-22/23 a session swept the other's uncommitted work into its commit while both worked the dotfiles tree. The dotfiles session pathspec'd around mine once; my 2bd7d56 then carried their settings-panel window-rule revert (100%-854 → 100%-584) under a message describing only hypridle. Nothing needed undoing — the change was wanted — but the commit misdescribes itself, and the next collision may not be benign. |
