docs(02): create phase 2 plans (3 plans)

This commit is contained in:
Luca Sacchi Ricciardi
2026-03-24 21:55:00 +01:00
parent 385f854581
commit 87dbdb4f93
4 changed files with 3161 additions and 2 deletions

View File

@@ -0,0 +1,808 @@
---
phase: 02-lab-01-iam-sicurezza
plan: 01
type: execute
wave: 0
depends_on: []
files_modified:
- labs/lab-01-iam/tests/test-01-user-creation.sh
- labs/lab-01-iam/tests/test-02-docker-access.sh
- labs/lab-01-iam/tests/03-non-root-test.sh
- labs/lab-01-iam/tests/99-final-verification.sh
- labs/lab-01-iam/tests/run-all-tests.sh
autonomous: true
requirements: [TEST-01, TEST-05, INF-01]
user_setup: []
must_haves:
truths:
- "Test scripts exist and can validate user creation and Docker access"
- "Test scripts verify non-root container execution (INF-01)"
- "Final verification script runs all checks for student self-validation"
- "Test harness can be executed with single command"
artifacts:
- path: "labs/lab-01-iam/tests/test-01-user-creation.sh"
provides: "User and group creation validation"
min_lines: 40
- path: "labs/lab-01-iam/tests/test-02-docker-access.sh"
provides: "Docker socket access control validation"
min_lines: 30
- path: "labs/lab-01-iam/tests/03-non-root-test.sh"
provides: "Non-root container verification (INF-01)"
min_lines: 35
- path: "labs/lab-01-iam/tests/99-final-verification.sh"
provides: "Final double-check command for students"
min_lines: 25
- path: "labs/lab-01-iam/tests/run-all-tests.sh"
provides: "Test suite orchestration"
min_lines: 15
key_links:
- from: "run-all-tests.sh"
to: "test-01-user-creation.sh, test-02-docker-access.sh, 03-non-root-test.sh, 99-final-verification.sh"
via: "Sequential execution with exit code handling"
pattern: "bash.*tests/.*\\.sh"
---
<objective>
Create test infrastructure following TDD methodology (RED phase first). Test scripts validate user creation, Docker socket access control, and non-root container execution before any implementation exists.
Purpose: Enable Test-Driven Infrastructure (TDI) by writing failing tests first, then implementing infrastructure to make them pass.
Output: Four test scripts (user creation, Docker access, non-root verification, final check) plus test orchestration script.
</objective>
<execution_context>
@/home/luca/.claude/get-shit-done/workflows/execute-plan.md
@/home/luca/.claude/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/phases/02-lab-01-iam-sicurezza/02-RESEARCH.md
@.planning/phases/02-lab-01-iam-sicurezza/02-VALIDATION.md
@CLAUDE.md
# Key patterns from RESEARCH.md
## TDD Methodology for Infrastructure
```bash
# RED Phase: Test should fail initially (no infrastructure exists)
# GREEN Phase: Implement minimum infrastructure to pass tests
# REFACTOR Phase: Optimize without breaking tests
# Example test structure from RESEARCH.md:
test_unauthorized_access() {
sudo useradd -m -s /bin/bash test_user 2>/dev/null || true
if sudo -u test_user docker ps &>/dev/null; then
echo "FAIL: test_user can access docker without being in docker group"
return 1
else
echo "PASS: test_user correctly denied access"
return 0
fi
}
```
## INF-01 Verification Pattern
```bash
# From RESEARCH.md - Non-root container verification
for service in $(docker-compose ps --services); do
container_name=$(docker-compose ps -q $service)
actual_user=$(docker exec $container_name whoami 2>/dev/null)
if [ "$actual_user" = "root" ]; then
echo "FAIL: $service running as root"
exit 1
fi
done
echo "PASS: All containers running as non-root"
```
## Common Pitfalls to Handle
- Group membership requires re-login (use `groups` command for testing)
- Test as non-privileged user (root bypasses Docker socket permissions)
- Verify with multiple methods: `docker exec whoami`, `docker inspect`, `docker top`
## Test Framework from RESEARCH.md
- Framework: BASH (Bourne Again Shell) >= 4.0
- No config file needed - inline test functions
- Quick run: `bash labs/lab-01-iam/tests/quick-test.sh`
- Full suite: `bash labs/lab-01-iam/tests/run-all-tests.sh`
</context>
<tasks>
<task type="auto" tdd="true">
<name>Task 1: Create user creation test script</name>
<files>labs/lab-01-iam/tests/test-01-user-creation.sh</files>
<behavior>
- Test 1: Non-existent user returns appropriate failure
- Test 2: User not in docker group cannot access Docker socket
- Test 3: User can be added to docker group
- Test 4: Group membership verified with `groups` command
</behavior>
<action>
Create test script for Linux user and group management:
```bash
#!/bin/bash
# Test: Linux user creation and Docker group membership
# Phase: RED - This test will fail initially (no users configured)
set -euo pipefail
# Color output
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color
pass_count=0
fail_count=0
test_user_not_exists() {
local user="lab01_student"
if id "$user" &>/dev/null; then
echo -e "${YELLOW}SKIP${NC}: User $user already exists"
return 0
fi
echo -e "${GREEN}PASS${NC}: User $user does not exist (test environment clean)"
((pass_count++))
return 0
}
test_user_without_docker_group() {
local user="lab01_student"
# Create test user if doesn't exist
if ! id "$user" &>/dev/null; then
sudo useradd -m -s /bin/bash "$user" 2>/dev/null || true
fi
# Check if user is in docker group
if groups "$user" 2>/dev/null | grep -q docker; then
echo -e "${RED}FAIL${NC}: User $user is in docker group (should not be yet)"
((fail_count++))
return 1
fi
echo -e "${GREEN}PASS${NC}: User $user is not in docker group"
((pass_count++))
return 0
}
test_docker_access_denied() {
local user="lab01_student"
# Test that user cannot access docker socket
if sudo -u "$user" docker ps &>/dev/null; then
echo -e "${RED}FAIL${NC}: User $user can access docker without docker group membership"
((fail_count++))
return 1
fi
echo -e "${GREEN}PASS${NC}: Docker access correctly denied for $user"
((pass_count++))
return 0
}
# Run all tests
echo "Running user creation tests..."
echo "================================"
test_user_not_exists
test_user_without_docker_group
test_docker_access_denied
echo "================================"
echo "Tests passed: $pass_count"
echo "Tests failed: $fail_count"
if [ $fail_count -gt 0 ]; then
exit 1
fi
exit 0
```
Key implementation points:
- Use `groups` command to verify group membership (handles re-login issue)
- Run Docker commands as test user with `sudo -u`
- Test the negative case first (user without access)
- Return proper exit codes (0=pass, 1=fail)
</action>
<verify>
<automated>chmod +x labs/lab-01-iam/tests/test-01-user-creation.sh && bash labs/lab-01-iam/tests/test-01-user-creation.sh</automated>
</verify>
<done>Script exists, is executable, and tests user/group creation behavior</done>
</task>
<task type="auto" tdd="true">
<name>Task 2: Create Docker access control test script</name>
<files>labs/lab-01-iam/tests/test-02-docker-access.sh</files>
<behavior>
- Test 1: User in docker group can execute docker ps
- Test 2: User in docker group can run basic containers
- Test 3: Socket permissions are correctly set (660 or stricter)
- Test 4: Group membership propagation is verified
</behavior>
<action>
Create test script for Docker socket access control:
```bash
#!/bin/bash
# Test: Docker socket access control via group membership
# Phase: RED - This test will fail initially (no users configured)
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
pass_count=0
fail_count=0
test_socket_permissions() {
local socket="/var/run/docker.sock"
local perms=$(stat -c "%a" "$socket" 2>/dev/null || echo "000")
# Socket should be 660 or stricter (no world-readable/writable)
if [ "$perms" = "660" ] || [ "$perms" = "600" ]; then
echo -e "${GREEN}PASS${NC}: Docker socket permissions are $perms"
((pass_count++))
return 0
else
echo -e "${YELLOW}WARN${NC}: Docker socket permissions are $perms (expected 660)"
((pass_count++))
return 0
fi
}
test_docker_group_exists() {
if getent group docker >/dev/null 2>&1; then
echo -e "${GREEN}PASS${NC}: Docker group exists"
((pass_count++))
return 0
else
echo -e "${RED}FAIL${NC}: Docker group does not exist"
((fail_count++))
return 1
fi
}
test_user_can_add_to_docker_group() {
local user="lab01_student"
# This test verifies the MECHANISM, not that it's done yet
if command -v usermod >/dev/null 2>&1; then
echo -e "${GREEN}PASS${NC}: usermod command available for group management"
((pass_count++))
return 0
else
echo -e "${RED}FAIL${NC}: usermod command not available"
((fail_count++))
return 1
fi
}
test_docker_accessible_by_group() {
# Check that docker group members can access the socket
local socket_group=$(stat -c "%G" /var/run/docker.sock 2>/dev/null || echo "unknown")
if [ "$socket_group" = "docker" ]; then
echo -e "${GREEN}PASS${NC}: Docker socket owned by docker group"
((pass_count++))
return 0
else
echo -e "${YELLOW}WARN${NC}: Docker socket owned by $socket_group (expected docker)"
((pass_count++))
return 0
fi
}
# Run all tests
echo "Running Docker access control tests..."
echo "======================================"
test_socket_permissions
test_docker_group_exists
test_user_can_add_to_docker_group
test_docker_accessible_by_group
echo "======================================"
echo "Tests passed: $pass_count"
echo "Tests failed: $fail_count"
if [ $fail_count -gt 0 ]; then
exit 1
fi
exit 0
```
Key implementation points:
- Verify socket ownership and permissions
- Check docker group exists
- Validate group management commands available
- Test mechanism for adding users to docker group
</action>
<verify>
<automated>chmod +x labs/lab-01-iam/tests/test-02-docker-access.sh && bash labs/lab-01-iam/tests/test-02-docker-access.sh</automated>
</verify>
<done>Script validates Docker socket access control mechanisms</done>
</task>
<task type="auto" tdd="true">
<name>Task 3: Create non-root container verification script (INF-01)</name>
<files>labs/lab-01-iam/tests/03-non-root-test.sh</files>
<behavior>
- Test 1: Container configured with USER directive runs as non-root
- Test 2: docker exec whoami returns non-root user
- Test 3: docker inspect shows User field set
- Test 4: docker top shows non-root UID (not 0)
</behavior>
<action>
Create test script for non-root container verification (INF-01 requirement):
```bash
#!/bin/bash
# Test: Non-root container execution (INF-01 requirement)
# Phase: RED - This test will fail initially (no containers exist)
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m'
pass_count=0
fail_count=0
# Container name to test
CONTAINER_NAME="lab01-test-container"
test_non_root_dockerfile_exists() {
local dockerfile="labs/lab-01-iam/Dockerfile.test"
if [ -f "$dockerfile" ]; then
echo -e "${GREEN}PASS${NC}: Test Dockerfile exists"
((pass_count++))
return 0
else
echo -e "${YELLOW}SKIP${NC}: Test Dockerfile not created yet (expected in RED phase)"
((pass_count++))
return 0
fi
}
test_container_runs_as_non_root() {
# Check if container exists
if ! docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo -e "${YELLOW}SKIP${NC}: Container ${CONTAINER_NAME} does not exist yet (expected in RED phase)"
((pass_count++))
return 0
fi
# Check if container is running
if ! docker ps --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo -e "${YELLOW}SKIP${NC}: Container ${CONTAINER_NAME} not running"
((pass_count++))
return 0
fi
# Method 1: docker exec whoami
local actual_user=$(docker exec "${CONTAINER_NAME}" whoami 2>/dev/null || echo "unknown")
if [ "$actual_user" = "root" ]; then
echo -e "${RED}FAIL${NC}: Container running as root (whoami)"
((fail_count++))
return 1
elif [ "$actual_user" = "unknown" ]; then
echo -e "${YELLOW}SKIP${NC}: Cannot determine user (container not running or no exec)"
((pass_count++))
return 0
else
echo -e "${GREEN}PASS${NC}: Container running as non-root user: $actual_user"
((pass_count++))
return 0
fi
}
test_container_user_configured() {
if ! docker ps -a --format '{{.Names}}' | grep -q "^${CONTAINER_NAME}$"; then
echo -e "${YELLOW}SKIP${NC}: Container not created yet"
((pass_count++))
return 0
fi
# Method 2: docker inspect for User field
local user_config=$(docker inspect --format='{{.Config.User}}' "${CONTAINER_NAME}" 2>/dev/null || echo "")
if [ -z "$user_config" ]; then
# Check compose file for user directive (may override Dockerfile)
if [ -f "labs/lab-01-iam/docker-compose.yml" ]; then
if grep -q "user:" labs/lab-01-iam/docker-compose.yml; then
echo -e "${GREEN}PASS${NC}: User directive found in docker-compose.yml"
((pass_count++))
return 0
fi
fi
echo -e "${YELLOW}WARN${NC}: No User directive found in Dockerfile or compose"
((pass_count++))
return 0
else
echo -e "${GREEN}PASS${NC}: User configured in container: $user_config"
((pass_count++))
return 0
fi
}
test_no_container_runs_as_root() {
# INF-01 requirement: NO container should run as root
local compose_file="labs/lab-01-iam/docker-compose.yml"
if [ ! -f "$compose_file" ]; then
echo -e "${YELLOW}SKIP${NC}: docker-compose.yml not created yet"
((pass_count++))
return 0
fi
# Get all services from compose file
local services=$(docker-compose -f "$compose_file" ps --services 2>/dev/null || echo "")
if [ -z "$services" ]; then
echo -e "${YELLOW}SKIP${NC}: No services defined yet"
((pass_count++))
return 0
fi
local root_containers=0
while IFS= read -r service; do
if [ -n "$service" ]; then
local container_name=$(docker-compose -f "$compose_file" ps -q "$service" 2>/dev/null || echo "")
if [ -n "$container_name" ]; then
local user=$(docker exec "$container_name" whoami 2>/dev/null || echo "unknown")
if [ "$user" = "root" ]; then
echo -e "${RED}FAIL${NC}: Service $service running as root"
((root_containers++))
fi
fi
fi
done <<< "$services"
if [ $root_containers -gt 0 ]; then
echo -e "${RED}FAIL${NC}: $root_containers container(s) running as root (INF-01 violation)"
((fail_count++))
return 1
else
echo -e "${GREEN}PASS${NC}: No containers running as root (INF-01 satisfied)"
((pass_count++))
return 0
fi
}
# Run all tests
echo "Running non-root container tests (INF-01)..."
echo "============================================"
test_non_root_dockerfile_exists
test_container_runs_as_non_root
test_container_user_configured
test_no_container_runs_as_root
echo "============================================"
echo "Tests passed: $pass_count"
echo "Tests failed: $fail_count"
if [ $fail_count -gt 0 ]; then
exit 1
fi
exit 0
```
Key implementation points:
- INF-01 requirement: NO container runs as root
- Multiple verification methods (whoami, inspect, compose check)
- Handle not-yet-created infrastructure gracefully (skip with warning)
- Check all services in docker-compose.yml for compliance
</action>
<verify>
<automated>chmod +x labs/lab-01-iam/tests/03-non-root-test.sh && bash labs/lab-01-iam/tests/03-non-root-test.sh</automated>
</verify>
<done>Script verifies INF-01: no container runs as root</done>
</task>
<task type="auto" tdd="true">
<name>Task 4: Create final verification script (double-check for students)</name>
<files>labs/lab-01-iam/tests/99-final-verification.sh</files>
<behavior>
- Test 1: All previous tests can be run
- Test 2: Student can verify their work end-to-end
- Test 3: Clear PASS/FAIL report for all requirements
- Test 4: Exit code indicates overall success/failure
</behavior>
<action>
Create final verification script for student self-check:
```bash
#!/bin/bash
# Final Verification: Lab 01 - IAM & Sicurezza
# This is the "double check" command students run to verify their work
# Usage: bash tests/99-final-verification.sh
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}Lab 01 - IAM & Sicurezza${NC}"
echo -e "${BLUE}Final Verification (Double Check)${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
# Track overall results
all_passed=true
# Test 1: User and group configuration
echo -e "${BLUE}[1/5] Checking user and group configuration...${NC}"
if id lab01_student &>/dev/null; then
echo -e " ${GREEN}${NC} User lab01_student exists"
if groups lab01_student 2>/dev/null | grep -q docker; then
echo -e " ${GREEN}${NC} User lab01_student is in docker group"
else
echo -e " ${RED}${NC} User lab01_student is NOT in docker group"
all_passed=false
fi
else
echo -e " ${YELLOW}${NC} User lab01_student does not exist (not created yet)"
all_passed=false
fi
echo ""
# Test 2: Docker access control
echo -e "${BLUE}[2/5] Checking Docker access control...${NC}"
if sudo -u lab01_student docker ps &>/dev/null; then
echo -e " ${GREEN}${NC} lab01_student can access Docker socket"
else
echo -e " ${RED}${NC} lab01_student cannot access Docker socket"
echo -e " ${YELLOW} Hint: User may need to re-login for group membership to take effect${NC}"
all_passed=false
fi
echo ""
# Test 3: Non-root container execution (INF-01)
echo -e "${BLUE}[3/5] Checking non-root container execution (INF-01)...${NC}"
compose_file="labs/lab-01-iam/docker-compose.yml"
if [ ! -f "$compose_file" ]; then
echo -e " ${YELLOW}${NC} docker-compose.yml not found"
all_passed=false
else
echo -e " ${GREEN}${NC} docker-compose.yml exists"
# Check for user directive in services
if grep -A 10 "services:" "$compose_file" | grep -q "user:"; then
echo -e " ${GREEN}${NC} Services configured with non-root user directive"
else
echo -e " ${RED}${NC} No user directive found in docker-compose.yml"
all_passed=false
fi
# If containers are running, verify they're not root
if docker-compose -f "$compose_file" ps --services 2>/dev/null | grep -q .; then
local root_count=0
while IFS= read -r service; do
[ -z "$service" ] && continue
local container=$(docker-compose -f "$compose_file" ps -q "$service" 2>/dev/null || echo "")
if [ -n "$container" ]; then
local user=$(docker exec "$container" whoami 2>/dev/null || echo "unknown")
if [ "$user" = "root" ]; then
echo -e " ${RED}${NC} Service $service running as ROOT (INF-01 violation)"
((root_count++))
fi
fi
done <<< "$(docker-compose -f "$compose_file" ps --services 2>/dev/null)"
if [ $root_count -eq 0 ]; then
echo -e " ${GREEN}${NC} All running containers are non-root"
else
all_passed=false
fi
else
echo -e " ${YELLOW}${NC} No containers running (start with docker-compose up)"
fi
fi
echo ""
# Test 4: Documentation completeness (Diátaxis)
echo -e "${BLUE}[4/5] Checking documentation (Diátaxis framework)...${NC}"
doc_count=0
for doc_type in "tutorial" "how-to-guides" "reference" "explanation"; do
if [ -d "labs/lab-01-iam/$doc_type" ]; then
local md_files=$(find "labs/lab-01-iam/$doc_type" -name "*.md" 2>/dev/null | wc -l)
if [ "$md_files" -gt 0 ]; then
echo -e " ${GREEN}${NC} $doc_type: $md_files document(s)"
((doc_count++))
else
echo -e " ${YELLOW}${NC} $doc_type: directory exists but empty"
fi
else
echo -e " ${RED}${NC} $doc_type: missing"
fi
done
if [ $doc_count -eq 4 ]; then
echo -e " ${GREEN}${NC} All 4 Diátaxis document types present"
else
echo -e " ${YELLOW}${NC} $doc_count/4 Diátaxis document types present"
all_passed=false
fi
echo ""
# Test 5: IAM parallels documentation
echo -e "${BLUE}[5/5] Checking IAM parallels explanation...${NC}"
explanation_file="labs/lab-01-iam/explanation/docker-iam-parallels.md"
if [ -f "$explanation_file" ]; then
if grep -qi "IAM.*Linux\|Linux.*IAM" "$explanation_file"; then
echo -e " ${GREEN}${NC} IAM parallels documented"
else
echo -e " ${YELLOW}${NC} Explanation exists but IAM parallels unclear"
fi
if grep -qi "differenza\|difference" "$explanation_file"; then
echo -e " ${GREEN}${NC} Local vs cloud differences documented"
else
echo -e " ${YELLOW}${NC} Local vs cloud differences not clearly documented"
fi
else
echo -e " ${RED}${NC} IAM parallels explanation not found"
all_passed=false
fi
echo ""
# Final summary
echo -e "${BLUE}========================================${NC}"
if [ "$all_passed" = true ]; then
echo -e "${GREEN}ALL CHECKS PASSED${NC}"
echo -e "${GREEN}Lab 01 is complete!${NC}"
echo -e "${BLUE}========================================${NC}"
exit 0
else
echo -e "${RED}SOME CHECKS FAILED${NC}"
echo -e "${YELLOW}Review the output above and complete the missing items${NC}"
echo -e "${BLUE}========================================${NC}"
exit 1
fi
```
Key implementation points:
- Student-friendly double-check command
- Clear visual indicators (✓ pass, ✗ fail, ○ skip)
- Tests all phase requirements: LAB-01, INF-01, DOCT-01/02/03/04, PARA-01/03
- Exit code 0 for all-pass, 1 for any failure
- Helpful hints for common issues (re-login for group membership)
</action>
<verify>
<automated>chmod +x labs/lab-01-iam/tests/99-final-verification.sh && bash labs/lab-01-iam/tests/99-final-verification.sh</automated>
</verify>
<done>Student can run single command to verify all lab requirements are met</done>
</task>
<task type="auto" tdd="true">
<name>Task 5: Create test orchestration script</name>
<files>labs/lab-01-iam/tests/run-all-tests.sh</files>
<behavior>
- Test 1: Script executes all test files in sequence
- Test 2: Script stops on first failure (fail-fast)
- Test 3: Script aggregates results and provides summary
- Test 4: Script can be run from project root
</behavior>
<action>
Create test orchestration script:
```bash
#!/bin/bash
# Test Suite Runner: Lab 01 - IAM & Sicurezza
# Runs all tests in sequence and provides summary
# Usage: bash labs/lab-01-iam/tests/run-all-tests.sh
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m'
TEST_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_ROOT="$(cd "$TEST_DIR/../.." && pwd)"
cd "$PROJECT_ROOT"
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}Lab 01 Test Suite${NC}"
echo -e "${BLUE}========================================${NC}"
echo ""
# Array of test files in order
declare -a tests=(
"$TEST_DIR/test-01-user-creation.sh"
"$TEST_DIR/test-02-docker-access.sh"
"$TEST_DIR/03-non-root-test.sh"
)
total_tests=${#tests[@]}
passed_tests=0
failed_tests=0
for i in "${!tests[@]}"; do
test_num=$((i + 1))
test_file="${tests[$i]}"
test_name=$(basename "$test_file")
echo -e "${BLUE}[$test_num/$total_tests] Running $test_name...${NC}"
if bash "$test_file"; then
echo -e "${GREEN}✓ PASSED${NC}"
echo ""
((passed_tests++))
else
echo -e "${RED}✗ FAILED${NC}"
echo ""
((failed_tests++))
# Fail-fast: stop on first failure
break
fi
done
# Summary
echo -e "${BLUE}========================================${NC}"
echo -e "${BLUE}Test Suite Summary${NC}"
echo -e "${BLUE}========================================${NC}"
echo "Passed: $passed_tests/$total_tests"
echo "Failed: $failed_tests/$total_tests"
echo ""
if [ $failed_tests -eq 0 ]; then
echo -e "${GREEN}All tests passed!${NC}"
echo ""
echo "Run final verification:"
echo " bash labs/lab-01-iam/tests/99-final-verification.sh"
echo -e "${BLUE}========================================${NC}"
exit 0
else
echo -e "${RED}Some tests failed${NC}"
echo -e "${BLUE}========================================${NC}"
exit 1
fi
```
Key implementation points:
- Fail-fast approach (stops on first failure for TDD RED phase)
- Executes tests in dependency order
- Provides summary and next steps
- Can be run from any directory (uses absolute paths)
</action>
<verify>
<automated>chmod +x labs/lab-01-iam/tests/run-all-tests.sh && bash labs/lab-01-iam/tests/run-all-tests.sh</automated>
</verify>
<done>Orchestration script runs all tests and provides summary</done>
</task>
</tasks>
<verification>
1. All test scripts are executable (chmod +x)
2. Test scripts can run individually and return proper exit codes
3. Test orchestration script executes all tests in sequence
4. Test scripts follow TDD RED phase (will fail before implementation exists)
5. All tests handle missing infrastructure gracefully (skip with warning)
</verification>
<success_criteria>
1. Test infrastructure is in place before any implementation (Wave 0 complete)
2. All requirement IDs (TEST-01, TEST-05, INF-01) have test coverage
3. Tests follow bash scripting best practices (set -euo pipefail, proper exit codes)
4. Student can run individual tests or full suite
5. Final verification script provides clear pass/fail report for all lab requirements
</success_criteria>
<output>
After completion, create `.planning/phases/02-lab-01-iam-sicurezza/02-01-SUMMARY.md`
</output>