# Arquitectura: MVVM, SOLID y Clean Architecture en web_mycode

Este documento es la **fuente de verdad** de arquitectura del repo. Los agentes deben leerlo
(**sección [Guía para agentes](#guía-para-agentes-leer-primero)**) antes de implementar cambios.

Resumen ejecutivo en [`AGENTS.md`](../AGENTS.md).

---

## Guía para agentes (leer primero)

### Flujo obligatorio

1. **Leer** esta sección y el [mapa de carpetas actual](#estructura-implementada-hoy).
2. **Ubicar** el cambio en la tabla [¿Dónde va mi cambio?](#dónde-va-mi-cambio).
3. **Implementar** sin violar [Prohibiciones](#prohibiciones).
4. **Validar** antes de cerrar la tarea:

```bash
php artisan architecture:audit --strict
php artisan test
```

Si `architecture:audit --strict` falla, la tarea **no está terminada**.

### Métricas (automáticas)

| Regla | Valor | Comando / archivo |
|-------|-------|-------------------|
| Líneas por archivo (objetivo) | **≤ 150** | `app/Support/Architecture/ArchitectureAuditor.php` |
| Líneas por archivo (duro) | **> 250** → dividir | mismo auditor |
| `panel.blade.php` | **≤ 80** líneas, sin CSS/JS inline | test `ArchitectureComplianceTest` |
| Chunks JS admin | cada `resources/js/admin/*.js` ≤ 150 | auditor incluye `resources/js/admin/` |

### ¿Dónde va mi cambio?

| Si necesitas… | Crear / editar en… |
|---------------|-------------------|
| Nueva página web o acción HTTP | `app/Presentation/Http/Controllers/Web/` + ruta en `routes/web.php` |
| Proxy bridge auth / admin / scan | `app/Presentation/Http/Controllers/Bridge/` + `routes/api.php` |
| Validación payload bridge admin | `app/Application/Bridge/AdminProxyPayloadResolver.php` (o handler nuevo) |
| Llamada HTTP a api.mycode.cl | `app/Infrastructure/Http/` (cliente o repositorio) |
| Caso de uso (orquestación) | `app/Application/{Admin\|Profile\|Bridge\|…}/` |
| Entidad, permiso, registro legal | `app/Domain/` |
| Datos para Blade (URLs, flags) | `app/Presentation/ViewModels/` + factory |
| Panel admin: comportamiento UI | `resources/js/admin/` → recompilar `public/js/admin/app.js` (`npm run production`) |
| Panel admin: estilos | `public/css/admin-panel.css` |
| Panel admin: markup shell | `resources/views/admin/panel.blade.php` + `admin/partials/*` |
| Binding interfaz → impl | `app/Providers/AppServiceProvider.php` |

### Prohibiciones

| Acción | Por qué |
|--------|---------|
| Nuevo controller en `app/Http/Controllers/` | Capa legacy; usar `Presentation/Http/Controllers/` |
| CSS o `<script>` inline en `panel.blade.php` | MVVM: vista delgada |
| Lógica de negocio en Blade | Usar ViewModel + Application |
| `if` encadenados en proxy admin por cada ruta | Usar resolver / handler en `Application/Bridge` |
| `use Illuminate\*` en `app/Domain/` | Domain framework-agnostic |
| Archivo > 150 líneas sin dividir | Falla `architecture:audit` |
| Shims vacíos `@deprecated extends …` | Rutas deben apuntar a la clase real |
| Duplicar autorización del servidor en UI | Fuente de verdad: API (`docs/admin-superadmin.md`) |

### Checklist rápido antes de PR

- [ ] ¿Archivo nuevo en la capa correcta?
- [ ] ¿Cada archivo PHP/Blade/JS admin ≤ 150 líneas?
- [ ] ¿Controller solo valida HTTP y delega?
- [ ] ¿`php artisan architecture:audit --strict` en verde?
- [ ] ¿`php artisan test` en verde?

---

## Contexto del repositorio

`web_mycode` es la capa web pública y el panel admin (`admin.mycode.cl`). No contiene toda la lógica de negocio:
consume **api.mycode.cl** vía bridge (`/api/bridge/*`) y `App\Infrastructure\Http\ApiMyCodeHttpClient`.

| Capa | Rol |
|------|-----|
| `routes/web.php`, `routes/api.php` | Entrada HTTP |
| `app/Presentation/Http/Controllers/*` | Orquestación request → response (delgada) |
| `app/Application/*` | Casos de uso, resolvers, renderers |
| `app/Domain/*` | Entidades, permisos, registros (sin Laravel) |
| `app/Infrastructure/*` | HTTP upstream, repos, cifrado |
| `app/Presentation/ViewModels/*` | Datos para Blade |
| `resources/views/*` | Vistas Blade |
| `resources/js/admin/*` | Lógica panel admin (chunks) |
| `public/js/admin/app.js` | Bundle servido al navegador |
| `tests/Feature/*` | Integración HTTP |

La API Laravel remota (usuarios admin, permisos en servidor) vive en **otro repositorio**. Aquí solo DTOs y reglas de **UI**.

---

## Estado implementado hoy

Migración base **completada** (audit estricto en verde). Pendiente evolutivo: MVVM JS con carpetas `core/`, `viewmodels/`, `views/` (hoy hay chunks numerados).

| Antes (monolito) | Estado | Ubicación actual |
|------------------|--------|------------------|
| `panel.blade.php` 2000+ líneas | ✅ Atomizado | Shell ~28 líneas + partials + CSS/JS externos |
| `ViewController` | ✅ Dividido | `Presentation/Http/Controllers/Web/*` |
| `ApiBridgeController` | ✅ Dividido | `Presentation/Http/Controllers/Bridge/*` + `Application/Bridge/*` |
| `PublicProfileApi` | ✅ Dividido | `Infrastructure/Http/Profile/*` + `Application/Profile/*` |
| `ApiMyCodeHttpClient` en Services | ✅ Movido | `Infrastructure/Http/` (alias deprecated en `Services/`) |
| MVVM JS por pantalla | ⏳ Opcional | Chunks `01-chunk.js`…`11-chunk.js` (funcional, renombrar después) |

**Allowlist legacy restante:** `app/Http/Controllers/ContactController.php` (hasta atomizar contacto).

---

## Objetivo de arquitectura

1. **Reglas de negocio** independientes de Laravel, Blade y `fetch`.
2. **Casos de uso** pequeños y testeables (una acción = una clase clara en `Application`).
3. **UI delgada**: controllers y Blade solo enlazan; panel admin en JS modular.
4. **Clases atómicas**: **≤ 150 líneas** por archivo; **> 250** prohibido (salvo allowlist).

---

## Clean Architecture (capas)

Flujo de dependencias: **Presentation → Application → Domain ← Infrastructure**.

```
┌─────────────────────────────────────────────────────────────┐
│  Presentation                                               │
│  Controllers, Form Requests, Blade, ViewModels, admin JS    │
└───────────────────────────┬─────────────────────────────────┘
                            │ usa
┌───────────────────────────▼─────────────────────────────────┐
│  Application (Use Cases)                                    │
│  ShowPersonProfileHandler, BridgeJsonProxy, ProfilePageRenderer │
└───────────────────────────┬─────────────────────────────────┘
                            │ usa
┌───────────────────────────▼─────────────────────────────────┐
│  Domain                                                     │
│  AdminUser, AdminPermission, LegalDocumentRegistry            │
└───────────────────────────▲─────────────────────────────────┘
                            │ implementa
┌───────────────────────────┴─────────────────────────────────┐
│  Infrastructure                                             │
│  ApiMyCodeHttpClient, PersonProfileRepository, Mail, Turnstile  │
└─────────────────────────────────────────────────────────────┘
```

**Reglas de dependencia:**

- `Domain` → no importa `Illuminate\*`.
- `Application` → solo `Domain` + interfaces propias (`Application/*/Contracts`).
- `Infrastructure` → implementa interfaces y habla con APIs externas.
- `Presentation` → solo handlers, ViewModels y vistas; sin lógica de negocio pesada.

### Estructura implementada hoy

```
app/
├── Domain/
│   ├── Admin/          # AdminPermission, AdminRole, AdminUser
│   └── Legal/          # LegalDocumentRegistry
├── Application/
│   ├── Bridge/         # BridgeJsonProxy, AdminProxyPayloadResolver
│   ├── Profile/        # Handlers, ProfilePageRenderer, decoders
│   └── Shared/         # RandomBackgroundPicker, etc.
├── Infrastructure/
│   └── Http/
│       ├── ApiMyCodeHttpClient.php
│       ├── ApiPayloadEncryption.php
│       └── Profile/    # PersonProfileRepository, PetProfileRepository, …
├── Presentation/
│   ├── Http/Controllers/
│   │   ├── Admin/      # AdminPanelController
│   │   ├── Bridge/     # Auth, Admin, Scan
│   │   └── Web/        # Home, Legal, Profile, Locale, Media
│   └── ViewModels/     # AdminPanelConfigViewModel, Factory
├── Support/Architecture/   # ArchitectureAuditor
└── Http/Controllers/       # SOLO legacy (ContactController); no añadir aquí
```

---

## MVVM en este proyecto

### Backend (Blade + PHP)

| MVVM | Ubicación |
|------|-----------|
| **Model** | `Domain/*`, DTOs en `Application` |
| **View** | `resources/views/*`, `admin/partials/*` |
| **ViewModel** | `Presentation/ViewModels/*` |

```php
// Presentation/Http/Controllers/Admin/AdminPanelController.php
return view('admin.panel', AdminPanelConfigFactory::fromRequest($request)->toViewData());
```

La vista lee `$vm`; no calcula permisos ni URLs.

### Panel admin (JS)

| MVVM | Ubicación actual | Objetivo evolutivo |
|------|------------------|-------------------|
| **Model** | chunks (normalize, storage) | `models/admin-session.js` |
| **ViewModel** | chunks (loadUsers, login…) | `viewmodels/*-viewmodel.js` |
| **View** | chunks (render*, DOM) | `views/*-view.js` |

Blade actual:

```blade
<link rel="stylesheet" href="{{ asset('css/admin-panel.css') }}">
<div id="admin-root" data-api-bridge-url="…" data-permission-catalog='@json($vm->permissionCatalog)'>
<script src="{{ asset('js/admin/app.js') }}" defer></script>
```

Tras editar chunks: `npm run production` (ver `webpack.mix.js`).

---

## SOLID (aplicación práctica)

| Principio | Regla en este repo |
|-----------|-------------------|
| **S** | Un controller por contexto (Legal, Profile, Bridge Auth, …) |
| **O** | Nuevo caso bridge → resolver/handler, no más `if` en proxy |
| **L** | Repos implementan interfaces de `Application/*/Contracts` |
| **I** | Interfaces pequeñas por contexto (no god `ApiClient`) |
| **D** | Handlers dependen de interfaces; bind en `AppServiceProvider` |

---

## Casos de uso (Application)

Referencia permisos admin: [`admin-superadmin.md`](./admin-superadmin.md).

| Caso de uso | Implementación actual / destino |
|-------------|--------------------------------|
| Perfil público persona | `ShowPersonProfileHandler` + `PersonProfileRepository` |
| Perfil público mascota | `ShowPetProfileHandler` + `PetProfileRepository` |
| Proxy JSON bridge | `BridgeJsonProxy` |
| Payload admin proxy | `AdminProxyPayloadResolver` |
| Login / list users admin (futuro) | `Application/Admin/*` handlers dedicados |

Cada handler nuevo: una clase, `handle()` o `__invoke()`, sin `Request` de Laravel dentro.

---

## Testing

| Capa | Ubicación |
|------|-----------|
| Arquitectura | `tests/Feature/ArchitectureComplianceTest.php` |
| Feature HTTP | `tests/Feature/*` |
| Unit (futuro) | `tests/Unit/{Domain,Application,Infrastructure}/` |

---

## Plan de migración — estado

| # | Entrega | Estado |
|---|---------|--------|
| 1 | CSS/JS del panel fuera del Blade | ✅ |
| 2 | feedback-modal + paginated-list en JS | ✅ (en chunks) |
| 3 | ViewModels PHP admin | ✅ |
| 4 | Dividir ViewController | ✅ |
| 5 | Bridge delgado + Application/Bridge | ✅ |
| 6 | Dividir PublicProfileApi | ✅ |
| 7 | MVVM JS (`core/`, `viewmodels/`, `views/`) | ⏳ Opcional |
| — | Atomizar ContactController | ⏳ Allowlist |

---

## Relación con la API remota

`docs/admin-superadmin.md` describe la API en **api.mycode.cl**. Este repo:

- **Sí:** DTOs UI, catálogo `AdminPermission`, qué botón mostrar.
- **No:** autorización definitiva en servidor (sigue en la API).

---

## Referencias internas

| Tema | Archivo |
|------|---------|
| Permisos admin | [`admin-superadmin.md`](./admin-superadmin.md) |
| Rutas bridge | `routes/api.php`, `Presentation/Http/Controllers/Bridge/` |
| Panel admin | `resources/views/admin/panel.blade.php`, `Presentation/Http/Controllers/Admin/AdminPanelController.php` |
| Auditor | `app/Support/Architecture/ArchitectureAuditor.php` |
| Instrucciones agentes | [`AGENTS.md`](../AGENTS.md), `.cursor/rules/architecture.mdc` |

---

## Validación automática

```bash
php artisan architecture:audit          # informe
php artisan architecture:audit --strict # debe pasar antes de merge
php artisan test --filter=ArchitectureComplianceTest
php artisan test                        # suite completa
```

**Estado:** `architecture:audit --strict` y tests de arquitectura en verde. Cualquier cambio que reintroduzca monolitos o capas incorrectas debe corregirse en el mismo PR.

---

## Resumen

| Principio | Práctica |
|-----------|----------|
| **Clean** | `Presentation` → `Application` → `Domain` ← `Infrastructure` |
| **MVVM** | ViewModels PHP; JS admin modular; Blade shell delgado |
| **SOLID** | Controllers/handlers pequeños; interfaces por contexto |
| **Átomos** | ≤ 150 líneas; validado por auditor + CI local |
