Enterprise Features: - Hosted mode with remote sync for team pattern aggregation - Community sharing with privacy-preserving anonymization - LLM-based semantic claim extraction with Gemini integration - Pattern learning with promotion to declarative extractors - High-entropy secrets extractor with configurable thresholds - Auth bypass and insecure cookies extractors Module Refactoring: - Split oversized files to comply with 500-line limit - Config split: types/core.rs, types/extractors.rs, types/hosted.rs, etc. - Handlers split: scan.rs, policy.rs, report.rs modules - Extractors split: declarative/, high_entropy_secrets/, insecure_cookies/ - Learning split: store modules with metrics and persistence SDK & Ontology: - stemedb-ontology SDK with fluent builders and StemeDB client - Pharma domain extractors for FDA Orange Book data - Consumer health UAT test infrastructure Code Quality: - Fixed clippy warnings (needless_borrows_for_generic_args) - Added KVStore trait imports where needed - Fixed utoipa path re-exports for OpenAPI docs Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
208 lines
5.5 KiB
Bash
Executable File
208 lines
5.5 KiB
Bash
Executable File
#!/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
|