{
  "name": "Security incidents",
  "nodes": [
    {
      "parameters": {
        "content": "Recibir XML del escaneo de NMAP, convertirlo, filtrarlo y mapearlo para procesamiento final.",
        "height": 112,
        "width": 304,
        "color": 5
      },
      "type": "n8n-nodes-base.stickyNote",
      "typeVersion": 1,
      "position": [
        -464,
        560
      ],
      "id": "430143d9-4c4d-457c-8bba-d73502d867d9",
      "name": "Sticky Note"
    },
    {
      "parameters": {
        "pollTimes": {
          "item": [
            {
              "mode": "everyMinute"
            }
          ]
        },
        "triggerOn": "specificFolder",
        "folderToWatch": {
          "__rl": true,
          "value": "13NpxBrNndvUDNFDP3VQCyN8FrltHEKY6",
          "mode": "list",
          "cachedResultName": "Store Seguridad",
          "cachedResultUrl": "https://drive.google.com/drive/folders/13NpxBrNndvUDNFDP3VQCyN8FrltHEKY6"
        },
        "event": "fileCreated",
        "options": {}
      },
      "id": "764793f7-eabe-485a-a1bc-38a4077ec2d6",
      "name": "Google Drive Trigger",
      "type": "n8n-nodes-base.googleDriveTrigger",
      "position": [
        -368,
        -48
      ],
      "typeVersion": 1,
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "operation": "download",
        "fileId": {
          "__rl": true,
          "mode": "id",
          "value": "={{ $json.id }}"
        },
        "options": {}
      },
      "id": "7f6cf6ac-51f7-412f-91a9-b21f6a375623",
      "name": "Download file",
      "type": "n8n-nodes-base.googleDrive",
      "position": [
        -160,
        -48
      ],
      "typeVersion": 3,
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "mode": "insert",
        "pineconeIndex": {
          "__rl": true,
          "value": "services-sheet-data",
          "mode": "list",
          "cachedResultName": "services-sheet-data"
        },
        "options": {}
      },
      "id": "1f4eb5cf-7156-4da7-99dd-3904a6e01f09",
      "name": "Pinecone Vector Store",
      "type": "@n8n/n8n-nodes-langchain.vectorStorePinecone",
      "position": [
        432,
        -48
      ],
      "typeVersion": 1.3,
      "credentials": {
        "pineconeApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "textSplittingMode": "custom",
        "options": {
          "metadata": {
            "metadataValues": [
              {
                "name": "file-name",
                "value": "={{ $('Download file').item.json.name }}"
              }
            ]
          }
        }
      },
      "id": "6c85d66d-71d6-45c9-82e8-02284e7127c1",
      "name": "Default Data Loader",
      "type": "@n8n/n8n-nodes-langchain.documentDefaultDataLoader",
      "position": [
        528,
        160
      ],
      "typeVersion": 1.1
    },
    {
      "parameters": {
        "chunkSize": 100,
        "chunkOverlap": 20,
        "options": {}
      },
      "id": "915d5b69-1614-492c-a139-3e13bb1c48ec",
      "name": "Recursive Character Text Splitter1",
      "type": "@n8n/n8n-nodes-langchain.textSplitterRecursiveCharacterTextSplitter",
      "position": [
        528,
        320
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "model": "nvidia/nv-embed-v1",
        "options": {}
      },
      "id": "7e0fd019-6e5f-4ca7-8906-19bdc0b85849",
      "name": "Embeddings OpenAI1",
      "type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
      "position": [
        288,
        272
      ],
      "typeVersion": 1.2,
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "content": "### Procesamiento de documentos & Embeddings\n\nMonitorea la carpeta \"Store Seguridad\" en Google Drive cada minuto. Al detectar un archivo nuevo, lo descarga, extrae el texto del PDF y lo vectoriza usando el modelo nvidia/nv-embed-v1. Los chunks se insertan en el \u00edndice services-sheet-data de Pinecone con el nombre del archivo como metadato.\nUna vez procesado, el archivo se mueve autom\u00e1ticamente a \"Store Seguridad Procesados\" para evitar reprocesamiento.",
        "height": 256,
        "width": 752,
        "color": 5
      },
      "id": "9776ee1f-b7b5-4e27-aa2c-666b1c20dfaa",
      "name": "Sticky Note1",
      "type": "n8n-nodes-base.stickyNote",
      "position": [
        -400,
        -368
      ],
      "typeVersion": 1
    },
    {
      "parameters": {
        "operation": "pdf",
        "options": {}
      },
      "type": "n8n-nodes-base.extractFromFile",
      "typeVersion": 1.1,
      "position": [
        96,
        -48
      ],
      "id": "53449d2f-c16d-40a0-a81d-52aec676983d",
      "name": "Extract from File"
    },
    {
      "parameters": {
        "operation": "move",
        "fileId": {
          "__rl": true,
          "value": "={{ $('Google Drive Trigger').item.json.id }}",
          "mode": "id"
        },
        "driveId": {
          "__rl": true,
          "mode": "list",
          "value": "My Drive"
        },
        "folderId": {
          "__rl": true,
          "value": "1JBOObm5gHj90LRoXTSa2FCXoa_XLYRDs",
          "mode": "list",
          "cachedResultName": "Store Seguridad Procesados",
          "cachedResultUrl": "https://drive.google.com/drive/folders/1JBOObm5gHj90LRoXTSa2FCXoa_XLYRDs"
        }
      },
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 3,
      "position": [
        784,
        -48
      ],
      "id": "3b9b57e9-5d37-4f84-8aa4-db15526a7274",
      "name": "Move file",
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "httpMethod": "POST",
        "path": "scan-results",
        "responseMode": "responseNode",
        "options": {
          "rawBody": true
        }
      },
      "type": "n8n-nodes-base.webhook",
      "typeVersion": 2.1,
      "position": [
        -512,
        752
      ],
      "id": "dac6f73a-f31f-45ef-b6b6-333a0afaf3c3",
      "name": "01 - Webhook Receptor",
      "alwaysOutputData": true
    },
    {
      "parameters": {
        "mode": "retrieve-as-tool",
        "toolDescription": "Utiliza esta herramienta para consultar informaci\u00f3n t\u00e9cnica, vulnerabilidades conocidas, riesgos asociados y recomendaciones de seguridad sobre servicios, productos y versiones detectadas en el escaneo.",
        "pineconeIndex": {
          "__rl": true,
          "value": "services-sheet-data",
          "mode": "list",
          "cachedResultName": "services-sheet-data"
        },
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.vectorStorePinecone",
      "typeVersion": 1.3,
      "position": [
        944,
        864
      ],
      "id": "c502b99d-f646-453d-b110-ae9c4d0b4340",
      "name": "Pinecone Vector Store2",
      "credentials": {
        "pineconeApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "model": "nvidia/nv-embed-v1",
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.embeddingsOpenAi",
      "typeVersion": 1.2,
      "position": [
        944,
        1056
      ],
      "id": "161b2b56-c995-462b-9780-57f3d3888690",
      "name": "Embeddings OpenAI2",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "model": {
          "__rl": true,
          "value": "openai/gpt-oss-20b",
          "mode": "list",
          "cachedResultName": "openai/gpt-oss-20b"
        },
        "builtInTools": {},
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.lmChatOpenAi",
      "typeVersion": 1.3,
      "position": [
        720,
        800
      ],
      "id": "9bb6eb32-4ea4-4b8a-b87d-e96901f3f08c",
      "name": "OpenAI Chat Model",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "conditions": {
          "options": {
            "caseSensitive": true,
            "leftValue": "",
            "typeValidation": "strict",
            "version": 3
          },
          "conditions": [
            {
              "id": "c67a5b0c-153a-4344-91fe-417a3f83b789",
              "leftValue": "={{ $json.headers['content-type'] }}",
              "rightValue": "xml",
              "operator": {
                "type": "string",
                "operation": "contains"
              }
            }
          ],
          "combinator": "and"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.if",
      "typeVersion": 2.3,
      "position": [
        -288,
        752
      ],
      "id": "5235526f-9395-4d85-a9dd-8f679163f5a4",
      "name": "02 - \u00bfContent-Type es XML?"
    },
    {
      "parameters": {
        "respondWith": "json",
        "responseBody": "{\n  \"error\": \"Se esperaba un archivo XML. Aseg\u00farate de enviar Content-Type: application/xml\"\n}",
        "options": {}
      },
      "type": "n8n-nodes-base.respondToWebhook",
      "typeVersion": 1.5,
      "position": [
        -64,
        960
      ],
      "id": "67ba2860-9302-4c42-829a-9d6229f78a67",
      "name": "03 - Error 400: No es XML"
    },
    {
      "parameters": {
        "operation": "xml",
        "options": {}
      },
      "type": "n8n-nodes-base.extractFromFile",
      "typeVersion": 1.1,
      "position": [
        -64,
        560
      ],
      "id": "d2dcc293-e39c-4e55-8b0d-4aa185949768",
      "name": "04 - XML texto a archivo"
    },
    {
      "parameters": {
        "jsCode": "// 1. Capturamos el texto crudo que viene de la IA\nlet rawText = $input.first().json.output[0].content[0].text\n\nif (!rawText) {\n  throw new Error(\"No se recibi\u00f3 texto del nodo de IA anterior.\");\n}\n\n// 2. Limpiamos las marcas de c\u00f3digo Markdown (```json y ```) si existen\nrawText = rawText.replace(/```json/gi, '');\nrawText = rawText.replace(/```/g, '');\nrawText = rawText.trim();\n\n// 3. Convertimos esa cadena de texto limpia en un objeto JSON real de JavaScript\nconst objetoLimpio = JSON.parse(rawText);\n\n// 4. Se lo devolvemos a n8n para que el siguiente nodo lo lea de forma nativa\nreturn objetoLimpio;"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        1936,
        560
      ],
      "id": "f279e7ee-60c1-4c79-9466-847ec7eeb5a5",
      "name": "Code: Parsear Texto a JSON"
    },
    {
      "parameters": {
        "html": "<html>\n<head>\n<style>\n  body { font-family: 'Segoe UI', Arial, sans-serif; color: #2D3748; padding: 45px; background-color: #ffffff; }\n  .header { border-bottom: 4px solid #1A365D; padding-bottom: 15px; margin-bottom: 30px; display: flex; justify-content: space-between; align-items: center; }\n  h1 { color: #1A365D; margin: 0; font-size: 26px; }\n  h2 { color: #2C5282; margin-top: 30px; font-size: 20px; border-bottom: 2px solid #E2E8F0; padding-bottom: 5px; }\n  \n  /* Sistema de alertas visuales para el Estado Global */\n  .status-box { padding: 8px 16px; border-radius: 6px; font-weight: bold; font-size: 14px; text-transform: uppercase; }\n  .Critico { background: #FED7D7; color: #9B2C2C; }\n  .Alerta { background: #FEEBC8; color: #9C4221; }\n  .Seguro { background: #C6F6D5; color: #22543D; }\n  \n  /* Tabla de inventario */\n  table { width: 100%; border-collapse: collapse; margin: 20px 0; }\n  th { background: #F7FAFC; padding: 12px; text-align: left; border-bottom: 2px solid #CBD5E0; color: #4A5568; font-weight: 600; }\n  td { padding: 12px; border-bottom: 1px solid #E2E8F0; font-size: 14px; }\n  .port-badge { background: #EDF2F7; padding: 2px 6px; border-radius: 4px; font-family: monospace; font-size: 12px; }\n  \n  /* Tarjetas de Mitigaci\u00f3n por Host */\n  .host-card { background: #F8FAFC; border: 1px solid #E2E8F0; padding: 20px; border-radius: 8px; margin-bottom: 20px; page-break-inside: avoid; }\n  .host-card h3 { margin-top: 0; margin-bottom: 12px; color: #2B6CB0; font-size: 16px; }\n  .section-title { font-weight: bold; color: #4A5568; margin-top: 8px; display: block; }\n</style>\n</head>\n<body>\n\n  <div class=\"header\">\n    <div>\n      <h1>Reporte Consolidado de Vulnerabilidades</h1>\n      <p style=\"margin: 5px 0 0 0; color: #718096;\">Analizador DevSecOps Automatizado | Fecha: <strong>{{ new Date().toLocaleDateString() }}</strong></p>\n    </div>\n    <div class=\"status-box {{ $json.estado_global }}\">\n      Riesgo: {{ $json.estado_global }}\n    </div>\n  </div>\n\n  <h2>1. Resumen Ejecutivo</h2>\n  <p style=\"line-height: 1.6; font-size: 15px;\">{{ $json.resumen_ejecutivo }}</p>\n\n  <h2>2. Inventario de Superficie de Ataque ({{ $json.conteo_hosts }} Hosts Detectados)</h2>\n  <table>\n    <thead>\n      <tr>\n        <th style=\"width: 25%;\">Direcci\u00f3n IP</th>\n        <th style=\"width: 75%;\">Puertos y Servicios Identificados</th>\n      </tr>\n    </thead>\n    <tbody>\n      {{ $json.detalle_hosts.map(host => `\n      <tr>\n        <td><strong>${host.ip}</strong></td>\n        <td><span class=\"port-badge\">${host.puertos}</span></td>\n      </tr>\n      `).join('') }}\n    </tbody>\n  </table>\n\n  <div style=\"page-break-before: always;\"></div>\n\n  <h2>3. Hallazgos y Planes de Mitigaci\u00f3n</h2>\n  {{ $json.detalle_hosts.map(host => `\n    <div class=\"host-card\">\n      <h3>\ud83d\udea8 Host Destino: ${host.ip}</h3>\n      <p><span class=\"section-title\">\ud83d\udd0d Hallazgos del Escaneo:</span> ${host.hallazgos}</p>\n      <p><span class=\"section-title\">\ud83d\udee1\ufe0f Acciones de Mitigaci\u00f3n Requeridas:</span> ${host.mitigacion}</p>\n    </div>\n  `).join('') }}\n\n</body>\n</html>"
      },
      "type": "n8n-nodes-base.html",
      "typeVersion": 1,
      "position": [
        2128,
        560
      ],
      "id": "c3b2bd9d-c4c3-4bc3-bc8c-26c0d8c684f5",
      "name": "HTML: Renderizar Plantilla"
    },
    {
      "parameters": {
        "method": "POST",
        "url": "https://api.pdfshift.io/v3/convert/pdf",
        "sendHeaders": true,
        "headerParameters": {
          "parameters": [
            {
              "name": "X-API-Key",
              "value": "sk_bd0870b03db031d43d928466e23b753b9890c2e5"
            }
          ]
        },
        "sendBody": true,
        "bodyParameters": {
          "parameters": [
            {
              "name": "source",
              "value": "={{ $json.html }}"
            }
          ]
        },
        "options": {
          "response": {
            "response": {
              "responseFormat": "file"
            }
          }
        }
      },
      "type": "n8n-nodes-base.httpRequest",
      "typeVersion": 4.4,
      "position": [
        2336,
        560
      ],
      "id": "188def6b-03f4-48e3-9aee-3bde6da79859",
      "name": "API: PDFShift (HTML a PDF)"
    },
    {
      "parameters": {
        "name": "=Reporte_Auditoria_{{ $now.toFormat('yyyy_MM_dd') }}.pdf",
        "driveId": {
          "__rl": true,
          "value": "My Drive",
          "mode": "list",
          "cachedResultName": "My Drive",
          "cachedResultUrl": "https://drive.google.com/drive/my-drive"
        },
        "folderId": {
          "__rl": true,
          "value": "1waUel7x50pKeibn9EbfhJELr17A3KnkJ",
          "mode": "list",
          "cachedResultName": "reportes_Seguridad",
          "cachedResultUrl": "https://drive.google.com/drive/folders/1waUel7x50pKeibn9EbfhJELr17A3KnkJ"
        },
        "options": {}
      },
      "type": "n8n-nodes-base.googleDrive",
      "typeVersion": 3,
      "position": [
        2544,
        560
      ],
      "id": "5d84ad6b-8b22-4698-b1dc-982df1391a84",
      "name": "Drive: Guardar Reporte Diario",
      "credentials": {
        "googleDriveOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "modelId": {
          "__rl": true,
          "value": "gpt-4o-mini",
          "mode": "list",
          "cachedResultName": "GPT-4O-MINI"
        },
        "responses": {
          "values": [
            {
              "role": "system",
              "content": "=Act\u00faa como un extractor de datos de seguridad. Tu objetivo es resumir los resultados de la auditor\u00eda en un formato JSON estrictamente v\u00e1lido.\n\nDATOS A PROCESAR:\n{{ JSON.stringify($json) }}\n\nESTRUCTURA JSON REQUERIDA (Responde SOLO el JSON):\n{\n\"resumen_ejecutivo\": \"texto breve del estado general\",\n\"estado_global\": \"Seguro | Alerta | Cr\u00edtico\",\n\"conteo_hosts\": n\u00famero,\n\"detalle_hosts\": [\n{\n\"ip\": \"...\",\n\"puertos\": \"lista de puertos y servicios\",\n\"hallazgos\": \"resumen de 1 p\u00e1rrafo de vulnerabilidades\",\n\"mitigacion\": \"pasos exactos a seguir\"\n}\n]\n}\n\nSi un host no tiene problemas, en 'hallazgos' pon 'Sin vulnerabilidades detectadas'.\""
            }
          ]
        },
        "builtInTools": {},
        "options": {}
      },
      "type": "@n8n/n8n-nodes-langchain.openAi",
      "typeVersion": 2.3,
      "position": [
        1632,
        560
      ],
      "id": "4f989c13-4016-4ce8-a913-012c1c0c0d06",
      "name": "LLM: Redactar Resumen Ejecutivo",
      "credentials": {
        "openAiApi": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "aggregate": "aggregateAllItemData",
        "options": {}
      },
      "id": "4cd9133a-fc50-45ea-a7fc-e5cc84f41c5e",
      "name": "Aggregate: Unificar An\u00e1lisis",
      "type": "n8n-nodes-base.aggregate",
      "typeVersion": 1,
      "position": [
        1456,
        560
      ],
      "notes": "C3: Espera que TODOS los hosts terminen de procesarse y los une en un array. Sin este nodo no hay resumen global."
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "value": "C0BA0NFJXB8",
          "mode": "list",
          "cachedResultName": "incidentes"
        },
        "text": "={{ $json.output }}",
        "otherOptions": {
          "mrkdwn": true
        }
      },
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.5,
      "position": [
        1216,
        560
      ],
      "id": "d867505c-8185-42bd-aab6-d460876b1604",
      "name": "Slack: Notificar Canal Interno",
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      }
    },
    {
      "parameters": {
        "promptType": "define",
        "text": "=Eres un analista experto en ciberseguridad ofensiva y defensiva. Tu tarea es analizar un host espec\u00edfico de un reporte Nmap.\nJSON DEL HOST:\n{{ JSON.stringify($json) }}\n\nREGLAS DE FORMATO (Usa Markdown de Slack):\n- Usa emojis para jerarquizar.\n- Usa negritas (*) para conceptos clave y guiones (-) para las listas. pero los * deben ir pegado a cada letra, nada de espacio\n- Separa las secciones con una l\u00ednea de guiones (-----).\n- No uses tablas complejas, usa listas con vi\u00f1etas.\n\n---\n\ud83d\udea8 REPORTE DE AUDITOR\u00cdA: {{ $json.hosts.ip }} \ud83d\udea8\nFecha: {{ $json.scan_date }}\n---------------------------------------------------\n\ud83d\udd0d An\u00e1lisis de Superficie de Ataque:\n\n\ud83d\udcbb Puertos de Sistema:\n(Lista aqu\u00ed los servicios cr\u00edticos detectados)\n\n\ud83d\uddc4\ufe0f Bases de Datos:\n(Lista aqu\u00ed los servicios de BD y riesgos)\n\n\ud83c\udf10 Servicios Web:\n(Lista aqu\u00ed los servicios web y versiones)\n\n\u26a0\ufe0f Riesgo Global:* [ALTO/MEDIO/BAJO]\n\ud83d\udee0 Acciones Prioritarias:\n- (Recomendaci\u00f3n 1)\n- (Recomendaci\u00f3n 2)",
        "options": {
          "systemMessage": "IMPORTANTE: Si la informaci\u00f3n t\u00e9cnica de Pinecone no menciona vulnerabilidades espec\u00edficas para una versi\u00f3n, no inventes riesgos; clasifica bas\u00e1ndote \u00fanicamente en la exposici\u00f3n del puerto"
        }
      },
      "type": "@n8n/n8n-nodes-langchain.agent",
      "typeVersion": 3.1,
      "position": [
        832,
        560
      ],
      "id": "f895385c-8e3d-4bd1-98cf-fff872570f72",
      "name": "Agent: Analista de Seguridad"
    },
    {
      "parameters": {
        "fieldToSplitOut": "hosts",
        "include": "allOtherFields",
        "options": {}
      },
      "type": "n8n-nodes-base.splitOut",
      "typeVersion": 1,
      "position": [
        560,
        560
      ],
      "id": "59cef263-2bec-4318-9d4e-b087c4950f67",
      "name": "Loop: Separar por Host Afectado"
    },
    {
      "parameters": {
        "jsCode": "function extractIPWithMask(command) {\n  const match = command.match(/\\b(\\d{1,3}(?:\\.\\d{1,3}){3}(?:\\/\\d{1,2})?)\\b/);\n  return match ? match[1] : null;\n}\n\nconst nmapData = $input.first().json.nmaprun;\n\nif (!nmapData) {\n  throw new Error('El XML no tiene formato nmap v\u00e1lido');\n}\n\nreturn {\n  scan_date: nmapData?.startstr,\n  network: extractIPWithMask(nmapData?.args),\n\n  hosts: (nmapData?.host || [])\n    .map(host => {\n      const address = host.address;\n\n      let ipItem;\n\n      if (Array.isArray(address)) {\n        ipItem = address.find(h => h.addrtype === \"ipv4\")?.addr;\n      } else {\n        ipItem = address?.addr;\n      }\n\n      const openPorts = host.ports?.port || [];\n\n      const mappedOpenPorts = openPorts\n        .filter(port => port.state?.state === 'open')\n        .map(port => ({\n          state: port.state?.state,\n          port: port.portid,\n          protocol: port.protocol,\n          service: port.service?.name,\n          product: port.service?.product,\n          cpe: port.service?.cpe,\n          ostype: port.service?.ostype\n        }));\n\n      return {\n        ip: ipItem,\n        openPorts: mappedOpenPorts\n      };\n    })\n\n    // ELIMINA hosts sin puertos abiertos\n    .filter(host => host.openPorts.length > 0)\n};"
      },
      "type": "n8n-nodes-base.code",
      "typeVersion": 2,
      "position": [
        336,
        560
      ],
      "id": "a4b00450-9e5c-4b91-82b5-6e29a274680a",
      "name": "code: Limpieza y Filtro Nmap"
    },
    {
      "parameters": {
        "options": {
          "mergeAttrs": true
        }
      },
      "type": "n8n-nodes-base.xml",
      "typeVersion": 1,
      "position": [
        128,
        560
      ],
      "id": "623a69fa-b196-4f28-b4ae-9e9256cfc103",
      "name": "XML archivo a JSON"
    },
    {
      "parameters": {
        "authentication": "oAuth2",
        "select": "channel",
        "channelId": {
          "__rl": true,
          "value": "C0BA0NFJXB8",
          "mode": "list",
          "cachedResultName": "incidentes"
        },
        "text": "==\ud83d\ude80 *Auditor\u00eda Finalizada con \u00c9xito* El an\u00e1lisis consolidado de la infraestructura ha terminado.\n\ud83d\udcc2 *Reporte:* `{{ $json.name }}`\n\ud83d\udd17 *Enlace en Drive:* {{ $json.webContentLink }}",
        "otherOptions": {
          "mrkdwn": true
        }
      },
      "id": "b14886b5-0567-4800-8754-4d3d22795823",
      "name": "C7 - Slack: Mensaje Cierre",
      "type": "n8n-nodes-base.slack",
      "typeVersion": 2.5,
      "position": [
        2800,
        560
      ],
      "credentials": {
        "slackOAuth2Api": {
          "name": "<your credential>"
        }
      },
      "notes": "C7: Mensaje de cierre en Slack con estad\u00edsticas globales y resumen ejecutivo generado por IA."
    }
  ],
  "connections": {
    "Google Drive Trigger": {
      "main": [
        [
          {
            "node": "Download file",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Download file": {
      "main": [
        [
          {
            "node": "Extract from File",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pinecone Vector Store": {
      "main": [
        [
          {
            "node": "Move file",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Default Data Loader": {
      "ai_document": [
        [
          {
            "node": "Pinecone Vector Store",
            "type": "ai_document",
            "index": 0
          }
        ]
      ]
    },
    "Recursive Character Text Splitter1": {
      "ai_textSplitter": [
        [
          {
            "node": "Default Data Loader",
            "type": "ai_textSplitter",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings OpenAI1": {
      "ai_embedding": [
        [
          {
            "node": "Pinecone Vector Store",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "Extract from File": {
      "main": [
        [
          {
            "node": "Pinecone Vector Store",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "01 - Webhook Receptor": {
      "main": [
        [
          {
            "node": "02 - \u00bfContent-Type es XML?",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Pinecone Vector Store2": {
      "ai_tool": [
        [
          {
            "node": "Agent: Analista de Seguridad",
            "type": "ai_tool",
            "index": 0
          }
        ]
      ]
    },
    "Embeddings OpenAI2": {
      "ai_embedding": [
        [
          {
            "node": "Pinecone Vector Store2",
            "type": "ai_embedding",
            "index": 0
          }
        ]
      ]
    },
    "OpenAI Chat Model": {
      "ai_languageModel": [
        [
          {
            "node": "Agent: Analista de Seguridad",
            "type": "ai_languageModel",
            "index": 0
          }
        ]
      ]
    },
    "02 - \u00bfContent-Type es XML?": {
      "main": [
        [
          {
            "node": "04 - XML texto a archivo",
            "type": "main",
            "index": 0
          }
        ],
        [
          {
            "node": "03 - Error 400: No es XML",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "04 - XML texto a archivo": {
      "main": [
        [
          {
            "node": "XML archivo a JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Code: Parsear Texto a JSON": {
      "main": [
        [
          {
            "node": "HTML: Renderizar Plantilla",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "HTML: Renderizar Plantilla": {
      "main": [
        [
          {
            "node": "API: PDFShift (HTML a PDF)",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "API: PDFShift (HTML a PDF)": {
      "main": [
        [
          {
            "node": "Drive: Guardar Reporte Diario",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "LLM: Redactar Resumen Ejecutivo": {
      "main": [
        [
          {
            "node": "Code: Parsear Texto a JSON",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Aggregate: Unificar An\u00e1lisis": {
      "main": [
        [
          {
            "node": "LLM: Redactar Resumen Ejecutivo",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Slack: Notificar Canal Interno": {
      "main": [
        [
          {
            "node": "Aggregate: Unificar An\u00e1lisis",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Agent: Analista de Seguridad": {
      "main": [
        [
          {
            "node": "Slack: Notificar Canal Interno",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Loop: Separar por Host Afectado": {
      "main": [
        [
          {
            "node": "Agent: Analista de Seguridad",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "code: Limpieza y Filtro Nmap": {
      "main": [
        [
          {
            "node": "Loop: Separar por Host Afectado",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "XML archivo a JSON": {
      "main": [
        [
          {
            "node": "code: Limpieza y Filtro Nmap",
            "type": "main",
            "index": 0
          }
        ]
      ]
    },
    "Drive: Guardar Reporte Diario": {
      "main": [
        [
          {
            "node": "C7 - Slack: Mensaje Cierre",
            "type": "main",
            "index": 0
          }
        ]
      ]
    }
  },
  "active": true,
  "settings": {
    "executionOrder": "v1",
    "binaryMode": "separate",
    "availableInMCP": false,
    "timeSavedMode": "fixed",
    "errorWorkflow": "x64sO6x67AiqtQGp",
    "callerPolicy": "workflowsFromSameOwner"
  },
  "versionId": "5afa7a49-c50b-4e29-a30f-fe6bd6ecafac",
  "meta": {
    "templateCredsSetupCompleted": true
  },
  "nodeGroups": [],
  "id": "olsp8QHULHlVOQbx",
  "tags": []
}