refactor: reorganizar openspec y planificacion con spec recaptcha

- renombrar openspec/ a _openspec/ (carpeta auxiliar)
- mover specs de features a changes/
- crear specs base: arquitectura-limpia, estandares-codigo, nomenclatura
- migrar _planificacion/ con design-system y roi-theme-template
- agregar especificacion recaptcha anti-spam (proposal, tasks, spec)
- corregir rutas y referencias en todas las specs

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
FrankZamora
2026-01-08 15:30:45 -06:00
parent 0d6b6db108
commit 0f6387ab46
58 changed files with 15364 additions and 1171 deletions

View File

@@ -0,0 +1,111 @@
# Proposal: reCAPTCHA v3 Anti-Spam Protection
## Problema
Los formularios del sitio (Newsletter Footer y Contact Form) carecen de protección CAPTCHA, haciéndolos vulnerables a spam automatizado. Actualmente solo cuentan con:
- Nonce de WordPress
- Rate limiting básico
- Sanitización de inputs
- Validación de email
## Solución Propuesta
Implementar **Google reCAPTCHA v3** como capa adicional de protección anti-spam.
### Por qué reCAPTCHA v3
| Característica | reCAPTCHA v2 | reCAPTCHA v3 |
|----------------|--------------|--------------|
| UX | Requiere interacción (checkbox/imágenes) | Invisible, sin fricción |
| Detección | Binaria (humano/bot) | Score 0.0-1.0 |
| Flexibilidad | Fija | Configurable por score |
| Impacto en conversión | Negativo | Mínimo |
### Credenciales
```
Site Key: 6LevZUQsAAAAAB6wcQ4iE6ckaTwgVR_ScBL3vqSj
```
> **Nota**: El Secret Key debe almacenarse en wp-config.php o como opción encriptada en BD, NUNCA en código fuente.
## Arquitectura Propuesta
```
Shared/
├── Domain/
│ └── Contracts/
│ └── RecaptchaValidatorInterface.php
├── Application/
│ └── Services/
│ └── RecaptchaValidationService.php
└── Infrastructure/
└── Services/
└── GoogleRecaptchaValidator.php
```
### Flujo de Validación
```
1. Frontend: Usuario envía formulario
2. Frontend: reCAPTCHA genera token automáticamente
3. Backend: AjaxHandler recibe token con datos del form
4. Backend: RecaptchaValidationService valida token con API de Google
5. Backend: Si score < threshold → rechazar como spam
6. Backend: Si score >= threshold → procesar formulario normalmente
```
## Formularios Afectados
1. **Newsletter Footer** (`Public/Footer/Infrastructure/Api/WordPress/NewsletterAjaxHandler.php`)
2. **Contact Form** (`Public/ContactForm/Infrastructure/Api/WordPress/ContactFormAjaxHandler.php`)
## Configuración Administrable
| Campo | Tipo | Default | Descripción |
|-------|------|---------|-------------|
| is_enabled | boolean | true | Habilitar/deshabilitar reCAPTCHA |
| site_key | text | - | Clave pública de reCAPTCHA |
| secret_key | text | - | Clave secreta (encriptada) |
| score_threshold | select | 0.5 | Umbral mínimo (0.3, 0.5, 0.7, 0.9) |
| action_newsletter | text | newsletter_submit | Acción para newsletter |
| action_contact | text | contact_submit | Acción para contacto |
## Impacto
### Archivos a Crear
- `Shared/Domain/Contracts/RecaptchaValidatorInterface.php`
- `Shared/Domain/Entities/RecaptchaResult.php`
- `Shared/Application/Services/RecaptchaValidationService.php`
- `Shared/Infrastructure/Services/GoogleRecaptchaValidator.php`
- `Schemas/recaptcha-settings.json`
- `Admin/RecaptchaSettings/Infrastructure/Ui/RecaptchaSettingsFormBuilder.php`
- `Admin/RecaptchaSettings/Infrastructure/FieldMapping/RecaptchaSettingsFieldMapper.php`
### Archivos a Modificar
- `Public/Footer/Infrastructure/Api/WordPress/NewsletterAjaxHandler.php`
- `Public/ContactForm/Infrastructure/Api/WordPress/ContactFormAjaxHandler.php`
- `Public/Footer/Infrastructure/Ui/FooterRenderer.php` (agregar script reCAPTCHA)
- `Public/ContactForm/Infrastructure/Ui/ContactFormRenderer.php` (agregar script reCAPTCHA)
- `functions.php` (registrar servicios en contenedor DI)
- `Admin/Infrastructure/Ui/AdminDashboardRenderer.php` (registrar tab de reCAPTCHA)
## Riesgos y Mitigaciones
| Riesgo | Probabilidad | Mitigación |
|--------|--------------|------------|
| API Google no disponible | Baja | Fallback: permitir envío (fail-open) |
| Falsos positivos | Media | Score threshold configurable |
| Latencia adicional | Baja | Validación asíncrona, timeout corto |
## Criterios de Aceptación
1. reCAPTCHA v3 integrado en ambos formularios
2. Score threshold configurable desde admin
3. Logging de intentos bloqueados
4. Sin impacto visible en UX del usuario
5. Fallback funcional si API falla
## Última actualización
2025-01-08

View File

@@ -0,0 +1,325 @@
# Especificación: reCAPTCHA v3 Anti-Spam Protection
## Purpose
Define la integración de Google reCAPTCHA v3 para proteger los formularios del sitio (Newsletter y Contact Form) contra spam automatizado, siguiendo Clean Architecture.
## Requirements
### Requirement: Configuración de reCAPTCHA
El sistema DEBE permitir configurar reCAPTCHA v3 desde el panel de administración.
#### Scenario: Schema JSON para configuración
- **WHEN** se crea el schema de configuración
- **THEN** DEBE ubicarse en `Schemas/recaptcha-settings.json`
- **AND** `component_name` DEBE ser `recaptcha-settings`
- **AND** DEBE incluir grupo VISIBILITY con `is_enabled`
- **AND** DEBE incluir grupo BEHAVIOR con `site_key`, `secret_key`, `score_threshold`
#### Scenario: Campos obligatorios del schema
- **GIVEN** el schema `recaptcha-settings.json`
- **WHEN** se define la estructura
- **THEN** `is_enabled` DEBE ser tipo boolean con default true
- **AND** `site_key` DEBE ser tipo text (clave pública)
- **AND** `secret_key` DEBE ser tipo text (clave secreta, almacenada encriptada)
- **AND** `score_threshold` DEBE ser tipo select con options: 0.3, 0.5, 0.7, 0.9
#### Scenario: Sincronización con BD
- **WHEN** se sincroniza el schema
- **THEN** ejecutar `wp roi-theme sync-component recaptcha-settings`
- **AND** los datos DEBEN ir a `wp_roi_theme_component_settings`
- **AND** `component_name` en BD DEBE ser `recaptcha-settings`
---
### Requirement: Contrato de Validación (Domain)
El Domain DEBE definir la interfaz de validación de reCAPTCHA.
#### Scenario: Ubicación de RecaptchaValidatorInterface
- **WHEN** se crea la interfaz
- **THEN** DEBE ubicarse en `Shared/Domain/Contracts/RecaptchaValidatorInterface.php`
- **AND** namespace DEBE ser `ROITheme\Shared\Domain\Contracts`
#### Scenario: Firma del método validate
- **WHEN** se define RecaptchaValidatorInterface
- **THEN** DEBE tener método `validate(string $token, string $action): RecaptchaResult`
- **AND** `$token` es el token generado por reCAPTCHA frontend
- **AND** `$action` es el nombre de la acción (newsletter_submit, contact_submit)
- **AND** retorna objeto `RecaptchaResult` con score y success
#### Scenario: Entidad RecaptchaResult
- **WHEN** se define el resultado de validación
- **THEN** DEBE existir `Shared/Domain/Entities/RecaptchaResult.php`
- **AND** DEBE tener propiedades: `success` (bool), `score` (float), `action` (string), `errorCodes` (array)
- **AND** DEBE tener método `isValid(float $threshold): bool`
---
### Requirement: Servicio de Aplicación
La capa Application DEBE orquestar la validación de reCAPTCHA.
#### Scenario: Ubicación del servicio
- **WHEN** se crea el servicio de aplicación
- **THEN** DEBE ubicarse en `Shared/Application/Services/RecaptchaValidationService.php`
- **AND** namespace DEBE ser `ROITheme\Shared\Application\Services`
#### Scenario: Inyección de dependencias
- **WHEN** se implementa RecaptchaValidationService
- **THEN** DEBE inyectar `RecaptchaValidatorInterface` via constructor
- **AND** DEBE inyectar `ComponentSettingsRepositoryInterface` para obtener configuración
- **AND** NO DEBE instanciar servicios directamente con `new`
#### Scenario: Lógica de validación con threshold
- **GIVEN** un token de reCAPTCHA y una acción
- **WHEN** se llama a `validateSubmission(string $token, string $action): bool`
- **THEN** DEBE obtener `score_threshold` de la configuración en BD
- **AND** DEBE llamar a `RecaptchaValidatorInterface::validate()`
- **AND** DEBE retornar `true` si `RecaptchaResult::isValid($threshold)` es true
- **AND** DEBE retornar `false` si score está por debajo del threshold
#### Scenario: Bypass cuando está deshabilitado
- **GIVEN** `is_enabled` es false en configuración
- **WHEN** se llama a `validateSubmission()`
- **THEN** DEBE retornar `true` sin llamar a la API de Google
- **AND** NO DEBE generar errores
---
### Requirement: Implementación de Infraestructura
La capa Infrastructure DEBE implementar la comunicación con API de Google.
#### Scenario: Ubicación del validador
- **WHEN** se implementa el validador
- **THEN** DEBE ubicarse en `Shared/Infrastructure/Services/GoogleRecaptchaValidator.php`
- **AND** namespace DEBE ser `ROITheme\Shared\Infrastructure\Services`
- **AND** DEBE implementar `RecaptchaValidatorInterface`
#### Scenario: Llamada a API de Google
- **WHEN** se valida un token
- **THEN** DEBE hacer POST a `https://www.google.com/recaptcha/api/siteverify`
- **AND** DEBE enviar `secret` (secret key) y `response` (token)
- **AND** DEBE usar `wp_remote_post()` de WordPress
- **AND** timeout DEBE ser máximo 5 segundos
#### Scenario: Parseo de respuesta exitosa
- **GIVEN** API de Google responde exitosamente
- **WHEN** se parsea la respuesta
- **THEN** DEBE extraer `success` (bool)
- **AND** DEBE extraer `score` (float 0.0-1.0)
- **AND** DEBE extraer `action` (string)
- **AND** DEBE retornar `RecaptchaResult` con estos valores
#### Scenario: Manejo de errores de API
- **GIVEN** API de Google no responde o responde con error
- **WHEN** se procesa la respuesta
- **THEN** DEBE retornar `RecaptchaResult` con `success = false`
- **AND** DEBE incluir códigos de error en `errorCodes`
- **AND** NO DEBE lanzar excepciones no controladas
---
### Requirement: Integración Frontend
Los Renderers DEBEN incluir el script de reCAPTCHA y generar tokens.
#### Scenario: Script de reCAPTCHA en FooterRenderer
- **WHEN** FooterRenderer genera HTML del newsletter
- **AND** reCAPTCHA está habilitado
- **THEN** DEBE incluir script: `<script src="https://www.google.com/recaptcha/api.js?render={site_key}"></script>`
- **AND** DEBE agregar input hidden `recaptcha_token` al formulario
- **AND** DEBE agregar JS para ejecutar `grecaptcha.execute()` al submit
#### Scenario: Script de reCAPTCHA en ContactFormRenderer
- **WHEN** ContactFormRenderer genera HTML del formulario
- **AND** reCAPTCHA está habilitado
- **THEN** DEBE incluir script de reCAPTCHA con site_key
- **AND** DEBE agregar input hidden `recaptcha_token`
- **AND** DEBE agregar JS para ejecutar `grecaptcha.execute()` al submit
#### Scenario: JavaScript de ejecución de reCAPTCHA
- **WHEN** usuario hace submit del formulario
- **THEN** JS DEBE interceptar el submit
- **AND** DEBE llamar `grecaptcha.execute(siteKey, {action: 'action_name'})`
- **AND** DEBE esperar el token (Promise)
- **AND** DEBE insertar token en input hidden
- **AND** DEBE continuar con el submit del formulario
#### Scenario: No cargar script si está deshabilitado
- **GIVEN** reCAPTCHA `is_enabled` es false
- **WHEN** se renderiza el formulario
- **THEN** NO DEBE incluir script de reCAPTCHA
- **AND** NO DEBE agregar input hidden de token
- **AND** formulario DEBE funcionar normalmente
---
### Requirement: Integración Backend (AjaxHandlers)
Los AjaxHandlers DEBEN validar el token de reCAPTCHA antes de procesar.
#### Scenario: Validación en NewsletterAjaxHandler
- **WHEN** se procesa suscripción de newsletter
- **AND** reCAPTCHA está habilitado
- **THEN** DEBE obtener `recaptcha_token` del POST
- **AND** DEBE llamar a `RecaptchaValidationService::validateSubmission()`
- **AND** si retorna false, DEBE responder con error JSON
- **AND** si retorna true, DEBE continuar procesamiento normal
#### Scenario: Validación en ContactFormAjaxHandler
- **WHEN** se procesa envío de formulario de contacto
- **AND** reCAPTCHA está habilitado
- **THEN** DEBE obtener `recaptcha_token` del POST
- **AND** DEBE llamar a `RecaptchaValidationService::validateSubmission()`
- **AND** si retorna false, DEBE responder con error JSON
- **AND** si retorna true, DEBE continuar procesamiento normal
#### Scenario: Mensaje de error por reCAPTCHA fallido
- **GIVEN** validación de reCAPTCHA falla
- **WHEN** AjaxHandler responde
- **THEN** DEBE retornar JSON con `success: false`
- **AND** mensaje DEBE ser genérico: "No se pudo verificar que eres humano. Intenta de nuevo."
- **AND** NO DEBE revelar detalles técnicos del score
#### Scenario: Inyección de dependencias en AjaxHandlers
- **WHEN** se modifican los AjaxHandlers
- **THEN** DEBEN inyectar `RecaptchaValidationService` via constructor
- **AND** NO DEBE instanciar servicios directamente
- **AND** DEBE seguir principio de Inversión de Dependencias
---
### Requirement: Panel de Administración
DEBE existir un FormBuilder para configurar reCAPTCHA.
#### Scenario: Ubicación del FormBuilder
- **WHEN** se crea el FormBuilder
- **THEN** DEBE ubicarse en `Admin/RecaptchaSettings/Infrastructure/Ui/RecaptchaSettingsFormBuilder.php`
- **AND** namespace DEBE ser `ROITheme\Admin\RecaptchaSettings\Infrastructure\Ui`
#### Scenario: Registro en getComponents
- **WHEN** se registra el FormBuilder
- **THEN** DEBE registrarse en `getComponents()` con ID `recaptcha-settings`
- **AND** DEBE aparecer en el menú del admin dashboard
#### Scenario: Campos del formulario admin
- **WHEN** se renderiza el formulario de configuración
- **THEN** DEBE mostrar toggle para `is_enabled`
- **AND** DEBE mostrar input text para `site_key`
- **AND** DEBE mostrar input password para `secret_key`
- **AND** DEBE mostrar select para `score_threshold` con opciones 0.3, 0.5, 0.7, 0.9
- **AND** DEBE seguir Design System: gradiente #0E2337#1e3a5f, borde #FF8600
#### Scenario: FieldMapper para mapeo de campos
- **WHEN** se crea el componente admin
- **THEN** DEBE existir `Admin/RecaptchaSettings/Infrastructure/FieldMapping/RecaptchaSettingsFieldMapper.php`
- **AND** DEBE implementar `FieldMapperInterface`
- **AND** DEBE registrarse en `FieldMapperRegistry`
---
### Requirement: Seguridad
La implementación DEBE seguir mejores prácticas de seguridad.
#### Scenario: Almacenamiento de secret key
- **WHEN** se guarda el secret key
- **THEN** DEBE almacenarse encriptado en BD
- **AND** NO DEBE aparecer en código fuente
- **AND** NO DEBE exponerse en frontend
#### Scenario: Site key en frontend
- **GIVEN** site key es público por diseño de Google
- **WHEN** se incluye en frontend
- **THEN** PUEDE incluirse en atributo de script
- **AND** DEBE obtenerse de configuración en BD
#### Scenario: Validación de token en backend
- **WHEN** se recibe token de reCAPTCHA
- **THEN** DEBE sanitizarse con `sanitize_text_field()`
- **AND** DEBE validarse que no esté vacío
- **AND** DEBE enviarse a API de Google para verificación real
#### Scenario: No confiar solo en frontend
- **GIVEN** tokens pueden ser fabricados
- **WHEN** se valida reCAPTCHA
- **THEN** SIEMPRE DEBE verificarse con API de Google en backend
- **AND** NUNCA confiar en validación solo de frontend
---
### Requirement: Logging y Monitoreo
El sistema DEBE registrar intentos de spam bloqueados.
#### Scenario: Log de intentos bloqueados
- **WHEN** reCAPTCHA bloquea un intento
- **THEN** DEBE registrar en log de WordPress
- **AND** DEBE incluir: timestamp, IP, action, score obtenido, threshold configurado
- **AND** NO DEBE incluir datos personales del usuario
#### Scenario: Log de errores de API
- **WHEN** API de Google falla
- **THEN** DEBE registrar error en log
- **AND** DEBE incluir código de error y mensaje
- **AND** DEBE permitir diagnóstico del problema
---
### Requirement: Fallback y Resiliencia
El sistema DEBE manejar fallos graciosamente.
#### Scenario: Fail-open cuando API no responde
- **GIVEN** API de Google no responde (timeout)
- **WHEN** se intenta validar
- **THEN** DEBE permitir el envío del formulario (fail-open)
- **AND** DEBE registrar el evento en log
- **AND** NO DEBE bloquear usuarios legítimos por falla de terceros
#### Scenario: Degradación cuando reCAPTCHA deshabilitado
- **GIVEN** administrador deshabilita reCAPTCHA
- **WHEN** se envía formulario
- **THEN** DEBE procesarse normalmente
- **AND** validaciones existentes (nonce, rate limit) DEBEN seguir activas
- **AND** NO DEBE generar errores por ausencia de token
---
## Checklist de Implementación
### Archivos a Crear
- [ ] `Schemas/recaptcha-settings.json`
- [ ] `Shared/Domain/Contracts/RecaptchaValidatorInterface.php`
- [ ] `Shared/Domain/Entities/RecaptchaResult.php`
- [ ] `Shared/Application/Services/RecaptchaValidationService.php`
- [ ] `Shared/Infrastructure/Services/GoogleRecaptchaValidator.php`
- [ ] `Admin/RecaptchaSettings/Infrastructure/Ui/RecaptchaSettingsFormBuilder.php`
- [ ] `Admin/RecaptchaSettings/Infrastructure/FieldMapping/RecaptchaSettingsFieldMapper.php`
### Archivos a Modificar
- [ ] `Public/Footer/Infrastructure/Ui/FooterRenderer.php`
- [ ] `Public/Footer/Infrastructure/Api/WordPress/NewsletterAjaxHandler.php`
- [ ] `Public/ContactForm/Infrastructure/Ui/ContactFormRenderer.php`
- [ ] `Public/ContactForm/Infrastructure/Api/WordPress/ContactFormAjaxHandler.php`
- [ ] `functions.php` (registro DI)
- [ ] `Admin/Infrastructure/Ui/AdminDashboardRenderer.php` (registrar componente)
- [ ] `Admin/Shared/Infrastructure/FieldMapping/FieldMapperRegistry.php`
### Validaciones
- [ ] Schema tiene campos de visibilidad
- [ ] Domain no tiene dependencias de Infrastructure
- [ ] Application solo depende de interfaces de Domain
- [ ] Todos los servicios inyectados via constructor
- [ ] CSS generado via CSSGeneratorService (si aplica)
- [ ] Secret key nunca expuesto en frontend
---
## Última actualización
2025-01-08

View File

@@ -0,0 +1,132 @@
# Tasks: reCAPTCHA v3 Anti-Spam Protection
## Fase 1: Especificación
- [x] Crear proposal.md
- [x] Crear tasks.md
- [x] Crear spec.md con formato Gherkin
- [ ] Obtener aprobación del usuario
## Fase 2: Implementación
### 2.1 Capa Domain (Contratos y Entidades)
- [ ] Crear `Shared/Domain/Contracts/RecaptchaValidatorInterface.php`
```php
interface RecaptchaValidatorInterface {
public function validate(string $token, string $action): RecaptchaResult;
}
```
- [ ] Crear `Shared/Domain/Entities/RecaptchaResult.php`
```php
final class RecaptchaResult {
public function __construct(
private bool $success,
private float $score,
private string $action,
private array $errorCodes = []
) {}
public function isValid(float $threshold): bool;
}
```
### 2.2 Capa Application (Servicios)
- [ ] Crear `Shared/Application/Services/RecaptchaValidationService.php`
- Orquestar validación
- Aplicar threshold configurable
- Logging de resultados
### 2.3 Capa Infrastructure (Implementación)
- [ ] Crear `Shared/Infrastructure/Services/GoogleRecaptchaValidator.php`
- Llamada HTTP a API de Google
- Manejo de errores y timeout
- Parseo de respuesta JSON
### 2.4 Schema y Admin UI
- [ ] Crear `Schemas/recaptcha-settings.json`
- Campos: is_enabled, site_key, secret_key, score_threshold, actions
- [ ] Sincronizar schema con BD: `wp roi-theme sync-component recaptcha-settings`
- [ ] Crear `Admin/RecaptchaSettings/Infrastructure/Ui/RecaptchaSettingsFormBuilder.php`
- [ ] Crear `Admin/RecaptchaSettings/Infrastructure/FieldMapping/RecaptchaSettingsFieldMapper.php`
- [ ] Registrar en `getComponents()` del AdminDashboardRenderer
- [ ] Registrar FieldMapper en FieldMapperRegistry
### 2.5 Integración Frontend
- [ ] Modificar `FooterRenderer.php`
- Agregar script de reCAPTCHA con site key
- Modificar form para incluir token hidden
- [ ] Modificar `ContactFormRenderer.php`
- Agregar script de reCAPTCHA con site key
- Modificar form para incluir token hidden
- [ ] Crear JS compartido para ejecutar reCAPTCHA y obtener token
### 2.6 Integración Backend
- [ ] Modificar `NewsletterAjaxHandler.php`
- Inyectar RecaptchaValidationService
- Validar token antes de procesar
- Retornar error si score bajo
- [ ] Modificar `ContactFormAjaxHandler.php`
- Inyectar RecaptchaValidationService
- Validar token antes de procesar
- Retornar error si score bajo
### 2.7 Registro DI
- [ ] Modificar `functions.php`
- Registrar RecaptchaValidatorInterface → GoogleRecaptchaValidator
- Registrar RecaptchaValidationService
## Fase 3: Integración y Validación
### 3.1 Testing Manual
- [ ] Probar Newsletter con reCAPTCHA habilitado
- [ ] Probar Contact Form con reCAPTCHA habilitado
- [ ] Probar con reCAPTCHA deshabilitado (fallback)
- [ ] Probar cambio de threshold desde admin
- [ ] Verificar logging de intentos
### 3.2 Validación de Arquitectura
- [ ] Ejecutar `validate-architecture.php recaptcha-settings`
- [ ] Verificar cumplimiento Clean Architecture
- [ ] Verificar inyección de dependencias correcta
### 3.3 Documentación
- [ ] Actualizar CLAUDE.md si es necesario
- [ ] Documentar configuración en admin
## Dependencias
| Tarea | Depende de |
|-------|------------|
| Application Service | Domain Contract |
| Infrastructure Service | Domain Contract |
| Admin FormBuilder | Schema JSON sincronizado |
| Frontend integration | Site Key configurado |
| Backend integration | Application Service + Infrastructure |
## Estimación de Archivos
| Tipo | Cantidad |
|------|----------|
| Nuevos | 7 |
| Modificados | 7 |
| Total | 14 |
### Archivos Nuevos
1. `Shared/Domain/Contracts/RecaptchaValidatorInterface.php`
2. `Shared/Domain/Entities/RecaptchaResult.php`
3. `Shared/Application/Services/RecaptchaValidationService.php`
4. `Shared/Infrastructure/Services/GoogleRecaptchaValidator.php`
5. `Schemas/recaptcha-settings.json`
6. `Admin/RecaptchaSettings/Infrastructure/Ui/RecaptchaSettingsFormBuilder.php`
7. `Admin/RecaptchaSettings/Infrastructure/FieldMapping/RecaptchaSettingsFieldMapper.php`
### Archivos a Modificar
1. `Public/Footer/Infrastructure/Api/WordPress/NewsletterAjaxHandler.php`
2. `Public/ContactForm/Infrastructure/Api/WordPress/ContactFormAjaxHandler.php`
3. `Public/Footer/Infrastructure/Ui/FooterRenderer.php`
4. `Public/ContactForm/Infrastructure/Ui/ContactFormRenderer.php`
5. `functions.php`
6. `Admin/Infrastructure/Ui/AdminDashboardRenderer.php`
7. `Admin/Shared/Infrastructure/FieldMapping/FieldMapperRegistry.php`
## Última actualización
2025-01-08