Les enseignants avaient besoin d'un outil pour créer des devoirs assignés à leurs classes, avec filtrage automatique par matière selon la classe sélectionnée. Le système valide que la date d'échéance tombe un jour ouvrable (lundi-vendredi) et empêche les dates dans le passé. Le domaine modélise le devoir comme un agrégat avec pièces jointes, statut brouillon/publié, et événements métier (création, modification, suppression). Les handlers de notification écoutent ces événements pour les futurs envois aux parents et élèves.
462 lines
21 KiB
YAML
462 lines
21 KiB
YAML
# This file is the entry point to configure your own services.
|
|
# Files in the packages/ subdirectory configure your dependencies.
|
|
|
|
# Put parameters here that don't need to change on each machine where the app is deployed
|
|
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
|
|
parameters:
|
|
tenant.base_domain: '%env(TENANT_BASE_DOMAIN)%'
|
|
app.url: '%env(APP_URL)%'
|
|
|
|
services:
|
|
# default configuration for services in this file
|
|
_defaults:
|
|
autowire: true # Automatically injects dependencies in your services.
|
|
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
|
|
bind:
|
|
# Bind activation tokens cache pool (7-day TTL)
|
|
Psr\Cache\CacheItemPoolInterface $activationTokensCache: '@activation_tokens.cache'
|
|
# Bind users cache pool (no TTL - persistent data)
|
|
Psr\Cache\CacheItemPoolInterface $usersCache: '@users.cache'
|
|
# Bind refresh tokens cache pool (7-day TTL)
|
|
Psr\Cache\CacheItemPoolInterface $refreshTokensCache: '@refresh_tokens.cache'
|
|
# Bind password reset tokens cache pool (1-hour TTL)
|
|
Psr\Cache\CacheItemPoolInterface $passwordResetTokensCache: '@password_reset_tokens.cache'
|
|
# Bind sessions cache pool (7-day TTL)
|
|
Psr\Cache\CacheItemPoolInterface $sessionsCache: '@sessions.cache'
|
|
# Bind student guardians cache pool (no TTL - persistent data)
|
|
Psr\Cache\CacheItemPoolInterface $studentGuardiansCache: '@student_guardians.cache'
|
|
# Bind paginated queries cache pool (1h TTL, tag-aware)
|
|
Symfony\Contracts\Cache\TagAwareCacheInterface $paginatedQueriesCache: '@paginated_queries.cache'
|
|
# Bind named message buses
|
|
Symfony\Component\Messenger\MessageBusInterface $eventBus: '@event.bus'
|
|
Symfony\Component\Messenger\MessageBusInterface $commandBus: '@command.bus'
|
|
Symfony\Component\Messenger\MessageBusInterface $queryBus: '@query.bus'
|
|
|
|
# makes classes in src/ available to be used as services
|
|
# this creates a service per class whose id is the fully-qualified class name
|
|
App\:
|
|
resource: '../src/'
|
|
exclude:
|
|
- '../src/DependencyInjection/'
|
|
- '../src/Entity/'
|
|
- '../src/Kernel.php'
|
|
# Exclude Domain layers - they should be pure PHP with no framework deps
|
|
- '../src/*/Domain/'
|
|
|
|
# Domain services need to be registered explicitly to avoid framework coupling
|
|
# Example: App\Administration\Application\Command\:
|
|
# resource: '../src/Administration/Application/Command/'
|
|
|
|
# Tenant services
|
|
App\Shared\Infrastructure\Tenant\TenantResolver:
|
|
arguments:
|
|
$baseDomain: '%tenant.base_domain%'
|
|
|
|
App\Shared\Infrastructure\Persistence\Doctrine\TenantAwareConnection:
|
|
alias: doctrine.dbal.default_connection
|
|
|
|
App\Shared\Infrastructure\Tenant\TenantDatabaseSwitcher:
|
|
alias: doctrine.dbal.default_connection
|
|
|
|
# TenantRegistry est configuré par environnement :
|
|
# - dev: config/packages/dev/tenant.yaml (tenants de test)
|
|
# - prod: à configurer via admin ou env vars
|
|
|
|
App\Shared\Infrastructure\Tenant\Command\CreateTenantDatabaseCommand:
|
|
arguments:
|
|
$masterDatabaseUrl: '%env(DATABASE_URL)%'
|
|
|
|
App\Shared\Infrastructure\Tenant\Command\TenantMigrateCommand:
|
|
arguments:
|
|
$projectDir: '%kernel.project_dir%'
|
|
|
|
# Administration services
|
|
# Bind Repository interfaces to their implementations
|
|
App\Administration\Domain\Repository\ActivationTokenRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Redis\RedisActivationTokenRepository
|
|
|
|
App\Administration\Infrastructure\Persistence\Cache\CachedUserRepository:
|
|
arguments:
|
|
$inner: '@App\Administration\Infrastructure\Persistence\Doctrine\DoctrineUserRepository'
|
|
|
|
App\Administration\Domain\Repository\UserRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Cache\CachedUserRepository
|
|
|
|
App\Administration\Infrastructure\Console\MigrateUsersToPostgresCommand:
|
|
arguments:
|
|
$source: '@App\Administration\Infrastructure\Persistence\Cache\CacheUserRepository'
|
|
$target: '@App\Administration\Infrastructure\Persistence\Doctrine\DoctrineUserRepository'
|
|
|
|
App\Administration\Application\Port\PasswordHasher:
|
|
alias: App\Administration\Infrastructure\Security\SymfonyPasswordHasher
|
|
|
|
# Clock interface binding
|
|
App\Shared\Domain\Clock:
|
|
alias: App\Shared\Infrastructure\Clock\SystemClock
|
|
|
|
# Domain policies (need explicit registration as Domain is excluded from autowiring)
|
|
App\Administration\Domain\Policy\ConsentementParentalPolicy:
|
|
autowire: true
|
|
|
|
# Email handlers
|
|
App\Administration\Infrastructure\Messaging\SendActivationConfirmationHandler:
|
|
arguments:
|
|
$appUrl: '%app.url%'
|
|
|
|
App\Administration\Infrastructure\Messaging\SendPasswordResetEmailHandler:
|
|
arguments:
|
|
$appUrl: '%app.url%'
|
|
|
|
App\Administration\Infrastructure\Messaging\SendPasswordResetConfirmationHandler:
|
|
arguments:
|
|
$appUrl: '%app.url%'
|
|
|
|
App\Shared\Infrastructure\Tenant\TenantUrlBuilder:
|
|
arguments:
|
|
$appUrl: '%app.url%'
|
|
$baseDomain: '%tenant.base_domain%'
|
|
|
|
# Audit Logger Service (writes to append-only audit_log table)
|
|
App\Shared\Application\Port\AuditLogger:
|
|
alias: App\Shared\Infrastructure\Audit\AuditLogger
|
|
|
|
App\Shared\Infrastructure\Audit\AuditLogger:
|
|
arguments:
|
|
$connection: '@doctrine.dbal.master_connection'
|
|
$appSecret: '%env(APP_SECRET)%'
|
|
|
|
App\Shared\Infrastructure\Audit\AuditLogRepository:
|
|
arguments:
|
|
$connection: '@doctrine.dbal.master_connection'
|
|
|
|
App\Shared\Infrastructure\Console\ArchiveAuditLogsCommand:
|
|
arguments:
|
|
$connection: '@doctrine.dbal.master_connection'
|
|
|
|
App\Shared\Infrastructure\Console\ReviewFailedMessagesCommand:
|
|
arguments:
|
|
$connection: '@doctrine.dbal.master_connection'
|
|
|
|
# Audit log handlers (use AuditLogger to write to database)
|
|
App\Shared\Infrastructure\Audit\Handler\AuditAuthenticationHandler:
|
|
arguments:
|
|
$appSecret: '%env(APP_SECRET)%'
|
|
|
|
# JWT Authentication
|
|
App\Administration\Infrastructure\Security\JwtPayloadEnricher:
|
|
tags:
|
|
- { name: kernel.event_listener, event: lexik_jwt_authentication.on_jwt_created, method: onJWTCreated }
|
|
|
|
App\Administration\Infrastructure\Security\DatabaseUserProvider:
|
|
arguments:
|
|
$userRepository: '@App\Administration\Domain\Repository\UserRepository'
|
|
|
|
App\SuperAdmin\Infrastructure\Persistence\Doctrine\DoctrineSuperAdminRepository:
|
|
arguments:
|
|
$connection: '@doctrine.dbal.master_connection'
|
|
|
|
App\SuperAdmin\Infrastructure\Persistence\Doctrine\DoctrineEstablishmentRepository:
|
|
arguments:
|
|
$connection: '@doctrine.dbal.master_connection'
|
|
|
|
App\SuperAdmin\Application\Query\GetEstablishmentsMetrics\GetEstablishmentsMetricsHandler:
|
|
arguments:
|
|
$connection: '@doctrine.dbal.master_connection'
|
|
|
|
# Refresh Token Repository
|
|
App\Administration\Domain\Repository\RefreshTokenRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Redis\RedisRefreshTokenRepository
|
|
|
|
# Password Reset Token Repository
|
|
App\Administration\Domain\Repository\PasswordResetTokenRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Redis\RedisPasswordResetTokenRepository
|
|
|
|
# Session Repository
|
|
App\Administration\Domain\Repository\SessionRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Redis\RedisSessionRepository
|
|
|
|
# Class Repository (Story 2.1 - Gestion des classes)
|
|
App\Administration\Domain\Repository\ClassRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Doctrine\DoctrineClassRepository
|
|
|
|
# Subject Repository (Story 2.2 - Gestion des matières)
|
|
App\Administration\Domain\Repository\SubjectRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Doctrine\DoctrineSubjectRepository
|
|
|
|
# Period Configuration Repository (Story 2.3 - Gestion des périodes)
|
|
App\Administration\Domain\Repository\PeriodConfigurationRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Doctrine\DoctrinePeriodConfigurationRepository
|
|
|
|
# Grading Configuration Repository (Story 2.4 - Mode de notation)
|
|
App\Administration\Domain\Repository\GradingConfigurationRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Doctrine\DoctrineGradingConfigurationRepository
|
|
|
|
# Class Assignment (Story 3.0 - Affectation élèves aux classes)
|
|
App\Administration\Domain\Repository\ClassAssignmentRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Doctrine\DoctrineClassAssignmentRepository
|
|
|
|
# Teacher Assignment (Story 2.8 - Affectation enseignants)
|
|
App\Administration\Domain\Repository\TeacherAssignmentRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Doctrine\DoctrineTeacherAssignmentRepository
|
|
|
|
App\Administration\Application\Port\TeacherAssignmentChecker:
|
|
alias: App\Administration\Infrastructure\Service\RepositoryTeacherAssignmentChecker
|
|
|
|
# Teacher Replacement Repository (Story 2.9 - Remplaçants temporaires)
|
|
App\Scolarite\Domain\Repository\TeacherReplacementRepository:
|
|
alias: App\Scolarite\Infrastructure\Persistence\Doctrine\DoctrineTeacherReplacementRepository
|
|
|
|
# Homework (Story 5.1 - Création de devoirs)
|
|
App\Scolarite\Domain\Repository\HomeworkRepository:
|
|
alias: App\Scolarite\Infrastructure\Persistence\Doctrine\DoctrineHomeworkRepository
|
|
|
|
App\Scolarite\Domain\Service\DueDateValidator:
|
|
autowire: true
|
|
|
|
App\Scolarite\Application\Port\FileStorage:
|
|
alias: App\Scolarite\Infrastructure\Storage\LocalFileStorage
|
|
|
|
App\Scolarite\Infrastructure\Storage\LocalFileStorage:
|
|
arguments:
|
|
$storagePath: '%kernel.project_dir%/var/storage'
|
|
|
|
# Schedule (Story 4.1 - Emploi du temps)
|
|
App\Scolarite\Domain\Repository\ScheduleSlotRepository:
|
|
alias: App\Scolarite\Infrastructure\Persistence\Doctrine\DoctrineScheduleSlotRepository
|
|
|
|
App\Scolarite\Domain\Repository\ScheduleExceptionRepository:
|
|
alias: App\Scolarite\Infrastructure\Persistence\Doctrine\DoctrineScheduleExceptionRepository
|
|
|
|
App\Scolarite\Domain\Service\ScheduleConflictDetector:
|
|
autowire: true
|
|
|
|
App\Scolarite\Application\Port\EnseignantAffectationChecker:
|
|
alias: App\Scolarite\Infrastructure\Service\CurrentYearEnseignantAffectationChecker
|
|
|
|
# Super Admin Repositories (Story 2.10 - Multi-établissements)
|
|
App\SuperAdmin\Domain\Repository\SuperAdminRepository:
|
|
alias: App\SuperAdmin\Infrastructure\Persistence\Doctrine\DoctrineSuperAdminRepository
|
|
|
|
App\SuperAdmin\Domain\Repository\EstablishmentRepository:
|
|
alias: App\SuperAdmin\Infrastructure\Persistence\Doctrine\DoctrineEstablishmentRepository
|
|
|
|
# School Calendar Repository (Story 2.11 - Calendrier scolaire)
|
|
App\Administration\Domain\Model\SchoolCalendar\SchoolCalendarRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Doctrine\DoctrineSchoolCalendarRepository
|
|
|
|
App\Administration\Application\Port\OfficialCalendarProvider:
|
|
alias: App\Administration\Infrastructure\Service\JsonOfficialCalendarProvider
|
|
|
|
App\Administration\Infrastructure\Service\JsonOfficialCalendarProvider:
|
|
arguments:
|
|
$dataDirectory: '%kernel.project_dir%/var/data/calendar'
|
|
|
|
# School Branding (Story 2.13 - Personnalisation visuelle)
|
|
App\Administration\Domain\Model\SchoolBranding\ContrastValidator:
|
|
autowire: true
|
|
|
|
App\Administration\Domain\Repository\SchoolBrandingRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Doctrine\DoctrineSchoolBrandingRepository
|
|
|
|
App\Administration\Application\Port\LogoStorage:
|
|
alias: App\Administration\Infrastructure\Storage\LocalLogoStorage
|
|
|
|
App\Administration\Infrastructure\Storage\LocalLogoStorage:
|
|
arguments:
|
|
$uploadDir: '%kernel.project_dir%/public/uploads'
|
|
$publicPath: '/uploads'
|
|
|
|
App\Administration\Application\Port\ImageProcessor:
|
|
alias: App\Administration\Infrastructure\Storage\ImagickImageProcessor
|
|
|
|
# Import Batch Repository (Story 3.1 - Import élèves via CSV)
|
|
App\Administration\Domain\Repository\ImportBatchRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Doctrine\DoctrineImportBatchRepository
|
|
|
|
# Saved Column Mapping Repository (Story 3.1 - T3.3 Réutilisation des mappings)
|
|
App\Administration\Domain\Repository\SavedColumnMappingRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Doctrine\DoctrineSavedColumnMappingRepository
|
|
|
|
# Teacher Import Batch Repository (Story 3.2 - Import enseignants via CSV)
|
|
App\Administration\Domain\Repository\TeacherImportBatchRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Doctrine\DoctrineTeacherImportBatchRepository
|
|
|
|
# Saved Teacher Column Mapping Repository (Story 3.2 - Réutilisation des mappings enseignants)
|
|
App\Administration\Domain\Repository\SavedTeacherColumnMappingRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Doctrine\DoctrineSavedTeacherColumnMappingRepository
|
|
|
|
# Parent Invitation Repository (Story 3.3 - Invitation parents)
|
|
App\Administration\Domain\Repository\ParentInvitationRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Doctrine\DoctrineParentInvitationRepository
|
|
|
|
# Student Guardian Repository (Story 2.7 - Liaison parents-enfants)
|
|
App\Administration\Infrastructure\Persistence\Cache\CacheStudentGuardianRepository:
|
|
arguments:
|
|
$inner: '@App\Administration\Infrastructure\Persistence\Doctrine\DoctrineStudentGuardianRepository'
|
|
|
|
App\Administration\Domain\Repository\StudentGuardianRepository:
|
|
alias: App\Administration\Infrastructure\Persistence\Cache\CacheStudentGuardianRepository
|
|
|
|
# Paginated Read Model Ports
|
|
App\Administration\Application\Port\PaginatedUsersReader:
|
|
alias: App\Administration\Infrastructure\ReadModel\DbalPaginatedUsersReader
|
|
|
|
App\Administration\Application\Port\PaginatedClassesReader:
|
|
alias: App\Administration\Infrastructure\ReadModel\DbalPaginatedClassesReader
|
|
|
|
App\Administration\Application\Port\PaginatedSubjectsReader:
|
|
alias: App\Administration\Infrastructure\ReadModel\DbalPaginatedSubjectsReader
|
|
|
|
App\Administration\Application\Port\PaginatedAssignmentsReader:
|
|
alias: App\Administration\Infrastructure\ReadModel\DbalPaginatedAssignmentsReader
|
|
|
|
App\Administration\Application\Port\PaginatedParentInvitationsReader:
|
|
alias: App\Administration\Infrastructure\ReadModel\DbalPaginatedParentInvitationsReader
|
|
|
|
App\Administration\Application\Port\PaginatedStudentImageRightsReader:
|
|
alias: App\Administration\Infrastructure\ReadModel\DbalPaginatedStudentImageRightsReader
|
|
|
|
# GradeExistenceChecker (stub until Notes module exists)
|
|
App\Administration\Application\Port\GradeExistenceChecker:
|
|
alias: App\Administration\Infrastructure\Service\NoOpGradeExistenceChecker
|
|
|
|
# ActiveRoleStore (session-scoped cache for active role switching)
|
|
App\Administration\Application\Port\ActiveRoleStore:
|
|
alias: App\Administration\Infrastructure\Service\CacheActiveRoleStore
|
|
|
|
# GeoLocation Service (null implementation - no geolocation)
|
|
App\Administration\Application\Port\GeoLocationService:
|
|
alias: App\Administration\Infrastructure\Service\NullGeoLocationService
|
|
|
|
# Password Reset Processor with rate limiters
|
|
App\Administration\Infrastructure\Api\Processor\RequestPasswordResetProcessor:
|
|
arguments:
|
|
$passwordResetByEmailLimiter: '@limiter.password_reset_by_email'
|
|
$passwordResetByIpLimiter: '@limiter.password_reset_by_ip'
|
|
|
|
# Parent Activation Processor with rate limiter
|
|
App\Administration\Infrastructure\Api\Processor\ActivateParentInvitationProcessor:
|
|
arguments:
|
|
$parentActivationByIpLimiter: '@limiter.parent_activation_by_ip'
|
|
|
|
# Login handlers
|
|
App\Administration\Infrastructure\Security\LoginSuccessHandler:
|
|
tags:
|
|
- { name: kernel.event_listener, event: lexik_jwt_authentication.on_authentication_success, method: onAuthenticationSuccess }
|
|
|
|
App\Administration\Infrastructure\Security\LoginFailureHandler:
|
|
tags:
|
|
- { name: security.authentication_failure_handler, firewall: api_login }
|
|
|
|
# Rate Limiter (délai Fibonacci + CAPTCHA + blocage IP)
|
|
App\Shared\Infrastructure\RateLimit\LoginRateLimiter:
|
|
arguments:
|
|
$cache: '@cache.rate_limiter'
|
|
|
|
App\Shared\Infrastructure\RateLimit\LoginRateLimiterInterface:
|
|
alias: App\Shared\Infrastructure\RateLimit\LoginRateLimiter
|
|
|
|
# Rate Limit Listener (vérifie le rate limit AVANT authentification)
|
|
App\Shared\Infrastructure\RateLimit\LoginRateLimitListener:
|
|
arguments:
|
|
$rateLimiterCache: '@cache.rate_limiter'
|
|
|
|
# Turnstile CAPTCHA Validator
|
|
# failOpen: true en dev (ne pas bloquer si API down), false en prod (sécurité)
|
|
App\Shared\Infrastructure\Captcha\TurnstileValidator:
|
|
arguments:
|
|
$secretKey: '%env(TURNSTILE_SECRET_KEY)%'
|
|
$failOpen: '%env(bool:default::TURNSTILE_FAIL_OPEN)%'
|
|
|
|
App\Shared\Infrastructure\Captcha\TurnstileValidatorInterface:
|
|
alias: App\Shared\Infrastructure\Captcha\TurnstileValidator
|
|
|
|
# =============================================================================
|
|
# Monitoring & Observability (Story 1.8)
|
|
# =============================================================================
|
|
|
|
# Prometheus CollectorRegistry - uses Redis for persistence between requests
|
|
Prometheus\Storage\Redis:
|
|
factory: ['App\Shared\Infrastructure\Monitoring\PrometheusStorageFactory', 'createRedisStorage']
|
|
arguments:
|
|
$redisUrl: '%env(REDIS_URL)%'
|
|
|
|
Prometheus\CollectorRegistry:
|
|
arguments:
|
|
$storageAdapter: '@Prometheus\Storage\Redis'
|
|
|
|
# Sentry/GlitchTip PII scrubber callback
|
|
App\Shared\Infrastructure\Monitoring\SentryBeforeSendCallback: ~
|
|
|
|
# Infrastructure Health Checker - shared service for health checks (DRY)
|
|
App\Shared\Infrastructure\Monitoring\InfrastructureHealthChecker:
|
|
arguments:
|
|
$connection: '@doctrine.dbal.master_connection'
|
|
$redisUrl: '%env(REDIS_URL)%'
|
|
|
|
# Interface alias for InfrastructureHealthChecker (allows testing with stubs)
|
|
App\Shared\Infrastructure\Monitoring\InfrastructureHealthCheckerInterface:
|
|
alias: App\Shared\Infrastructure\Monitoring\InfrastructureHealthChecker
|
|
|
|
# Health Check Controller - uses shared InfrastructureHealthChecker
|
|
App\Shared\Infrastructure\Monitoring\HealthCheckController: ~
|
|
|
|
# Metrics Controller - restricted to internal networks in production
|
|
App\Shared\Infrastructure\Monitoring\MetricsController:
|
|
arguments:
|
|
$appEnv: '%kernel.environment%'
|
|
|
|
# Health Metrics Collector - exposes health_check_status gauge
|
|
App\Shared\Infrastructure\Monitoring\HealthMetricsCollector: ~
|
|
|
|
# Interface alias for HealthMetricsCollector (allows testing with stubs)
|
|
App\Shared\Infrastructure\Monitoring\HealthMetricsCollectorInterface:
|
|
alias: App\Shared\Infrastructure\Monitoring\HealthMetricsCollector
|
|
|
|
# Sentry context enricher - adds tenant/user/correlation_id to error reports
|
|
# Explicitly registered to ensure HubInterface dependency is resolved
|
|
App\Shared\Infrastructure\Monitoring\SentryContextEnricher:
|
|
arguments:
|
|
$sentryHub: '@Sentry\State\HubInterface'
|
|
|
|
# Monolog processors for structured logging
|
|
App\Shared\Infrastructure\Monitoring\CorrelationIdLogProcessor:
|
|
tags:
|
|
- { name: monolog.processor }
|
|
|
|
App\Shared\Infrastructure\Monitoring\PiiScrubberLogProcessor:
|
|
tags:
|
|
- { name: monolog.processor }
|
|
|
|
# =============================================================================
|
|
# Messenger & Async (Story 2.5b)
|
|
# =============================================================================
|
|
|
|
# Fibonacci retry strategy for async transport
|
|
App\Shared\Infrastructure\Messenger\FibonacciRetryStrategy: ~
|
|
|
|
# Dead-letter alert: sends admin email when message exhausts all retries
|
|
App\Shared\Infrastructure\Messenger\DeadLetterAlertHandler:
|
|
arguments:
|
|
$adminEmail: '%env(ADMIN_ALERT_EMAIL)%'
|
|
tags:
|
|
- { name: kernel.event_listener, event: Symfony\Component\Messenger\Event\WorkerMessageFailedEvent }
|
|
|
|
# Messenger metrics middleware (handled/failed counters)
|
|
App\Shared\Infrastructure\Messenger\MessengerMetricsMiddleware: ~
|
|
|
|
# Messenger queue metrics collector (messages waiting gauge)
|
|
App\Shared\Infrastructure\Monitoring\MessengerMetricsCollector: ~
|
|
|
|
# =============================================================================
|
|
# Test environment overrides
|
|
# =============================================================================
|
|
when@test:
|
|
services:
|
|
# Use null rate limiter in test environment to avoid IP blocking during E2E tests
|
|
App\Shared\Infrastructure\RateLimit\LoginRateLimiterInterface:
|
|
alias: App\Shared\Infrastructure\RateLimit\NullLoginRateLimiter
|
|
|
|
App\Shared\Infrastructure\RateLimit\NullLoginRateLimiter:
|
|
autowire: true
|