46 lines
1.7 KiB
Bash
Executable File
46 lines
1.7 KiB
Bash
Executable File
#!/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
|