#!/bin/bash # # Multi-Pack Conflict Resolution Test # # Tests what happens when two Trust Packs have different values for the same concept. # # Usage: ./test-multi-pack-conflict.sh # set -e SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../../.." && pwd)" APHORIA_BIN="$PROJECT_ROOT/target/release/aphoria" TEST_DIR="/tmp/uat-multi-pack" # Colors RED='\033[0;31m' GREEN='\033[0;32m' YELLOW='\033[1;33m' NC='\033[0m' TESTS_PASSED=0 TESTS_FAILED=0 pass() { echo -e "${GREEN}✓${NC} $1"; TESTS_PASSED=$((TESTS_PASSED + 1)); } fail() { echo -e "${RED}✗${NC} $1"; TESTS_FAILED=$((TESTS_FAILED + 1)); } info() { echo -e "${YELLOW}→${NC} $1"; } section() { echo ""; echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"; echo "$1"; echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"; } # Build if needed if [ ! -f "$APHORIA_BIN" ]; then info "Building Aphoria (release)..." (cd "$PROJECT_ROOT" && cargo build --release --package aphoria) fi rm -rf "$TEST_DIR" mkdir -p "$TEST_DIR" section "Step 1: Create Security Team Pack (TLS 1.2)" SECURITY_DIR="$TEST_DIR/security-team" mkdir -p "$SECURITY_DIR" cd "$SECURITY_DIR" cat > Cargo.toml << 'EOF' [package] name = "security-standards" version = "0.1.0" edition = "2021" EOF cat > aphoria.toml << 'EOF' [episteme] data_dir = ".aphoria/db" [project] name = "security-standards" EOF mkdir -p src && echo "fn main() {}" > src/main.rs info "Blessing TLS 1.2 minimum..." "$APHORIA_BIN" bless "code://standard/tls/min_version" \ --predicate version --value "1.2" \ --reason "Security team: TLS 1.2 minimum" "$APHORIA_BIN" policy export --name "Security-Team" --output security-team.pack pass "Security team pack created (TLS 1.2)" section "Step 2: Create Compliance Team Pack (TLS 1.3)" COMPLIANCE_DIR="$TEST_DIR/compliance-team" mkdir -p "$COMPLIANCE_DIR" cd "$COMPLIANCE_DIR" cat > Cargo.toml << 'EOF' [package] name = "compliance-standards" version = "0.1.0" edition = "2021" EOF cat > aphoria.toml << 'EOF' [episteme] data_dir = ".aphoria/db" [project] name = "compliance-standards" EOF mkdir -p src && echo "fn main() {}" > src/main.rs info "Blessing TLS 1.3 minimum..." "$APHORIA_BIN" bless "code://standard/tls/min_version" \ --predicate version --value "1.3" \ --reason "Compliance team: TLS 1.3 required for PCI-DSS 4.0" "$APHORIA_BIN" policy export --name "Compliance-Team" --output compliance-team.pack pass "Compliance team pack created (TLS 1.3)" section "Step 3: Create Dev Project with TLS 1.1 (violates both)" DEV_DIR="$TEST_DIR/dev-team" mkdir -p "$DEV_DIR/config" cd "$DEV_DIR" cat > Cargo.toml << 'EOF' [package] name = "my-service" version = "0.1.0" edition = "2021" EOF cat > aphoria.toml << 'EOF' [episteme] data_dir = ".aphoria/db" [project] name = "my-service" EOF mkdir -p src && echo "fn main() {}" > src/main.rs cat > config/tls.yaml << 'EOF' tls: min_version: "1.1" EOF pass "Dev project created with TLS 1.1" section "Step 4: Import Both Packs" info "Importing security team pack..." "$APHORIA_BIN" policy import "$SECURITY_DIR/security-team.pack" pass "Security team pack imported" info "Importing compliance team pack..." "$APHORIA_BIN" policy import "$COMPLIANCE_DIR/compliance-team.pack" pass "Compliance team pack imported" section "Step 5: Scan and Check Results" info "Running scan..." SCAN_OUTPUT=$("$APHORIA_BIN" scan --persist --format json 2>&1) echo "$SCAN_OUTPUT" > scan-results.json # Check for conflicts CONFLICT_COUNT=$(echo "$SCAN_OUTPUT" | grep '"verdict"' | wc -l | tr -d ' ') if [ "${CONFLICT_COUNT:-0}" -ge 1 ]; then pass "Scan found $CONFLICT_COUNT conflict(s)" else fail "Expected at least 1 conflict, found ${CONFLICT_COUNT:-0}" fi # Check which pack appears in policy_source info "Checking policy_source attribution..." PACK_NAME=$(grep -o '"pack_name"[[:space:]]*:[[:space:]]*"[^"]*"' scan-results.json | head -1 | sed 's/.*"\([^"]*\)"$/\1/') if [ -n "$PACK_NAME" ]; then pass "Policy source found: $PACK_NAME" else fail "No policy_source in output" fi # Check if BOTH packs appear (this is the key question) SECURITY_APPEARS=$(grep "Security-Team" scan-results.json 2>/dev/null | wc -l | tr -d ' ') COMPLIANCE_APPEARS=$(grep "Compliance-Team" scan-results.json 2>/dev/null | wc -l | tr -d ' ') echo "" info "Pack appearance check:" echo " Security-Team appears: $SECURITY_APPEARS time(s)" echo " Compliance-Team appears: $COMPLIANCE_APPEARS time(s)" if [ "${SECURITY_APPEARS:-0}" -gt 0 ] && [ "${COMPLIANCE_APPEARS:-0}" -gt 0 ]; then pass "BOTH packs appear in conflict output" else info "Only one pack appears (second import overwrites first)" echo " Current behavior: Last imported pack wins" fi section "Step 6: Show Actual Output" echo "" echo "Conflicts found:" grep -A 20 '"sources"' scan-results.json | head -30 || true section "Summary" echo "" echo "Test Results:" echo " Passed: $TESTS_PASSED" echo " Failed: $TESTS_FAILED" echo "" echo "Observation:" if [ "${SECURITY_APPEARS:-0}" -gt 0 ] && [ "${COMPLIANCE_APPEARS:-0}" -gt 0 ]; then echo " Multi-pack conflict resolution WORKS - both packs shown" else echo " Multi-pack: Second import OVERWRITES first (same subject key)" echo " Future work: Support multiple policy sources per concept" fi echo "" if [ "$TESTS_FAILED" -gt 0 ]; then exit 1 else exit 0 fi