Refresh the passwordless sudo indicator on change instead of polling (#15026)
* Refresh the passwordless sudo indicator on change instead of polling Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Refresh the sudo indicator after failed changes and on a wall-clock deadline Addresses Codex review: a rolled-back renewal skipped the refresh, the monotonic user timer paused through suspend, and default timer accuracy allowed a minute's delay. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Test the sudo indicator refreshes by running the grant flows Replace source-string checks with runs of timed, renewed, failed, permanent and disable flows against the fixture, asserting the recorded omarchy-shell refresh and wall-clock systemd-run --user timer. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
8bd1b7c045
commit
3c1f7b780f
5 files changed
+96
-14
No files matched your search
@@ -58,6 +58,8 @@ case "$name" in
|
||||
[[ ${TEST_POST_PUBLISH_FAIL:-0} != 1 ]] || : >"$TEST_GRANT_ROOT/run/omarchy-sudo-passwordless-package-removing"
|
||||
;;
|
||||
systemd-run)
|
||||
# The indicator's user refresh timer is not the root expiry timer.
|
||||
[[ ${1:-} != --user ]] || exit 0
|
||||
[[ ${TEST_TIMER_FAIL:-0} != 1 ]] || exit 1
|
||||
if [[ ${TEST_CANCEL_ENABLE:-0} == 1 ]]; then kill -TERM "$PPID"; fi
|
||||
;;
|
||||
@@ -67,6 +69,7 @@ case "$name" in
|
||||
date)
|
||||
if [[ ${TEST_EXPIRED:-0} == 1 && $* == '-u +%Y%m%d%H%M%SZ' ]]; then echo 99991231235959Z; else /usr/bin/date "$@"; fi
|
||||
;;
|
||||
omarchy-shell) ;;
|
||||
getent) printf '%s:x:1000:1000:Test:/nonexistent:/bin/bash\n' "${TEST_ACCOUNT:-audituser}" ;;
|
||||
sudo)
|
||||
if [[ ${1:-} == -h ]]; then echo 'usage: sudo [-N] command'; exit 0; fi
|
||||
@@ -86,6 +89,7 @@ case "$name" in
|
||||
TEST_EUID=0 /usr/bin/bash -p "$@"
|
||||
else
|
||||
[[ ${2:-} != __status ]] || exit "${TEST_STATUS:-3}"
|
||||
[[ ${2:-} != __enable || ${TEST_ENABLE_FAIL:-0} != 1 ]] || exit 1
|
||||
fi
|
||||
;;
|
||||
gum)
|
||||
@@ -100,7 +104,7 @@ case "$name" in
|
||||
esac
|
||||
STUB
|
||||
chmod +x "$test_tmp/bin/mock"
|
||||
for name in stat chown install rm mv systemd-run systemctl date getent sudo gum; do
|
||||
for name in stat chown install rm mv systemd-run systemctl date getent sudo gum omarchy-shell; do
|
||||
ln -s mock "$test_tmp/bin/$name"
|
||||
done
|
||||
|
||||
@@ -114,7 +118,7 @@ for name in ('omarchy-sudo-passwordless', 'omarchy-security-functions'):
|
||||
target = str(temp/'hooks') if path == '/usr/share/libalpm/hooks' else str(temp) + path
|
||||
text = text.replace(path, target)
|
||||
text = text.replace('((EUID == 0))', '((${TEST_EUID:-1} == 0))')
|
||||
for command in ('stat', 'chown', 'install', 'rm', 'mv', 'systemd-run', 'systemctl', 'date', 'getent', 'sudo', 'gum'):
|
||||
for command in ('stat', 'chown', 'install', 'rm', 'mv', 'systemd-run', 'systemctl', 'date', 'getent', 'sudo', 'gum', 'omarchy-shell'):
|
||||
text = text.replace('/usr/bin/' + command, str(temp/'bin'/command))
|
||||
(temp/name).write_text(text)
|
||||
(temp/name).chmod(0o755)
|
||||
|
||||
@@ -17,7 +17,8 @@ assert(!widget.includes('sudoHorizontal') && !widget.includes('sudoVertical'), '
|
||||
assert(!indicator.includes('visible:'), 'sudo uses the shared indicator visibility and hover behavior')
|
||||
assert(indicator.includes('command: ["omarchy-sudo-passwordless", "--active"]'), 'indicator uses the noninteractive grant probe')
|
||||
assert(indicator.includes('root.granted = exitCode === 0 && exitStatus === 0'), 'failed or interrupted probes do not claim an active grant')
|
||||
assert(indicator.includes('interval: 5000') && indicator.includes('onTriggered: root.refresh()'), 'indicator refreshes after activation, revocation, and expiry')
|
||||
assert(!indicator.includes('Timer'), 'indicator does not poll the sudo probe')
|
||||
assert(indicator.includes('function onRefreshRequested() { root.refresh() }'), 'indicator probes when the indicator host asks for a refresh')
|
||||
assert(indicator.includes('command: ["omarchy-sudo-passwordless", "--disable"]'), 'active indicator revokes access through a background process')
|
||||
assert(indicator.includes('if (root.granted) disableProc.running = true'), 'active click bypasses the terminal launcher')
|
||||
assert(indicator.includes('root.indicatorHost.refresh()'), 'disabling access refreshes all indicator instances immediately')
|
||||
@@ -34,3 +35,57 @@ revoke.running = false
|
||||
press(button, revoke)
|
||||
assertDeepEqual(launched, ['omarchy-launch-floating-terminal-with-presentation omarchy-sudo-passwordless'], 'inactive click still opens interactive setup')
|
||||
JS
|
||||
|
||||
# Run the public grant flows against the fixture's stand-ins and check the
|
||||
# refreshes they push, without touching the host shell or user timers.
|
||||
source "$SHELL_TEST_DIR/fixtures/passwordless-sudo-test.sh"
|
||||
refresh="omarchy-shell -q omarchy.indicators refresh"
|
||||
run_grant_flow() {
|
||||
: >"$test_tmp/commands"
|
||||
env "$@" /usr/bin/bash -p "$test_tmp/omarchy-sudo-passwordless" "${grant_args[@]}" >"$test_tmp/public.log" 2>&1 || true
|
||||
}
|
||||
refresh_follows() {
|
||||
grep -A1 -- "$1" "$test_tmp/commands" | grep -qxF -- "$refresh"
|
||||
}
|
||||
user_timers() {
|
||||
grep -c '^systemd-run --user ' "$test_tmp/commands" || true
|
||||
}
|
||||
|
||||
grant_args=(15)
|
||||
before=$EPOCHSECONDS
|
||||
run_grant_flow TEST_STATUS=3 TEST_CONFIRM_STATUS=0
|
||||
after=$EPOCHSECONDS
|
||||
refresh_follows ' __enable [0-9]* 15$' || fail "timed enable must refresh the indicator after the grant changes"
|
||||
timer=$(grep '^systemd-run --user ' "$test_tmp/commands") || fail "timed enable must schedule an expiry refresh"
|
||||
timer_pattern="^systemd-run --user --quiet --collect --on-calendar=@([0-9]+) --timer-property=AccuracySec=1s -- $test_tmp/bin/omarchy-shell -q omarchy.indicators refresh$"
|
||||
[[ $timer =~ $timer_pattern ]] || fail "unexpected expiry refresh timer: $timer"
|
||||
deadline=${BASH_REMATCH[1]}
|
||||
(( deadline >= before + 15 * 60 + 2 && deadline <= after + 15 * 60 + 2 )) || fail "expiry refresh must fire just after the wall-clock deadline"
|
||||
pass "timed enable refreshes now and on a wall-clock timer just after expiry"
|
||||
|
||||
run_grant_flow TEST_STATUS=0
|
||||
refresh_follows ' __enable [0-9]* 15$' || fail "renewal must refresh the indicator"
|
||||
(( $(user_timers) == 1 )) || fail "renewal must schedule an expiry refresh"
|
||||
pass "renewing a timed grant refreshes and reschedules the expiry refresh"
|
||||
|
||||
run_grant_flow TEST_STATUS=0 TEST_ENABLE_FAIL=1
|
||||
refresh_follows ' __enable [0-9]* 15$' || fail "failed renewal must still refresh the indicator"
|
||||
(( $(user_timers) == 0 )) || fail "failed renewal must not schedule an expiry refresh"
|
||||
pass "a failed grant change still refreshes the indicator"
|
||||
|
||||
grant_args=(permanent)
|
||||
run_grant_flow TEST_STATUS=3 TEST_CONFIRM_STATUS=0
|
||||
refresh_follows ' __enable [0-9]* permanent$' || fail "permanent enable must refresh the indicator"
|
||||
(( $(user_timers) == 0 )) || fail "permanent enable must not schedule an expiry refresh"
|
||||
pass "permanent enable refreshes without scheduling an expiry refresh"
|
||||
|
||||
assert_disable_refreshes() {
|
||||
run_grant_flow TEST_STATUS=0
|
||||
refresh_follows ' __disable [0-9]*$' || fail "disable ${grant_args[*]} must refresh the indicator"
|
||||
(( $(user_timers) == 0 )) || fail "disable must not schedule an expiry refresh"
|
||||
}
|
||||
grant_args=()
|
||||
assert_disable_refreshes
|
||||
grant_args=(--disable)
|
||||
assert_disable_refreshes
|
||||
pass "disabling access refreshes the indicator"
|
||||
Reference in new issue
Block a user