fix: resolve 11 test failures, clean up stale files, add NVMe build cache

Test Fixes:
- Fixed grep regex matching `test:iso)` instead of `iso|iso:demo)` by
  using `grep -F` for literal string matching in 3 test files
- Increased grep context from -A 5 to -A 15 for FDE reference tests
  since FDE mention is 9+ lines into the iso command block

Stale Files:
- Deleted test-iso.sh (merged into run.sh in Session 4)
- Deleted verify.sh (orphaned, never referenced anywhere)

Documentation:
- Fixed stale test file references in COMPLIANCE.md
- Updated TEST-COVERAGE.md to remove "delegates to test-iso.sh"
- Added JOURNAL.md entry with full audit findings
- Updated STATUS.md timestamp

NVMe Build Cache (from previous session, was uncommitted):
- Added Docker volume `knel-football-cache` for build caching
- Added `clean:cache` and `cache` commands to run.sh
- Cache preserves bootstrap + package downloads between builds

Test Results: 786 pass, 0 fail, 16 VM skip

💘 Generated with Crush

Assisted-by: GLM-5.1 via Crush <crush@charm.land>
This commit is contained in:
reachableceo
2026-05-07 07:51:56 -05:00
parent 0fb9abe43e
commit 94abcfffda
10 changed files with 104 additions and 458 deletions

View File

@@ -6,6 +6,60 @@
--- ---
## Entry 2026-05-07 (Session 7): Full Project Audit & Fix
### Context
User requested full project re-orientation. Deep audit of all hooks, tests, docs, and code against PRD.
### Audit Findings
#### Test Fixes (11 → 0 failures)
- **Root cause**: `grep 'iso)'` regex matched `test:iso)` before `iso|iso:demo)` due to `|` being regex OR
- **Fix**: Changed all affected greps to use `grep -F 'iso|iso:demo)'` (literal string match)
- **Files fixed**: `tests/unit/build-iso_comprehensive_test.bats` (8), `tests/unit/run_comprehensive_test.bats` (2), `tests/unit/run_test.bats` (1)
- Also increased grep context from `-A 5` to `-A 15` for FDE reference tests (content is 9+ lines into iso block)
#### Stale Files Deleted
- `test-iso.sh` - merged into run.sh in Session 4, was still in repo
- `verify.sh` - orphaned, never referenced, duplicated `run.sh test`
#### Documentation Fixes
- `docs/TEST-COVERAGE.md` line 23: Updated stale "delegates to test-iso.sh" reference
- `docs/COMPLIANCE.md` lines 73-75: Fixed wrong test filenames (firewall_test → firewall-setup_test, etc.)
#### Uncommitted run.sh Changes (carried over from last session)
- Added `CACHE_VOLUME` for NVMe build cache via Docker volume
- Added `clean:cache` and `cache` commands
- Build cache restore/save around `lb build` for faster iteration
- Cache preserves bootstrap + package downloads between builds (~5 min saved)
### Known Issues Identified (not fixed this session - deferred)
| Issue | Severity | Notes |
|-------|----------|-------|
| `firewall-setup.sh` live hook blocks all outbound | High | Static default-deny, no WireGuard allow; live system has no network |
| `disable-package-management.sh` destroys dpkg db | High | `rm -rf /var/lib/dpkg/*` breaks anything querying installed packages |
| `encryption-validation.sh` inverted conditional | Medium | motd file created only if it already exists (backwards) |
| `kernel.exec-shield = 1` in kernel-hardening.sh | Low | Red Hat-specific, doesn't exist on Debian |
| `src/build-iso.sh` $VERSION undefined | Medium | Build always reports failure even on success |
| NTFS mount needs ntfs-3g but not in package list | Low | USB automount will fail for NTFS drives |
| `audispd-plugins` may not exist in Debian 13 | Low | Deprecated/removed from trixie |
### Test Results
```
786 tests, 0 failures, 16 VM skips
Lint: 0 shellcheck warnings
ISO: 824 MB, built 2026-05-01
```
### Verification
```bash
./run.sh lint # Zero warnings
./run.sh test # 786 pass, 0 fail, 16 skip (VM)
```
---
## Entry 2026-02-20 (Session 6): Security Audit Findings Implementation ## Entry 2026-02-20 (Session 6): Security Audit Findings Implementation
### Context ### Context

View File

@@ -1,6 +1,6 @@
# KNEL-Football Project Status Report # KNEL-Football Project Status Report
> **Last Updated**: 2026-05-01 11:20 CDT > **Last Updated**: 2026-05-07 (Session 7 - Full Audit)
> **Maintained By**: AI Agent (Crush) > **Maintained By**: AI Agent (Crush)
> **Purpose**: Quick-glance status for project manager > **Purpose**: Quick-glance status for project manager

View File

@@ -70,9 +70,9 @@ This document maps security compliance requirements to implementation components
| Test Type | Test File | Validation Target | Coverage | | Test Type | Test File | Validation Target | Coverage |
|-----------|------------|-----------------|----------| |-----------|------------|-----------------|----------|
| Unit Tests | `tests/unit/firewall_test.bats` | Firewall configuration parsing | 🔧 | | Unit Tests | `tests/unit/firewall-setup_test.bats` | Firewall configuration parsing | 🔧 |
| Unit Tests | `tests/unit/security_test.bats` | Security hardening functions | 🔧 | | Unit Tests | `tests/unit/security-hardening_test.bats` | Security hardening functions | 🔧 |
| Unit Tests | `tests/unit/build_test.bats` | Build process functions | 🔧 | | Unit Tests | `tests/unit/build-iso_comprehensive_test.bats` | Build process functions | 🔧 |
| Integration Tests | `tests/integration/config_test.bats` | Configuration file validation | 🌐 | | Integration Tests | `tests/integration/config_test.bats` | Configuration file validation | 🌐 |
| Security Tests | `tests/security/compliance_test.bats` | Compliance verification | 🔒 | | Security Tests | `tests/security/compliance_test.bats` | Compliance verification | 🔒 |

View File

@@ -20,7 +20,7 @@
- run.sh exists and is executable - run.sh exists and is executable
- run.sh shows usage with help command - run.sh shows usage with help command
- run.sh creates output and build directories - run.sh creates output and build directories
- run.sh test:iso delegates to test-iso.sh - run.sh test:iso provides VM testing commands
- run.sh clean removes artifacts - run.sh clean removes artifacts
**Lines Covered**: Basic validation and command dispatch **Lines Covered**: Basic validation and command dispatch

34
run.sh
View File

@@ -13,6 +13,7 @@ readonly DOCKER_IMAGE="knel-football-dev:latest"
readonly OUTPUT_DIR="${SCRIPT_DIR}/output" readonly OUTPUT_DIR="${SCRIPT_DIR}/output"
readonly BUILD_DIR="${SCRIPT_DIR}/tmp" readonly BUILD_DIR="${SCRIPT_DIR}/tmp"
readonly BUILD_LOG="/tmp/knel-iso-build.log" readonly BUILD_LOG="/tmp/knel-iso-build.log"
readonly CACHE_VOLUME="knel-football-cache"
# VM Testing Configuration (system libvirt for virt-manager visibility, /tmp for no sudo) # VM Testing Configuration (system libvirt for virt-manager visibility, /tmp for no sudo)
readonly ISO_PATH="${SCRIPT_DIR}/output/knel-football-secure.iso" readonly ISO_PATH="${SCRIPT_DIR}/output/knel-football-secure.iso"
@@ -854,6 +855,8 @@ Build Commands:
iso:demo Build demo/CI ISO (hardcoded test credentials, serial console) iso:demo Build demo/CI ISO (hardcoded test credentials, serial console)
monitor [secs] Monitor build progress (default: check every 180s) monitor [secs] Monitor build progress (default: check every 180s)
clean Clean build artifacts clean Clean build artifacts
clean:cache Remove NVMe build cache (force full rebuild)
cache Show build cache status
Test Commands: Test Commands:
test Run all tests test Run all tests
@@ -966,6 +969,18 @@ main() {
rm -rf "${OUTPUT_DIR:?}"/* rm -rf "${OUTPUT_DIR:?}"/*
rm -rf "${BUILD_DIR:?}"/* rm -rf "${BUILD_DIR:?}"/*
;; ;;
clean:cache)
echo "Removing NVMe build cache (Docker volume: ${CACHE_VOLUME})..."
docker volume rm "${CACHE_VOLUME}" 2>/dev/null || echo "Cache volume not found"
;;
cache)
echo "Build cache status (Docker volume: ${CACHE_VOLUME}):"
if docker volume inspect "${CACHE_VOLUME}" &>/dev/null; then
docker run --rm -v "${CACHE_VOLUME}:/cache" alpine sh -c 'echo "Size: $(du -sh /cache 2>/dev/null | cut -f1)" && ls -la /cache/'
else
echo "No cache volume exists (will be created on next build)"
fi
;;
validate) validate)
echo "Running ISO validation..." echo "Running ISO validation..."
"${SCRIPT_DIR}/scripts/validate-iso.sh" "${SCRIPT_DIR}/scripts/validate-iso.sh"
@@ -1003,6 +1018,7 @@ main() {
--user root \ --user root \
-v "${SCRIPT_DIR}:/workspace:ro" \ -v "${SCRIPT_DIR}:/workspace:ro" \
-v "${OUTPUT_DIR}:/output" \ -v "${OUTPUT_DIR}:/output" \
-v "${CACHE_VOLUME}:/cache" \
-e TZ="America/Chicago" \ -e TZ="America/Chicago" \
-e DEBIAN_FRONTEND="noninteractive" \ -e DEBIAN_FRONTEND="noninteractive" \
-e LC_ALL="C" \ -e LC_ALL="C" \
@@ -1044,6 +1060,17 @@ if [ "${KNEL_BUILD_MODE}" = "demo" ]; then
fi fi
fi && fi &&
# Restore build cache from NVMe Docker volume
# Preserves bootstrap + package downloads between builds (~5 min saved)
if [ -d /cache/bootstrap ]; then
echo "Restoring build cache from NVMe..." &&
mkdir -p ./cache &&
cp -a /cache/* ./cache/ &&
echo "Cache restored (bootstrap + packages)"
else
echo "No build cache found (first build or cache cleared)"
fi &&
# Create Secure Boot binary hook inline # Create Secure Boot binary hook inline
echo "Creating Secure Boot hook..." && echo "Creating Secure Boot hook..." &&
mkdir -p config/hooks/binary && mkdir -p config/hooks/binary &&
@@ -1209,6 +1236,13 @@ chmod +x config/hooks/binary/0200-secureboot-uki.hook &&
echo "Starting ISO build..." && echo "Starting ISO build..." &&
timeout 3600 lb build && timeout 3600 lb build &&
# Save build cache to NVMe Docker volume for next rebuild
echo "Saving build cache to NVMe..." &&
mkdir -p /cache &&
cp -a ./cache/* /cache/ 2>/dev/null || true &&
echo "Cache saved (bootstrap + packages)" &&
ISO_FILE=$(find . -name "*.iso" -type f | head -1) && ISO_FILE=$(find . -name "*.iso" -type f | head -1) &&
if [ -n "$ISO_FILE" ]; then if [ -n "$ISO_FILE" ]; then
echo "ISO created: $ISO_FILE" echo "ISO created: $ISO_FILE"

View File

@@ -1,298 +0,0 @@
#!/bin/bash
# KNEL-Football ISO Testing Script
# Creates and boots a VM using libvirt/virsh to test the ISO
# Runs on HOST system (not inside Docker)
# Copyright © 2026 Known Element Enterprises LLC
# License: GNU Affero General Public License v3.0 only
set -euo pipefail
# Configuration variables
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
readonly SCRIPT_DIR
_vm_name="knel-test-$(date +%Y%m%d-%H%M%S)"
readonly VM_NAME="$_vm_name"
readonly ISO_PATH="${SCRIPT_DIR}/output/knel-football-secure-v1.0.0.iso"
readonly DISK_SIZE="20G"
readonly DISK_PATH="${SCRIPT_DIR}/tmp/${VM_NAME}.qcow2"
readonly RAM="4096" # 4GB RAM
readonly VCPUS="2"
# shellcheck disable=SC2034
readonly NETWORK="none"
readonly CPU_MODEL="host-model"
# Colors for output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
# Logging functions
log_info() {
echo -e "${GREEN}[INFO]${NC} $*"
}
log_warn() {
echo -e "${YELLOW}[WARN]${NC} $*"
}
log_error() {
echo -e "${RED}[ERROR]${NC} $*" >&2
}
# Usage information
usage() {
cat <<EOF
KNEL-Football ISO Tester - Test the ISO in a libvirt VM
Usage: $0 [COMMAND] [OPTIONS]
COMMANDS:
create Create and start VM with ISO
start Start existing VM
stop Stop running VM
console Connect to VM console
destroy Stop and remove VM
status Show VM status
list List all test VMs
OPTIONS:
-h, --help Show this help message
-n, --name Custom VM name (default: auto-generated)
-r, --ram RAM in MB (default: 4096)
-c, --cpus Number of VCPUs (default: 2)
-d, --disk Disk size (default: 20G)
EXAMPLES:
$0 create # Create and start VM
$0 create -n my-test -r 8192 # Create with 8GB RAM
$0 console # Connect to VM console
$0 destroy # Remove VM
REQUIREMENTS:
- libvirt / virsh installed on host
- libvirt running
- ISO must exist at: ${ISO_PATH}
- Sufficient disk space in tmp/
For more information, see: README.md
EOF
}
# Check prerequisites
check_prerequisites() {
log_info "Checking prerequisites..."
# Check if virsh is available
if ! command -v virsh &> /dev/null; then
log_error "virsh not found. Please install libvirt:"
echo " Ubuntu/Debian: sudo apt install libvirt-daemon-system virtinst"
echo " RHEL/CentOS: sudo yum install libvirt virt-install"
exit 1
fi
# Check if libvirtd is running
if ! virsh list &> /dev/null; then
log_error "libvirtd is not running. Please start it:"
echo " sudo systemctl start libvirtd"
exit 1
fi
# Check if ISO exists
if [[ ! -f "${ISO_PATH}" ]]; then
log_error "ISO not found at: ${ISO_PATH}"
log_warn "Please build the ISO first using: ./run.sh iso"
exit 1
fi
log_info "Prerequisites check passed"
}
# Create VM
create_vm() {
log_info "Creating VM: ${VM_NAME}"
log_info "ISO: ${ISO_PATH}"
log_info "Disk: ${DISK_SIZE} (${DISK_PATH})"
log_info "RAM: ${RAM} MB, VCPUs: ${VCPUS}"
# Create disk image
log_info "Creating disk image..."
qemu-img create -f qcow2 "${DISK_PATH}" "${DISK_SIZE}"
# Create VM definition
log_info "Defining VM..."
virt-install \
--name "${VM_NAME}" \
--memory "${RAM}" \
--vcpus "${VCPUS}" \
--cpu "${CPU_MODEL}" \
--disk path="${DISK_PATH}",format=qcow2,bus=virtio \
--cdrom "${ISO_PATH}" \
--graphics vnc \
--noautoconsole \
--os-variant debian12 \
--boot cdrom,hd \
--metadata description="KNEL-Football Secure OS Test VM"
log_info "VM created and started successfully"
log_info "Connect to console with: $0 console ${VM_NAME}"
}
# Start VM
start_vm() {
log_info "Starting VM: ${VM_NAME}"
virsh start "${VM_NAME}"
log_info "VM started"
}
# Stop VM
stop_vm() {
log_info "Stopping VM: ${VM_NAME}"
virsh shutdown "${VM_NAME}"
log_info "VM shutdown signal sent"
}
# Connect to console
connect_console() {
log_info "Connecting to VM console: ${VM_NAME}"
log_info "Press Ctrl+] to exit console"
virsh console "${VM_NAME}"
}
# Destroy VM
destroy_vm() {
log_warn "This will permanently remove VM: ${VM_NAME}"
# Check if VM is running
if virsh domstate "${VM_NAME}" 2>/dev/null | grep -q "running"; then
log_info "Stopping VM..."
virsh destroy "${VM_NAME}"
fi
# Undefine VM
log_info "Undefining VM..."
virsh undefine "${VM_NAME}"
# Remove disk
if [[ -f "${DISK_PATH}" ]]; then
log_info "Removing disk: ${DISK_PATH}"
rm -f "${DISK_PATH}"
fi
log_info "VM destroyed"
}
# Show VM status
show_status() {
log_info "VM Status: ${VM_NAME}"
if ! virsh dominfo "${VM_NAME}" 2>/dev/null; then
log_error "VM not found: ${VM_NAME}"
exit 1
fi
echo ""
virsh dominfo "${VM_NAME}"
echo ""
log_info "VM interfaces:"
virsh domiflist "${VM_NAME}" || log_warn "No interface information available"
}
# List all test VMs
list_vms() {
log_info "Listing KNEL-Football test VMs..."
echo ""
virsh list --all | grep "knel-test-" || log_warn "No test VMs found"
echo ""
log_info "Disk images:"
ls -lh "${SCRIPT_DIR}"/tmp/knel-test-*.qcow2 2>/dev/null || log_warn "No test disk images found"
}
# Parse command line arguments
COMMAND=""
CUSTOM_NAME=""
while [[ $# -gt 0 ]]; do
case $1 in
-h | --help)
usage
exit 0
;;
-n | --name)
CUSTOM_NAME="$2"
shift 2
;;
-r | --ram)
RAM="$2"
shift 2
;;
-c | --cpus)
VCPUS="$2"
shift 2
;;
-d | --disk)
DISK_SIZE="$2"
shift 2
;;
create | start | stop | console | destroy | status | list)
COMMAND="$1"
shift
;;
*)
if [[ -z "${COMMAND}" ]]; then
log_error "Unknown option: $1"
usage
exit 1
else
# VM name for commands that take it
CUSTOM_NAME="$1"
shift
fi
;;
esac
done
# Use custom name if provided
if [[ -n "${CUSTOM_NAME}" && "${COMMAND}" != "create" ]]; then
VM_NAME="${CUSTOM_NAME}"
fi
# Set default command
COMMAND="${COMMAND:-help}"
# Main execution
main() {
case "${COMMAND}" in
create)
check_prerequisites
create_vm
;;
start)
check_prerequisites
start_vm
;;
stop)
check_prerequisites
stop_vm
;;
console)
connect_console
;;
destroy)
destroy_vm
;;
status)
show_status
;;
list)
list_vms
;;
help|*)
usage
;;
esac
}
main

View File

@@ -237,31 +237,31 @@
# ============================================================================= # =============================================================================
@test "run.sh iso uses docker run" { @test "run.sh iso uses docker run" {
grep -A 100 'iso)' /workspace/run.sh | grep -q "docker run" grep -A 100 -F 'iso|iso:demo)' /workspace/run.sh | grep -q "docker run"
} }
@test "run.sh iso runs as root in container" { @test "run.sh iso runs as root in container" {
grep -A 100 'iso)' /workspace/run.sh | grep -q "\-\-user root" grep -A 100 -F 'iso|iso:demo)' /workspace/run.sh | grep -q "\-\-user root"
} }
@test "run.sh iso uses privileged mode for loop devices" { @test "run.sh iso uses privileged mode for loop devices" {
grep -A 100 'iso)' /workspace/run.sh | grep -q "\-\-privileged" grep -A 100 -F 'iso|iso:demo)' /workspace/run.sh | grep -q "\-\-privileged"
} }
@test "run.sh iso mounts workspace read-only" { @test "run.sh iso mounts workspace read-only" {
grep -A 100 'iso)' /workspace/run.sh | grep -q "/workspace:ro" grep -A 100 -F 'iso|iso:demo)' /workspace/run.sh | grep -q "/workspace:ro"
} }
@test "run.sh iso mounts output directory" { @test "run.sh iso mounts output directory" {
grep -A 100 'iso)' /workspace/run.sh | grep -q "/output" grep -A 100 -F 'iso|iso:demo)' /workspace/run.sh | grep -q "/output"
} }
@test "run.sh iso sets timezone" { @test "run.sh iso sets timezone" {
grep -A 100 'iso)' /workspace/run.sh | grep -q "TZ=" grep -A 100 -F 'iso|iso:demo)' /workspace/run.sh | grep -q "TZ="
} }
@test "run.sh iso sets noninteractive frontend" { @test "run.sh iso sets noninteractive frontend" {
grep -A 100 'iso)' /workspace/run.sh | grep -q "DEBIAN_FRONTEND" grep -A 100 -F 'iso|iso:demo)' /workspace/run.sh | grep -q "DEBIAN_FRONTEND"
} }
# ============================================================================= # =============================================================================
@@ -285,7 +285,7 @@
# ============================================================================= # =============================================================================
@test "run.sh iso references host FDE" { @test "run.sh iso references host FDE" {
grep -A 10 'iso)' /workspace/run.sh | grep -qi "fde\|encryption" grep -A 10 -F 'iso|iso:demo)' /workspace/run.sh | grep -qi "fde\|encryption"
} }
@test "run.sh has check_host_fde function defined" { @test "run.sh has check_host_fde function defined" {

View File

@@ -182,7 +182,7 @@
# ============================================================================= # =============================================================================
@test "run.sh iso command uses Docker" { @test "run.sh iso command uses Docker" {
grep -A 50 'iso)' /workspace/run.sh | grep -q "docker run" grep -A 50 -F 'iso|iso:demo)' /workspace/run.sh | grep -q "docker run"
} }
@test "run.sh test command uses Docker" { @test "run.sh test command uses Docker" {
@@ -307,7 +307,7 @@
} }
@test "run.sh iso command references host FDE" { @test "run.sh iso command references host FDE" {
grep -A 5 'iso)' /workspace/run.sh | grep -qi "fde\|encryption" grep -A 15 -F 'iso|iso:demo)' /workspace/run.sh | grep -qi "fde\|encryption"
} }
@test "run.sh provides clear FDE error message" { @test "run.sh provides clear FDE error message" {

View File

@@ -132,7 +132,7 @@
} }
@test "run.sh references host FDE for iso command" { @test "run.sh references host FDE for iso command" {
grep -A 5 "iso)" /workspace/run.sh | grep -qi "fde\|encryption" grep -A 15 -F 'iso|iso:demo)' /workspace/run.sh | grep -qi "fde\|encryption"
} }
@test "run.sh has check_host_fde function" { @test "run.sh has check_host_fde function" {

144
verify.sh
View File

@@ -1,144 +0,0 @@
#!/bin/bash
# Comprehensive project verification script
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
cd "$SCRIPT_DIR"
PASS=0
FAIL=0
RESULTS=""
log_pass() { PASS=$((PASS+1)); RESULTS+=" [PASS] $1\n"; }
log_fail() { FAIL=$((FAIL+1)); RESULTS+=" [FAIL] $1\n"; }
log_info() { RESULTS+=" [INFO] $1\n"; }
echo "=== KNEL-Football Project Verification ==="
echo ""
# 1. Docker available
echo "Phase 1: Environment checks..."
if docker info &>/dev/null; then
log_pass "Docker daemon running"
else
log_fail "Docker daemon not running"
fi
# 2. Docker image exists
if docker images --format '{{.Repository}}' | grep -q 'knel-football-dev'; then
log_pass "Docker build image exists"
else
log_fail "Docker build image missing (run: ./run.sh build)"
fi
# 3. Lint (warning level only)
echo "Phase 2: Lint checks..."
LINT_OUTPUT=$(docker run --rm -v "$SCRIPT_DIR":/workspace knel-football-dev:latest bash -c \
'shellcheck --severity=warning /workspace/src/*.sh /workspace/config/hooks/installed/*.sh /workspace/config/hooks/live/*.sh' 2>&1 || true)
if [ -z "$LINT_OUTPUT" ]; then
log_pass "Shellcheck (warning level) clean"
else
log_fail "Shellcheck warnings found:"
echo "$LINT_OUTPUT" | while read -r line; do log_info " $line"; done
fi
# 4. Run full test suite
echo "Phase 3: Test suite..."
TEST_OUTPUT=$(./run.sh test 2>&1)
TEST_COUNT=$(echo "$TEST_OUTPUT" | grep -c "^ok" || true)
TEST_FAIL=$(echo "$TEST_OUTPUT" | grep -c "^not ok" || true)
if [ "$TEST_FAIL" -eq 0 ]; then
log_pass "All $TEST_COUNT tests passing"
else
log_fail "$TEST_FAIL tests failing out of $((TEST_COUNT+TEST_FAIL))"
echo "$TEST_OUTPUT" | grep "^not ok" | while read -r line; do log_info " $line"; done
fi
# 5. ISO artifact check
echo "Phase 4: ISO artifact..."
if ls output/*.iso &>/dev/null; then
ISO_FILE=$(find output -name '*.iso' -type f | head -1)
ISO_SIZE=$(du -h "$ISO_FILE" | cut -f1)
log_pass "ISO exists: $ISO_FILE ($ISO_SIZE)"
# Check checksums
if [ -f "${ISO_FILE}.sha256" ]; then
log_pass "SHA256 checksum file exists"
else
log_fail "SHA256 checksum file missing"
fi
else
log_info "No ISO artifact found (build with: ./run.sh iso)"
fi
# 6. VM testing capability
echo "Phase 5: VM test capability..."
if command -v virsh &>/dev/null; then
log_pass "virsh available for VM testing"
if virsh list --all &>/dev/null; then
log_pass "libvirt daemon accessible"
# Check for any existing test VMs
EXISTING_VMS=$(virsh list --all --name 2>/dev/null | grep -c 'knel-test' || true)
if [ "$EXISTING_VMS" -gt 0 ]; then
log_info "Found $EXISTING_VMS existing test VM(s)"
else
log_info "No existing test VMs"
fi
else
log_info "libvirt daemon not accessible (may need sudo/libvirtd group)"
fi
else
log_info "virsh not installed - VM testing not available on this host"
fi
# 7. Git status
echo "Phase 6: Git status..."
if git diff --quiet && git diff --cached --quiet; then
log_pass "Working tree clean"
else
log_fail "Uncommitted changes present"
fi
AHEAD=$(git rev-list --count '@{u}..HEAD' 2>/dev/null || echo "?")
log_info "Branch is $AHEAD commit(s) ahead of origin/main"
# 8. Source file integrity
echo "Phase 7: Source file integrity..."
for f in src/build-iso.sh src/security-hardening.sh src/firewall-setup.sh; do
if [ -f "$f" ] && [ -x "$f" ]; then
log_pass "$f exists and is executable"
else
log_fail "$f missing or not executable"
fi
done
# 9. Config file integrity
echo "Phase 8: Config integrity..."
for f in config/preseed.cfg config/hooks/installed/encryption-setup.sh config/hooks/installed/encryption-validation.sh config/hooks/live/security-hardening.sh config/hooks/live/firewall-setup.sh; do
if [ -f "$f" ]; then
log_pass "$f exists"
else
log_fail "$f missing"
fi
done
# 10. Check for Unicode characters that break shellcheck
echo "Phase 9: Unicode check..."
UNICODE_FILES=$(grep -rl '✓\|✗\|✔\|✘' src/ config/ 2>/dev/null || true)
if [ -z "$UNICODE_FILES" ]; then
log_pass "No problematic Unicode characters in shell scripts"
else
log_fail "Unicode characters found in: $UNICODE_FILES"
fi
# Summary
echo ""
echo "=== RESULTS ==="
echo -e "$RESULTS"
echo ""
echo "Summary: $PASS passed, $FAIL failed"
if [ "$FAIL" -gt 0 ]; then
echo "STATUS: ACTION REQUIRED"
exit 1
else
echo "STATUS: ALL GOOD"
exit 0
fi