Commit Graph

31 Commits

Author SHA1 Message Date
DevEnv nis2-agile
5413730b00 [FIX] Policy: UNIQUE(policy_id,version) + diff LCS posizionale (findings review)
- Migrazione 030: UNIQUE uq_policy_version su policy_versions (de-dup prima, idempotente).
  approve() ora usa INSERT ... ON DUPLICATE KEY UPDATE -> riapprovare la stessa versione
  aggiorna lo snapshot invece di duplicarlo. Verificato E2E: 2x approve v1.0 -> 1 sola riga.
- diff(): sostituito il confronto set-based (falsi negativi su righe duplicate/riordino) con
  un vero diff LCS line-by-line con posizioni. Verificato E2E: bump v1->v2 -> added 2, removed 1 corretti.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 11:39:38 +02:00
DevEnv nis2-agile
0dc2a11040 [FEAT] Connettori per-azienda nella card cliente (Evidence Automation) - config in DB, secret nel vault
Richiesta utente: 'le credenziali si configurano nella card per ogni azienda cliente'.
- Migrazione 029: tabella org_connectors (config NON segreta + vault_key_alias + secret_status). NESSUN segreto nel DB.
- OrganizationController: listConnectors/saveConnector/deleteConnector + connectorOrgGuard (org_admin/compliance_manager propria org, o firm che la gestisce, o super_admin)
- Difesa: i campi segreti (client_secret/api_key/...) inviati vengono STRIPPATI prima del salvataggio (verificato E2E: non finiscono nel DB)
- saveConnector ritorna cli_hint col comando vault-cli per caricare il segreto (write-path vault = solo CLI admin, confermato leggendo server.js: solo GET /v1/credentials/*)
- UI: pannello 'Connettori' nella card di companies.html (8 tipi, tenant/client id, toggle attivo, stato segreto, modal)
- Route organizations/{id}/connectors GET/PUT/DELETE (type nel body)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 10:51:44 +02:00
DevEnv nis2-agile
14c06c8881 [FEAT] Policy attestation + versioning/diff (P3 policy management)
- Migrazione 028: policy_versions (snapshot per diff/storico) + policy_attestations (presa visione per versione)
- approve() crea snapshot versione automaticamente
- attest (dipendente prende visione versione corrente), attestations (copertura % membri), pendingAttestations
- versions (storico), diff?from&to (added/removed line-by-line)
- Attestation version-aware: un nuovo bump versione richiede ri-attestazione (verificato E2E)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 10:20:59 +02:00
DevEnv nis2-agile
1a5db30073 [FEAT] Self-assessment fornitori (P3 supply chain) - portale pubblico con token
- Migrazione 027: tabella supplier_questionnaires (token hash, risposte, score, risk_level, scadenza)
- SupplyChainController: sendQuestionnaire (JWT, genera link 30gg), publicQuestionnaire + submitPublicQuestionnaire (NO auth, token), questionnaireStatus
- 8 domande sicurezza Art.21.2.d (ISO27001/MFA/patching/backup/incident/access/encryption/subfornitori) pesate -> score 0-100 -> risk_level + aggiornamento suppliers.risk_score
- public/supplier-assessment.html: portale standalone (no login) per il fornitore
- Pulito route map supplychain (rimossi duplicati + entry malformata PueT + metodi inesistenti)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 10:19:01 +02:00
DevEnv nis2-agile
1be3bd01a4 [FEAT] Risk quantitativo FAIR + KRI dashboard (P2)
Competizione coi GRC enterprise sul risk management quantitativo:
- FairService: simulazione Monte Carlo FAIR (PERT su TEF e Loss Magnitude),
  ALE in EUR con percentili P10/P50/P90 + istogramma, deterministico (seed da input)
- RiskController::computeFair -> POST /risks/{id}/fair (persiste parametri+ALE)
- RiskController::fairRegister -> GET /risks/fairRegister (portfolio ALE EUR)
- KRI: listKri/createKri/updateKri (GET/POST /risks/kri, PUT /risks/kri/{id})
  con stato semaforo green/amber/red su soglie+direzione
- Migrazione 026: risks += parametri FAIR + ale_min/ml/max/mean; nuova tabella kri

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 09:25:46 +02:00
DevEnv nis2-agile
4924075142 [FEAT] Asset import CMDB/cloud + scoring automatico GV.OC-04 (P2)
- AssetScoringService::inferCriteria: euristica 6 criteri da campi CMDB
  (criticality, data_classification, internet_facing, dependencies, regulated)
- AssetController::import (JWT org_admin/compliance_manager) + bulkUpsert condiviso:
  upsert dedup su external_ref, scoring auto GV.OC-04, max 1000 asset/batch
- ServicesController::ingestAssets -> POST /services/assets-ingest (scope ingest:assets) per connettori CMDB/cloud
- Migrazione 025: assets += external_ref + discovery_source + indice univoco dedup
- Route POST:assetsIngest (services) + POST:import (assets)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 09:14:12 +02:00
DevEnv nis2-agile
307993fbad [FEAT] Evidence Automation + Continuous Control Monitoring (P1)
Colma il gap competitivo vs Vanta/Drata (compliance automation):
- ServicesController::ingestEvidence -> POST /services/evidence-ingest (scope ingest:evidence)
  raccolta evidenze automatiche dai connettori (M365/Google/AWS/Azure/IdP/EDR/SIEM), batch fino a 200, upsert idempotente su external_ref
- recomputeControlMonitoring: ricalcolo monitoring_status (healthy/warning/stale/failing) per freschezza+esito
- controlsMonitoring -> GET /services/controls-monitoring (scope read:compliance): coverage + summary semafori
- Migrazione 024: tabella control_evidence_auto + compliance_controls.{monitoring_status,last_checked_at,freshness_days}
- Route POST:evidenceIngest, GET:controlsMonitoring

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 08:55:26 +02:00
DevEnv nis2-agile
21909994c2 [FEAT] Ingestion incidenti SIEM/SOC/EDR (P1) -> endpoint /services/incidents-ingest
- ServicesController::ingestIncident: crea incidente Art.23 da alert esterno (scope ingest:incidents)
- Dedup su external_ref (org+ref), mapSeverity (CVSS/P1-P5/stringhe -> enum)
- Classificazione AI best-effort (classifyIncident: IS-1..4, severity, significativita)
- Deadline Art.23 (24h/72h/30g) su incidenti significativi + webhook dispatch
- Migrazione 023: incidents += source/source_system/external_ref + indice univoco dedup
- Route POST:incidentsIngest in index.php

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-30 08:41:57 +02:00
DevEnv nis2-agile
5c545ea3d0 [FEAT] Integrazione analisi docs/nis2 v1.7.0 — scoring asset, tassonomia incidenti, PIR, NIST CSF, fonti certe
Fase 1 - Asset Relevance Scoring NIS2 (GV.OC-04): metodologia 0-100 a 6 criteri,
  AssetScoringService + endpoint scoringGrid/score/relevantSystems + UI assets.html + registro stampabile.
Fase 2 - Tassonomia incidenti Determina ACN 164179/2025: IS-1..4 + regime essenziale/importante (Allegati 3/4).
Fase 3 - Post-Incident Review (5-Whys) + metriche TTD/TTC/TTR + timestamp di fase.
Fase 4 - Mapping NIST CSF 2.0 (43 controlli) reference-only.
Fonti certe: registry config/nis2_sources.php + grounding AI (vieta riferimenti inventati) +
  citazioni help.js + ingest PDF normativi nella KB RAG (scripts/ingest-nis2-sources.php).
Migrazioni 020/021/022 (additive idempotenti). Fix VectorService IP Qdrant (drift .5->.3).
Analisi concorrenza Evix (docs/EVIX_ANALISI_CONCORRENZA.html, gap-driven).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 17:15:13 +02:00
DevEnv nis2-agile
a7a21faa82 [FEAT] Knowledge Base RAG multi-livello (SYSTEM/FIRM/ORG) + Qdrant + Voyage
- KnowledgeBaseController: ingest, list, firmOrgs, search, delete
- VectorService (Qdrant + buildAuthzFilter), EmbedService (Voyage), RagService (pipeline)
- AIService::askWithRag con fallback graceful
- docker-compose: servizio qdrant + env Voyage (chiave da .env/vault, no hardcoded)
- SQL 012 consulting_firms, 013 firm_assignments + kb_uploaded_documents
- public/kb.html + kb.js (upload, lista, search preview)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 15:44:13 +02:00
DevEnv nis2-agile
9b53ca3ba1 [FEAT] MktgLead getJsonBody + script import-feedback-to-nexus + seed demo agile-tech
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-29 15:42:05 +02:00
DevEnv nis2-agile
e4f9e9179e [FEAT] Allineamento NIS2 ↔ TRPG (Fasi 1-5): SSO + Sessions + Reset + Impersonate + Branding
Implementazione completa del progetto allineamento alla suite Evix (TRPG/lg231),
basato sul doc canonico docs/GAP_TRPG_NIS2_ALIGNMENT.md (5 fasi, 18 gap).

Version 1.0.0 → 1.5.0

Fase 1 — SSO Federation (v1.1.0)
- Migration 015_sso_columns: users.sso_identity_id + password_version
- application/services/SsoHelper.php (client SSO dual-mode, cURL nativo, zero deps)
- AuthController::login() + changePassword() conditional SSO (SSO_MODE=local default)

Fase 2 — Multi-device Sessions (v1.2.0)
- Migration 016_active_sessions: tabella + refresh_tokens.session_jti
- BaseController::requireAuth() verifica jti + last_activity throttle + parseDeviceLabel
- login() genera jti, logout/changePassword revoca selettiva
- GET/DELETE /auth/sessions[/{id}]
- UI settings.html tab Sicurezza con lista device + revoca

Fase 3 — Password Reset + Tenant Switcher (v1.3.0)
- Migration 017_password_reset_tokens (TTL 30min, single-use)
- POST /auth/forgot-password (risposta opaca) + reset-password
- Pagine forgot-password.html + reset-password.html (con strength bar)
- EmailService::sendPasswordReset
- POST /auth/switchContext con rotazione JWT + organization_id claim
- Dropdown tenant in sidebar esposto a tutti gli utenti con ≥2 org

Fase 4 — Impersonate + Preferences + Versioning UI (v1.4.0)
- POST /auth/impersonate (super_admin o consulente stesso firm, TTL 1h, audit)
- Migration 018_user_preferences: users.theme/timezone/notif_email/notif_inapp
- GET/PUT /auth/preferences
- Sidebar footer mostra versione + changelog modal su click

Fase 5 — Branding white-label + Auth-gate (v1.5.0)
- Migration 019_firm_branding (logo/colori/brand_name per consulting firm)
- BrandingController GET /branding/current (auth opzionale) + PUT
- common.js auto-applica CSS variables al boot
- public/js/auth-gate.js (gate password client-side per docs riservati, da TRPG)

Skip motivati:
- G15 demo login: simulator esistenti coprono
- G18 refactor controllers: rinviato (~5gg, valore tecnico solo)

Cron sync SSO: AgileHub Ticket #220 aperto a team AGILEHUB per estendere
sso-password-sync.sh al DB nis2_agile_db. Prerequisito per switch SSO_MODE=dual.

Backup files: tutti i file modificati hanno .bak.pre-{fase}-{ts} sia in DEV
sia in /var/www/nis2-agile/.backups/ su Hetzner (rollback ready).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-29 13:18:35 +02:00
DevEnv nis2-agile
1382530189 [FEAT] Sistema Segnalazioni & Risoluzione AI (feedback)
Adattato da alltax.it — il sistema più maturo testato con utenti reali.

Backend:
- FeedbackController: 6 endpoint (submit, mine, list, show, update, resolve)
- FeedbackService: createReport + classifyWithAI + broadcastResolution
- AIService::classifyFeedback() — 10s timeout, 500 token, JSON puro
- EmailService::sendFeedbackResolved() — broadcast email org
- DB migration 014: tabella feedback_reports

Frontend:
- feedback.js: FAB rosso #EF4444, modal 2 fasi (form → AI → password gate)
- Tab "Le mie segnalazioni" con badge status
- Auto-init su tutte le pagine autenticate (common.js::checkAuth)
- api.js: 6 metodi client; style.css: stili completi

Worker:
- scripts/feedback-worker.php: cron ogni 30 min
  → docker exec nis2-agile-devenv + Claude Code CLI
  → risoluzione autonoma con POST /api/feedback/{id}/resolve

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-10 08:51:52 +01:00
DevEnv nis2-agile
4be541e9b5 [FIX] reset-demo.sql: gestione trigger audit_log + drop/recreate
Il trigger prevent_audit_log_delete blocca DELETE e interrompe lo script.
Fix: drop triggers prima di DELETE audit_logs, poi ricrea.
Richiede esecuzione con utente root MySQL.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 09:51:40 +01:00
DevEnv nis2-agile
eddc2fe79d [FIX] reset-demo.sql: adatta a struttura reale DB (incident_timeline, capa_actions, email_log, users)
- incident_timeline: join su incidents (no organization_id diretto)
- corrective_actions → capa_actions, non_conformity_id → ncr_id
- email_log: filtra per recipient LIKE '%.demo%' (no organization_id)
- users INSERT: first_name/last_name/status → full_name/is_active

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-09 09:04:48 +01:00
DevEnv nis2-agile
c906a6eff3 [DB] Fix migration 013: MySQL 8.0 compat + script deploy idempotente
- Rimosso ADD COLUMN IF NOT EXISTS (non supportato MySQL 8.0 standard)
- Aggiunto deploy_013.sh: script bash idempotente con check information_schema

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 16:48:53 +01:00
DevEnv nis2-agile
cb0988da27 [LICENSE] Gestione licenze marketing + campi commerciali estesi
- licenseExt.html: dashboard marketing per generare/gestire licenze
  Login JWT super_admin, stats strip (totali/usate/orgs/utenti),
  form genera con label/piano/durata/max-aziende/max-utenti/prezzo/reseller,
  lista paginata con filtri stato+canale, dettaglio modale, revoca/rigenera,
  export CSV e copia token/URL
- Migration 013: invites +max_users_per_org, +price_eur, +reseller_name
  organizations +license_max_users (da provisioning)
- InviteController::create() gestisce nuovi campi, validate() espone max_users_per_org
- ServicesController::provision() salva license_max_users nell'org

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 15:34:38 +01:00
DevEnv nis2-agile
612befd66d [INVITE] Sistema inviti/licenze B2B + provisioning con invite_token
- InviteController: CRUD inviti (gen, list, show, revoke, rigenera, validate)
- Token inv_* sha256-hashed, one-shot o multi-use, canali, scadenza
- ServicesController::provision() accetta invite_token al posto di X-Provision-Secret
  Piano e durata forzati dall'invito, markUsed() chiaamto dopo provisioning riuscito
- index.php: routing /api/invites/* aggiunto (controller + action map)
- integrazioniext.html: nuovo tab "Inviti & Licenze" con flow completo, endpoints,
  esempi curl/php, guida lg231 aggiornata con sezione provisioning automatico

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 15:22:25 +01:00
DevEnv nis2-agile
6933e1d3fb [INTEG] Provisioning B2B automatico + fix JWT helpers
- POST /api/services/provision: onboarding automatico tenant da lg231
  - X-Provision-Secret auth (master secret, non org-specific)
  - Crea org (con tutti i dati lg231: P.IVA, ATECO, sede, PEC, fatturato)
  - Crea admin user con password temporanea (must_change_password=1)
  - Genera API Key scope [read:all, write:all, admin:org, sso:login]
  - Emette JWT 2h per apertura immediata UI
  - Callback webhook a lg231 con api_key
  - Idempotent: stessa P.IVA → restituisce org esistente
  - Audit: org.provisioned severity=critical
- config.php: PROVISION_SECRET (env var)
- BaseController: base64UrlEncode/Decode da private → protected
- Migration 011: colonne provisioning + must_change_password + indexes

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 15:02:11 +01:00
DevEnv nis2-agile
3321509d02 [TEST] Bottone Reset+Simula+Testa Tutto + preserva admin Benassati
- test-runner.php: bottone verde scuro in cima al tab Test che esegue
  reset DB → simulazioni → smoke test in sequenza
- reset-demo.sql: INSERT ON DUPLICATE KEY per cristiano.benassati@gmail.com
  (super_admin, Silvia1978!@) — sopravvive a qualsiasi reset
- Tab Credenziali: admin permanente in cima alla tabella

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 14:35:20 +01:00
DevEnv nis2-agile
874eabb6fc [FEAT] Simulazioni Demo + Audit Trail Certificato SHA-256
- 5 scenari reali: Onboarding, Ransomware Art.23, Data Breach Supply Chain,
  Whistleblowing SCADA, Audit Hash Chain Verification
- simulate-nis2.php: 3 aziende (DataCore/MedClinic/EnerNet), 10 fasi, CLI+SSE
- AuditService.php: hash chain SHA-256 stile lg231 (prev_hash+entry_hash)
- Migration 010: prev_hash, entry_hash, severity, performed_by su audit_logs
- AuditController: GET chain-verify + GET export-certified
- reset-demo.sql: reset dati demo idempotente
- public/simulate.html: web runner SSE con console dark-theme
- Sidebar: link Simulazione Demo + Integrazioni

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 13:56:53 +01:00
DevEnv nis2-agile
a8ef41dc35 [FIX] Migration SQL: INT NOT NULL per FK verso organizations/users (signed)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-07 13:22:08 +01:00
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
DevEnv nis2-agile
f5884b32d3 [FIX] Migration 006: usa stored procedure per indici condizionali
Compatibilita' MySQL 8.0: rimosso CREATE INDEX IF NOT EXISTS,
rimosso DELIMITER per trigger (incompatibile con pipe stdin).
Migration semplificata con solo CREATE INDEX e ALTER TABLE IF NOT EXISTS.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 12:08:44 +01:00
DevEnv nis2-agile
a5eb84108a [FIX] Migration 006: usa stored procedure per indici condizionali
Compatibilita' MySQL 8.0: CREATE INDEX IF NOT EXISTS non supportato,
uso procedura helper con check su information_schema.statistics

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 12:05:04 +01:00
DevEnv nis2-agile
18dec35380 [FIX] Migration 006: fix sintassi CREATE INDEX per MySQL 8.0
Sostituito ALTER TABLE ADD INDEX IF NOT EXISTS con CREATE INDEX IF NOT EXISTS
per compatibilita' MySQL 8.0.x

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 12:04:16 +01:00
DevEnv nis2-agile
782389849f [SEC+UX] Hardening sicurezza + miglioramenti UX pre-audit
SICUREZZA:
- index.php: rimosso CORS wildcard in debug mode (solo origini autorizzate)
- AuthController: getClientIP() con X-Forwarded-For sicuro (proxy-aware)
- AuthController: refresh token con SELECT FOR UPDATE in transazione atomica
- AIService: anonimizzazione dati org nei prompt Anthropic API (no nome/fatturato)

UX AUDIT-READY:
- dashboard.html: gauge rinominato 'Avanzamento implementazione misure Art.21'
- incidents.html: decision tree Art.23 con 5 criteri per 'Is Significant?'
- policies.html: banner warning obbligatorio su bozze generate da AI
- risks.html: tooltip dettagliati scala Likelihood/Impact (ISO 27005)
- assessment.html: progress bar % completamento risposta domande

DB:
- migration 006: indici performance + audit_log immutabile (trigger) + soft delete

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 12:01:33 +01:00
DevEnv nis2-agile
7080695d06 [FEAT] Ruolo Consulente + Wizard Registrazione v2
- register.html: step 0 scelta profilo (Azienda / Consulente)
- onboarding.html: wizard 4-step con P.IVA obbligatoria (auto-fetch CertiSource)
- companies.html: nuova dashboard consulente con cards aziende e compliance score
- common.js: org-switcher sidebar + role labels corretti per consulente
- login.html: routing post-login (consulente → companies.html)
- api.js: isConsultant(), setUserRole(), register con user_type
- AuthController: user_type=consultant → role=consultant in users table
- OnboardingController: multi-org per consulente, duplicate VAT check
- 005_consultant_support.sql: aggiunge 'consultant' a user_organizations.role ENUM

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-20 08:53:30 +01:00
4e3408e9f6 [FEAT] Visura auto-fill, adesione volontaria, modulo NCR/CAPA
1. Fix auto-fill visura: mapping corretto suggested_sector e employees_range,
   indicatori visivi verdi sui campi auto-compilati, fatturato sempre manuale
2. Adesione volontaria: colonna voluntary_compliance, checkbox in onboarding
   step 5 quando not_applicable, toggle in settings, reset su ri-classificazione
3. Modulo NCR/CAPA: NonConformityController con 10 endpoint API,
   tabelle non_conformities + capa_actions, generazione NCR dai gap assessment,
   predisposizione integrazione SistemiG.agile (webhook + sync)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-18 08:12:57 +01:00
6f4b457ce0 [FEAT] Add EmailService, RateLimitService, ReportService + integrations
Services:
- EmailService: CSIRT notifications (24h/72h/30d), training alerts, welcome email
- RateLimitService: File-based rate limiting for auth and AI endpoints
- ReportService: Executive HTML report, CSV exports (risks/incidents/controls/assets)

Integrations:
- AuthController: Rate limiting on login (5/min, 20/h) and register (3/10min)
- IncidentController: Email notifications on CSIRT milestones
- AuditController: Executive report and CSV export endpoints
- Router: 429 rate limit error handling, new audit export routes

Database:
- Migration 002: email_log table for notification tracking

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 19:12:46 +01:00
ae78a2f7f4 [CORE] Initial project scaffold - NIS2 Agile Compliance Platform
Complete MVP implementation including:
- PHP 8.4 backend with Front Controller pattern (80+ API endpoints)
- Multi-tenant architecture with organization_id isolation
- JWT authentication (HS256, 2h access + 7d refresh tokens)
- 14 controllers: Auth, Organization, Assessment, Dashboard, Risk,
  Incident, Policy, SupplyChain, Training, Asset, Audit, Admin
- AI Service integration (Anthropic Claude API) for gap analysis,
  risk suggestions, policy generation, incident classification
- NIS2 gap analysis questionnaire (~80 questions, 10 categories)
- MySQL schema (20 tables) with NIS2 Art. 21 compliance controls
- NIS2 Art. 23 incident reporting workflow (24h/72h/30d)
- Frontend: login, register, dashboard, assessment wizard, org setup
- Docker configuration (PHP-FPM + Nginx + MySQL)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-17 17:50:18 +01:00