#!/usr/bin/env bash set -uo pipefail # Plan-18 MVP-0 chat session audit: hash-linked, tamper-evident, no raw secret storage. SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../scripts/bash/casan-paths.sh" CHAT="$CASAN_HARNESS_ROOT/scripts/bash/chat-readonly.py" WORK="$(mktemp -d)" trap 'rm -rf "$WORK"' EXIT export CASAN_STATE_ROOT="$WORK/state" PASS=0; FAIL=0 pass() { echo "PASS: $1"; PASS=$((PASS + 1)); } fail() { echo "FAIL: $1"; FAIL=$((FAIL + 1)); } echo "===== Plan-18 MVP-0 chat session audit =====" python3 "$CHAT" ask --message "Summarize Plan 18 MVP-0" --actor alice --chat-id audit-chat >/dev/null python3 "$CHAT" ask --message "What evidence sources does Plan 13 have?" --actor alice --chat-id audit-chat >/dev/null python3 "$CHAT" verify-audit > "$WORK/verify.out" \ && grep -q 'ok=true records=2' "$WORK/verify.out" \ && pass "chat audit verifies hash chain" || fail "chat audit verify failed" AUDIT="$CASAN_STATE_ROOT/logs/chat/chat-turns.jsonl" ! grep -q 'API_KEY=supersecret' "$AUDIT" \ && pass "audit stores refs/previews, not raw secret tokens" || fail "raw secret leaked to audit" python3 - "$AUDIT" <<'PY' import json, sys rows = [json.loads(l) for l in open(sys.argv[1]) if l.strip()] rows[0]["decision"] = "TAMPERED" open(sys.argv[1], "w").write("\n".join(json.dumps(r) for r in rows) + "\n") PY set +e python3 "$CHAT" verify-audit > "$WORK/tamper.out" RC=$? set -e 2>/dev/null || true [[ "$RC" -eq 1 ]] && grep -q 'ok=false' "$WORK/tamper.out" \ && pass "chat audit detects tampering" || fail "chat audit tamper not detected" echo "" echo "===== CHAT SESSION AUDIT SUMMARY: PASS=$PASS FAIL=$FAIL =====" [[ "$FAIL" -eq 0 ]] || exit 1