#!/usr/bin/env bash set -euo pipefail SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "$SCRIPT_DIR/../scripts/bash/casan-paths.sh" RESOLVER="$CASAN_HARNESS_ROOT/scripts/bash/chat-model-resolver.py" TURN="$CASAN_HARNESS_ROOT/scripts/bash/chat-turn.py" W="$(mktemp -d)"; trap 'rm -rf "$W"' EXIT export CASAN_STATE_ROOT="$W/state" PASS=0; FAIL=0 pass() { echo "PASS: $1"; PASS=$((PASS+1)); } fail() { echo "FAIL: $1"; FAIL=$((FAIL+1)); } python3 "$RESOLVER" list --actor viewer-a --role viewer --model-role read_only > "$W/list.json" python3 - "$W/list.json" <<'PY' && pass "viewer can see only policy-allowed local read model" || fail "model list policy incorrect" import json, sys d=json.load(open(sys.argv[1])); local=next(x for x in d['providers'] if x['id']=='local') cloud=next(x for x in d['providers'] if x['id']=='cloud-openai') assert local['allowed'] and local['configured']; assert not cloud['allowed'] PY python3 "$RESOLVER" bind --actor viewer-a --role viewer --model-role read_only --provider local > "$W/local.json" \ && grep -q '"decision": "BOUND"' "$W/local.json" && pass "local provider selection is audited and bound" || fail "local provider binding failed" set +e python3 "$RESOLVER" bind --actor viewer-a --role viewer --model-role read_only --provider cloud-openai > "$W/cloud.json" RC=$? set -e [[ "$RC" -eq 2 ]] && grep -q '"decision": "DENIED"' "$W/cloud.json" && pass "unauthorized or unconfigured cloud provider denied" || fail "cloud provider was not denied" set +e python3 "$TURN" ask --message 'Summarize Plan 18 status' --actor viewer-a --role viewer --project default --chat-id model-select --model-provider cloud-openai > "$W/turn.json" RC=$? set -e [[ "$RC" -eq 2 ]] && grep -q 'credential_not_configured\|provider_not_allowed' "$W/turn.json" && pass "chat turn cannot bypass model provider policy" || fail "chat bypassed model policy" echo "===== CHAT MODEL SELECTION SUMMARY: PASS=$PASS FAIL=$FAIL =====" [[ "$FAIL" -eq 0 ]]