- Update all() method to check for *_FILE variables and resolve their base variables
- Ensures APP_KEY, DB_PASSWORD, etc. are resolved even if they don't exist in the array
- Two-pass approach: first processes existing variables, second checks for *_FILE patterns
- Fixes issue where APP_KEY was empty even though APP_KEY_FILE existed
- Update all() to automatically resolve Docker Secrets (*_FILE pattern) for empty variables
- Ensures DB_PASSWORD, REDIS_PASSWORD, etc. are resolved from their *_FILE counterparts when empty
- Variables like DB_PASSWORD_FILE are still included in output, but empty values are replaced with resolved secrets
- Fixes issue where DB_PASSWORD and REDIS_PASSWORD appeared empty in logs even though *_FILE variables existed
- Update get() method to treat empty strings as 'not set' for Docker Secrets resolution
- Allows Docker Secrets (*_FILE pattern) to override empty values
- Preserves original behavior: explicitly set empty strings are still returned
- Fixes issue where RAPIDMAIL_USERNAME and RAPIDMAIL_PASSWORD appear empty even when Docker Secrets are available
- Update all() to merge internal variables with system environment variables
- Ensures variables set after initialization (e.g., by PHP-FPM) are included
- Internal variables take precedence over system variables
- Fixes issue where RAPIDMAIL_USERNAME and RAPIDMAIL_PASSWORD were missing in all() output
- Fix priority order in loadSystemEnvironment() to check and first
- Add dynamic fallback in Environment::get() to handle variables set after initialization
- Ensure all environment variables are captured during bootstrap, including those set dynamically by PHP-FPM/FastCGI
Fixes issue where environment variables like RAPIDMAIL_USERNAME and RAPIDMAIL_PASSWORD were missing during bootstrap but available later in request processing.
- Improve WireGuard client IP calculation logic (find next available IP)
- Add local wireguard-clients directory for storing client configs
- Integrate Redis pool into CacheInitializer
- Improve ContainerBootstrapper with better imports and Redis pool
- Add monitoring role tags for better task organization
- Update WireGuard documentation
- Store generated WireGuard client configs locally
- Add fallback to 'latest' tag when build fails
- Add fallback mechanism when pulling specific image tag fails
- Fix code style: move opening brace in ObjectInfo
- Remove unused comment in ObjectStorage
- Use RedisConnectionPool when available for consistency
- Use named parameters when creating RedisQueue to prevent parameter confusion
- Fix RedisQueue constructor error where strings were passed instead of connection object
- Add deployment/ansible/templates/.env.production.j2 used by secrets playbook
- Enhance deploy-update.yml to read registry creds from vault or CI
- Update production-deploy workflow to pass registry credentials to Ansible
- Remove obsolete GitHub-style workflows under .gitea (conflicted naming)
Why: make the production pipeline executable end-to-end with Ansible and
consistent secrets handling; avoid legacy CI configs interfering.
- Commented out RateLimitMiddleware in MiddlewareManager
- RateLimit system not fully implemented yet (missing Storage, Initializer)
- Added ENV_SETUP.md documentation for .env file structure
- Website was returning HTTP 500 due to missing StorageInterface binding
TODO: Implement complete RateLimit system with Storage interface and DI bindings
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude <noreply@anthropic.com>
BREAKING CHANGE: Requires PHP 8.5.0RC3
Changes:
- Update Docker base image from php:8.4-fpm to php:8.5.0RC3-fpm
- Enable ext-uri for native WHATWG URL parsing support
- Update composer.json PHP requirement from ^8.4 to ^8.5
- Add ext-uri as required extension in composer.json
- Move URL classes from Url.php85/ to Url/ directory (now compatible)
- Remove temporary PHP 8.4 compatibility workarounds
Benefits:
- Native URL parsing with Uri\WhatWg\Url class
- Better performance for URL operations
- Future-proof with latest PHP features
- Eliminates PHP version compatibility issues
- Mount /home/deploy/michaelschiemer/current:/var/www/html:ro in php and queue-worker services
- This allows deployment via rsync without requiring Docker image rebuild
- Storage volume still mounted as writable overlay for runtime data
- Change default DB_DRIVER to 'pgsql' for PostgreSQL
Deployment Architecture:
- rsync deploys code to /home/deploy/michaelschiemer/releases/{timestamp}
- Atomic symlink switch to /home/deploy/michaelschiemer/current
- PHP containers mount current/ for immediate code updates
- No rebuild needed - code changes are live after symlink switch
Benefits:
- Faster deployments (no Docker rebuild)
- Code changes reflected immediately
- Zero-downtime releases
- Easy rollback via symlink change
- Create AnsibleDeployStage using framework's Process module for secure command execution
- Integrate AnsibleDeployStage into DeploymentPipelineCommands for production deployments
- Add force_deploy flag support in Ansible playbook to override stale locks
- Use PHP deployment module as orchestrator (php console.php deploy:production)
- Fix ErrorAggregationInitializer to use Environment class instead of $_ENV superglobal
Architecture:
- BuildStage → AnsibleDeployStage → HealthCheckStage for production
- Process module provides timeout, error handling, and output capture
- Ansible playbook supports rollback via rollback-git-based.yml
- Zero-downtime deployments with health checks
- Replace all $_ENV references with Environment::get() calls
- Fixes ErrorAggregatorInterface binding in production where $_ENV is not populated
- Environment class properly loads from .env file which is mounted in containers
AbstractSaga::getName() is non-static, but child classes
(UserOnboardingSaga, OrderFulfillmentSaga) tried to override it as static.
Also fixed ConsoleCommand usage:
- ConsoleCommand is an attribute, not an interface
- SagaCommands and ReplayCommands now use #[ConsoleCommand] attributes
- All command methods properly annotated