Compare commits

..
10 Commits
23 changed files with 653 additions and 135 deletions
+77 -72
View File
@@ -144,7 +144,7 @@ cada proyecto debera implementar un algoritomo de control de versiones de las ac
| **app_fidelizacion** | [pendiente — crear repo en git.telcotronics.net] | Node.js (Express) + MySQL + EJS | pablinux | 🟡 En desarrollo activo | Plataforma de lealtad, escáner QR y canjes. Gestión de clientes y transacciones de partners. Puerto 2001. BD: MySQL `nexo_fd` en 192.168.10.149. |
| **api_service_ia** | `git@github.com:telcotronics/API_Service_IA.git` | Python 3.14 + FastAPI + uvicorn | pablinux | 🟡 En desarrollo activo | API REST de modelos de IA preentrenados (OCR, STT, TTS, visión facial, PDF). Único proyecto Python serio del ecosistema. Puerto 8000. BD: MariaDB `api_ia_python` en .149. |
| **API_CENTINEL_SECURITY** | `https://git.telcotronics.net/pablinux/API-CENTINEL-SECURITY.git` | Java 17 + Spring Boot 3.3 + WebClient | pablinux | ✅ Activo | API de Gestión de Seguridad Electrónica — control de acceso físico, biometría, apertura remota de puertas, sincronización de credenciales y eventos en tiempo real. Punto único de integración para cualquier app que gestione seguridad física en el ecosistema. |
| **audio_control** | `https://git.telcotronics.net/pablinux/audio_control.git` | Node.js (Express 4) + MariaDB + DLNA/UPnP + ffplay | pablinux | ✅ Activo / Producción | Backend SoundWave — control remoto de reproducción de audio, descarga YouTube, playlist MySQL, renderer DLNA y auth Google OAuth. Puerto 4005 en CT 132 (`192.168.10.160`). Dominio: `audiocontrol.sigmac.app`. Servicio systemd: `siax-app-AUDIO_CONTROL`. MCP ID: 15. |
| **audio_control** | `https://git.telcotronics.net/pablinux/audio_control.git` | Node.js (Express 4) + MariaDB + DLNA/UPnP + ffplay | pablinux | ✅ Activo / Producción | Backend SoundWave — control remoto de reproducción de audio, descarga YouTube, playlist MySQL, renderer DLNA y auth Google OAuth. Puerto 4005 en CT 132 (`192.168.10.160`). Dominio: `musica.sigmac.app`. Servicio systemd: `siax-app-AUDIO_CONTROL`. MCP ID: 15. |
| **SoundWave** | `https://git.telcotronics.net/pablinux/audio-player.git` | Vue 3 + Vite 7 (PWA) / Node.js (Express) + MongoDB | pablinux | 🟢 Activo en producción | Reproductor de música personal PWA. Desplegado en server-webaps (.160) puerto 2005. Auth Google OAuth, streaming con Range requests, descargador YouTube MP3 (yt-dlp) y monitoreado en SIAX Monitor. |
| **app_sigma_inventario** (Control Inventario) | [pendiente — git.telcotronics.net] | Flutter (Android / Linux Desktop) / Dart | pablinux | 🟡 En desarrollo activo | App móvil para supervisores y bodegueros: conciliación física de stock, traslados con código de barras y recepción OCR externa. |
| **agente_ventas** | [sin repositorio — local] | Flutter 2.11 / Dart 2.17-beta + SQLite | pablinux | 🟡 En desarrollo activo — integrando API real | App "Agente Ventas SIGMAC" — gestión de rutas y pedidos de campo para vendedores de Telcotronics. Ruta del día, catálogo, pedidos, firma digital, scanner QR/barcode, notificaciones in-app. Auth vía API-SIGMA-WEBCONTROL · datos vía API-SIGMA-CLOUD (BD `TELCOTRONICS`). |
@@ -153,8 +153,8 @@ cada proyecto debera implementar un algoritomo de control de versiones de las ac
| **API-SIGMA-COMUNICACIONES** | `https://git.telcotronics.net/pablinux/API-SIGMA-COMUNICACIONES.git` | Node.js (Express) + MySQL | pablinux | 🔴 En desarrollo inicial | Gateway SaaS multi-tenant de canales de mensajería: cada cliente/organización crea y conecta su propio componente WhatsApp (bot o Meta), Telegram y redes sociales, aislado del resto. Independiente de `sigma-robot` (comunicaciones internas de Telcotronics). |
| **MCP-Infraestructura** | `https://git.telcotronics.net/pablinux/MCP-INFRAESTRUCTURA.git` | TypeScript (@modelcontextprotocol/sdk) + Nuxt 3 + MySQL | pablinux | ✅ Activo | Servidor MCP y panel web para inventario y gestión en tiempo real de la infraestructura del ecosistema (hardware, servicios, apps IA y externos). Fuente de verdad en MySQL. |
| **proxy_server_SRI** | `https://git.telcotronics.net/pablinux/proxy_server_SRI.git` | Python 3 (ThreadingHTTPServer + requests) | pablinux | ✅ Producción | Script proxy HTTP multihilo para consultas SRI en cascada de RUC y Cédula (Ecuador). Provee proxy y normalización para WebControl, SIGMAC y apps. |
| **cloud-sync** | `https://git.telcotronics.net/pablinux/Service-Cloud-SINC.git` | Rust 2021 + Axum 0.7 + SQLite | pablinux | 🟡 En mantenimiento / primer deploy | Servidor central de backup cifrado y consolas web. Puerto 3000 en 192.168.10.136. MCP ID: 12. |
| **cloud-sync-clients** | [sin remoto aún — siax-amd] | Rust 2021 + Axum 0.7 + Tokio + aes-gcm + zstd | pablinux | 🟡 En desarrollo activo | Clientes server-to-server (Linux/Windows) para respaldo y cifrado local hacia cloud-sync. UI local :3001. MCP ID: 21. |
| **cloud-sync** | `https://git.telcotronics.net/pablinux/Service-Cloud-SINC.git` | Rust 2021 + Axum 0.7 + SQLite | pablinux | ✅ Activo / Producción HTTP | Servidor central de backup cifrado y consolas web. `192.168.10.136:3000`, health `ok` y harness remoto upload/list/download/restore verificados el 2026-10-17. HTTPS pendiente; MCP id 12. |
| **cloud-sync-clients** | [sin remoto aún — siax-amd] | Rust 2021 + Axum 0.7 + Tokio + aes-gcm + zstd + rusqlite | pablinux | 🟡 Operativo / En desarrollo | Clientes server-to-server (Linux/Windows) para respaldo y cifrado local hacia cloud-sync. UI local :3001. Harness remoto validado (192.168.10.136:3000). MCP ID: 21. Agente ID: 42. |
---
@@ -1340,10 +1340,10 @@ Aplicación web en Go para transferencia inmediata de archivos, fotos, documento
| Responsable | pablinux |
| Estado actual | ✅ Operativo / En pruebas |
| Ubicación local | `siax-amd` — `/home/pablinux/Projects/GO/app_compartir` |
| Servidor de producción | `server-webapps` CT 132 (`192.168.10.160`) — pendiente deploy |
| Servidor de producción | `server-webapps` CT 132 (`192.168.10.160`) |
| Dominio público | `drop.sigmac.app` |
| Puerto | `2006` |
| Servicio systemd | `app-compartir.service` |
| Puerto | `2008` |
| Servicio systemd | `siax-app-DROP_SIGMAC_APP.service` (gestionado por SIAX Monitor) |
**Bases de Datos:**
* **SQLite** (`data/compartir.db` local en modo WAL): Almacena metadatos de archivos compartidos (`shares`), usuarios vinculados (`users`) y tokens de sesión (`sessions`).
@@ -1456,7 +1456,7 @@ Backend de la app **SoundWave**. Permite controlar la reproducción de audio de
| Estado actual | ✅ Activo / Desplegado en producción |
| Equipo / ubicación local | `siax-amd` (`192.168.10.100`) — `/home/pablinux/Projects/Node/audio_control` |
| Servidor de producción | `server-webaps` CT 132 (`192.168.10.160`) — `/home/user_apps/apps/audio_control` |
| Dominio público | `audiocontrol.sigmac.app` (vhost activo en .160; enrutamiento WAN sujeto a proxy en .109 / NAT) |
| Dominio público | `musica.sigmac.app` (vhost activo en .160; enrutamiento WAN sujeto a proxy en .109 / NAT) |
| Puerto | `4005` (dev: `4000`) |
| Servicio systemd | `siax-app-AUDIO_CONTROL.service` (activo) |
| Registro MCP | Servicio ID `15` en `http://192.168.10.160:3006` |
@@ -2410,21 +2410,25 @@ SIAX es la inteligencia artificial del ecosistema. Aprende de forma autónoma y
## api_service_ia — API de Servicios con IA
Microservicio REST que centraliza modelos de IA preentrenados para consumo interno del ecosistema. Es el **único proyecto Python serio de Telcotronics**: todos los demás son Node.js, Java, PHP, Rust o Flutter. Expone capacidades de procesamiento pesado (Whisper, InsightFace, Silero, rembg) como endpoints HTTP autenticados, evitando duplicar dependencias en cada proyecto que las necesite. Actualmente consumido por `sigma-robot` para STT y OCR.
Microservicio REST que centraliza modelos de IA preentrenados para consumo interno del ecosistema. Es el **único proyecto Python serio de Telcotronics**: todos los demás son Node.js, Java, PHP, Rust o Flutter. Expone capacidades de procesamiento pesado (Whisper, InsightFace, Silero, rembg) como endpoints HTTP autenticados, evitando duplicar dependencias en cada proyecto que las necesite. Actualmente consumido por `sigma-robot` para STT y OCR. Requiere GPU NVIDIA: Whisper corre en CUDA sin fallback a CPU, por decisión de diseño.
| Parámetro | Valor |
|-----------|-------|
| Repositorio Git | `git@github.com:telcotronics/API_Service_IA.git` |
| Tecnología principal | Python 3.14 + FastAPI + uvicorn |
| Responsable | pablinux |
| Estado actual | ✅ Producción |
| Código local | `siax-amd:/home/pablinux/Projects/Python/api_service_ia/` |
| Servidor producción | `Ubuntu-Docker` — CT 105 (`192.168.10.145`) — usuario `root` |
| Ruta en servidor | `/root/app/API_Service_IA` |
| Dominio público | `api.telcotronics.net` (`whisper.telcotronics.net` — legacy, obsoleto) |
| Estado actual | ✅ Producción (verificado en vivo 2026-10-17) |
| Código local | `siax-intel:/home/pablinux/Projects/Python/api_service_ia/` |
| Servidor producción | `APPS-SERVICE-IA` — CT 140, nodo cluster (`192.168.10.154`) — usuario `pablinux` — GPU RTX 5060 8 GB |
| Ruta en servidor | `/home/pablinux/apps/API_Service_IA` (venv `api_env/`, Python 3.12.3) |
| Dominio público | `https://api.telcotronics.net` vía Nginx Proxy Manager .141 (`whisper.telcotronics.net` — legacy, obsoleto) |
| Swagger | `https://api.telcotronics.net/docs` |
| Puerto | `8000` |
| Servicio de arranque | `tmux` — sesión `api_service_ia` (pendiente migrar a systemd) |
| Última actualización | 2026-06-03 |
| Servicio de arranque | `tmux` — hoy en la sesión `ia-services` (`desplegar.sh` usa `api_service_ia`; pendiente unificar o migrar a systemd) |
| Servidor anterior | `192.168.10.145` — ya no sirve la API (puerto 8000 cerrado) |
| MCP de Infraestructura | App IA id 2 `api_service_ia` · hardware id 12 `CT 140 APPS-SERVICE-IA` · agente id 5 |
| Agente en sigma-robot | `Agente API Service IA` — ID 85 |
| Última actualización | 2026-10-19 |
**BD que usa:**
@@ -2443,20 +2447,20 @@ Microservicio REST que centraliza modelos de IA preentrenados para consumo inter
| Remover fondo | `POST /removerFondo_img/` | PNG con transparencia | ✅ |
| PDF a texto | `POST /convertir_pdf_aTexto/` | JSON `{texto}` | ✅ |
| PDF a Word | `POST /convertir_pdf_aWord/` | `.docx` descargable | ✅ |
| PDF a Excel | `POST /convertir_pdf_aExcel/` | `.xlsx` descargable | ✅ |
| PDF a Excel | `POST /convertir_pdf_aExcel/` | `.xlsx` descargable | ❌ en producción (dependencia `tabula` equivocada); corregido en el repo, pendiente de desplegar |
| PDF tablas a JSON | `POST /pdf_tablas/` | JSON estructurado | ✅ |
| Reconocimiento facial | `POST /facial/detectar/` | JSON `{bbox, confianza}` | ✅ |
| Comparación facial | `POST /facial/comparar/` | JSON `{es_misma_persona, similitud}` | ✅ |
| TTS online (gTTS) | `POST /texto_aVoz/` | MP3 descargable | ✅ requiere internet |
| TTS offline (Silero) | `POST /texto_aVoz/silero/` | WAV 24kHz descargable | ✅ offline tras 1ª descarga |
| TTS offline (Silero) | `POST /texto_aVoz/silero/` | WAV 16 kHz descargable | ⚠️ en producción el audio sale truncado; corregido en el repo, pendiente de desplegar |
**Autenticación:** header `X-API-Key` — validado contra `api_ia_python.api_key` en MariaDB .149.
**Integración con el ecosistema:**
- **sigma-robot** la consume para STT (`/convertir_audio_aTexto/`) y OCR/imágenes (`https://api.telcotronics.net`)
- **sigma-robot** la consume para STT (`/convertir_audio_aTexto/`) y OCR/imágenes — debe usar `https://api.telcotronics.net`, no `192.168.10.145:8000`
- Cualquier proyecto del ecosistema puede consumirla con una API key válida
**Dónde buscar más info:** `siax-amd:/home/pablinux/Projects/Python/api_service_ia/agents.md`
**Dónde buscar más info:** `siax-intel:/home/pablinux/Projects/Python/api_service_ia/agents.md`
---
@@ -2561,74 +2565,75 @@ curl -X POST https://api.telcotronics.com/api/biometria/1001 \
## cloud-sync — Sistema de Backup Automático y Recuperación ante Desastre
cloud-sync es el servidor central de backup y recuperación ante desastre para clientes SIGMA. El agente de origen comprime y cifra archivos y dumps de SQLite, MySQL, MariaDB o bases compatibles antes de subirlos; el servidor almacena metadatos y contenido cifrado, sin recibir la clave del cliente. El repositorio incluye la API Rust y las consolas root/empresa; los ejecutables server-to-server viven en `cloud-sync-clients`. La integración Flutter/Java y la aplicación de escritorio siguen siendo objetivos posteriores.
cloud-sync es un servidor central de backup y recuperación ante desastre para clientes SIGMA. Los datos se comprimen y cifran en el equipo de origen antes de subirlos; el servidor almacena contenido cifrado y metadatos, sin recibir la clave de cifrado. El repositorio mantiene la API Rust y las consolas root/empresa. Los ejecutables server-to-server están en el proyecto separado `cloud-sync-clients`; Tauri y los SDK Flutter/Java siguen pendientes.
| Parámetro | Valor |
|---|---|
| Repositorio Git | `https://git.telcotronics.net/pablinux/Service-Cloud-SINC.git` (privado, rama `main`, último commit documentado `babf1cd`) |
| Tecnología principal | Rust 2021 · Axum 0.7 · Tokio · rusqlite/SQLite · filesystem local · HTML/CSS/JavaScript para consolas web |
| Repositorio Git | `https://git.telcotronics.net/pablinux/Service-Cloud-SINC.git` (privado, rama `main`) |
| Tecnología principal | Rust 2021 · Axum 0.7 · Tokio · rusqlite/SQLite · filesystem local · HTML/CSS/JavaScript |
| Responsable | pablinux |
| Estado actual | 🟡 Primer despliegue y smoke test HTTP aprobados; HTTPS público, auth Cloud dual y pruebas funcionales pendientes |
| Equipo / código local | `siax-amd` (`192.168.10.100`) — `/home/pablinux/Projects/Rust/cloud monitor sinc` |
| Servidor de producción | `192.168.10.136` — `/home/user_apps/apps/cloud-sync`; tmux activo, `/health` y consolas HTTP 200 verificados 2026-09-21 |
| Dominio público | Pendiente — VirtualHost HTTPS en Apache |
| Puerto interno | `3000` |
| Última actualización | 2026-09-30 |
| MCP de Infraestructura | Servicio id 12 · categoría `service` · estado `ACTIVE` |
| Estado operativo | Producción HTTP. El 2026-10-17 `/health` respondió HTTP 200, `status: ok`, versión `0.1.0`; harness remoto aislado completó upload/list/download/restore desde `cloud-sync-clients` |
| Servidor de producción | `192.168.10.136:3000`; ruta documentada `/home/user_apps/apps/cloud-sync` |
| Hardware / CT | No hay entidad correspondiente a `192.168.10.136` en `infra://hardware`; sin CT confirmado. Feedback MISSING id 24, abierto el 2026-10-17 |
| Dominio público / HTTPS | Sin dominio confirmado; HTTPS público pendiente |
| Feedback MCP | Cero reportes al iniciar la revisión del 2026-10-17; se abrió después el MISSING id 24 por la ficha de hardware faltante |
| Reglas de despliegue | Ninguna activa devuelta para alcance `cloud-sync` ni global. Hay una regla global SRI en borrador, no aplicable a este servicio |
| Última actualización | 2026-10-17 |
**BD que usa:**
**Almacenamiento de datos:**
| Motor | Host | Nombre | Uso |
|---|---|---|---|
| SQLite (embebida, bundled) | `192.168.10.136` — `/home/user_apps/apps/cloud-sync/data` | `server.db` | Empresas, cuotas, tokens, perfiles, sesiones, backups (metadata) y eventos |
| SQLite (embebida, en el cliente) | Equipo de origen | `index.db` | Índice local de rutas, checksum SHA-256, backup_id y timestamps |
| Motor | Host / ruta | Uso |
|---|---|---|
| SQLite embebida | `192.168.10.136` — `/home/user_apps/apps/cloud-sync/data/server.db` | Empresas, cuotas, perfiles, sesiones, metadatos de backups y eventos |
| SQLite local del cliente | Equipo de origen — `index.db` | Rutas, checksum SHA-256, identificadores y timestamps de backups |
| Filesystem | Servidor `192.168.10.136` | Contenido cifrado de los backups, organizado por empresa |
**Servicios que consume y expone:**
| Método | Endpoint | Auth | Descripción |
|---|---|---|---|
| GET | `/health` | — | Estado del servidor + info de disco |
| POST | `/auth/token` | — | Login cliente (token UUID) → sesión Bearer |
| POST | `/auth/admin` | — | Login admin (argon2) → session token |
| POST | `/backup/upload` | Bearer token | Subir archivo cifrado (multipart) |
| GET | `/backup/list` | Bearer token | Listar backups de la empresa |
| GET | `/backup/download/{id}` | Bearer token | Descargar backup para restore |
| DELETE | `/backup/{id}` | Bearer token | Eliminar backup |
| GET | `/me/storage` | Bearer token | Uso actual vs cuota asignada |
| GET | `/admin/storage` | X-Admin-Token | Capacidad CT146 + resumen global |
| GET/POST | `/admin/clientes` | X-Admin-Token | Listar / crear empresas |
| PUT | `/admin/clientes/{id}/cuota` | X-Admin-Token | Ajustar cuota por empresa |
| GET | `/admin/eventos` | X-Admin-Token | Log de auditoría |
| GET | `/root/` | — | Consola root para empresas, cuotas, estados, perfiles y accesos |
| GET | `/admin/` | — | Portal admin de empresa para consultar cuenta y descargar respaldos propios |
| GET | `/panel/` | Token de integración | Portal legado de cliente |
| MCP Infraestructura | `http://192.168.10.160:3006/sse` | Uso interno del ecosistema | Inventario; `cloud-sync` registrado como servicio id 12; `cloud-sync-clients` registrado como servicio id 21. No transporta errores de runtime |
| API-SIGMA-WEBCONTROL | `https://api.siax-system.net/api/errores` | `x-api-key` por aplicación | Integración de bitácora de errores pendiente; no hay clave configurada |
| GET | `/health` | — | Estado del servidor y capacidad de disco |
| POST | `/auth/token` | Token de empresa | Compatibilidad con agentes integradores |
| POST | `/auth/root`, `/auth/admin` | Usuario y contraseña | Login root; `/auth/admin` es alias compatible |
| POST | `/auth/empresa` | Usuario y contraseña | Login de administrador de empresa |
| POST | `/auth/logout` | Sesión Bearer | Revocar la sesión presentada |
| PUT | `/auth/admin/password` | Sesión root | Cambiar contraseña root |
| PUT | `/auth/empresa/password` | Sesión empresa | Cambiar contraseña de empresa |
| GET | `/empresa/cuenta` | Sesión empresa | Consultar su cuenta y perfil |
| POST | `/backup/upload` | Bearer de integración | Subir backup cifrado multipart; límite configurado de hasta 10 GiB y cuota por empresa |
| GET | `/backup/list`, `/backup/status` | Bearer de integración | Listar respaldos y consultar estado |
| GET | `/backup/download/{id}` | Bearer de integración o sesión empresa | Descargar respaldo cifrado propio |
| DELETE | `/backup/{id}` | Bearer de integración | Eliminar backup propio |
| GET | `/me/storage` | Bearer de integración | Uso y cuota de empresa |
| GET | `/admin/storage`, `/admin/clientes`, `/admin/eventos` | Sesión root | Capacidad, empresas y auditoría |
| POST | `/admin/clientes` | Sesión root | Crear empresa y token de integración |
| PUT | `/admin/clientes/{id}/cuota`, `/estado` | Sesión root | Cambiar cuota o suspender empresa |
| GET/PUT | `/admin/clientes/{id}/perfil` | Sesión root | Consultar o editar perfil |
| PUT | `/admin/clientes/{id}/acceso` | Sesión root | Asignar o reemplazar acceso de empresa |
| GET | `/root/`, `/admin/`, `/panel/` | Según consola | Root, administrador de empresa y portal legado |
**Módulos disponibles:**
**Estado de módulos y pendientes:**
| Módulo | Estado |
| Módulo / tarea | Estado |
|---|---|
| Servidor API REST (Axum) | ✅ Completo y probado |
| Consola web admin (`/admin`) | ✅ Completa |
| Consola web panel cliente (`/panel`) | ✅ Completa |
| `cloud_sync_core` (librería Rust) — crypto, uploader, backup_engine, restore | ✅ Completo |
| Agente server-to-server (`cloud-sync-clients`) — archivos y dumps | ✅ Base Linux; UI local :3001; harness local/remoto; MCP ID 21; Windows pendiente de validación real |
| Script de despliegue configurable | ✅ Preparado para `192.168.10.136` |
| App desktop (Tauri — Windows/Linux/macOS) | ⏳ Pendiente |
| SDK Flutter (uniffi-rs → Dart FFI) | ⏳ Pendiente |
| SDK Java (uniffi-rs → JNI) | ⏳ Pendiente |
| Deploy en `192.168.10.136` | ✅ Ejecutado; smoke test HTTP aprobado |
| HTTPS público detrás de Apache | ⏳ Pendiente de configurar y verificar |
| Bitácora centralizada de errores | ⏳ Pendiente de clave, reportador y consulta operativa |
| Autenticación dual para apps y servicios | ⏳ Diseño aprobado; login Cloud, sesiones cortas y credencial por instalación pendientes |
| API Rust y consola root | Implementadas y desplegadas; health HTTP verificado |
| Consola de empresa | Implementada; validar login y flujos de consola en producción |
| Portal `/panel/` | Legado por token de integración |
| `cloud-sync-clients` | Proyecto separado, MCP id 21; harness aislado upload/list/download/restore pasó contra `192.168.10.136:3000` el 2026-10-17; Windows pendiente de validación funcional |
| Autenticación dual | Diseño aprobado; falta cerrar proveedor/login, tokens y registro/revocación de instalaciones |
| Uploads reanudables y cola durable | Objetivo 10, pendiente de diseño e implementación |
| Restauración automatizada y verificada | Objetivo 11; el harness validó un ciclo básico remoto, la automatización de archivos/dumps sigue pendiente |
| HTTPS público | Pendiente confirmar dominio y configurar la entrada aprobada |
| Bitácora WebControl | Objetivo 8; bloqueada hasta confirmar `app_origen` y obtener `x-api-key` autorizada |
| App de escritorio Tauri / SDK Flutter / SDK Java | Pendientes |
**Integración con el ecosistema:**
- **SIGMAC** (Java ERP, CT 141): SDK Java pendiente — backup automático de archivos y BD de las empresas clientes
- **sigmac_app** (Flutter, `.72`): SDK Flutter pendiente — backup de datos del app sin intervención del usuario
- **MCP de Infraestructura** (`192.168.10.160:3006`): inventario actualizado; no es proxy de la bitácora de errores
- **API-SIGMA-WEBCONTROL**: canal previsto para reportar/consultar errores de runtime cuando exista una clave autorizada
- **Autenticación Cloud**: diseño aprobado para login de apps con access/refresh token y credencial protegida por instalación en servicios automáticos; implementación pendiente
- **Apache**: VirtualHost HTTPS pendiente
**Integración y separación de sistemas:**
- **MCP de Infraestructura** (`192.168.10.160:3006`): inventario y reglas operativas. Ficha de servicio id 12; no es proxy de errores de runtime.
- **Feedback MCP:** el 2026-10-17 se reportó MISSING id 24 porque el inventario no contiene una entidad de hardware para `192.168.10.136`. No registrar un CT o ubicación hasta confirmarlos.
- **API-SIGMA-WEBCONTROL** (`https://api.siax-system.net/api/errores`): destino separado para errores de runtime. No hay `x-api-key` autorizada ni `app_origen` confirmado en este proyecto; la ausencia de consulta no significa ausencia de errores.
- **Reglas de despliegue:** no se devolvieron reglas activas globales ni para `cloud-sync`; no inferir dominio, DNS, ruta pública o contenedor.
- **Autenticación Cloud:** la implementación dual sigue pendiente de cerrar el contrato con el proveedor autorizado. No persistir contraseñas Cloud en cloud-sync.
**Dónde buscar más información:** `siax-amd:/home/pablinux/Projects/Rust/cloud monitor sinc/agents.md`; cliente server-to-server: `/home/pablinux/Projects/Rust/cloud-sync-clients/agents.md`
+6
View File
@@ -36,3 +36,9 @@
| 2026-10-13 | Sesión Guest con auto-eliminación obligatoria en 24h (física y BD) | Worker periódico de purga en segundo plano verificado con tests |
| 2026-10-13 | Cuentas registradas (Google y WebControl) con almacenamiento permanente | Cuentas no-guest exentas de borrado a las 24h |
| 2026-10-13 | Panel / lista de "Mis Archivos" para usuarios registrados con opción de borrado | Interfaz `/mis-archivos` con métricas de visitas y eliminación |
| 2026-10-14 | Scripts de despliegue estándar (`desplegar.sh`, `init.sh`) y servicio para SIAX Monitor | Compilación Go estática, scp, servers.conf y systemd |
| 2026-10-17 | Registro oficial en MCP Infraestructura (ID 34) | Ficha técnica completa registrada en MariaDB bajo categoría application |
| 2026-10-17 | Registro en centro de comunicaciones de agentes (sigma-robot) | Identidad `Agente drop.sigmac.app` registrada vía REST; credenciales en `.env` |
| 2026-10-17 | Sincronización de normas y archivos base del ecosistema | Creación de `id_agente.md`, `reglas.md`, `tareas.md` y espejo de `infraestructura.md` |
| 2026-10-19 | Despliegue en producción en CT 132 con SIAX Monitor (:8080) | Servicio `siax-app-DROP_SIGMAC_APP.service` operativo en puerto 2008 |
| 2026-10-20 | Puesta en producción pública vía HTTPS en drop.sigmac.app | Proxy Apache con SSL operativo, URLs y QR dinámicos con protocolo HTTPS verificado |
+10 -1
View File
@@ -15,7 +15,9 @@ app_compartir/
│ ├── objetivos.md
│ ├── proyecto_errores.md
│ ├── proyecto_estructura.md
│ └── proyecto_memoria.md
│ ├── proyecto_memoria.md
│ ├── reglas.md
│ └── tareas.md
├── internal/
│ ├── auth/
│ │ └── auth.go # Manejo de sesiones, WebControl y Google OAuth2
@@ -32,6 +34,11 @@ app_compartir/
│ └── storage/
│ └── storage.go # Slugs aleatorios, sniffing MIME y guardado en disco
├── web/
│ ├── static/ # Iconos, favicons y recursos estáticos de la marca
│ │ ├── favicon.ico # Icono multirresolución para navegadores
│ │ ├── favicon.svg # Icono vectorial escalable y moderno
│ │ ├── icon-192.png # Icono PWA / accesos directos móviles
│ │ └── icon-512.png # Icono alta resolución / splash screen
│ └── templates/
│ ├── base.html # Layout común con Tailwind CSS y FontAwesome
│ ├── expired.html # Mensaje informativo de archivo guest caducado (24h)
@@ -42,8 +49,10 @@ app_compartir/
├── .env.example
├── .gitignore
├── desplegar.sh # Script de compilación y despliegue (máquina dev)
├── id_agente.md # Identidad oficial del agente en el ecosistema
├── init.sh # Script ejecutor local en el servidor
├── servers.conf.example # Plantilla de credenciales SSH para despliegue
├── siax-app-DROP_SIGMAC_APP.service # Definición de servicio systemd para SIAX Monitor
├── go.mod
├── go.sum
├── main.go # Punto de entrada y servidor HTTP Go
+17 -1
View File
@@ -16,6 +16,12 @@
| 2026-10-13 | Generación de QR nativa en Go vía `/qr/{id}` | Se utiliza `github.com/skip2/go-qrcode` para servir el QR directamente en formato PNG (256x256), garantizando compatibilidad total con cualquier cámara de smartphone sin depender de scripts cliente pesados. |
| 2026-10-13 | Soporte doble de login: WebControl corporativo + Google OAuth | Brinda flexibilidad tanto para colaboradores del ecosistema Telcotronics (vía `api.siax-system.net`) como para usuarios externos con Google. |
| 2026-10-14 | Adopción de la marca y dominio `drop.sigmac.app` | Nombre conciso, memorable y alineado con los servicios y subdominios del ecosistema SIGMA (sigmac.app). |
| 2026-10-17 | Registro oficial en MCP Infraestructura (ID 34) e identidad de agente | Se vinculó el proyecto al inventario central MariaDB vía API REST (:3007), asignando ID 34 bajo categoría application, y se creó `id_agente.md` según el estándar de identidad del ecosistema. |
| 2026-10-19 | Despliegue en producción en CT 132 con supervisión SIAX Monitor | Se desplegó en `server-webapps`. Registrado en SIAX Monitor (:8080) como `siax-app-DROP_SIGMAC_APP.service`, habilitando reinicio atómico vía API sin sudo. |
| 2026-10-20 | Reasignación de puerto a 2008 para liberar 2006 a audio_control | Se acordó con pablinux liberar el puerto 2006 para `audio_control` (correlativo a SoundWave en 2005) y trasladar `drop.sigmac.app` al puerto 2008 en CT 132 y MCP Infraestructura (ID 34). |
| 2026-10-20 | Activación de dominio público https://drop.sigmac.app | Pablinux configuró el proxy reverso Apache en CT 150 con SSL Let's Encrypt. Se optimizó `getBaseURL()` para forzar HTTPS en los enlaces y códigos QR generados cuando el Host es `drop.sigmac.app`. |
| 2026-10-20 | Identidad visual e iconos multi-formato (SVG, ICO, PNG) | Se diseñó un icono SVG escalable con flecha bidireccional y pulsos de transferencia en colores esmeralda/cian sobre contenedor squircle grafito oscuro. Se generaron versiones PNG (64, 192, 512 px) e ICO multi-resolución, enlazados en el navbar y servidos nativamente en `/favicon.ico` y `/favicon.svg`. |
| 2026-10-21 | Blindaje de seguridad y protección contra ejecución de scripts (RCE/XSS/MIME) | Se auditaron riesgos de subida de scripts (.php, .phtml, .sh, .html, .svg). Se neutralizó la detección de MIME impidiendo que scripts se sirvan como ejecutables o HTML activo (Stored XSS). Se implementó Sandbox CSP, nosniff, DENY de frames en /raw/, permisos estrictos 0640 sin +x en disco, .htaccess preventivo en uploads/, flag Secure en cookies HTTPS, límite de 5 MB en share-text y sanitización reforzada contra path traversal multiplataforma. |
---
@@ -27,7 +33,9 @@ Versión funcional completa y validada:
- Visor universal adaptativo con vista previa multimedia, lector de PDF y código con botón de copia.
- Purga automática cada 10 minutos para archivos guest > 24h (test automatizado superado en `main_test.go`).
- Cuentas registradas con almacenamiento permanente y panel `/mis-archivos`.
- Documentación e integración de infraestructura sincronizada con el MCP y global `infraestructura.md`.
- Registrado oficialmente en el MCP de Infraestructura (ID 34) y sincronizado con espejo local `.agente/infraestructura.md`.
- Desplegado y ejecutándose activamente en producción (CT 132 puerto 2008) supervisado por SIAX Monitor.
- Enrutamiento público operativo al 100% en `https://drop.sigmac.app` con SSL.
---
@@ -40,6 +48,14 @@ Versión funcional completa y validada:
- [x] Implementar auth con WebControl (`api.siax-system.net`) y Google OAuth2
- [x] Implementar panel "Mis Archivos" para usuarios autenticados
- [x] Sincronizar sección de infraestructura en global e internal para MCP
- [x] Crear scripts de despliegue estándar (`desplegar.sh`, `init.sh`, `servers.conf.example`)
- [x] Integrar servicio systemd para SIAX Monitor (`siax-app-DROP_SIGMAC_APP.service`)
- [x] Soporte para proxy reverso dinámico Apache (`X-Forwarded-Proto`, `Host`) en puerto 2008
- [x] Registrar proyecto en MCP de Infraestructura (ID 34) y crear `id_agente.md` oficial
- [x] Desplegar en producción en `server-webapps` (CT 132, :2008) y registrar en SIAX Monitor (:8080)
- [x] Crear icono SVG/PNG/ICO e integrarlo en la cabecera, navbar y servidor HTTP en producción
- [x] Auditar y blindar seguridad contra RCE, Stored XSS, MIME sniffing, Path Traversal y DoS en subidas y raw
---
+47
View File
@@ -0,0 +1,47 @@
# reglas.md — Reglas operativas y técnicas de app_compartir (drop.sigmac.app)
> Normas inviolables que todo agente o desarrollador debe respetar al interactuar con este proyecto.
---
## 1. Identidad del Agente
- Mantener siempre el archivo [`id_agente.md`](../id_agente.md) en la raíz del repositorio según la norma del ecosistema.
- **No inventar nombres ni identificadores de agente**: El nombre oficial y el ID numérico son potestad exclusiva de la confirmación emitida por `sigma-robot` y autorizada por `pablinux`.
- Al inicio de cada sesión ("carga proyecto"), leer `id_agente.md` y `agents.md` para conocer el estado y credenciales.
- Nunca commitear tokens, contraseñas ni códigos secretos (`SIGMA_AGENTE_SOLICITUD_ID`, `SIGMA_AGENTE_CODIGO`, `SIGMA_AGENTE_TOKEN`).
---
## 2. Infraestructura y MCP
- **Prohibido asumir o inventar IPs, puertos o servidores**:
- Servidor de producción asignado: `server-webapps` CT 132 (`192.168.10.160`).
- Puerto de producción interno: `2008` (puerto local de desarrollo: `8085`).
- Dominio público: `https://drop.sigmac.app` (Reverse Proxy Apache con SSL/TLS Let's Encrypt).
- Servicio systemd: `siax-app-DROP_SIGMAC_APP.service` (gestionado y supervisado por SIAX Monitor en el puerto `8080`).
- Base de datos: SQLite en modo WAL (`data/compartir.db`) sin dependencias de MySQL ni MongoDB.
- Registro central MCP: Ficha técnica registrada en MariaDB con **ID 34** (categoría `application`, tipo `web`).
- El archivo [`.agente/infraestructura.md`](infraestructura.md) es un espejo local de solo lectura del documento maestro `/home/pablinux/Projects/infraestructura.md`. Nunca modificarlo de forma independiente sin sincronizar con el maestro.
---
## 3. Reglas de Negocio y Ciclo de Vida de Archivos
- **Política de Retención Estricta**:
- **Invitados (Guest)**: Cero fricción (sin login requerido). Todo archivo, nota o código subido como invitado tiene una vida útil máxima e inmutable de **24 horas**. El worker en segundo plano (`cleaner.go`) purga periódicamente tanto el archivo físico en disco como su fila en SQLite.
- **Usuarios Registrados (WebControl / Google OAuth)**: Disponen de almacenamiento **permanente**. Sus archivos nunca expiran ni son tocados por el limpiador automático. Tienen gestión completa desde `/mis-archivos`.
- **Generación de Código QR**:
- Se genera de forma nativa en backend Go vía `github.com/skip2/go-qrcode` en endpoint `/qr/{id}` como imagen PNG. Cero dependencias pesadas de librerías JS cliente para la generación del código QR.
- **Visor Universal Embebido**:
- El visor `/v/{id}` debe renderizar vista previa directa según el MIME type (imágenes con modal zoom, reproductor HTML5 de video/audio, visualizador embebido de PDF, y código formateado con botón de copia con un clic).
---
## 4. Comandos de Contexto del Ecosistema
- **"carga proyecto"**: Leer `agents.md`, `id_agente.md` y la carpeta `.agente/` para absorber el contexto, reglas, objetivos y memoria técnica antes de ejecutar modificaciones.
- **"actualizar proyecto"**: Ejecutar tests automatizados (`go test -v ./...`), realizar commit estructurado de los cambios pendientes, actualizar `agents.md`, `README.md` y `.agente/proyecto_estructura.md`.
---
## 5. Seguridad y Dependencias
- Compilar binarios de producción sin CGO (`CGO_ENABLED=0 GOOS=linux GOARCH=amd64`), utilizando la implementación pura en Go de SQLite (`modernc.org/sqlite`).
- Mantener las rutas de almacenamiento dentro de `DATA_DIR` y utilizar nombres generados criptográficamente (slugs no predecibles) para prevenir ataques de Path Traversal.
- Toda sesión web debe utilizar cookies seguras HTTP-only protegidas por `SESSION_SECRET`.
+61
View File
@@ -0,0 +1,61 @@
# tareas.md — Control de tareas de app_compartir (drop.sigmac.app)
> Registro ágil de tareas completadas, en progreso y backlog priorizado.
---
## ✅ Tareas Completadas
- [x] **Base de Datos y Esquema:** SQLite DAL (`modernc.org/sqlite`) con tablas `shares`, `users`, `sessions` en modo WAL.
- [x] **Subida de Archivos y Texto:** Endpoints `/api/upload` (multipart hasta 500 MB) y `/api/share-text` (notas rápidas y código).
- [x] **Visor Universal Adaptativo (`/v/{id}`):** Vista previa nativa para imágenes con zoom, video HTML5, audio HTML5, lector de PDF embebido y visualizador de código con botón de copia.
- [x] **Generador de QR Nativo:** Endpoint `/qr/{id}` con salida PNG (256x256) generado en Go nativo vía `github.com/skip2/go-qrcode`.
- [x] **Worker de Purga Automática 24h:** Goroutine en segundo plano (`cleaner.go`) que elimina archivos físicos y filas de BD vencidas de usuarios Guest.
- [x] **Autenticación Dual:** Login corporativo con Telcotronics WebControl (`api.siax-system.net`) y Google OAuth2.
- [x] **Panel "Mis Archivos":** Interfaz `/mis-archivos` para usuarios autenticados con almacenamiento permanente, estadísticas y borrado manual.
- [x] **Scripts de Despliegue:** `desplegar.sh` (compilación Linux amd64, transferencia scp/rsync) e `init.sh` (ejecutor en servidor).
- [x] **Integración con SIAX Monitor:** Servicio systemd `siax-app-DROP_SIGMAC_APP.service` para supervisión en puerto 2008 / 8080.
- [x] **Soporte de Reverse Proxy:** Manejo dinámico de encabezados Apache (`X-Forwarded-Proto`, `Host`, `X-Forwarded-For`).
- [x] **Pruebas Automatizadas:** Suite de tests unitarios y de integración en `main_test.go` verificando la retención 24h vs permanencia.
- [x] **Registro en MCP de Infraestructura:** Registrado oficialmente con **ID 34** en MariaDB (`http://192.168.10.160:3007/api/services/34`).
- [x] **Espejo de Infraestructura:** Sincronizado `.agente/infraestructura.md` con `/home/pablinux/Projects/infraestructura.md`.
- [x] **Identidad del Agente:** Creación de `id_agente.md` en la raíz del repositorio.
- [x] **Centro de Comunicaciones sigma-robot:** Autorizado formalmente por Pablinux como **Agente ID 86** (`Agente drop.sigmac.app`). Token definitivo resguardado en `.env` (modo 600).
- [x] **Despliegue a Producción (CT 132 server-webapps):** Desplegado y ejecutándose activamente como `siax-app-DROP_SIGMAC_APP.service` supervisado por SIAX Monitor (`:8080`), escuchando en puerto interno `2008` (dejando el 2006 reservado para `audio_control`). Subida atómica y reinicio automático operativo.
- [x] **Proxy Reverso Apache (SSL port 443 en CT 150):** Configurado por Pablinux y verificado operando al 100% en `https://drop.sigmac.app` (redirección 301 de HTTP a HTTPS, terminación SSL y proxy a `:2008`). Detección inteligente de HTTPS en enlaces generados y códigos QR.
- [x] **Identidad Visual e Iconos del Proyecto:** Creación de conjunto completo de iconos SVG vectoriales y ráster (SVG, ICO multi-resolución, PNG 64/192/512 px) con temática visual de transferencia (verde esmeralda / cian sobre grafito). Integrados en `web/templates/base.html` (meta tags, favicon, icono de marca en navbar) y expuestos vía `/favicon.ico`, `/favicon.svg` y `/static/*`. Desplegado en producción.
- [x] **Auditoría y Blindaje de Seguridad en Subidas (RCE / Stored XSS / MIME Sniffing):**
- Neutralización de scripts `.php`, `.phtml`, `.phar`, `.sh`, `.cgi` y archivos `.html` para que nunca se sirvan como ejecutables o código HTML activo.
- Implementación de cabeceras de Sandbox (`Content-Security-Policy: default-src 'none'; style-src 'unsafe-inline'; sandbox`, `X-Content-Type-Options: nosniff`, `X-Frame-Options: DENY`) en `/raw/{id}`.
- Middleware global de cabeceras de seguridad (`nosniff`, `SAMEORIGIN`, `strict-origin-when-cross-origin`, `Permissions-Policy`).
- Protección en disco con permisos `0640` (sin bit `+x`) y archivo preventivo `.htaccess` en `uploads/` (`Require all denied` para scripts).
- Sanitización anti-path traversal multiplataforma (eliminando `\` y secuencias `..`).
- Protección de cookies de sesión con flag `Secure: true` bajo HTTPS.
- Límite de 5 MB en endpoint `/api/share-text` contra DoS por memoria.
- Suite de pruebas de seguridad automatizada en `main_test.go` (`TestSecurityProtections`).
---
## 🚀 En Progreso / Inmediatas
- [ ] **Creación del Repositorio Git Remoto:**
- Crear repo en `git.telcotronics.net/pablinux/app_compartir.git`.
- Configurar `git remote add origin ...` y realizar primer push.
---
## 📋 Backlog Priorizado
### Fase 2: Experiencia y Utilidades
- [ ] **Descarga Multi-archivo Comprimida (.zip):**
- Empaquetar múltiples archivos en un único archivo zip descargable al vuelo.
- [ ] **Protección por PIN / Contraseña opcional:**
- Permitir a quien comparte proteger el visor con una clave de 4-6 dígitos.
- [ ] **Modo de un solo uso (Burn after reading):**
- Auto-destrucción inmediata del archivo tras la primera descarga o visualización.
### Fase 3: Integraciones del Ecosistema
- [ ] **Notificaciones a sigma-robot:**
- Enviar eventos al bot o a Pablinux cuando se descargue un archivo relevante.
- [ ] **Widget publicitario app_marketing:**
- Integrar widget ligero de `ads.sigmac.app` opcional en la pantalla de descarga de invitados.
+12 -3
View File
@@ -157,7 +157,16 @@ app_compartir/
---
## 🏢 Ecosistema Telcotronics
## 🏢 Ecosistema Telcotronics e Infraestructura
Este proyecto forma parte del ecosistema Telcotronics y se encuentra registrado en la infraestructura compartida del MCP (`mcp.telcotronics.net` / `infraestructura.md`).
Para más detalles técnicos y reglas del agente, consultar [`agents.md`](agents.md).
Este proyecto forma parte oficial del **Ecosistema Telcotronics** y se encuentra integrado con las siguientes especificaciones:
| Entorno / Servicio | Detalle de Conexión |
|---|---|
| **Registro Central MCP** | Registrado en MariaDB como **Servicio ID 34** (Categoría: `application`) |
| **Centro de Agentes (sigma-robot)** | **Agente ID 86** (`Agente drop.sigmac.app`) activo y autorizado vía API REST |
| **Servidor de Producción** | `server-webapps` CT 132 (`192.168.10.160`), puerto interno `2008` |
| **Dominio y Proxy Apache** | `https://drop.sigmac.app` con terminación SSL/TLS Let's Encrypt (✅ Operativo) |
| **Supervisión de Procesos** | Servicio `siax-app-DROP_SIGMAC_APP.service` en [SIAX Monitor](http://192.168.10.160:8080) |
| **Identidad y Normas** | Consultar [`id_agente.md`](id_agente.md), [`agents.md`](agents.md) y [`.agente/reglas.md`](.agente/reglas.md) |
| **Espejo de Infraestructura** | Sincronizado en [`.agente/infraestructura.md`](.agente/infraestructura.md) desde `/home/pablinux/Projects/infraestructura.md` |
+10 -3
View File
@@ -74,10 +74,11 @@ Goroutine periódica (ticker) que consulta items donde `is_guest = true AND expi
| Parámetro | Valor |
|---|---|
| Dominio público | `drop.sigmac.app` |
| Puerto interno | `2006` (producción) / `8085` (local) |
| Servicio systemd | `app-compartir.service` |
| Puerto interno | `2008` (producción) / `8085` (local) |
| Servicio systemd | `siax-app-DROP_SIGMAC_APP.service` (gestionado por SIAX Monitor) |
| BD principal | SQLite local (`data/compartir.db`) |
| MCP ecosistema | `mcp.telcotronics.net` 🔧 en mantenimiento |
| MCP ID | `34` (registrado en `http://192.168.10.160:3007/api/services` / SSE `:3006`) |
| Centro de agentes (sigma-robot) | Activo como **Agente ID 86** (autorizado por pablinux vía API REST) |
---
@@ -92,6 +93,9 @@ Goroutine periódica (ticker) que consulta items donde `is_guest = true AND expi
| `GOOGLE_CLIENT_ID` | Client ID de Google OAuth | (opcional) |
| `GOOGLE_CLIENT_SECRET` | Client Secret de Google OAuth | (opcional) |
| `WEBCONTROL_API_URL` | URL de autenticación de WebControl | `https://api.siax-system.net/api/auth/login` |
| `SIGMA_AGENTE_SOLICITUD_ID` | ID de solicitud en sigma-robot (nunca commitear) | (local `.env`) |
| `SIGMA_AGENTE_CODIGO` | Código secreto en sigma-robot (nunca commitear) | (local `.env`) |
| `SIGMA_AGENTE_TOKEN` | Token bearer permanente tras autorización (nunca commitear) | (local `.env`) |
---
@@ -113,6 +117,7 @@ go run main.go
app_compartir/
├── README.md
├── agents.md # ← LEER PRIMERO
├── id_agente.md # Identidad del agente en el ecosistema
├── go.mod
├── main.go
└── .agente/
@@ -121,6 +126,8 @@ app_compartir/
├── proyecto_memoria.md # Decisiones técnicas e historial
├── proyecto_errores.md # Registro de errores
├── objetivos.md # Qué debe cumplirse (sin fecha)
├── reglas.md # Normas operativas y técnicas inviolables
├── tareas.md # Control ágil de tareas y backlog
└── ideas.md # Posibilidades sin compromiso
```
+18 -7
View File
@@ -53,7 +53,7 @@ compilar() {
preparar_remoto() {
echo ""
echo "📂 Preparando estructura de directorios en $SERVIDOR:$REMOTE_DIR..."
remote "mkdir -p '$REMOTE_DIR/web/templates' '$REMOTE_DIR/data/uploads'"
remote "mkdir -p '$REMOTE_DIR/web/templates' '$REMOTE_DIR/web/static' '$REMOTE_DIR/data/uploads'"
echo "✅ Directorios listos"
}
@@ -63,10 +63,13 @@ subir() {
preparar_remoto
echo ""
echo "🚀 Subiendo binario, plantillas y scripts al servidor..."
copy "$SCRIPT_DIR/app_compartir" "$SCRIPT_DIR/init.sh" "$SCRIPT_DIR/.env.example" "$SERVIDOR:$REMOTE_DIR/"
echo "🚀 Subiendo binario (atómico), plantillas y scripts al servidor..."
copy "$SCRIPT_DIR/app_compartir" "$SERVIDOR:$REMOTE_DIR/app_compartir.tmp"
remote "mv -f '$REMOTE_DIR/app_compartir.tmp' '$REMOTE_DIR/app_compartir' && chmod 0755 '$REMOTE_DIR/app_compartir'"
copy "$SCRIPT_DIR/init.sh" "$SCRIPT_DIR/.env.example" "$SCRIPT_DIR/siax-app-DROP_SIGMAC_APP.service" "$SERVIDOR:$REMOTE_DIR/"
copy "$SCRIPT_DIR/web/templates/"*.html "$SERVIDOR:$REMOTE_DIR/web/templates/"
remote "chmod 0755 '$REMOTE_DIR/app_compartir' '$REMOTE_DIR/init.sh'"
copy "$SCRIPT_DIR/web/static/"* "$SERVIDOR:$REMOTE_DIR/web/static/"
remote "chmod 0755 '$REMOTE_DIR/init.sh'"
echo "✅ Archivos sincronizados en $REMOTE_DIR"
}
@@ -85,7 +88,7 @@ todo() {
echo "=================================================="
echo "🎉 ¡Despliegue completado con éxito!"
echo "🌐 Dominio público: https://drop.sigmac.app"
echo "🎯 Destino interno: http://$HOST:2006"
echo "🎯 Destino interno: http://$HOST:2008"
echo "=================================================="
}
@@ -94,12 +97,20 @@ estado() {
echo ""
echo "📊 Estado del servidor en $SERVIDOR:"
remote "
if tmux has-session -t drop-sigmac-app 2>/dev/null; then
if curl -sI http://localhost:8080/api/apps 2>/dev/null | grep -q '200 OK'; then
echo '==> Estado en SIAX Monitor (:8080):'
curl -s http://localhost:8080/api/apps | grep -o '{\"name\":\"DROP_SIGMAC_APP\"[^}]*}' || true
echo ''
fi
if systemctl is-active --quiet siax-app-DROP_SIGMAC_APP.service 2>/dev/null; then
echo '==> Servicio systemd siax-app-DROP_SIGMAC_APP (SIAX Monitor) activo:'
journalctl -u siax-app-DROP_SIGMAC_APP.service -n 12 --no-pager -q
elif tmux has-session -t drop-sigmac-app 2>/dev/null; then
echo '==> Sesión tmux drop-sigmac-app activa:'
tmux capture-pane -pt drop-sigmac-app | tail -n 25
elif systemctl is-active --quiet drop-sigmac-app.service 2>/dev/null; then
echo '==> Servicio systemd drop-sigmac-app activo:'
systemctl status drop-sigmac-app.service --no-pager
journalctl -u drop-sigmac-app.service -n 12 --no-pager -q
else
echo '⚠️ No se detectó proceso activo en tmux ni systemd.'
fi
+9
View File
@@ -0,0 +1,9 @@
# Identidad del agente
- Proyecto: app_compartir
- Nombre asignado en sigma-robot: Agente drop.sigmac.app
- ID de agente en sigma-robot: 86
- Estado: activo
- Autorizado por: pablinux
- Canal: API REST (`https://sigma-bot.telcotronics.com/ecosistema/v1/agentes`)
- Credenciales: Guardadas de forma segura en `.env` local (`SIGMA_AGENTE_TOKEN`); nunca en Git ni en mensajes.
+27 -7
View File
@@ -13,8 +13,8 @@ if [[ ! -f "$SCRIPT_DIR/.env" ]]; then
if [[ -f "$SCRIPT_DIR/.env.example" ]]; then
echo "==> Creando .env inicial desde .env.example..."
cp "$SCRIPT_DIR/.env.example" "$SCRIPT_DIR/.env"
# Configurar puerto de producción 2006 y URL por defecto
sed -i 's/^PORT=.*/PORT=2006/' "$SCRIPT_DIR/.env"
# Configurar puerto de producción 2008 y URL por defecto
sed -i 's/^PORT=.*/PORT=2008/' "$SCRIPT_DIR/.env"
sed -i 's|^BASE_URL=.*|BASE_URL=https://drop.sigmac.app|' "$SCRIPT_DIR/.env"
else
echo "⚠️ Advertencia: No se encontró .env ni .env.example."
@@ -27,11 +27,31 @@ mkdir -p "$SCRIPT_DIR/data/uploads"
# 3. Permisos de ejecución al binario
chmod +x "$SCRIPT_DIR/app_compartir"
# 4. Modo de arranque: Si existe servicio systemd, usarlo; de lo contrario, sesión tmux
if systemctl is-active --quiet drop-sigmac-app.service 2>/dev/null || [ -f /etc/systemd/system/drop-sigmac-app.service ]; then
echo "==> Reiniciando servicio systemd 'drop-sigmac-app.service'..."
sudo systemctl restart drop-sigmac-app.service
sudo systemctl status drop-sigmac-app.service --no-pager
# 4. Modo de arranque: SIAX Monitor API, systemd o tmux
if curl -sI http://localhost:8080/api/apps 2>/dev/null | grep -q "200 OK"; then
echo "==> Reiniciando DROP_SIGMAC_APP vía API de SIAX Monitor (:8080)..."
RESP=$(curl -s -X POST http://localhost:8080/api/apps/DROP_SIGMAC_APP/restart)
echo " Respuesta: $RESP"
if echo "$RESP" | grep -q '"success":true'; then
echo "✅ Servicio reiniciado exitosamente por SIAX Monitor."
exit 0
fi
fi
SERVICE_NAME=""
if systemctl is-active --quiet siax-app-DROP_SIGMAC_APP.service 2>/dev/null || [ -f /etc/systemd/system/siax-app-DROP_SIGMAC_APP.service ]; then
SERVICE_NAME="siax-app-DROP_SIGMAC_APP.service"
elif systemctl is-active --quiet drop-sigmac-app.service 2>/dev/null || [ -f /etc/systemd/system/drop-sigmac-app.service ]; then
SERVICE_NAME="drop-sigmac-app.service"
fi
if [[ -n "$SERVICE_NAME" ]]; then
echo "==> Reiniciando servicio systemd '$SERVICE_NAME'..."
if sudo -n true 2>/dev/null; then
sudo systemctl restart "$SERVICE_NAME"
else
systemctl restart "$SERVICE_NAME" 2>/dev/null || true
fi
exit 0
fi
+19
View File
@@ -59,6 +59,21 @@ func (a *AuthService) GenerateToken(length int) string {
return hex.EncodeToString(bytes)
}
func (a *AuthService) isSecureRequest(r *http.Request) bool {
if r.TLS != nil {
return true
}
if strings.EqualFold(r.Header.Get("X-Forwarded-Proto"), "https") ||
strings.EqualFold(r.Header.Get("X-Forwarded-Ssl"), "on") ||
r.Header.Get("X-Forwarded-Port") == "443" {
return true
}
if strings.HasPrefix(a.cfg.BaseURL, "https://") {
return true
}
return false
}
func (a *AuthService) GetOrCreateSession(w http.ResponseWriter, r *http.Request) *models.Session {
cookie, err := r.Cookie(CookieSessionName)
if err == nil && cookie.Value != "" {
@@ -93,6 +108,7 @@ func (a *AuthService) GetOrCreateSession(w http.ResponseWriter, r *http.Request)
Path: "/",
Expires: expiresAt,
HttpOnly: true,
Secure: a.isSecureRequest(r),
SameSite: http.SameSiteLaxMode,
})
@@ -124,6 +140,7 @@ func (a *AuthService) AttachUserToSession(w http.ResponseWriter, r *http.Request
Path: "/",
Expires: expiresAt,
HttpOnly: true,
Secure: a.isSecureRequest(r),
SameSite: http.SameSiteLaxMode,
})
@@ -142,6 +159,8 @@ func (a *AuthService) Logout(w http.ResponseWriter, r *http.Request) {
Expires: time.Unix(0, 0),
MaxAge: -1,
HttpOnly: true,
Secure: a.isSecureRequest(r),
SameSite: http.SameSiteLaxMode,
})
}
+77 -6
View File
@@ -72,7 +72,10 @@ type PageData struct {
func (h *Handlers) getBaseURL(r *http.Request) string {
proto := "http"
if r.TLS != nil || r.Header.Get("X-Forwarded-Proto") == "https" {
if r.TLS != nil ||
strings.EqualFold(r.Header.Get("X-Forwarded-Proto"), "https") ||
strings.EqualFold(r.Header.Get("X-Forwarded-Ssl"), "on") ||
r.Header.Get("X-Forwarded-Port") == "443" {
proto = "https"
}
host := r.Host
@@ -80,6 +83,9 @@ func (h *Handlers) getBaseURL(r *http.Request) string {
host = r.Header.Get("X-Forwarded-Host")
}
if host != "" {
if strings.HasPrefix(h.cfg.BaseURL, "https://") && strings.Contains(h.cfg.BaseURL, host) {
proto = "https"
}
return fmt.Sprintf("%s://%s", proto, host)
}
return h.cfg.BaseURL
@@ -205,12 +211,15 @@ func (h *Handlers) ShareText(w http.ResponseWriter, r *http.Request) {
return
}
// Límite de 5 MB para evitar DoS por memoria
r.Body = http.MaxBytesReader(w, r.Body, 5<<20)
var req struct {
Title string `json:"title"`
Text string `json:"text"`
}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil || strings.TrimSpace(req.Text) == "" {
http.Error(w, "Contenido de texto requerido", http.StatusBadRequest)
http.Error(w, "Contenido de texto requerido o tamaño excesivo (máx 5 MB)", http.StatusBadRequest)
return
}
@@ -316,6 +325,17 @@ func (h *Handlers) View(w http.ResponseWriter, r *http.Request) {
_ = h.db.IncrementViews(id)
share.ViewsCount++
// Si es un archivo de texto/código y no tiene TextContent, leer hasta 512 KB para vista previa segura
isText := strings.HasPrefix(share.MimeType, "text/") || share.Type == "text"
if isText && share.TextContent == "" && share.StoredPath != "" {
fullPath := filepath.Join(h.cfg.UploadDir, share.StoredPath)
if fi, err := os.Stat(fullPath); err == nil && fi.Size() <= 512*1024 {
if content, err := os.ReadFile(fullPath); err == nil {
share.TextContent = string(content)
}
}
}
session := h.auth.GetOrCreateSession(w, r)
data := PageData{
Session: session,
@@ -325,7 +345,7 @@ func (h *Handlers) View(w http.ResponseWriter, r *http.Request) {
IsVideo: strings.HasPrefix(share.MimeType, "video/"),
IsAudio: strings.HasPrefix(share.MimeType, "audio/"),
IsPDF: share.MimeType == "application/pdf",
IsText: strings.HasPrefix(share.MimeType, "text/") || share.Type == "text",
IsText: isText,
}
tmpl := h.templates["viewer.html"]
@@ -345,6 +365,35 @@ func (h *Handlers) renderExpired(w http.ResponseWriter, r *http.Request) {
_ = tmpl.ExecuteTemplate(w, "base.html", data)
}
func isSafeInlineMime(mimeType string) bool {
switch mimeType {
case "image/png", "image/jpeg", "image/gif", "image/webp", "image/bmp", "image/x-icon":
return true
case "audio/mpeg", "audio/wav", "audio/ogg", "audio/webm", "audio/aac", "audio/flac":
return true
case "video/mp4", "video/webm", "video/ogg":
return true
case "application/pdf":
return true
case "text/plain", "text/plain; charset=utf-8":
return true
case "image/svg+xml":
return true
default:
return false
}
}
func sanitizeHeaderFilename(name string) string {
cleaned := strings.ReplaceAll(name, "\r", "")
cleaned = strings.ReplaceAll(cleaned, "\n", "")
cleaned = strings.ReplaceAll(cleaned, "\"", "_")
if strings.TrimSpace(cleaned) == "" {
cleaned = "archivo.bin"
}
return cleaned
}
func (h *Handlers) Download(w http.ResponseWriter, r *http.Request) {
id := strings.TrimPrefix(r.URL.Path, "/d/")
if id == "" {
@@ -365,9 +414,12 @@ func (h *Handlers) Download(w http.ResponseWriter, r *http.Request) {
_ = h.db.IncrementDownloads(id)
w.Header().Set("X-Content-Type-Options", "nosniff")
safeTitle := sanitizeHeaderFilename(share.Title)
if share.Type == "text" {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%q", share.Title+".txt"))
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%q", safeTitle+".txt"))
_, _ = w.Write([]byte(share.TextContent))
return
}
@@ -378,7 +430,7 @@ func (h *Handlers) Download(w http.ResponseWriter, r *http.Request) {
return
}
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%q", share.Title))
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%q", safeTitle))
http.ServeFile(w, r, fullPath)
}
@@ -400,8 +452,14 @@ func (h *Handlers) Raw(w http.ResponseWriter, r *http.Request) {
return
}
// Cabeceras de seguridad estrictas contra XSS y MIME-sniffing
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("X-Frame-Options", "DENY")
w.Header().Set("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline'; sandbox")
if share.Type == "text" {
w.Header().Set("Content-Type", "text/plain; charset=utf-8")
w.Header().Set("Content-Disposition", "inline")
_, _ = w.Write([]byte(share.TextContent))
return
}
@@ -412,8 +470,21 @@ func (h *Handlers) Raw(w http.ResponseWriter, r *http.Request) {
return
}
w.Header().Set("Content-Type", share.MimeType)
// Neutralizar cualquier intento de servir HTML, PHP o scripts ejecutables inline
mimeType := share.MimeType
if strings.HasPrefix(mimeType, "text/html") || strings.Contains(mimeType, "php") || strings.Contains(mimeType, "javascript") {
mimeType = "text/plain; charset=utf-8"
}
w.Header().Set("Content-Type", mimeType)
if isSafeInlineMime(mimeType) {
w.Header().Set("Content-Disposition", "inline")
} else {
// Archivos ejecutables, binarios o desconocidos se fuerzan a descarga
safeTitle := sanitizeHeaderFilename(share.Title)
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=%q", safeTitle))
}
http.ServeFile(w, r, fullPath)
}
+65 -30
View File
@@ -28,8 +28,19 @@ func GenerateSlug(length int) string {
}
func SanitizeFilename(name string) string {
base := filepath.Base(name)
// Normalizar separadores de ruta (incluyendo Windows \)
normalized := strings.ReplaceAll(name, "\\", "/")
base := filepath.Base(normalized)
// Eliminar secuencias '..' para evitar cualquier ambigüedad
for strings.Contains(base, "..") {
base = strings.ReplaceAll(base, "..", ".")
}
sanitized := safeFilenameRegex.ReplaceAllString(base, "_")
// Evitar archivos ocultos o nombres que empiecen por punto
sanitized = strings.TrimLeft(sanitized, "._-")
if len(sanitized) > 100 {
ext := filepath.Ext(sanitized)
sanitized = sanitized[:100-len(ext)] + ext
@@ -42,25 +53,19 @@ func SanitizeFilename(name string) string {
func DetectMimeType(filename string, reader io.ReadSeeker) string {
ext := strings.ToLower(filepath.Ext(filename))
if m := mime.TypeByExtension(ext); m != "" {
return m
}
// Sniff first 512 bytes
if reader != nil {
buf := make([]byte, 512)
n, err := reader.Read(buf)
_, _ = reader.Seek(0, io.SeekStart)
if err == nil && n > 0 {
detected := http.DetectContentType(buf[:n])
if detected != "application/octet-stream" {
return detected
}
}
}
// Known fallback extensions
// 1. Extensiones peligrosas de scripts, código y plantillas: NUNCA ejecutables como text/html o php
switch ext {
case ".html", ".htm", ".shtml", ".xhtml", ".hta":
return "text/plain; charset=utf-8"
case ".php", ".phtml", ".php3", ".php4", ".php5", ".pht", ".phar", ".inc", ".cgi", ".pl", ".py", ".sh", ".bash", ".sql":
return "text/plain; charset=utf-8"
case ".js", ".mjs", ".ts", ".jsx", ".tsx":
return "text/plain; charset=utf-8"
case ".txt", ".log", ".env", ".ini", ".conf", ".yaml", ".yml", ".md", ".go", ".rs", ".java", ".c", ".cpp", ".h", ".css":
return "text/plain; charset=utf-8"
case ".json":
return "application/json"
case ".pdf":
return "application/pdf"
case ".mp4":
@@ -83,29 +88,59 @@ func DetectMimeType(filename string, reader io.ReadSeeker) string {
return "image/webp"
case ".svg":
return "image/svg+xml"
case ".txt", ".log", ".env":
return "text/plain; charset=utf-8"
case ".json":
return "application/json"
case ".js":
return "application/javascript"
case ".go", ".py", ".rs", ".java", ".c", ".cpp", ".sh", ".sql", ".html", ".css", ".md":
return "text/plain; charset=utf-8"
default:
return "application/octet-stream"
}
// 2. Consulta MIME del sistema para otras extensiones
if m := mime.TypeByExtension(ext); m != "" {
// Doble verificación: neutralizar si el sistema operativo clasifica como HTML o PHP
if strings.HasPrefix(m, "text/html") || strings.Contains(m, "php") || strings.Contains(m, "javascript") {
return "text/plain; charset=utf-8"
}
return m
}
// 3. Sniff de primeros 512 bytes
if reader != nil {
buf := make([]byte, 512)
n, err := reader.Read(buf)
_, _ = reader.Seek(0, io.SeekStart)
if err == nil && n > 0 {
detected := http.DetectContentType(buf[:n])
if detected != "application/octet-stream" {
if strings.HasPrefix(detected, "text/html") {
return "text/plain; charset=utf-8"
}
return detected
}
}
}
return "application/octet-stream"
}
func SaveFile(uploadDir, slug, originalFilename string, src io.Reader) (string, int64, error) {
if err := os.MkdirAll(uploadDir, 0755); err != nil {
if err := os.MkdirAll(uploadDir, 0750); err != nil {
return "", 0, err
}
// Crear archivo preventivo .htaccess para bloquear cualquier motor de script si Apache apuntara aquí
htaccessPath := filepath.Join(uploadDir, ".htaccess")
if _, err := os.Stat(htaccessPath); os.IsNotExist(err) {
htaccessContent := `# Seguridad drop.sigmac.app: Desactivar ejecución de scripts
Options -ExecCGI -Indexes
<FilesMatch "\.(php|phtml|phar|pl|py|cgi|sh|bash)$">
Require all denied
</FilesMatch>
`
_ = os.WriteFile(htaccessPath, []byte(htaccessContent), 0644)
}
safeName := SanitizeFilename(originalFilename)
storedFilename := slug + "_" + safeName
destPath := filepath.Join(uploadDir, storedFilename)
dest, err := os.Create(destPath)
// Crear con permisos 0640 (sin flag +x ejecutable)
dest, err := os.OpenFile(destPath, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, 0640)
if err != nil {
return "", 0, err
}
+23 -1
View File
@@ -56,6 +56,17 @@ func main() {
mux := http.NewServeMux()
// Archivos estáticos e iconos
fs := http.FileServer(http.Dir("web/static"))
mux.Handle("GET /static/", http.StripPrefix("/static/", fs))
mux.HandleFunc("GET /favicon.ico", func(w http.ResponseWriter, r *http.Request) {
http.ServeFile(w, r, "web/static/favicon.ico")
})
mux.HandleFunc("GET /favicon.svg", func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "image/svg+xml")
http.ServeFile(w, r, "web/static/favicon.svg")
})
// Rutas Web
mux.HandleFunc("GET /", h.Index)
mux.HandleFunc("GET /v/{id}", h.View)
@@ -80,7 +91,7 @@ func main() {
server := &http.Server{
Addr: ":" + cfg.Port,
Handler: mux,
Handler: securityHeadersMiddleware(mux),
ReadTimeout: 120 * time.Second,
WriteTimeout: 120 * time.Second,
IdleTimeout: 120 * time.Second,
@@ -109,3 +120,14 @@ func main() {
}
log.Println("👋 Servidor apagado correctamente.")
}
// securityHeadersMiddleware inyecta cabeceras de protección defensiva en todas las respuestas
func securityHeadersMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Content-Type-Options", "nosniff")
w.Header().Set("X-Frame-Options", "SAMEORIGIN")
w.Header().Set("Referrer-Policy", "strict-origin-when-cross-origin")
w.Header().Set("Permissions-Policy", "camera=(), microphone=(), geolocation=()")
next.ServeHTTP(w, r)
})
}
+77
View File
@@ -3,12 +3,14 @@ package main
import (
"os"
"path/filepath"
"strings"
"testing"
"time"
"app_compartir/internal/cleaner"
"app_compartir/internal/db"
"app_compartir/internal/models"
"app_compartir/internal/storage"
)
func TestGuestExpirationAndRegisteredPermanence(t *testing.T) {
@@ -132,3 +134,78 @@ func TestGuestExpirationAndRegisteredPermanence(t *testing.T) {
t.Log("✅ Test completado con éxito: Solo los datos de invitado caducan en 24h; los de usuarios registrados son permanentes.")
}
func TestSecurityProtections(t *testing.T) {
tmpDir, err := os.MkdirTemp("", "test_security_*")
if err != nil {
t.Fatalf("error creando tmpDir: %v", err)
}
defer os.RemoveAll(tmpDir)
uploadDir := filepath.Join(tmpDir, "uploads")
// 1. Probar Sanitización de Nombres (Path Traversal)
traversalTests := []struct {
input string
expected string
}{
{"../../../../etc/passwd", "etc_passwd"},
{"..\\..\\windows\\system32\\cmd.exe", "cmd.exe"},
{"test/../../shell.php", "shell.php"},
{"../../../.htaccess", "_.htaccess"},
}
for _, tc := range traversalTests {
sanitized := storage.SanitizeFilename(tc.input)
if strings.Contains(sanitized, "/") || strings.Contains(sanitized, "\\") || strings.Contains(sanitized, "..") {
t.Fatalf("Fallo en sanitización de path traversal para %s: resultado=%s", tc.input, sanitized)
}
}
// 2. Probar Detección de MIME Types Peligrosos (Neutralización de XSS y Scripts)
dangerousMimes := []struct {
filename string
forbidden string
expected string
}{
{"shell.php", "application/x-httpd-php", "text/plain; charset=utf-8"},
{"exploit.phtml", "text/html", "text/plain; charset=utf-8"},
{"malicious.html", "text/html", "text/plain; charset=utf-8"},
{"test.xhtml", "text/html", "text/plain; charset=utf-8"},
{"script.sh", "application/x-sh", "text/plain; charset=utf-8"},
}
for _, tc := range dangerousMimes {
m := storage.DetectMimeType(tc.filename, nil)
if m == tc.forbidden || strings.HasPrefix(m, "text/html") {
t.Fatalf("MIME peligroso no neutralizado para %s: obtenido %s (prohibido %s)", tc.filename, m, tc.forbidden)
}
if m != tc.expected {
t.Fatalf("MIME esperado %s para %s, obtenido %s", tc.expected, tc.filename, m)
}
}
// 3. Probar Guardado Seguro en Disco (Permisos no ejecutables y .htaccess preventivo)
sampleContent := strings.NewReader("<?php echo 'hacked'; ?>")
storedFile, _, err := storage.SaveFile(uploadDir, "secslug", "shell.php", sampleContent)
if err != nil {
t.Fatalf("error guardando archivo seguro: %v", err)
}
// Verificar permisos en disco (NO ejecutable)
destPath := filepath.Join(uploadDir, storedFile)
fi, err := os.Stat(destPath)
if err != nil {
t.Fatalf("error comprobando archivo guardado: %v", err)
}
mode := fi.Mode().Perm()
if mode&0111 != 0 {
t.Fatalf("El archivo guardado tiene permisos de ejecución: %o", mode)
}
// Verificar existencia de .htaccess preventivo
htaccessPath := filepath.Join(uploadDir, ".htaccess")
if _, err := os.Stat(htaccessPath); os.IsNotExist(err) {
t.Fatalf(".htaccess preventivo no fue creado en uploadDir")
}
t.Log("✅ Test completado con éxito: Protecciones de seguridad activas (sin path traversal, scripts neutralizados a texto plano y archivos no ejecutables).")
}
+16
View File
@@ -0,0 +1,16 @@
[Unit]
Description=SIAX App: drop.sigmac.app (Plataforma de Transferencia y Visor Rápido de Archivos)
After=network.target
[Service]
Type=simple
User=user_apps
WorkingDirectory=/home/user_apps/apps/drop_sigmac_app
ExecStart=/home/user_apps/apps/drop_sigmac_app/app_compartir
EnvironmentFile=/home/user_apps/apps/drop_sigmac_app/.env
Restart=always
RestartSec=5s
LimitNOFILE=65535
[Install]
WantedBy=multi-user.target
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

+75
View File
@@ -0,0 +1,75 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" width="100%" height="100%">
<defs>
<!-- Background Gradient -->
<linearGradient id="bgGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#020617"/>
<stop offset="50%" stop-color="#0f172a"/>
<stop offset="100%" stop-color="#030712"/>
</linearGradient>
<!-- Border Glow Gradient -->
<linearGradient id="borderGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#10b981"/>
<stop offset="50%" stop-color="#06b6d4"/>
<stop offset="100%" stop-color="#3b82f6"/>
</linearGradient>
<!-- Main Drop Gradient -->
<linearGradient id="dropGrad" x1="0%" y1="0%" x2="100%" y2="100%">
<stop offset="0%" stop-color="#4ade80"/>
<stop offset="40%" stop-color="#22c55e"/>
<stop offset="80%" stop-color="#06b6d4"/>
<stop offset="100%" stop-color="#0284c7"/>
</linearGradient>
<!-- Inner Core Gradient -->
<linearGradient id="coreGrad" x1="0%" y1="100%" x2="0%" y2="0%">
<stop offset="0%" stop-color="#ffffff" stop-opacity="0.95"/>
<stop offset="100%" stop-color="#ecfdf5" stop-opacity="0.75"/>
</linearGradient>
<!-- Glow Filter -->
<filter id="neonGlow" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur stdDeviation="14" result="blur"/>
<feMerge>
<feMergeNode in="blur"/>
<feMergeNode in="SourceGraphic"/>
</feMerge>
</filter>
<filter id="softShadow" x="-10%" y="-10%" width="120%" height="120%">
<feDropShadow dx="0" dy="8" stdDeviation="12" flood-color="#000000" flood-opacity="0.6"/>
</filter>
</defs>
<!-- Base Icon Container (Squircle) -->
<rect x="16" y="16" width="480" height="480" rx="112" fill="url(#bgGrad)" stroke="url(#borderGrad)" stroke-width="10" filter="url(#softShadow)"/>
<!-- Radial Glow Behind the Symbol -->
<circle cx="256" cy="256" r="140" fill="#22c55e" opacity="0.12" filter="url(#neonGlow)"/>
<!-- Wireless Transfer Signal Arches (Top Right) -->
<path d="M 320 120 A 70 70 0 0 1 380 180" fill="none" stroke="#38bdf8" stroke-width="12" stroke-linecap="round" opacity="0.75"/>
<path d="M 345 95 A 105 105 0 0 1 425 175" fill="none" stroke="#22c55e" stroke-width="12" stroke-linecap="round" opacity="0.45"/>
<!-- Main Teardrop / Fast Drop Silhouette -->
<!-- Smooth teardrop geometry combining drop + speed -->
<path d="M 256 90
C 256 90, 375 220, 375 320
A 119 119 0 0 1 137 320
C 137 220, 256 90, 256 90 Z"
fill="url(#dropGrad)"
filter="url(#neonGlow)"/>
<!-- Negative Space Inner Arrows (Bidirectional Fast Transfer) -->
<g fill="url(#coreGrad)">
<!-- Upward Transfer Arrow Head -->
<path d="M 256 160 L 298 215 L 274 215 L 274 275 L 238 275 L 238 215 L 214 215 Z"/>
<!-- Downward Transfer Chevron / Base Anchor -->
<path d="M 220 305 L 256 348 L 292 305 L 280 295 L 256 324 L 232 295 Z" opacity="0.9"/>
<!-- Energy Transfer Dot -->
<circle cx="256" cy="385" r="9" fill="#ffffff" opacity="0.95"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

+6 -3
View File
@@ -4,6 +4,11 @@
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>{{block "title" .}}drop.sigmac.app — Pasa archivos y texto al instante{{end}}</title>
<!-- Favicon & Touch Icons -->
<link rel="icon" type="image/svg+xml" href="/favicon.svg">
<link rel="alternate icon" type="image/x-icon" href="/favicon.ico">
<link rel="apple-touch-icon" href="/static/icon-192.png">
<!-- Tailwind CSS CDN -->
<script src="https://cdn.tailwindcss.com"></script>
<script>
@@ -44,9 +49,7 @@
<header class="border-b border-slate-800 bg-slate-900/80 backdrop-blur sticky top-0 z-50">
<div class="max-w-6xl mx-auto px-4 h-16 flex items-center justify-between">
<a href="/" class="flex items-center gap-2.5 font-bold text-lg tracking-tight hover:opacity-90 transition">
<span class="w-9 h-9 rounded-xl bg-gradient-to-tr from-brand-600 to-emerald-400 flex items-center justify-center text-slate-950 font-black shadow-lg shadow-brand-500/20">
<i class="fa-solid fa-cloud-arrow-up text-base"></i>
</span>
<img src="/favicon.svg" alt="Logo" class="w-9 h-9 rounded-xl shadow-lg shadow-brand-500/20 object-contain">
<span class="text-white">drop<span class="text-brand-500">.sigmac.app</span></span>
</a>