Add sprint 04 validation docs
Authored by
mfwolffe <wolffemf@dukes.jmu.edu>
- SHA
649608aaf987695e8d49b9e73ff384d5f4729dd1- Parents
-
1b09a6f - Tree
34f9154
649608a
649608aaf987695e8d49b9e73ff384d5f4729dd11b09a6f
34f9154| Status | File | + | - |
|---|---|---|---|
| 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 @@ | ||
| 12 | 12 | 2. `cargo run -p garcardctl -- status` |
| 13 | 13 | 3. `cargo run -p garcard -- prompt --mode secret --message "Validation prompt"` |
| 14 | 14 | |
| 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 | + | |
| 15 | 24 | ## Config |
| 16 | 25 | Default config path: `~/.config/garcard/config.toml` |
| 17 | 26 | |
@@ -34,3 +43,26 @@ See `examples/config.toml` for a minimal local starter file. | ||
| 34 | 43 | `GARCARD_PROMPT_COMMAND` is optional. If unset, `garcard` runs the built-in |
| 35 | 44 | `garcard prompt` gartk dialog path and falls back to `systemd-ask-password` |
| 36 | 45 | 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}" | |