gardesk/garcard / 649608a

Browse files

Add sprint 04 validation docs

Authored by mfwolffe <wolffemf@dukes.jmu.edu>
SHA
649608aaf987695e8d49b9e73ff384d5f4729dd1
Parents
1b09a6f
Tree
34f9154

5 changed files

StatusFile+-
M README.md 32 0
A RELEASE_NOTES.md 26 0
A examples/sprint-04-validation-report-2026-02-20.md 27 0
A examples/sprint-04-validation.md 48 0
A examples/validate-sprint-04.sh 109 0
README.mdmodified
@@ -12,6 +12,15 @@
1212
 2. `cargo run -p garcardctl -- status`
1313
 3. `cargo run -p garcard -- prompt --mode secret --message "Validation prompt"`
1414
 
15
+## User Service
16
+1. Install unit file:
17
+   - `install -Dm644 garcard.service ~/.config/systemd/user/garcard.service`
18
+2. Enable and start:
19
+   - `systemctl --user daemon-reload`
20
+   - `systemctl --user enable --now garcard`
21
+3. Check health:
22
+   - `cargo run -q -p garcardctl -- status`
23
+
1524
 ## Config
1625
 Default config path: `~/.config/garcard/config.toml`
1726
 
@@ -34,3 +43,26 @@ See `examples/config.toml` for a minimal local starter file.
3443
 `GARCARD_PROMPT_COMMAND` is optional. If unset, `garcard` runs the built-in
3544
 `garcard prompt` gartk dialog path and falls back to `systemd-ask-password`
3645
 when the X11 prompt backend is unavailable.
46
+
47
+## Validation Docs
48
+1. `examples/sprint-02-validation.md`
49
+2. `examples/sprint-03-validation-report-2026-02-18.md`
50
+3. `examples/sprint-04-validation.md`
51
+4. `examples/validate-sprint-02.sh`
52
+5. `examples/validate-sprint-03-integration.sh`
53
+6. `examples/validate-sprint-04.sh`
54
+
55
+## Troubleshooting
56
+1. `Authorization requires authentication but no agent is available`
57
+   - ensure daemon is running: `cargo run -q -p garcardctl -- ping`
58
+   - restart daemon after polkit restart: `cargo run -q -p garcardctl -- quit` then relaunch
59
+2. `failed to connect to garcard daemon ...`
60
+   - check socket path from `garcardctl status`
61
+   - if using custom socket, export the same `GARCARD_SOCKET` for both daemon and ctl
62
+3. Prompt did not open in X11
63
+   - run with debug logs: `RUST_LOG=garcard=debug cargo run -p garcard -- daemon`
64
+   - verify fallback path by setting `GARCARD_PROMPT_COMMAND` explicitly
65
+
66
+## Known Limitations
67
+1. Policy results are host-specific; some actions may auto-authorize and not trigger prompts.
68
+2. Current implementation targets logged-in user sessions on X11.
RELEASE_NOTES.mdadded
@@ -0,0 +1,26 @@
1
+# garcard 0.1.0-rc1
2
+
3
+## Highlights
4
+1. Polkit authentication agent backend with queue-aware auth state tracking.
5
+2. Built-in gartk prompt path with timeout/cancel behavior and ask-password fallback.
6
+3. Daemon health/reconnect loop with forced reconnect support (`SIGHUP` + maintenance pass).
7
+4. `garcardctl` operational commands: `ping`, `status`, `version`, `auth-summary`, `quit`.
8
+
9
+## Hardening Included In Sprint 04
10
+1. Same-UID enforcement for local IPC control clients.
11
+2. Reduced panic surface in prompt color setup paths.
12
+3. Best-effort scrubbing of helper prompt response buffers after use.
13
+
14
+## Validation Coverage
15
+1. Sprint 02 live callback and reconnect validation:
16
+   - `examples/sprint-02-validation-report-2026-02-18.md`
17
+2. Sprint 03 ecosystem + runtime probes:
18
+   - `examples/sprint-03-validation-report-2026-02-18.md`
19
+3. Sprint 04 reliability harness/checklist:
20
+   - `examples/validate-sprint-04.sh`
21
+   - `examples/sprint-04-validation.md`
22
+
23
+## Known Limitations
24
+1. Challenge prompting depends on host polkit policy; some actions may auto-authorize.
25
+2. Scope is logged-in user sessions (X11), not greeter/session-manager flows.
26
+3. Full panel controls in `gargears` remain limited to discovery/visibility for now.
examples/sprint-04-validation-report-2026-02-20.mdadded
@@ -0,0 +1,27 @@
1
+# Sprint 04 Validation Report (2026-02-20)
2
+
3
+## Scope
4
+1. Hardening regression checks after Sprint 04 code changes.
5
+2. Automated reliability checks for daemon restart resilience.
6
+
7
+## Commands
8
+1. `cargo test --workspace`
9
+2. `./examples/validate-sprint-04.sh` (executed with default `stub` backend)
10
+
11
+## Results
12
+1. Workspace tests passed (`39` garcard tests + workspace crates).
13
+2. `validate-sprint-04.sh` passed baseline and restart loop checks:
14
+   - daemon reachable via `ping`/`status`
15
+   - restart loop completed (`3` stop/start iterations)
16
+   - post-restart status and auth summary remained healthy (`idle`)
17
+3. Optional interactive `pkcheck` loop was intentionally skipped in this run:
18
+   - requires live polkit challenge flow and operator interaction.
19
+
20
+## Hardening Outcomes Confirmed
21
+1. IPC control path now validates same-UID peer credentials.
22
+2. Prompt UI runtime path no longer relies on panic/`expect` for color parsing.
23
+3. Helper response buffers are scrubbed after sending to helper socket.
24
+
25
+## Remaining Manual Sprint 04 Checks
26
+1. Daemon restart during an active prompt in polkit mode.
27
+2. Session shutdown/logout race while prompt is active.
examples/sprint-04-validation.mdadded
@@ -0,0 +1,48 @@
1
+# Sprint 04 Validation Checklist
2
+
3
+Run these checks from an active X11 user session.
4
+
5
+## Automated Baseline
6
+1. `cargo test --workspace`
7
+2. `./examples/validate-sprint-04.sh`
8
+
9
+Expected:
10
+1. All tests pass.
11
+2. Daemon survives restart loop and remains reachable over IPC.
12
+
13
+## Interactive Challenge Loop
14
+1. `GARCARD_SPRINT04_BACKEND=polkit ./examples/validate-sprint-04.sh`
15
+2. Complete two `pkcheck` prompts (cancel/deny/success combinations).
16
+
17
+Expected:
18
+1. Prompt appears for challenge actions.
19
+2. `garcardctl auth-summary` updates and remains responsive across iterations.
20
+
21
+## Daemon Restart During Active Prompt
22
+1. Start daemon in one terminal:
23
+   - `RUST_LOG=garcard=debug GARCARD_AGENT_BACKEND=polkit cargo run -p garcard -- daemon`
24
+2. Trigger challenge in another terminal:
25
+   - `pkcheck --allow-user-interaction --process $$ --action-id com.mesonbuild.install.run`
26
+3. While prompt is visible, restart daemon:
27
+   - `cargo run -q -p garcardctl -- quit`
28
+   - relaunch daemon command from step 1.
29
+4. Re-run the same `pkcheck` command.
30
+
31
+Expected:
32
+1. Active prompt interruption does not wedge daemon state.
33
+2. Relaunched daemon accepts new requests with clean `auth-summary`.
34
+
35
+## Session Shutdown/Logout Race
36
+1. Start daemon with debug logs.
37
+2. Trigger an auth prompt.
38
+3. Send `SIGTERM` to daemon PID while request is active.
39
+4. Relaunch daemon and run `garcardctl status`.
40
+
41
+Expected:
42
+1. Daemon exits cleanly without stale socket.
43
+2. Relaunch succeeds without manual socket cleanup.
44
+
45
+## Security Spot Checks
46
+1. Verify secret response handling does not log plaintext values.
47
+2. Confirm IPC control socket mode remains owner-only in production (`600`).
48
+3. Validate only same-UID peers can control daemon IPC.
examples/validate-sprint-04.shadded
@@ -0,0 +1,109 @@
1
+#!/usr/bin/env bash
2
+set -euo pipefail
3
+
4
+SOCKET_PATH="${GARCARD_SPRINT04_SOCKET:-${PWD}/target/garcard-sprint04.sock}"
5
+BACKEND="${GARCARD_SPRINT04_BACKEND:-stub}"
6
+RESTART_LOOPS="${GARCARD_SPRINT04_RESTART_LOOPS:-3}"
7
+PKCHECK_LOOPS="${GARCARD_SPRINT04_PKCHECK_LOOPS:-2}"
8
+ACTION_ID="${GARCARD_SPRINT04_ACTION_ID:-com.mesonbuild.install.run}"
9
+LOG_FILE="${GARCARD_SPRINT04_LOG:-${PWD}/target/garcard-sprint04.log}"
10
+
11
+if command -v garcard >/dev/null 2>&1; then
12
+  DAEMON_CMD=(garcard daemon)
13
+else
14
+  DAEMON_CMD=(cargo run -q -p garcard -- daemon)
15
+fi
16
+
17
+if command -v garcardctl >/dev/null 2>&1; then
18
+  CTL_CMD=(garcardctl)
19
+else
20
+  CTL_CMD=(cargo run -q -p garcardctl --)
21
+fi
22
+
23
+DAEMON_PID=0
24
+
25
+run_ctl() {
26
+  GARCARD_SOCKET="${SOCKET_PATH}" "${CTL_CMD[@]}" "$@"
27
+}
28
+
29
+wait_for_daemon() {
30
+  local tries=100
31
+  while (( tries > 0 )); do
32
+    if run_ctl ping >/dev/null 2>&1; then
33
+      return 0
34
+    fi
35
+    sleep 0.2
36
+    tries=$((tries - 1))
37
+  done
38
+  echo "daemon did not become ready in time"
39
+  return 1
40
+}
41
+
42
+start_daemon() {
43
+  GARCARD_SOCKET="${SOCKET_PATH}" \
44
+    GARCARD_AGENT_BACKEND="${BACKEND}" \
45
+    "${DAEMON_CMD[@]}" >>"${LOG_FILE}" 2>&1 &
46
+  DAEMON_PID=$!
47
+  wait_for_daemon
48
+}
49
+
50
+stop_daemon() {
51
+  if [[ "${DAEMON_PID}" -gt 0 ]] && kill -0 "${DAEMON_PID}" 2>/dev/null; then
52
+    run_ctl quit >/dev/null 2>&1 || true
53
+    wait "${DAEMON_PID}" 2>/dev/null || true
54
+  fi
55
+  DAEMON_PID=0
56
+}
57
+
58
+cleanup() {
59
+  stop_daemon
60
+  rm -f "${SOCKET_PATH}"
61
+}
62
+trap cleanup EXIT
63
+
64
+echo "Sprint 04 validation"
65
+echo "  socket: ${SOCKET_PATH}"
66
+echo "  backend: ${BACKEND}"
67
+echo "  log: ${LOG_FILE}"
68
+
69
+mkdir -p "$(dirname "${SOCKET_PATH}")"
70
+mkdir -p "$(dirname "${LOG_FILE}")"
71
+rm -f "${SOCKET_PATH}" "${LOG_FILE}"
72
+start_daemon
73
+
74
+echo "[1/4] Baseline daemon health"
75
+run_ctl ping
76
+run_ctl status
77
+run_ctl auth-summary
78
+
79
+echo "[2/4] Restart resilience loop (${RESTART_LOOPS} iterations)"
80
+for i in $(seq 1 "${RESTART_LOOPS}"); do
81
+  echo "  iteration ${i}: stop/start daemon"
82
+  run_ctl quit >/dev/null
83
+  wait "${DAEMON_PID}" 2>/dev/null || true
84
+  DAEMON_PID=0
85
+  start_daemon
86
+  run_ctl ping >/dev/null
87
+done
88
+
89
+echo "[3/4] Post-restart health"
90
+run_ctl status
91
+run_ctl auth-summary
92
+
93
+echo "[4/4] Optional interactive auth loop"
94
+if [[ "${BACKEND}" == "polkit" ]] && command -v pkcheck >/dev/null 2>&1; then
95
+  echo "  running ${PKCHECK_LOOPS} pkcheck attempts for action ${ACTION_ID}"
96
+  for i in $(seq 1 "${PKCHECK_LOOPS}"); do
97
+    set +e
98
+    pkcheck --allow-user-interaction --process "$$" --action-id "${ACTION_ID}"
99
+    rc=$?
100
+    set -e
101
+    echo "  pkcheck[${i}] rc=${rc}"
102
+    run_ctl auth-summary || true
103
+  done
104
+else
105
+  echo "  skipped (requires BACKEND=polkit and pkcheck installed)"
106
+fi
107
+
108
+echo "Validation complete. Log output:"
109
+echo "  ${LOG_FILE}"