# Sudoers grants for the TinyUSB HIL rig agent user. Generic-by-UID: grants target "#1000", the # first regular account on Debian/Ubuntu (the rig agent user) — no username hardcoded, no edit # needed. If your agent user is a different UID, change #1000 accordingly (e.g. #1001), or swap # to a group with "%groupname". The actions-runner path is wildcarded (/home/*/) since a UID # doesn't name a home directory. # # Deploy (from the repo root, needs your password once): # sudo install -m0440 -oroot -groot test/hil/tinyusb-sudoer /etc/sudoers.d/tinyusb-sudoer # sudo visudo -c # # The referenced helper scripts are versioned under .claude/skills/ and installed with: # sudo install -m0755 -oroot -groot .claude/skills/usb-recover/scripts/usb_recover.sh /usr/local/sbin/ # sudo install -m0755 -oroot -groot .claude/skills/usb-debug/scripts/usb_dyndbg.sh /usr/local/sbin/ # # What each grant is for: # dmesg - read kernel log (USB events, usbtest results) # uhubctl - hub port power control (only works on buses with ppps) # usb_recover.sh - narrow sysfs USB reset helper (see .claude/skills/usb-recover) # usb_dyndbg.sh - kernel dynamic-debug toggle for USB modules (see .claude/skills/usb-debug) # tee usbtest sysfs paths - bind/unbind the usbtest host driver (test/hil/usbtest.py) # tee .../driver/unbind - steal the interface from a foreign driver before binding usbtest # modprobe usbtest - load the usbtest module on demand # testusb - run test cases when the device node is not user-writable (no udev # rule); with the shipped 99-tinyusb udev rule the node is 0666 and # this grant is unused # systemctl stop/start - stop/start the CI GitHub Actions runner service around manual hardware # actions.runner.* runs so it doesn't reflash boards mid-test (see the hil skill). Granted # on the root-owned systemctl unit (actions.runner.-. # .service), NOT on ~/actions-runner/svc.sh — that script lives in the # runner user's writable home, so sudo on it would equal passwordless root. # Find the unit: systemctl list-units 'actions.runner.*' # (controller re-bind after a driverless pci-rebind is handled by usb_recover.sh pci-bind, which # is already covered by the usb_recover.sh grant above — no extra sudoers rule needed.) # systemctl reboot --force - last-resort USB recovery when a testusb D-state URB is unkillable and # neither pci-reset (ENOTTY on Renesas) nor pci-bind can revive the # controller (see the usb-recover skill). --force is required: a graceful # reboot blocks in shutdown waiting for the wedged D-state process to # terminate (it never does), so plain reboot stalls; --force terminates # services and reboots immediately. Plain reboot kept for non-wedge use. # An @reboot one-shot resumes the working session afterwards. # NB: '#1000' below is a UID specifier (sudoers(5) User_List syntax), NOT a comment — these # lines are live grants for uid 1000. #1000 ALL=(root) NOPASSWD: /usr/bin/dmesg, /sbin/uhubctl #1000 ALL=(root) NOPASSWD: /usr/local/sbin/usb_recover.sh #1000 ALL=(root) NOPASSWD: /usr/local/sbin/usb_dyndbg.sh #1000 ALL=(root) NOPASSWD: /usr/bin/systemctl stop actions.runner.*, /usr/bin/systemctl start actions.runner.* #1000 ALL=(root) NOPASSWD: /usr/local/bin/testusb * #1000 ALL=(root) NOPASSWD: /usr/bin/systemctl reboot --force, /usr/bin/systemctl reboot #1000 ALL=(root) NOPASSWD: /usr/bin/tee /sys/bus/usb/drivers/usbtest/new_id, /usr/bin/tee /sys/bus/usb/drivers/usbtest/remove_id, /usr/bin/tee /sys/bus/usb/drivers/usbtest/bind, /usr/bin/tee /sys/bus/usb/drivers/usbtest/unbind, /usr/bin/tee /sys/bus/usb/devices/*/driver/unbind, /usr/bin/tee /sys/module/usbtest/parameters/pattern, /usr/sbin/modprobe usbtest