Actualiza toolkit operativo y documentación

This commit is contained in:
urieljareth
2026-09-10 20:53:50 -06:00
parent 3b7209dcc1
commit 714057bfc8
69 changed files with 6023 additions and 384 deletions
+164 -99
View File
@@ -1,128 +1,193 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Guía para Claude Code (claude.ai/code) al trabajar en este repositorio.
## What this repo is
## Antes de invocar cualquier herramienta
This is **not an application codebase**. It is an operations toolkit: PowerShell
wrapper scripts plus context/runbook documentation that let an agent diagnose and
manage a single local Proxmox host (`192.168.0.200`, node `thinkcentre`) and the
self-hosted Coolify stack running inside its LXC `102`. There is no build, lint,
or test step — the "commands" are the operational scripts in `scripts/` and
`coolify_skill/scripts/`.
1. Carga los secretos: `. .\.env.local.ps1` (gitignored). Sin esto, todas las
llamadas a API lanzan excepción.
2. Lee **[docs/TOOL-INDEX.md](docs/TOOL-INDEX.md)** — es el catálogo canónico de
todo lo ejecutable: firma real de cada script, variables de entorno que
requiere, y si es solo-lectura o mutante. **Su §1 lista seis gotchas que
producen resultados silenciosamente incorrectos.** No los adivines.
3. Para el estado actual del sistema (qué existe, qué versión corre):
[docs/proxmox-inventory.md](docs/proxmox-inventory.md).
User-facing docs are in Spanish; scripts and skill files are in English.
Los seis gotchas, en una línea cada uno (detalle en el índice):
## Core architecture
- **`-Raw` está invertido entre wrappers.** En Coolify y Cloudflare, sin `-Raw`
recibes un *string*, no objetos: filtrar da vacío sin error.
- **`Invoke-ProxmoxSsh.ps1` corrompe comillas anidadas.** Para comandos con más
de un nivel de comillas, codifica en base64.
- **Los nombres de contenedor llevan sufijo uuid y cambian en cada redeploy.**
Resuélvelos siempre; nunca los escribas a mano.
- **`/applications/*` de la API de Coolify da 404 por el hostname público
(Cloudflare), no por Coolify.** Contra el origen
(`http://192.168.0.117:8000/api/v1`, `$env:COOLIFY_API_URL_ORIGIN`) la API
completa responde; y desde v4.2 los endpoints de estado exigen POST.
- **"Verde en Coolify" no es "enrutado en Traefik".** La UI mira `running`;
Traefik exige `healthy`. Un servicio nuevo aún arrancando da `503 no available
server` sin que nada esté mal configurado.
- **Un `502` casi siempre es el puerto.** Coolify saca el puerto de Traefik del
`:puerto` del FQDN guardado; sin él cae al `EXPOSE` de la imagen. Si no
coinciden, `connection refused`.
**Everything reaches the host through one SSH path.** There is no direct Docker or
local network access. The layering is:
## Qué es este repo
**No es el código de una aplicación.** Es un toolkit de operaciones: wrappers de
PowerShell más documentación de contexto y runbooks que permiten a un agente
diagnosticar y administrar un homelab — un host Proxmox local (`192.168.0.200`,
nodo `thinkcentre`) y el stack Coolify que corre dentro de su LXC `102`. No hay
build, lint ni tests: los "comandos" son los scripts operativos.
**Convención de idioma:** la documentación (`docs/`, `README.md`, este archivo)
está en español. Los scripts y los `SKILL.md`/`TOOLS.md` de cada skill están en
inglés.
## Router de intención → herramienta
Lo que pide el usuario, y con qué se resuelve. Para la firma completa de cada
script, ve al [índice](docs/TOOL-INDEX.md).
| El usuario pide… | Usa |
|---|---|
| "¿está bien el servidor?", "revisa el Proxmox" | `.\scripts\Test-ProxmoxConnection.ps1` y luego `.\scripts\Get-ProxmoxInventory.ps1` |
| "inventario de LXC/VMs", "qué hay corriendo" | `.\scripts\Get-ProxmoxInventory.ps1` |
| "¿está corriendo X?", "estado de los contenedores" | `.\coolify_skill\scripts\Get-CoolifyDockerStatus.ps1 -Filter <regex>` |
| "logs de X" | `.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker logs <nombre-resuelto> --tail 100"` |
| "qué apps hay en Coolify", "dame el uuid de X" | `.\coolify_skill\scripts\Invoke-CoolifyApi.ps1 -Path "/resources" -Raw` |
| cualquier cosa de la API de Coolify | `.\coolify_skill\scripts\Invoke-CoolifyApi.ps1` — pero revisa primero qué endpoints viven (§1.4 del índice) |
| "¿está online el sitio X?" | `.\deploy_skill\scripts\Test-ServiceOnline.ps1 -Fqdn https://x.urieljareth.org` |
| "el servicio nuevo está en verde pero da 503 / `no available server`" | `.\coolify_skill\scripts\Test-CoolifyServiceReady.ps1 -Uuid <uuid> -WaitSeconds 600` — **espera, no redeployes**; ver §1.5 del índice |
| "arregla el túnel de Cloudflare", rutas/DNS | `.\scripts\Invoke-CloudflareApi.ps1` + [docs/runbooks/cloudflare-tunnel.md](docs/runbooks/cloudflare-tunnel.md) |
| "Chatwoot perdió el enterprise" | diagnostica con `.\scripts\Get-ChatwootLicenseStatus.ps1 -Deep`; repara con `Apply-ChatwootEnterprisePatch.ps1 -ReenableAccountFeatures` |
| "que arranque solo tras un apagón" | `.\scripts\Install-CoolifyAutostart.ps1 -VerifyOnly` primero |
| "publica este proyecto en Coolify" | **lee §4 del índice antes**. Stack compose → `New-CoolifyService.ps1` (arreglado y verificado el 2026-08-24); app git → flujo UI con Playwright |
| "una app de Coolify sigue el `main` de upstream y se rompió" | [docs/casos/firecrawl-stack-minimo.md](docs/casos/firecrawl-stack-minimo.md) — cambiar a imágenes precompiladas y compose propio |
| "valida que este proyecto se puede deployar" | `.\deploy_skill\scripts\Test-PreDeployChecklist.ps1 -Path <ruta> -Strict` |
| "estoy construyendo una app para este Coolify" | [docs/AGENTS-coolify-apps.md](docs/AGENTS-coolify-apps.md) (contrato de red, puertos, dominios, volúmenes) |
| "crea/lista un repo en Gitea", "sube esto a Gitea" | `.\gitea_skill\scripts\` — ver §5 del índice |
| "diagnosticar/iniciar Hermes (LXC 100)", "MiniMax-M3" | `.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct status 100"` + [docs/casos/hermes-minimax-m3-setup.md](docs/casos/hermes-minimax-m3-setup.md) |
| "un contenedor no conecta a su base de datos" | ver "Gotcha de red Docker" abajo |
## Arquitectura
**Todo llega al host por un único camino SSH.** No hay acceso directo a Docker ni
a la red interna:
```
PowerShell script → Invoke-ProxmoxSshCommand (scripts/ProxmoxAgent.ps1)
script PowerShell → Invoke-ProxmoxSshCommand (scripts/ProxmoxAgent.ps1)
→ ssh [email protected]
→ pct exec 102 -- docker ... (for any Docker/Coolify container work)
→ pct exec 102 -- docker ... (cualquier trabajo de Docker/Coolify)
```
- [scripts/ProxmoxAgent.ps1](scripts/ProxmoxAgent.ps1) is the shared library. **Dot-source it** (`. .\scripts\ProxmoxAgent.ps1`) to get `Get-ProxmoxConfig`, `Invoke-ProxmoxSshCommand`, and `Invoke-ProxmoxApi`. Every other script dot-sources it rather than reimplementing connection logic.
- **Config resolution:** `Get-ProxmoxConfig` reads env vars (`PROXMOX_HOST`, `PROXMOX_NODE`, `PROXMOX_SSH_KEY`, `PROXMOX_COOLIFY_LXC`, etc.) and falls back to hardcoded local defaults. SSH works with defaults alone; **API calls require `PROXMOX_API_TOKEN_ID` + `PROXMOX_API_TOKEN_SECRET`** (otherwise `Invoke-ProxmoxApi` throws). The Coolify LXC ID (`102`) comes from config — don't hardcode it in new scripts; use `$config.CoolifyLxc`.
- Two independent APIs: the **Proxmox REST API** (via `curl.exe -k`, PVE token header) and the **Coolify API** (via `Invoke-RestMethod`, Bearer token, base `https://coolify.urieljareth.org/api/v1`). They use different scripts and different env vars.
- Docker is **not** managed on the Proxmox host directly — it lives inside LXC `102`. Any container command must be wrapped as `pct exec 102 -- docker ...`.
- **The deploy pipeline** ([deploy_skill/](deploy_skill/)) is the end-to-end path from "local project" to "live on `*.urieljareth.org`": scaffold compliant Dockerfile/compose → pre-deploy checklist → create GitHub repo → push → register + deploy via Coolify API → verify. It also covers rollback. Requires `GITHUB_TOKEN` + `COOLIFY_TOKEN` in `.env.local.ps1`; `git push` uses Windows Credential Manager (`wincred`), verified for the `urieljarethbusiness-cpu` GitHub account. See [deploy_skill/SKILL.md](deploy_skill/SKILL.md) and [docs/AGENTS-coolify-apps.md](docs/AGENTS-coolify-apps.md).
- [scripts/ProxmoxAgent.ps1](scripts/ProxmoxAgent.ps1) es la librería compartida.
**Hazle dot-source** (`. .\scripts\ProxmoxAgent.ps1`) para obtener
`Get-ProxmoxConfig`, `Invoke-ProxmoxSshCommand` e `Invoke-ProxmoxApi`. Todos los
demás scripts la consumen en lugar de reimplementar la conexión.
- **Resolución de configuración:** `Get-ProxmoxConfig` lee variables de entorno
(`PROXMOX_HOST`, `PROXMOX_NODE`, `PROXMOX_SSH_KEY`, `PROXMOX_COOLIFY_LXC`…) y
cae a los defaults locales hardcodeados. SSH funciona solo con los defaults;
**las llamadas a la API exigen `PROXMOX_API_TOKEN_ID` +
`PROXMOX_API_TOKEN_SECRET`** (si faltan, `Invoke-ProxmoxApi` lanza). El ID del
LXC de Coolify (`102`) viene de la config: usa `$config.CoolifyLxc`, no lo
hardcodees en scripts nuevos.
- **Cuatro APIs independientes**, con scripts y variables distintas: Proxmox REST
(`curl.exe -k`, header de token PVE), Coolify (`Invoke-RestMethod`, Bearer,
base `https://coolify.urieljareth.org/api/v1`), Cloudflare y Gitea.
- Docker **no** se administra en el host Proxmox: vive dentro del LXC `102`.
Todo comando de contenedor va envuelto en `pct exec 102 -- docker ...`.
## Common commands
## Gotcha de red Docker
Run from the project root in PowerShell.
Cuando una app de Coolify y su base de datos son contenedores hermanos en la
misma red Docker, la app debe alcanzar la DB **por su nombre de servicio Docker,
no por `localhost`** (Nextcloud, por ejemplo, usa el host `nextcloud-db`). El DNS
entre servicios es la causa raíz habitual de los fallos de "conexión a la base de
datos" aquí. Compruébalo con:
```powershell
# Load private secrets (gitignored) — needed for any API call
. .\.env.local.ps1
# Smoke test: config + SSH read + Docker sample + API auth (exits 1 on any FAIL)
.\scripts\Test-ProxmoxConnection.ps1
# Full inventory snapshot (host, LXC, QEMU, Docker in LXC 102)
.\scripts\Get-ProxmoxInventory.ps1
# Arbitrary read-only SSH command
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct list"
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker ps -a"
# Proxmox REST API (after env token loaded)
. .\scripts\ProxmoxAgent.ps1
Invoke-ProxmoxApi -Path "/version"
# Coolify container status through LXC 102
.\coolify_skill\scripts\Get-CoolifyDockerStatus.ps1 -All
# Coolify API (requires COOLIFY_TOKEN)
.\coolify_skill\scripts\Invoke-CoolifyApi.ps1 -Path "/projects"
.\coolify_skill\scripts\Invoke-CoolifyApi.ps1 -Method POST -Path "/projects" -BodyJson $body
# Cloudflare API (requires CLOUDFLARE_API_TOKEN) — full tunnel/DNS control
.\scripts\Invoke-CloudflareApi.ps1 -Path "/user/tokens/verify"
# Gitea API (requires GITEA_URL + GITEA_TOKEN) — self-hosted git hosting
.\gitea_skill\scripts\Test-GiteaConnection.ps1
.\gitea_skill\scripts\Get-GiteaRepo.ps1 -List
.\gitea_skill\scripts\Invoke-GiteaApi.ps1 -Path "/user"
.\gitea_skill\scripts\Sync-GiteaRemote.ps1 -AppPath .\my-app -CreateIfMissing -Force
.\scripts\Invoke-ProxmoxSsh.ps1 -Command "pct exec 102 -- docker exec <app> getent hosts <nombre-servicio>"
```
For the Coolify API reference: don't read the whole tree. Search
`coolify_skill/references/` with `rg`, then open the single matching
`references/ops/*.md` operation file.
## Reglas de operación (las imponen las skills — cúmplelas)
## Deploying a new project to Coolify
- **Solo-lectura primero.** El default es diagnosticar: list, status, logs,
inspect, health checks.
- **Confirma antes de cualquier cambio de estado.** Pregunta explícitamente antes
de: `pct`/`qm` start/stop/reboot/destroy; `docker` restart/stop/rm/compose
up-down; deploys de Coolify o cualquier `POST`/`PUT`/`PATCH`/`DELETE`; escritura
de variables de entorno; y todo cambio de firewall, red, storage, volumen,
clave o token. Para acciones riesgosas: captura el estado actual y enuncia
primero el camino de rollback.
- **Nunca escribas secretos en el repo.** Ni tokens, passwords, claves privadas,
cookies o secretos de token PVE — no en Markdown, no en scripts, no en logs.
Viven solo en `.env.local.ps1` (gitignored) o en el almacén del SO. `.gitignore`
bloquea además `ACCESS.md`, `*.key`, `*.pem`, `*.crt`. Al depurar bases de
datos, verifica conectividad sin imprimir credenciales.
- **Prefiere los scripts del repo** antes que cadenas de comandos manuales
largas, y no ejecutes comandos destructivos amplios construidos desde strings
generados.
End-to-end pipeline (scaffold → checklist → GitHub repo → push → Coolify app +
deploy → verify). Requires `GITHUB_TOKEN` and `COOLIFY_TOKEN` in
`.env.local.ps1`. `git push` uses Windows Credential Manager, not the PAT.
## Chatwoot: el parche enterprise se degrada solo — pero un guard lo auto-repara
```powershell
. .\.env.local.ps1
El parche no se pierde al actualizar. `Internal::CheckNewVersionsJob` hace ping
diario a `hub.2.chatwoot.com` (a los `MD5(INSTALLATION_IDENTIFIER).hex % 1440`
minutos pasada la medianoche UTC = **16:16 UTC** en esta instalación) y reescribe
`INSTALLATION_PRICING_PLAN` con la respuesta del hub; después
`ReconcilePlanConfigService` apaga los 9 feature flags premium en **todas** las
cuentas. De ahí tres consecuencias:
# Full pipeline on a local project
.\deploy_skill\scripts\Publish-ProjectToCoolify.ps1 `
-AppPath .\my-app -AppName my-app `
-Fqdn https://my-app.urieljareth.org `
-Stack node -AppPort 8080 -Init
- **El SQL de 3 filas no basta.** Los flags por cuenta viven en
`accounts.feature_flags` (bitmask). Usa
`.\scripts\Apply-ChatwootEnterprisePatch.ps1 -ReenableAccountFeatures`;
comprueba el estado con `.\scripts\Get-ChatwootLicenseStatus.ps1 -Deep`.
- **Los `UPDATE` por SQL no invalidan la caché Redis de `GlobalConfig`** (TTL de
1 día, `V1:GLOBAL_CONFIG:*`) porque se saltan el `after_commit :clear_cache` de
`InstallationConfig`. Cualquier parche por SQL debe llamar además a
`GlobalConfig.clear_cache`.
- **No bloquees `hub.2.chatwoot.com`.** Ese mismo host relaya el push móvil
(`ChatwootHub.send_push`), activo aquí porque `FIREBASE_*` está vacío. En su
lugar, [scripts/chatwoot-enterprise-guard.sh](scripts/chatwoot-enterprise-guard.sh)
corre en el host Proxmox desde `/root/scripts/`, agendado por
`/etc/cron.d/chatwoot-enterprise-guard` cada 5 minutos, y repara un revert
detectado en ~13s (log: `/var/log/chatwoot-enterprise-guard.log`, solo escribe
cuando actúa).
# Or step-by-step
.\deploy_skill\scripts\Initialize-CoolifyProject.ps1 -Path .\my-app -Stack node
.\deploy_skill\scripts\Test-PreDeployChecklist.ps1 -Path .\my-app -Strict
.\deploy_skill\scripts\New-GitHubRepo.ps1 -Name my-app
.\deploy_skill\scripts\New-CoolifyApplication.ps1 -RepoUrl https://github.com/urieljarethbusiness-cpu/my-app.git `
-Fqdn https://my-app.urieljareth.org -PortsExposes 8080
.\deploy_skill\scripts\Test-PostDeploy.ps1 -Fqdn https://my-app.urieljareth.org -ContainerName my-app-main
Nunca pulses `Refresh` en `/super_admin/settings`.
# Rollback to a previous commit
.\deploy_skill\scripts\Invoke-CoolifyRollback.ps1 -AppPath .\my-app -ApplicationUuid <uuid> -CommitSha <sha>
```
> **Estado al 2026-08-07:** corre **`chatwoot/chatwoot:v4.16.2`** (el pin
> documentado antes era `v4.16.1`, así que el pin no sostuvo la versión). El plan
> está en `enterprise` y una ejecución manual del guard pasa correctamente, pero
> el log registra `ERROR: no se pudo leer INSTALLATION_PRICING_PLAN` durante la
> ventana del update. El guard tiene el nombre del contenedor hardcodeado
> (`postgres-c11xzy2tx2cdapm32f5b89vy`), así que **un redeploy que cambie el
> sufijo lo deja ciego**. Análisis completo, registro de ejecución y rollback:
> [docs/runbooks/chatwoot-update.md](docs/runbooks/chatwoot-update.md).
## Operating rules (enforced by the skills — follow them)
## Túnel de Cloudflare
- **Read-only first.** Default to diagnostics: list, status, logs, inspect, health checks.
- **Confirm before any state change.** Explicitly ask the user before: `pct`/`qm` start/stop/reboot/destroy; `docker` restart/stop/rm/compose up/down; Coolify deploys or any `POST`/`PUT`/`PATCH`/`DELETE`; env-var writes; and any firewall/network/storage/volume/key/token change. For risky actions, capture current state and state the rollback path first.
- **Never write secrets into the repo.** No tokens, passwords, private keys, cookies, or PVE token secrets in Markdown, scripts, or logs. Secrets live only in `.env.local.ps1` (gitignored) or the OS secret store. `.gitignore` also blocks `ACCESS.md`, `*.key`, `*.pem`, `*.crt`, etc. When debugging databases, verify connectivity without echoing credentials.
- **Prefer repo scripts over long manual command strings**, and don't run broad destructive commands built from generated strings.
El túnel es **gestionado desde el dashboard** (el ingress baja del edge — se ve
como `INF Updated to new configuration version=N` en los logs de `cloudflared`).
Corrige rutas en el dashboard o vía
[scripts/Invoke-CloudflareApi.ps1](scripts/Invoke-CloudflareApi.ps1), **nunca**
editando archivos en el host. Los puertos 6001/6002 deben usar `http://`. Ver
[docs/runbooks/cloudflare-tunnel.md](docs/runbooks/cloudflare-tunnel.md).
## Docker networking gotcha
## Dónde vive el contexto
When a Coolify app and its database are sibling containers on the same Docker
network, the app must reach the DB by its **Docker service name, not `localhost`**
(e.g. Nextcloud uses host `nextcloud-db`). Service-to-service DNS is the usual
root cause of "database connection" failures here — check with
`pct exec 102 -- docker exec <app> getent hosts <service-name>`.
| Qué | Dónde |
|---|---|
| **Catálogo de herramientas + gotchas** | **[docs/TOOL-INDEX.md](docs/TOOL-INDEX.md)** |
| Estado verificado del sistema | [docs/proxmox-inventory.md](docs/proxmox-inventory.md) |
| Procedimientos vigentes | [docs/runbooks/](docs/runbooks/) — `conexion.md`, `diagnostico.md`, `coolify-docker.md`, `seguridad.md`, `cloudflare-tunnel.md`, `autostart-coolify.md`, `nextcloud.md`, `baserow.md`, `chatwoot-update.md` |
| Casos resueltos paso a paso | [docs/casos/](docs/casos/) — `chatwoot-enterprise-patch.md`, `hermes-minimax-m3-setup.md`, `coolify-servicio-nuevo-503-no-available-server.md`, `firecrawl-stack-minimo.md` |
| Incidentes archivados (**no fuente de verdad**) | [docs/incidentes/](docs/incidentes/) |
| Contrato para *construir* una app deployable | [docs/AGENTS-coolify-apps.md](docs/AGENTS-coolify-apps.md) |
| Reglas operativas por dominio | [agent/SKILL.md](agent/SKILL.md), [coolify_skill/SKILL.md](coolify_skill/SKILL.md), [deploy_skill/SKILL.md](deploy_skill/SKILL.md), [gitea_skill/SKILL.md](gitea_skill/SKILL.md) |
| Ejemplos ejecutables por dominio | el `TOOLS.md` de cada carpeta `*_skill/` |
| Referencia de la API de Coolify | `coolify_skill/references/ops/*.md` — **busca con `rg`, no cargues el árbol** |
## Where context lives
- [docs/proxmox-inventory.md](docs/proxmox-inventory.md) — verified topology, LXC list, observed containers, access model. Treat as the source of truth for current state.
- [docs/runbooks/](docs/runbooks/) — concrete procedures: `conexion.md`, `diagnostico.md`, `coolify-docker.md`, `seguridad.md`, `cloudflare-tunnel.md`, `autostart-coolify.md` (power-outage auto-start of LXC 102 + tunnel), plus app-specific `nextcloud.md` and `baserow.md`.
- Cloudflare tunnel: the tunnel is **dashboard-managed** (ingress comes from the edge, see `INF Updated to new configuration version=N` in `cloudflared` logs) — fix routes in the dashboard or via [scripts/Invoke-CloudflareApi.ps1](scripts/Invoke-CloudflareApi.ps1), not by editing files on the host. Ports 6001/6002 must use `http://`. See [docs/runbooks/cloudflare-tunnel.md](docs/runbooks/cloudflare-tunnel.md).
- [agent/SKILL.md](agent/SKILL.md) + [agent/TOOLS.md](agent/TOOLS.md) — Proxmox agent operating skill.
- [coolify_skill/SKILL.md](coolify_skill/SKILL.md) + [coolify_skill/TOOLS.md](coolify_skill/TOOLS.md) — Coolify agent operating skill and API reference index.
- [docs/AGENTS-coolify-apps.md](docs/AGENTS-coolify-apps.md) — compatibility guide for agents **developing** an app to deploy on this Coolify instance (networking, ports, domains/TLS, env, volumes, healthchecks) + pre-deploy checklist. Source this when building a new app, not when operating an existing one.
- [deploy_skill/SKILL.md](deploy_skill/SKILL.md) + [deploy_skill/TOOLS.md](deploy_skill/TOOLS.md) — deploy pipeline skill (scaffold → push → Coolify API → verify → rollback).
- [gitea_skill/SKILL.md](gitea_skill/SKILL.md) + [gitea_skill/TOOLS.md](gitea_skill/TOOLS.md) — self-hosted Gitea skill: list/create/mirror repos, wire a `gitea` remote, push headlessly via one-shot `http.extraHeader` (token never persisted). Distinct from deploy_skill (which targets Coolify); this manages the git hosting layer.
- `PROXMOX/`, `proxmox-agent/`, `proxmox-skill/` are **legacy pointer folders** — they only redirect to the live docs above. Don't add content there.
Para la referencia de la API de Coolify: no leas el árbol completo. Busca en
`coolify_skill/references/` con `rg` y abre el único `references/ops/*.md` que
coincida.