nis2-agile/docs/sql/007_services_api.sql
DevEnv nis2-agile 86e9bdded2 [FEAT] Services API, Webhook, Whistleblowing, Normative + integrazioni
Sprint completo — prodotto presentation-ready:

Services API (read-only, API Key + scope):
- GET /api/services/status|compliance-summary|risks-feed|incidents-feed
- GET /api/services/controls-status|assets-critical|suppliers-risk|policies-approved
- GET /api/services/openapi (spec OpenAPI 3.0.3 JSON)

Webhook Outbound (Stripe-like HMAC-SHA256):
- CRUD api_keys + webhook_subscriptions (Settings → 2 nuovi tab)
- WebhookService: retry 3x backoff (0s/5min/30min), delivery log
- Trigger auto in IncidentController, RiskController, PolicyController
- Delivery log, test ping, processRetry

Nuovi moduli:
- WhistleblowingController (Art.32 NIS2): anonimato garantito, timeline, token tracking
- NormativeController: feed NIS2/ACN/DORA con ACK tracciato per audit

Frontend:
- whistleblowing.html: form submit anonimo/firmato + gestione CISO
- normative.html: feed con presa visione documentata + progress bar ACK
- public/docs/api.html: documentazione API dark theme (Swagger-like)
- settings.html: tab API Keys + tab Webhook
- integrations/: guide per lg231, SustainAI, AllRisk, SIEM (widget + codice)
- Sidebar: Segnalazioni + Normative aggiunte a common.js

DB: migration 007 (api_keys, webhook_subscriptions, webhook_deliveries),
    008 (whistleblowing_reports + timeline),
    009 (normative_updates + normative_ack + seed NIS2/ACN/DORA/ISO)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 13:20:24 +01:00

88 lines
5.1 KiB
SQL

-- ============================================================
-- NIS2 Agile - Migration 007: Services API & Webhooks
-- Tabelle per API Keys esterne, Webhook subscriptions e delivery log
-- ============================================================
-- ── API KEYS ─────────────────────────────────────────────────
-- Chiavi API per accesso esterno ai servizi NIS2
-- Separate dai JWT sessione, con scopo e permessi specifici
CREATE TABLE IF NOT EXISTS api_keys (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
organization_id INT UNSIGNED NOT NULL,
created_by INT UNSIGNED NOT NULL,
name VARCHAR(100) NOT NULL, -- Nome descrittivo es. "SIEM Integration"
key_prefix VARCHAR(12) NOT NULL, -- Prefisso visibile es. "nis2_abc123"
key_hash VARCHAR(64) NOT NULL, -- SHA-256 della chiave completa
scopes JSON NOT NULL, -- Array di scope: ["read:risks","read:incidents","read:all"]
last_used_at TIMESTAMP NULL DEFAULT NULL,
expires_at TIMESTAMP NULL DEFAULT NULL,
is_active TINYINT(1) NOT NULL DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_org (organization_id),
INDEX idx_key_hash (key_hash),
INDEX idx_active (is_active)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ── WEBHOOK SUBSCRIPTIONS ────────────────────────────────────
-- Sottoscrizioni webhook outbound: quando avvengono eventi NIS2,
-- NIS2 notifica sistemi esterni (SIEM, GRC, 231 Agile, SustainAI)
CREATE TABLE IF NOT EXISTS webhook_subscriptions (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
organization_id INT UNSIGNED NOT NULL,
created_by INT UNSIGNED NOT NULL,
name VARCHAR(100) NOT NULL, -- Es. "231 Agile Notify"
url VARCHAR(512) NOT NULL, -- URL destinazione POST
secret VARCHAR(64) NOT NULL, -- Usato per HMAC-SHA256 firma
events JSON NOT NULL, -- Array eventi: ["incident.created","risk.high_created"]
is_active TINYINT(1) NOT NULL DEFAULT 1,
last_triggered_at TIMESTAMP NULL DEFAULT NULL,
failure_count INT UNSIGNED DEFAULT 0, -- Errori consecutivi (auto-pause se >10)
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_org (organization_id),
INDEX idx_active (is_active)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ── WEBHOOK DELIVERIES ───────────────────────────────────────
-- Log di ogni tentativo di consegna webhook (audit + retry)
CREATE TABLE IF NOT EXISTS webhook_deliveries (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
subscription_id INT UNSIGNED NOT NULL,
organization_id INT UNSIGNED NOT NULL,
event_type VARCHAR(60) NOT NULL, -- Es. "incident.created"
event_id VARCHAR(36) NOT NULL, -- UUID dell'evento
payload MEDIUMTEXT NOT NULL, -- JSON payload inviato
status ENUM('pending','delivered','failed','retrying') DEFAULT 'pending',
http_status SMALLINT UNSIGNED NULL, -- Codice HTTP risposta
response_body TEXT NULL, -- Risposta del server (max 2KB)
attempt TINYINT UNSIGNED DEFAULT 1, -- Tentativo corrente (max 3)
next_retry_at TIMESTAMP NULL DEFAULT NULL, -- Prossimo retry schedulato
delivered_at TIMESTAMP NULL DEFAULT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_subscription (subscription_id),
INDEX idx_org (organization_id),
INDEX idx_status (status),
INDEX idx_event (event_type, event_id),
INDEX idx_retry (status, next_retry_at)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- ── FOREIGN KEYS ─────────────────────────────────────────────
ALTER TABLE api_keys
ADD CONSTRAINT fk_apikeys_org FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
ADD CONSTRAINT fk_apikeys_user FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE;
ALTER TABLE webhook_subscriptions
ADD CONSTRAINT fk_webhooksub_org FOREIGN KEY (organization_id) REFERENCES organizations(id) ON DELETE CASCADE,
ADD CONSTRAINT fk_webhooksub_user FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE CASCADE;
ALTER TABLE webhook_deliveries
ADD CONSTRAINT fk_webhookdel_sub FOREIGN KEY (subscription_id) REFERENCES webhook_subscriptions(id) ON DELETE CASCADE;