══════════════════════════════════════════════════════════════════════
RESETEA.NET — DOCUMENTACIÓN TÉCNICA
Actualizado: 2026-04
══════════════════════════════════════════════════════════════════════


PUERTOS
───────
80    Nginx — HTTP (redirige a HTTPS automáticamente)
443   Nginx — HTTPS (SSL/TLS, certificado Let's Encrypt)
8787  Node.js/Express — Solo escucha en 127.0.0.1 (loopback, no expuesto)
      Nginx hace de proxy inverso: /api/* → 127.0.0.1:8787

      ⚠  El puerto 8787 NO debe abrirse en el firewall. Solo Nginx lo usa.


ENDPOINTS DE LA API
────────────────────
Base: https://resetea.net/api/

POST /api/erase
  Descripción: Envía carta GDPR Art. 17 al DPO de la plataforma.
  Content-Type: application/json
  Rate limit:  10 peticiones / hora / IP
  Body:
    {
      "provider":  "instagram",   ← obligatorio
      "email":     "tu@email.com",← obligatorio
      "nickname":  "usuario123",  ← opcional
      "phone":     "+34 600...",  ← opcional
      "address":   "Calle...",    ← opcional
      "extra":     "Texto libre"  ← opcional
    }
  Respuesta OK:
    { "status": "ok", "message": "...", "reference": "abc123def456" }
  Respuesta proveedor sin email:
    { "status": "use_form", "formUrl": "https://...", "reference": "..." }
  Respuesta error:
    { "error": "descripción del error" }

GET /api/egosearch?q=<consulta>
  Descripción: Busca en la web menciones del término indicado.
  Rate limit:  8 peticiones / minuto / IP
  Parámetros:
    q  (string, 2-150 chars) — nombre o alias a buscar
  Respuesta:
    { "results": [ { "title", "url", "snippet", "domain", "engine" } ], "query", "total" }
  Nota: sin operadores especiales, la query se envuelve en comillas automáticamente.

GET /api/gmail/auth?provider=&name=&email=&...
  Descripción: Inicia flujo OAuth2 para enviar carta desde Gmail del usuario.
  Parámetros:  provider, name, email (obligatorios) + nickname, phone, address, extra, requestType (opcionales)
  Respuesta:   Redirect a Google OAuth2.
  Requiere:    GOOGLE_CLIENT_ID y GOOGLE_CLIENT_SECRET en .env

GET /api/gmail/callback?code=&state=&error=
  Descripción: Callback OAuth2 de Google. Envía el email y descarta el token.
  Respuesta:   Redirect a /plantillas.html?oauth=ok|cancelled|error|no_email

GET /api/health
  Descripción: Health check.
  Respuesta:   { "status": "ok" }


VARIABLES DE ENTORNO (.env en api/)
─────────────────────────────────────
Obligatorias:
  SALT              Cadena aleatoria larga para hash de referencia de auditoría.
                    Ejemplo: openssl rand -hex 32
  PORT              Puerto del servidor Node.js. Por defecto: 8787

Opcionales — Gmail OAuth2 (sin esto el botón "Enviar desde mi Gmail" no funciona):
  GOOGLE_CLIENT_ID      ID de cliente OAuth2 de Google Cloud Console
  GOOGLE_CLIENT_SECRET  Secreto del cliente OAuth2
  GOOGLE_REDIRECT_URI   URI de callback. Valor: https://resetea.net/api/gmail/callback

Opcionales — Google Custom Search (sin esto egosearch usa SearXNG):
  GOOGLE_API_KEY    API Key de Google Cloud Console (Custom Search API habilitada)
  GOOGLE_CSE_ID     ID del motor de búsqueda de Programmable Search Engine

Plantilla del archivo .env:
  SALT=<openssl rand -hex 32>
  PORT=8787
  GOOGLE_CLIENT_ID=
  GOOGLE_CLIENT_SECRET=
  GOOGLE_REDIRECT_URI=https://resetea.net/api/gmail/callback
  GOOGLE_API_KEY=
  GOOGLE_CSE_ID=


DEPENDENCIAS DEL BACKEND (npm)
────────────────────────────────
Producción (api/package.json):
  express            ^4.19.2   Framework HTTP
  helmet             ^7.1.0    Cabeceras de seguridad HTTP
  express-rate-limit ^7.3.1    Rate limiting por IP
  nodemailer         ^6.9.13   Envío de emails via sendmail local
  googleapis         ^144.0.0  Gmail API + OAuth2 (para envío desde Gmail del usuario)
  dotenv             ^16.4.5   Carga de variables de entorno desde .env

Sin dependencias de frontend (HTML/CSS/JS puro, sin frameworks).


SOFTWARE DEL SISTEMA NECESARIO
────────────────────────────────
Obligatorio:
  Node.js   >= 18          Servidor backend
  npm       >= 8           Gestor de paquetes Node
  Nginx                    Servidor web / proxy inverso
  Certbot   (Let's Encrypt) Certificados SSL — certbot --nginx

Para el envío de emails (POST /api/erase):
  Un MTA (Mail Transfer Agent) local que provea /usr/sbin/sendmail.
  Opciones comunes:
    · Postfix:  apt install postfix   (recomendado, configurar como "Internet Site")
    · msmtp:    apt install msmtp msmtp-mta  (más simple, relay a servidor externo)
    · Exim4:    apt install exim4

  ⚠  SIN MTA el endpoint POST /api/erase fallará silenciosamente.
     El binario /usr/sbin/sendmail debe existir en el sistema.
     Para verificar: which sendmail

  Dominio de envío configurado en mailer.js:
    From: privacy@resetea.net
  El dominio resetea.net debe tener registros SPF/DKIM/DMARC correctos
  para que los emails no lleguen a spam.


CONFIGURACIÓN DE NGINX
───────────────────────
Archivo: infra/nginx-resetea.conf
Copiar en: /etc/nginx/sites-available/resetea.net
Activar:   ln -s /etc/nginx/sites-available/resetea.net /etc/nginx/sites-enabled/
           nginx -t && nginx -s reload

Lo que hace:
  · Puerto 80 → redirect 301 a HTTPS.
  · Puerto 443 → sirve public/ como estático.
  · /api/* → proxy a 127.0.0.1:8787 con X-Real-IP = $remote_addr.
  · Rate limit Nginx: 20 req/s por IP, burst 40 en /api/.
  · Headers de seguridad: HSTS, X-Frame-Options, CSP, Referrer-Policy,
    Permissions-Policy, COOP, X-Content-Type-Options.
  · Timeout proxy: read 15s, connect 5s.
  · server_tokens off (oculta versión de Nginx).

SSL (Let's Encrypt):
  certbot --nginx -d resetea.net
  Rutas de certificados:
    /etc/letsencrypt/live/resetea.net/fullchain.pem
    /etc/letsencrypt/live/resetea.net/privkey.pem


FUENTES TIPOGRÁFICAS (public/fonts/)
──────────────────────────────────────
RECION.otf / RECION.ttf                 Títulos (h1, h2, h3, chips, logo)
Italiana-Regular.ttf                    Alternativa serif
CormorantGaramond-Regular.woff2         Cuerpo de texto elegante
CormorantGaramond-Italic.woff2          Cursiva


ARRANCAR EL BACKEND
────────────────────
cd /var/www/resetea.net/api
npm install           ← solo la primera vez o tras cambiar package.json
node app.js           ← arranque simple

Para producción (sin systemd todavía):
  npm install -g pm2
  pm2 start app.js --name resetea
  pm2 save
  pm2 startup            ← genera el comando para arranque automático

Para crear un servicio systemd (recomendado):
  Crear /etc/systemd/system/resetea.service:
    [Unit]
    Description=RESETEA.NET backend
    After=network.target

    [Service]
    Type=simple
    User=www-data
    WorkingDirectory=/var/www/resetea.net/api
    ExecStart=/usr/bin/node app.js
    Restart=on-failure
    EnvironmentFile=/var/www/resetea.net/api/.env

    [Install]
    WantedBy=multi-user.target

  systemctl enable resetea
  systemctl start resetea


APIS EXTERNAS UTILIZADAS
─────────────────────────
SearXNG (instancias públicas — sin key, gratuito):
  Se usa como motor de búsqueda para egosurfing cuando no hay Google CSE.
  Instancias hardcodeadas en egosearch.js:
    https://searx.be
    https://priv.au
    https://search.mdosch.de
    https://searxng.site
  Se prueban en orden hasta obtener resultados. Timeout: 7s por instancia.

Google Custom Search API (opcional — mejora calidad de resultados):
  https://programmablesearchengine.google.com/
  https://console.cloud.google.com/ → Custom Search API
  Requiere: GOOGLE_API_KEY + GOOGLE_CSE_ID en .env

Google Gmail API + OAuth2 (opcional — envío desde Gmail del usuario):
  https://console.cloud.google.com/ → APIs y servicios → Gmail API
  Tipo de credencial: OAuth2, Aplicación web
  URI de redirección autorizado: https://resetea.net/api/gmail/callback
  Scope usado: https://www.googleapis.com/auth/gmail.send
  Requiere: GOOGLE_CLIENT_ID + GOOGLE_CLIENT_SECRET en .env
  El token es de un solo uso (access_type: 'online', no refresh token).

Let's Encrypt (Certbot):
  Renovación automática via cron o systemd timer.
  Verificar: certbot renew --dry-run


ESTRUCTURA DE ARCHIVOS
───────────────────────
/var/www/resetea.net/
  public/
    index.html          Panel principal
    concienciacion.html Derechos GDPR
    plantillas.html     Generador de cartas (JS local)
    tipos.html          Tipos de información personal
    egosurfing.html     Guía OSINT + buscador integrado
    index.css           Design system completo (tema cálido, caoba/salvia)
    fonts/              Tipografías locales
  api/
    app.js              Entrada: Express + helmet + rate-limit + rutas
    routes/
      erase.js          POST /api/erase — validación + envío GDPR
      egosearch.js      GET /api/egosearch — búsqueda SearXNG/Google CSE
      gmail_oauth.js    GET /api/gmail/auth y /callback — OAuth2 Gmail
    services/
      mailer.js         Datos de 12 DPOs + plantilla carta Art.17 + nodemailer
    .env                Variables de entorno (NO subir a git)
    package.json        Dependencias npm
  infra/
    nginx-resetea.conf  Config Nginx lista para copiar
  CONTEXT.txt           Contexto del proyecto (este documento complementario)
  DOCS.txt              Este archivo
  context_puppeteer.txt Diseño de automatización Puppeteer (pendiente)
