Files
Panama/tests/quickshell/health-service-contract.sh
T

350 lines
17 KiB
Bash
Executable File

#!/usr/bin/env bash
# Health owns the accepted diagnostic snapshot. A newer unreadable response
# must degrade diagnostics without discarding the last report that Settings
# and future health surfaces will render.
set -euo pipefail
repo_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
source_harness="$repo_dir/config/dot/quickshell/health-harness.qml"
service="$repo_dir/config/dot/quickshell/services/Health.qml"
shell="$repo_dir/config/dot/quickshell/shell.qml"
warning_snapshot='{"schemaVersion":1,"generatedAt":"2026-08-18T00:00:00Z","summary":{"status":"warning","healthy":0,"warnings":2,"errors":0,"unconfigured":0},"context":{"session":"hyprland","versions":[{"id":"quickshell","version":"0.3.0"}]},"checks":[{"id":"integration.calendar","group":"integrations","title":"Calendar","status":"warning","detail":"Calendar probe timed out.","action":{"kind":"open","label":"Open Date & Time","confirm":false,"target":"datetime"}},{"id":"panama.caffeine","group":"panama-tools","title":"Caffeine","status":"warning","detail":"Duplicate inhibitors are active.","action":{"kind":"repair","label":"Release duplicate inhibitors","confirm":false}}]}'
confirm_snapshot="$(jq -c '
.summary.status = "error"
| .summary.errors = 1
| .checks += [{
id: "desktop.quickshell",
group: "desktop-foundation",
title: "Quickshell",
status: "error",
detail: "Panama shell needs to restart.",
action: {kind: "repair", label: "Restart Panama", confirm: true}
}]
' <<<"$warning_snapshot")"
projection_snapshot="$(jq -c '
.fixtureSecret = "fixture-secret"
| .summary.fixtureSecret = "fixture-secret"
| .context.fixtureSecret = "fixture-secret"
| .context.versions[0].fixtureSecret = "fixture-secret"
| .checks[0].fixtureSecret = "fixture-secret"
' <<<"$warning_snapshot")"
adversarial_snapshot="$(jq -c '
.fixtureSecret = "fixture-secret"
| .summary.fixtureSecret = "fixture-secret"
| .context.fixtureSecret = "fixture-secret"
| .context.versions[0].fixtureSecret = "fixture-secret"
| .checks[0].fixtureSecret = "fixture-secret"
| .checks[0].action.fixtureSecret = "fixture-secret"
' <<<"$warning_snapshot")"
fail() {
printf 'health service contract: %s\n' "$1" >&2
exit 1
}
[[ -f "$service" ]] || fail 'Health.qml is missing'
[[ -f "$source_harness" ]] || fail 'health harness is missing'
[[ -f "$shell" ]] || fail 'shell.qml is missing'
# shell.qml is not started here: it is the active desktop shell. Keep this
# contract static while pinning the typed, redacted IPC boundary it exports.
python3 - "$shell" <<'PY' || fail 'health IPC contract is missing or exposes unsafe state'
import re
import sys
text = open(sys.argv[1], encoding="utf-8").read()
match = re.search(r'IpcHandler \{\s*target: "health"(?P<body>.*?)\n \}', text, re.S)
if not match:
raise SystemExit(1)
body = match.group("body")
required = (
'function refresh(): bool { return Health.refresh(); }',
'function status(): string {',
'summary: Health.summary,',
'busy: Health.busy,',
'generation: Health.generation,',
'acceptedGeneration: Health.acceptedGeneration,',
'checks: Health.checks.map(check => ({ id: check.id, status: check.status }))',
'ShellState.openSettings("services");',
'Health.refresh();',
'function repair(id: string): bool { return Health.repair(id, true); }',
)
if any(entry not in body for entry in required):
raise SystemExit(1)
if 'Health.snapshot' in body or 'Health.diagnostics' in body:
raise SystemExit(1)
status = re.search(r'function status\(\): string \{\s*return JSON\.stringify\(\{(?P<fields>.*?)\n \}\);', body, re.S)
if not status:
raise SystemExit(1)
keys = re.findall(r'^\s*([A-Za-z][A-Za-z0-9]*):', status.group("fields"), re.M)
if keys != ["summary", "busy", "generation", "acceptedGeneration", "checks"]:
raise SystemExit(1)
PY
fixture_dir="$(mktemp -d /tmp/panama-health.XXXXXX)"
config_path="$fixture_dir/quickshell"
cp -a "$repo_dir/config/dot/quickshell" "$config_path"
harness="$config_path/health-harness.qml"
python3 - "$harness" <<'PY'
import sys
path = sys.argv[1]
source = open(path, encoding="utf-8").read()
needle = ' function repair(id: string): bool { return Health.repair(id, false); }\n'
replacement = needle + ''' function externalRepair(id: string): bool { return Health.repair(id, true); }
function pendingRefreshRace(): string {
const before = Health.generation;
Health.finishRepair(0, "panama.caffeine", false, JSON.stringify({
schemaVersion: 1,
checkId: "panama.caffeine",
accepted: true,
exitCode: 0,
message: "Fixture repair completed."
}));
const accepted = Health.refresh();
return JSON.stringify({ accepted: accepted, before: before });
}
'''
if needle not in source:
raise SystemExit("health harness repair seam is missing")
open(path, "w", encoding="utf-8").write(source.replace(needle, replacement))
PY
helper="$fixture_dir/panama-doctor"
copy_bin="$fixture_dir/bin"
copy_file="$fixture_dir/copied-report.json"
repair_mode_file="$fixture_dir/repair-mode"
repair_log="$fixture_dir/repair.log"
notification_log="$fixture_dir/notifications.log"
printf 'success\n' >"$repair_mode_file"
printf '%s\n' \
'#!/usr/bin/env bash' \
'printf "%s\n" "$*" >>"$PANAMA_HEALTH_REPAIR_LOG"' \
'if [[ "$1" == "--json" ]]; then' \
' sleep 0.2' \
" printf '%s\\n' '$warning_snapshot'" \
' exit 0' \
'fi' \
'if [[ "$1" == "--repair" && "$2" == "panama.caffeine" && "$3" == "--json" ]]; then' \
' sleep 0.25' \
' case "$(cat "$PANAMA_HEALTH_REPAIR_MODE_FILE")" in' \
' success) printf "{\"schemaVersion\":1,\"checkId\":\"panama.caffeine\",\"accepted\":true,\"exitCode\":0,\"message\":\"Duplicate inhibitors were released.\"}\\n"; exit 0 ;;' \
' failed) printf "{\"schemaVersion\":1,\"checkId\":\"panama.caffeine\",\"accepted\":true,\"exitCode\":7,\"message\":\"Duplicate inhibitors could not be released.\"}\\n"; exit 7 ;;' \
' mismatch) printf "{\"schemaVersion\":1,\"checkId\":\"desktop.vicinae\",\"accepted\":true,\"exitCode\":0,\"message\":\"Wrong row.\"}\\n"; exit 0 ;;' \
' *) printf "not-json\\n"; exit 0 ;;' \
' esac' \
'fi' \
'if [[ "$1" == "--repair" && "$2" == "desktop.quickshell" && "$3" == "--json" ]]; then' \
' sleep 0.25' \
' printf "{\"schemaVersion\":1,\"checkId\":\"desktop.quickshell\",\"accepted\":true,\"exitCode\":0,\"message\":\"Panama shell restart was requested.\"}\\n"' \
' exit 0' \
'fi' \
'exit 2' >"$helper"
chmod +x "$helper"
mkdir -p "$copy_bin"
printf '%s\n' \
'#!/usr/bin/env bash' \
'/usr/bin/cat > "$PANAMA_HEALTH_COPY_FILE"' >"$copy_bin/wl-copy"
printf '%s\n' \
'#!/usr/bin/env bash' \
'printf "%s\n" "$*" >>"$PANAMA_HEALTH_NOTIFICATION_LOG"' >"$copy_bin/notify-send"
chmod +x "$copy_bin/wl-copy" "$copy_bin/notify-send"
run() {
PATH="$copy_bin:$PATH" PANAMA_HEALTH_HELPER="$helper" PANAMA_HEALTH_COPY_FILE="$copy_file" \
PANAMA_HEALTH_REPAIR_MODE_FILE="$repair_mode_file" PANAMA_HEALTH_REPAIR_LOG="$repair_log" \
PANAMA_HEALTH_NOTIFICATION_LOG="$notification_log" qs -p "$harness" "$@"
}
harness_pid=""
cleanup() {
[[ -n "$harness_pid" ]] && kill "$harness_pid" >/dev/null 2>&1 || true
rm -rf "$fixture_dir"
}
trap cleanup EXIT
PATH="$copy_bin:$PATH" PANAMA_HEALTH_HELPER="$helper" PANAMA_HEALTH_COPY_FILE="$copy_file" \
PANAMA_HEALTH_REPAIR_MODE_FILE="$repair_mode_file" PANAMA_HEALTH_REPAIR_LOG="$repair_log" \
PANAMA_HEALTH_NOTIFICATION_LOG="$notification_log" \
qs -p "$harness" --daemonize >/dev/null
for _ in $(seq 1 40); do
run ipc show 2>/dev/null | rg -q '^target health-test$' && break
sleep 0.1
done
run ipc show 2>/dev/null | rg -q '^target health-test$' || fail 'test IPC target did not start'
harness_pid="$(run list | awk '/Process ID:/ { print $3; exit }')"
[[ "$(run ipc call health-test accept "$warning_snapshot" 0)" == "true" ]] \
|| fail 'valid warning snapshot was rejected'
state="$(run ipc call health-test status)"
jq -e '.status == "warning" and .acceptedGeneration == 0 and .checks == ["integration.calendar", "panama.caffeine"] and .diagnosticUnavailable == false' \
>/dev/null <<<"$state" || fail "valid warning snapshot was not accepted intact: $state"
[[ "$(run ipc call health-test accept "$projection_snapshot" 0)" == "true" ]] \
|| fail 'snapshot with unknown non-action fields was rejected instead of safely projected'
stored_report="$(run ipc call health-test report)"
! grep -Fq 'fixture-secret' <<<"$stored_report" \
|| fail "accepted snapshot retained an unknown secret field: $stored_report"
[[ "$(run ipc call health-test copy)" == "true" ]] \
|| fail 'copy report was refused'
for _ in $(seq 1 40); do
[[ -f "$copy_file" ]] && break
sleep 0.1
done
[[ -f "$copy_file" ]] || fail 'copy report did not reach wl-copy'
! grep -Fq 'fixture-secret' "$copy_file" \
|| fail 'copied report retained an unknown secret field'
adversarial_result="$(run ipc call health-test accept "$adversarial_snapshot" 1)"
[[ "$adversarial_result" == "true" || "$adversarial_result" == "false" ]] \
|| fail "adversarial action fixture did not return a Boolean: $adversarial_result"
stored_report="$(run ipc call health-test report)"
! grep -Fq 'fixture-secret' <<<"$stored_report" \
|| fail "adversarial snapshot leaked an unknown secret field: $stored_report"
[[ "$(run ipc call health-test accept "$warning_snapshot" -1)" == "false" ]] \
|| fail 'older generation replaced the current snapshot'
state="$(run ipc call health-test status)"
jq -e '.acceptedGeneration == 0 and .checks == ["integration.calendar", "panama.caffeine"]' \
>/dev/null <<<"$state" || fail "older generation altered accepted state: $state"
[[ "$(run ipc call health-test accept '{not json' 1)" == "false" ]] \
|| fail 'malformed snapshot was accepted'
state="$(run ipc call health-test status)"
jq -e '.diagnosticUnavailable == true and .checks == ["integration.calendar", "panama.caffeine"]' \
>/dev/null <<<"$state" || fail "malformed snapshot discarded the last valid checks: $state"
before_generation="$(jq -r .generation <<<"$state")"
run ipc call health-test queue >/dev/null
state="$(run ipc call health-test status)"
jq -e '.queuedRefresh == true and .generation == ($before + 1)' --argjson before "$before_generation" \
>/dev/null <<<"$state" || fail "two refreshes did not retain exactly one follow-up: $state"
for _ in $(seq 1 120); do
state="$(run ipc call health-test status)"
jq -e '.busy == false and .generation == ($before + 2) and .queuedRefresh == false' --argjson before "$before_generation" \
>/dev/null <<<"$state" && break
sleep 0.1
done
jq -e '.busy == false and .generation == ($before + 2) and .queuedRefresh == false' --argjson before "$before_generation" \
>/dev/null <<<"$state" || fail "queued refresh did not run exactly once: $state"
printf 'success\n' >"$repair_mode_file"
repair_generation="$(jq -r .generation <<<"$state")"
[[ "$(run ipc call health-test repair panama.caffeine)" == "true" ]] \
|| fail 'repairable check was refused'
run ipc call health-test queue >/dev/null
working_state="$(run ipc call health-test status)"
jq -e '.repairingId == "panama.caffeine" and .queuedRefresh == true
and (.checkStates[] | select(.id == "panama.caffeine") | .status) == "warning"' \
>/dev/null <<<"$working_state" || fail "repair did not retain the degraded row while working: $working_state"
for _ in $(seq 1 120); do
state="$(run ipc call health-test status)"
jq -e '.busy == false and .generation == ($before + 1) and .queuedRefresh == false' --argjson before "$repair_generation" \
>/dev/null <<<"$state" && break
sleep 0.1
done
jq -e '.busy == false and .generation == ($before + 1) and .queuedRefresh == false
and .lastRepair == {schemaVersion:1, checkId:"panama.caffeine", accepted:true, exitCode:0, message:"Duplicate inhibitors were released."}
and (.checkStates[] | select(.id == "panama.caffeine") | .status) == "warning"' \
--argjson before "$repair_generation" >/dev/null <<<"$state" \
|| fail "accepted repair was trusted before exactly one observed rescan: $state"
# A syntactically valid command failure remains inline for Settings and still
# receives exactly one observed rescan.
printf 'failed\n' >"$repair_mode_file"
failure_generation="$(jq -r .generation <<<"$state")"
[[ "$(run ipc call health-test repair panama.caffeine)" == "true" ]] \
|| fail 'second repairable check was refused'
for _ in $(seq 1 120); do
state="$(run ipc call health-test status)"
jq -e '.busy == false and .generation == ($before + 1)' --argjson before "$failure_generation" \
>/dev/null <<<"$state" && break
sleep 0.1
done
jq -e '.lastRepair.checkId == "panama.caffeine"
and .lastRepair.accepted == true and .lastRepair.exitCode == 7
and .lastRepair.message == "Duplicate inhibitors could not be released."
and .generation == ($before + 1)' --argjson before "$failure_generation" \
>/dev/null <<<"$state" || fail "known repair failure was not retained inline: $state"
[[ ! -e "$notification_log" || ! -s "$notification_log" ]] \
|| fail 'Settings-originated repair emitted an external notification'
# A malformed or mismatched helper response is contained and cannot masquerade
# as recovery; it also schedules only one scan.
printf 'mismatch\n' >"$repair_mode_file"
mismatch_generation="$(jq -r .generation <<<"$state")"
[[ "$(run ipc call health-test repair panama.caffeine)" == "true" ]] \
|| fail 'mismatch repair fixture was refused'
for _ in $(seq 1 120); do
state="$(run ipc call health-test status)"
jq -e '.busy == false and .generation == ($before + 1)' --argjson before "$mismatch_generation" \
>/dev/null <<<"$state" && break
sleep 0.1
done
jq -e '.lastRepair.checkId == "panama.caffeine" and .lastRepair.accepted == false
and .lastRepair.exitCode == 0 and .generation == ($before + 1)' \
--argjson before "$mismatch_generation" >/dev/null <<<"$state" \
|| fail "mismatched repair JSON escaped containment: $state"
# A refresh arriving after repair settlement but before the deferred mandatory
# scan is coalesced into that scan instead of starting an extra generation.
pending_race="$(run ipc call health-test pendingRefreshRace)"
jq -e '.accepted == false' >/dev/null <<<"$pending_race" \
|| fail "refresh escaped the post-repair pending window: $pending_race"
pending_generation="$(jq -r .before <<<"$pending_race")"
for _ in $(seq 1 120); do
state="$(run ipc call health-test status)"
jq -e '.busy == false and .generation == ($before + 1) and .queuedRefresh == false' \
--argjson before "$pending_generation" >/dev/null <<<"$state" && break
sleep 0.1
done
jq -e '.busy == false and .generation == ($before + 1) and .queuedRefresh == false' \
--argjson before "$pending_generation" >/dev/null <<<"$state" \
|| fail "pending-window refresh created duplicate scans: $state"
# External IPC cannot bypass an authored confirmation. The same current row is
# still repairable through Settings' external=false path after UI confirmation.
confirm_generation="$(jq -r .generation <<<"$state")"
[[ "$(run ipc call health-test accept "$confirm_snapshot" "$confirm_generation")" == "true" ]] \
|| fail 'confirmation fixture was rejected'
before_repair_lines="$(wc -l <"$repair_log")"
[[ "$(run ipc call health-test externalRepair desktop.quickshell)" == "false" ]] \
|| fail 'external repair bypassed confirmation'
[[ "$(wc -l <"$repair_log")" == "$before_repair_lines" ]] \
|| fail 'external confirmation rejection started a process'
[[ "$(run ipc call health-test repair desktop.quickshell)" == "true" ]] \
|| fail 'confirmed Settings repair was refused'
for _ in $(seq 1 120); do
state="$(run ipc call health-test status)"
jq -e '.busy == false and .generation == ($before + 1)' \
--argjson before "$confirm_generation" >/dev/null <<<"$state" && break
sleep 0.1
done
jq -e '.lastRepair == {schemaVersion:1, checkId:"desktop.quickshell", accepted:true, exitCode:0, message:"Panama shell restart was requested."}
and .generation == ($before + 1)' --argjson before "$confirm_generation" \
>/dev/null <<<"$state" || fail "confirmed Settings repair did not complete safely: $state"
[[ "$(grep -Fc -- '--repair desktop.quickshell --json' "$repair_log")" == 1 ]] \
|| fail 'confirmed Settings repair did not start exactly one repair process'
[[ "$(run ipc call health-test repair unknown.check)" == "false" ]] \
|| fail 'unknown check started a repair'
[[ "$(run ipc call health-test repair integration.calendar)" == "false" ]] \
|| fail 'non-repairable check started a repair'
state="$(run ipc call health-test status)"
jq -e '.repairingId == "" and .generation == ($before + 1)' --argjson before "$confirm_generation" \
>/dev/null <<<"$state" || fail "rejected repair altered process state: $state"
python3 - "$service" <<'PY' || fail 'external repair failure notification is not bounded'
import sys
source = open(sys.argv[1], encoding="utf-8").read()
assert 'if (failed && external && !failureNotification.running)' in source
assert '"notify-send", "-a", "Panama", "-i", "dialog-error-symbolic"' in source
assert '"Panama action failed", "The requested health repair could not be completed."' in source
PY
trap - EXIT
cleanup
printf 'health service contract: PASS\n'