Files
cyber-mawonaj 6978fbb5b8 feat(app) : phase 2 — endpoint /api/alerts, inbox, flows Node-RED
- POST /api/alerts : token Bearer (comparaison temps constant, 503 si non
  configuré), schéma d'alerte PRD §4.4 validé Zod, exempté du SSO dans les hooks
- Persistance alertes.yaml + commits git (réception, « traité »)
- Inbox /alertes : filtres par profil impacté et statut, actions « Marquer
  traité » et « Créer/MAJ fiche » avec pré-remplissage du formulaire registre
  depuis l'alerte (aucun champ licence/capacité inventé)
- nodered-flows/ : 4 flows importables (rss-ingest, license-watch, classifier
  avec le prompt figé du PRD §6 embarqué tel quel, notify) — nœuds core
  uniquement, configuration par variables d'env, README de câblage
- Vérifié : check/lint/test (27) /build verts, autofixer propre, JSON des flows
  et fonctions embarquées validés, test fumée HTTP (201/400/401 sur l'endpoint,
  inbox, traité + commit, pré-remplissage MAJ fiche)
2026-08-01 10:40:18 -04:00

70 lines
2.2 KiB
JSON

[
{
"id": "tab_notify",
"type": "tab",
"label": "veille-ia : notify",
"disabled": false,
"info": "PRD §5.4 — Routage des urgences hautes : notification ntfy (instance locale ou ntfy.sh). Le reste reste en inbox.\n\nVariables d'environnement :\n- NTFY_URL (ex. https://ntfy.sh/mon-topic-secret ou https://ntfy.mon-domaine.tld/veille) — si absent, la notification est ignorée avec un avertissement.\n\nPour l'email SMTP YunoHost : ajouter un noeud e-mail (node-red-node-email, non inclus ici pour rester sans dépendance externe) avec smtp localhost:25."
},
{
"id": "nt_http_in",
"type": "http in",
"z": "tab_notify",
"name": "POST notify",
"url": "/veille-ia/notify",
"method": "post",
"upload": false,
"swaggerDoc": "",
"x": 130,
"y": 100,
"wires": [["nt_formater"]]
},
{
"id": "nt_formater",
"type": "function",
"z": "tab_notify",
"name": "Formater notification",
"func": "const a = msg.alerte || msg.payload || {};\nconst topic = env.get('NTFY_URL');\nif (!topic) {\n node.warn('NTFY_URL non défini : notification ignorée');\n msg.payload = { envoye: false, raison: 'NTFY_URL absent' };\n return [null, msg];\n}\nmsg.method = 'POST';\nmsg.url = topic;\nmsg.headers = {\n 'Title': `veille-ia : ${a.type || 'alerte'}`,\n 'Priority': a.urgence === 'haute' ? '5' : '3',\n 'Tags': 'warning',\n 'content-type': 'text/plain; charset=utf-8'\n};\nmsg.payload = [\n a.titre || '(sans titre)',\n '',\n a.resume || '',\n '',\n ...(a.sources || [])\n].join('\\n');\nreturn [msg, null];",
"outputs": 2,
"timeout": "",
"noerr": 0,
"initialize": "",
"finalize": "",
"libs": [],
"x": 350,
"y": 100,
"wires": [["nt_ntfy"], ["nt_response"]]
},
{
"id": "nt_ntfy",
"type": "http request",
"z": "tab_notify",
"name": "POST ntfy",
"method": "use",
"ret": "txt",
"paytoqs": "ignore",
"url": "",
"tls": "",
"persist": false,
"proxy": "",
"insecureHTTPParser": false,
"authType": "",
"senderr": false,
"headers": [],
"x": 570,
"y": 80,
"wires": [["nt_response"]]
},
{
"id": "nt_response",
"type": "http response",
"z": "tab_notify",
"name": "200",
"statusCode": "200",
"headers": {},
"x": 730,
"y": 100,
"wires": []
}
]