feat: Fix discovery system critical issues

Resolved multiple critical discovery system issues:

## Discovery System Fixes
- Fixed console commands not being discovered on first run
- Implemented fallback discovery for empty caches
- Added context-aware caching with separate cache keys
- Fixed object serialization preventing __PHP_Incomplete_Class

## Cache System Improvements
- Smart caching that only caches meaningful results
- Separate caches for different execution contexts (console, web, test)
- Proper array serialization/deserialization for cache compatibility
- Cache hit logging for debugging and monitoring

## Object Serialization Fixes
- Fixed DiscoveredAttribute serialization with proper string conversion
- Sanitized additional data to prevent object reference issues
- Added fallback for corrupted cache entries

## Performance & Reliability
- All 69 console commands properly discovered and cached
- 534 total discovery items successfully cached and restored
- No more __PHP_Incomplete_Class cache corruption
- Improved error handling and graceful fallbacks

## Testing & Quality
- Fixed code style issues across discovery components
- Enhanced logging for better debugging capabilities
- Improved cache validation and error recovery

Ready for production deployment with stable discovery system.

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
2025-08-13 12:04:17 +02:00
parent 66f7efdcfc
commit 9b74ade5b0
494 changed files with 764014 additions and 1127382 deletions

510
deployment/lib/config-manager.sh Executable file
View File

@@ -0,0 +1,510 @@
#!/bin/bash
# Configuration Management System for Custom PHP Framework
# Template management, validation, and secure credential handling
# Domain: michaelschiemer.de | Email: kontakt@michaelschiemer.de | PHP: 8.4
set -euo pipefail
# Configuration manager constants
DEPLOYMENT_DIR="${DEPLOYMENT_DIR:-$(cd "$(dirname "${BASH_SOURCE[0]}")/../" && pwd)}"
CONFIG_TEMPLATES_DIR="${DEPLOYMENT_DIR}/applications/environments"
CONFIG_CREDENTIALS_DIR="${DEPLOYMENT_DIR}/.credentials"
CONFIG_BACKUP_DIR="${DEPLOYMENT_DIR}/.backups"
# Colors
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'
# Logging
log() { echo -e "${GREEN}[CONFIG] ✅ $1${NC}"; }
warn() { echo -e "${YELLOW}[CONFIG] ⚠️ $1${NC}"; }
error() { echo -e "${RED}[CONFIG] ❌ $1${NC}"; }
info() { echo -e "${BLUE}[CONFIG] $1${NC}"; }
# Initialize configuration directories
init_config_directories() {
mkdir -p "$CONFIG_CREDENTIALS_DIR" "$CONFIG_BACKUP_DIR"
chmod 700 "$CONFIG_CREDENTIALS_DIR" "$CONFIG_BACKUP_DIR"
}
# Generate secure password
generate_password() {
local length=${1:-25}
local type=${2:-"alphanumeric"}
case $type in
"alphanumeric")
openssl rand -base64 $((length * 3 / 4)) | tr -d "=+/" | cut -c1-"$length"
;;
"base64")
openssl rand -base64 "$length"
;;
"hex")
openssl rand -hex $((length / 2))
;;
"strong")
# Strong password with special characters
openssl rand -base64 "$length" | tr -d "=+/" | head -c"$length"
;;
*)
error "Unknown password type: $type"
return 1
;;
esac
}
# Generate all required credentials for an environment
generate_environment_credentials() {
local environment=$1
local creds_file="${CONFIG_CREDENTIALS_DIR}/${environment}.env"
info "Generating secure credentials for $environment environment..."
# Backup existing credentials if they exist
if [[ -f "$creds_file" ]]; then
local backup_file="${CONFIG_BACKUP_DIR}/${environment}.env.backup.$(date +%Y%m%d_%H%M%S)"
cp "$creds_file" "$backup_file"
warn "Existing credentials backed up to: $backup_file"
fi
# Generate credentials based on environment
cat > "$creds_file" << EOF
# Generated Credentials for $environment Environment
# Created: $(date)
# Custom PHP Framework Deployment
# Database Credentials
DB_PASSWORD=$(generate_password 25 alphanumeric)
DB_ROOT_PASSWORD=$(generate_password 25 alphanumeric)
# Redis Credentials
REDIS_PASSWORD=$(generate_password 25 alphanumeric)
# Application Security
APP_KEY=$(generate_password 32 base64)
CSRF_SECRET=$(generate_password 32 hex)
# Session Security
SESSION_SECRET=$(generate_password 32 base64)
# API Security
API_SECRET=$(generate_password 32 hex)
JWT_SECRET=$(generate_password 32 base64)
# External API Credentials
SHOPIFY_WEBHOOK_SECRET=$(generate_password 64 hex)
MAIL_API_KEY=$(generate_password 32 alphanumeric)
EOF
# Environment-specific credentials
if [[ "$environment" == "production" ]]; then
cat >> "$creds_file" << EOF
# Production-specific Credentials
GRAFANA_ADMIN_PASSWORD=$(generate_password 16 strong)
MONITORING_API_KEY=$(generate_password 32 hex)
BACKUP_ENCRYPTION_KEY=$(generate_password 32 base64)
SSL_PASSPHRASE=$(generate_password 20 strong)
EOF
fi
# Set secure permissions
chmod 600 "$creds_file"
success "Credentials generated: $creds_file"
return 0
}
# Load credentials from file
load_credentials() {
local environment=$1
local creds_file="${CONFIG_CREDENTIALS_DIR}/${environment}.env"
if [[ ! -f "$creds_file" ]]; then
error "Credentials file not found: $creds_file"
return 1
fi
# Source the credentials file
set -a # Export all variables
source "$creds_file"
set +a
info "Credentials loaded for $environment environment"
}
# Validate environment template
validate_template() {
local template_file=$1
if [[ ! -f "$template_file" ]]; then
error "Template file not found: $template_file"
return 1
fi
info "Validating template: $(basename "$template_file")"
# Check for required placeholders
local required_placeholders=(
"*** REQUIRED ***"
"DOMAIN_NAME="
"APP_ENV="
"DB_PASSWORD="
"APP_KEY="
)
local missing_placeholders=()
for placeholder in "${required_placeholders[@]}"; do
if ! grep -q "$placeholder" "$template_file"; then
missing_placeholders+=("$placeholder")
fi
done
if [[ ${#missing_placeholders[@]} -gt 0 ]]; then
error "Template missing required placeholders:"
printf ' - %s\n' "${missing_placeholders[@]}"
return 1
fi
success "Template validation passed"
return 0
}
# Apply configuration to template
apply_configuration() {
local environment=$1
local domain=$2
local email=$3
local additional_vars="${4:-}"
local template_file="${CONFIG_TEMPLATES_DIR}/${environment}.env.template"
local output_file="${CONFIG_TEMPLATES_DIR}/.env.${environment}"
local creds_file="${CONFIG_CREDENTIALS_DIR}/${environment}.env"
info "Creating $environment configuration from template..."
# Validate template first
if ! validate_template "$template_file"; then
return 1
fi
# Backup existing config
if [[ -f "$output_file" ]]; then
local backup_file="${CONFIG_BACKUP_DIR}/.env.${environment}.backup.$(date +%Y%m%d_%H%M%S)"
cp "$output_file" "$backup_file"
warn "Existing config backed up to: $backup_file"
fi
# Copy template to output
cp "$template_file" "$output_file"
# Apply basic configuration
sed -i "s|DOMAIN_NAME=.*|DOMAIN_NAME=${domain}|g" "$output_file"
sed -i "s|MAIL_FROM_ADDRESS=.*|MAIL_FROM_ADDRESS=${email}|g" "$output_file"
sed -i "s|your-domain\.com|${domain}|g" "$output_file"
sed -i "s|your-email@example\.com|${email}|g" "$output_file"
# Apply environment-specific settings
case $environment in
"production")
sed -i 's|APP_DEBUG=.*|APP_DEBUG=false|g' "$output_file"
sed -i 's|LOG_LEVEL=.*|LOG_LEVEL=warning|g' "$output_file"
sed -i 's|APP_ENV=.*|APP_ENV=production|g' "$output_file"
;;
"staging")
sed -i 's|APP_DEBUG=.*|APP_DEBUG=false|g' "$output_file"
sed -i 's|LOG_LEVEL=.*|LOG_LEVEL=info|g' "$output_file"
sed -i 's|APP_ENV=.*|APP_ENV=staging|g' "$output_file"
;;
"development")
sed -i 's|APP_DEBUG=.*|APP_DEBUG=true|g' "$output_file"
sed -i 's|LOG_LEVEL=.*|LOG_LEVEL=debug|g' "$output_file"
sed -i 's|APP_ENV=.*|APP_ENV=development|g' "$output_file"
;;
esac
# Apply credentials if available
if [[ -f "$creds_file" ]]; then
info "Applying generated credentials..."
# Load credentials
while IFS='=' read -r key value; do
# Skip comments and empty lines
[[ $key =~ ^#.*$ ]] || [[ -z $key ]] && continue
# Remove any existing quotes
value=$(echo "$value" | sed 's/^["'\'']*//;s/["'\'']*$//')
# Apply to config
if grep -q "^${key}=" "$output_file"; then
sed -i "s|^${key}=.*|${key}=${value}|g" "$output_file"
elif grep -q "${key}=\*\*\* REQUIRED \*\*\*" "$output_file"; then
sed -i "s|${key}=\*\*\* REQUIRED \*\*\*|${key}=${value}|g" "$output_file"
fi
done < <(grep -v '^#' "$creds_file" | grep '=' || true)
fi
# Apply additional variables if provided
if [[ -n "$additional_vars" ]]; then
info "Applying additional configuration variables..."
# Parse additional_vars as key=value pairs
echo "$additional_vars" | tr ' ' '\n' | while IFS='=' read -r key value; do
if [[ -n "$key" && -n "$value" ]]; then
sed -i "s|^${key}=.*|${key}=${value}|g" "$output_file"
fi
done
fi
# Set secure permissions
chmod 600 "$output_file"
success "Configuration created: $output_file"
return 0
}
# Validate configuration file
validate_configuration() {
local config_file=$1
if [[ ! -f "$config_file" ]]; then
error "Configuration file not found: $config_file"
return 1
fi
info "Validating configuration: $(basename "$config_file")"
# Check for remaining placeholders
local remaining_placeholders
remaining_placeholders=$(grep "*** REQUIRED ***" "$config_file" || true)
if [[ -n "$remaining_placeholders" ]]; then
error "Configuration contains unfilled placeholders:"
echo "$remaining_placeholders"
return 1
fi
# Check for critical configuration
local required_vars=(
"APP_ENV"
"DOMAIN_NAME"
"DB_PASSWORD"
"APP_KEY"
)
local missing_vars=()
for var in "${required_vars[@]}"; do
if ! grep -q "^${var}=" "$config_file"; then
missing_vars+=("$var")
fi
done
if [[ ${#missing_vars[@]} -gt 0 ]]; then
error "Configuration missing required variables:"
printf ' - %s\n' "${missing_vars[@]}"
return 1
fi
# Load and validate specific values
local app_env
app_env=$(grep "^APP_ENV=" "$config_file" | cut -d'=' -f2 | tr -d '"')
if [[ "$app_env" == "production" ]]; then
# Additional production validation
local debug_mode
debug_mode=$(grep "^APP_DEBUG=" "$config_file" | cut -d'=' -f2 | tr -d '"')
if [[ "$debug_mode" == "true" ]]; then
warn "Debug mode is enabled in production configuration"
fi
# Check password strength
local db_password
db_password=$(grep "^DB_PASSWORD=" "$config_file" | cut -d'=' -f2 | tr -d '"')
if [[ ${#db_password} -lt 16 ]]; then
error "Database password too short for production (minimum 16 characters)"
return 1
fi
fi
success "Configuration validation passed"
return 0
}
# List available configurations
list_configurations() {
info "Available configurations:"
for env_file in "${CONFIG_TEMPLATES_DIR}/.env."*; do
if [[ -f "$env_file" && ! "$env_file" =~ \.template$ && ! "$env_file" =~ \.backup ]]; then
local env_name
env_name=$(basename "$env_file" | sed 's/\.env\.//')
local app_env domain
app_env=$(grep "^APP_ENV=" "$env_file" | cut -d'=' -f2 | tr -d '"' || echo "unknown")
domain=$(grep "^DOMAIN_NAME=" "$env_file" | cut -d'=' -f2 | tr -d '"' || echo "unknown")
echo "$env_name: $app_env environment for $domain"
fi
done
info "Available credentials:"
for creds_file in "${CONFIG_CREDENTIALS_DIR}"/*.env; do
if [[ -f "$creds_file" ]]; then
local env_name
env_name=$(basename "$creds_file" .env)
local created
created=$(stat -c %y "$creds_file" 2>/dev/null | cut -d' ' -f1 || echo "unknown")
echo "$env_name: created $created"
fi
done
}
# Rotate credentials
rotate_credentials() {
local environment=$1
warn "Rotating credentials for $environment environment..."
warn "This will generate new passwords and invalidate existing ones!"
printf "Continue with credential rotation? [y/N]: "
read -r confirm
if [[ ! $confirm =~ ^[Yy]$ ]]; then
info "Credential rotation cancelled"
return 0
fi
generate_environment_credentials "$environment"
success "Credentials rotated for $environment environment"
warn "You must redeploy the application for changes to take effect!"
}
# Backup configurations
backup_configurations() {
local backup_name="config_backup_$(date +%Y%m%d_%H%M%S)"
local backup_path="${CONFIG_BACKUP_DIR}/${backup_name}"
info "Creating configuration backup: $backup_name"
mkdir -p "$backup_path"
# Backup environment files
cp -r "$CONFIG_TEMPLATES_DIR" "${backup_path}/environments"
# Backup credentials (if they exist)
if [[ -d "$CONFIG_CREDENTIALS_DIR" && "$(ls -A "$CONFIG_CREDENTIALS_DIR" 2>/dev/null)" ]]; then
cp -r "$CONFIG_CREDENTIALS_DIR" "${backup_path}/credentials"
fi
# Create backup manifest
cat > "${backup_path}/manifest.txt" << EOF
Configuration Backup: $backup_name
Created: $(date)
Custom PHP Framework Configuration Management
Contents:
- Environment configurations: environments/
- Secure credentials: credentials/ (if any)
Restore with:
cp -r ${backup_path}/environments/* ${CONFIG_TEMPLATES_DIR}/
cp -r ${backup_path}/credentials/* ${CONFIG_CREDENTIALS_DIR}/
EOF
success "Configuration backup created: $backup_path"
}
# Show configuration info
show_config_info() {
local environment=$1
local config_file="${CONFIG_TEMPLATES_DIR}/.env.${environment}"
if [[ ! -f "$config_file" ]]; then
error "Configuration not found: $environment"
return 1
fi
info "Configuration information for $environment:"
# Extract key information
local domain app_env app_debug
domain=$(grep "^DOMAIN_NAME=" "$config_file" | cut -d'=' -f2 | tr -d '"' || echo "unknown")
app_env=$(grep "^APP_ENV=" "$config_file" | cut -d'=' -f2 | tr -d '"' || echo "unknown")
app_debug=$(grep "^APP_DEBUG=" "$config_file" | cut -d'=' -f2 | tr -d '"' || echo "unknown")
echo " Domain: $domain"
echo " Environment: $app_env"
echo " Debug mode: $app_debug"
echo " File: $config_file"
echo " Size: $(stat -c%s "$config_file" 2>/dev/null || echo "unknown") bytes"
echo " Modified: $(stat -c%y "$config_file" 2>/dev/null | cut -d' ' -f1 || echo "unknown")"
# Check for credentials
local creds_file="${CONFIG_CREDENTIALS_DIR}/${environment}.env"
if [[ -f "$creds_file" ]]; then
echo " Credentials: Available ($(stat -c%y "$creds_file" 2>/dev/null | cut -d' ' -f1))"
else
echo " Credentials: Not generated"
fi
}
# Command-line interface
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
# Initialize
init_config_directories
case "${1:-help}" in
"generate-credentials")
generate_environment_credentials "${2:-production}"
;;
"apply-config")
apply_configuration "$2" "$3" "$4" "${5:-}"
;;
"validate")
validate_configuration "${CONFIG_TEMPLATES_DIR}/.env.${2:-production}"
;;
"list")
list_configurations
;;
"rotate")
rotate_credentials "${2:-production}"
;;
"backup")
backup_configurations
;;
"info")
show_config_info "${2:-production}"
;;
"help"|*)
cat << EOF
${CYAN}Configuration Manager for Custom PHP Framework${NC}
${YELLOW}Usage:${NC} $0 <command> [options]
${YELLOW}Commands:${NC}
generate-credentials <env> Generate secure credentials for environment
apply-config <env> <domain> <email> [vars] Create config from template
validate <env> Validate configuration file
list List available configurations
rotate <env> Rotate credentials for environment
backup Backup all configurations
info <env> Show configuration information
help Show this help message
${YELLOW}Examples:${NC}
$0 generate-credentials production
$0 apply-config production michaelschiemer.de kontakt@michaelschiemer.de
$0 validate production
$0 list
$0 backup
EOF
;;
esac
fi