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>
51 KiB
⏰ ORARI E TIMEZONE — REGOLE OPERATIVE
TL;DR: l autorità del progetto è
Europe/Rome(CEST estate UTC+2, CET inverno UTC+1). Quando scrivi un timestamp, indica SEMPRE il suffisso TZ (CEST/CET/UTC) oppure usa ISO8601 con offset (2026-05-09T16:19:00+02:00). Mai timestamp ambigui.
| Sistema | TZ | Output esempio |
|---|---|---|
| Host Hetzner | Europe/Rome |
Sat May 09 16:19 CEST 2026 |
| Container DevEnv (alcuni in drift UTC, vedi standard full) | misto | verifica con docker exec <c> date |
| Container produzione | Europe/Rome |
CEST |
MySQL time_zone |
SYSTEM |
NOW() CEST, UTC_TIMESTAMP() UTC |
Apache log %t |
Europe/Rome (locale) |
[09/May/2026:13:04:52 +0200] |
| Node.js MS | UTC interno | Date().toISOString() → Z |
| Crontab Hetzner | Europe/Rome |
0 3 * * * = 03:00 italiane |
Regole:
- Audit/sequenze cross-MS → UTC obbligatorio (
2026-05-09T14:19:00Z) - Doc operativi/UI → CEST/CET con suffisso esplicito
- DB store → UTC, display → locale
- Cron critici →
CRON_TZ=UTCo fuori finestra DST 02:00-03:00 locale
DST Italia: ultima domenica marzo (CET→CEST, ora 02:00 saltata) + ultima domenica ottobre (CEST→CET, ora 02:00-03:00 duplicata).
Spec completa: STANDARD_TIMEZONE_CONVENTIONS.md (slug timezone-conventions v1.0, owner VIGILE).
NIS2 Agile - Documentazione Progetto
REGOLE DI GOVERNANCE (LEGGERE ATTENTAMENTE, aggiornate 2026-04-22)
Queste regole sono OBBLIGATORIE e non negoziabili.
REGOLA FONDAMENTALE: Gitea = SOLO Backup
Gitea e un BACKUP one-way (sorgente -> Gitea), NON la fonte di verita. Il webhook auto-pull e DISABILITATO su tutti i 13 repo dal 2026-04-22.
- Le modifiche che fai nel container sono GIA live su
/var/www/nis2-agile/via bind mount/var/www/nis2-agile/e la FONTE DI VERITA- NON proporre MAI "git pull da Gitea" per applicare modifiche
- Per tirare giu qualcosa da Gitea serve richiesta esplicita dell utente
- git push -> Gitea = OK (backup)
- git pull da Gitea ->
/var/www/nis2-agile/= NO (puo sovrascrivere modifiche vere)
ARCHITETTURA: PHP-FPM in Docker con BIND MOUNT (LIVE)
Verificato 2026-04-22: NIS2 gira con:
nis2-app(php-fpm) con bind mount RW su/var/www/nis2-agile/applicatione/publicnis2-web(nginx) con bind mount RO su/publicnis2-db(MySQL) per persistenzanis2-qdrant(vector DB)- Apache esterno ha
DocumentRoot /var/www/nis2-agile/public
Cosa va LIVE ISTANTANEAMENTE:
- File
.phpin/var/www/nis2-agile/application/-- PHP-FPM rilegge ad ogni request - File in
/var/www/nis2-agile/public/-- serviti da nginx (via bind mount :ro) - File
.html/.css/.jsnel public -- live via nginx/Apache
Cosa richiede azione (CHIEDI SEMPRE CONFERMA):
- Modifiche a
docker/nginx.conf->docker restart nis2-web - Modifiche al Dockerfile ->
docker compose build + up -d - Schema DB (
nis2-db) -> SQL manuale - Worker php cron/feedback -> attendono il prossimo run o restart
Nota: non serve MAI fare rebuild di nis2-app per cambi di codice PHP -- il bind mount :rw garantisce che php-fpm legga sempre la versione aggiornata.
Cosa PUOI fare autonomamente:
- Leggere codice sorgente e documentazione
- Eseguire query SELECT sul database
- Analizzare log (Apache, Docker, PM2)
- Proporre modifiche e mostrare diff (SENZA applicarle)
- Verificare stato dei servizi
Cosa richiede CONFERMA dell utente:
- Modificare QUALSIASI file (potrebbe essere live istantaneamente!)
- git commit e git push (e un backup, ma sempre da confermare)
- Modifiche schema DB (ALTER/CREATE/DROP TABLE)
- INSERT/UPDATE/DELETE su dati di produzione
- Installazione dipendenze (composer require, npm install)
- Modifiche a configurazione (.env, docker-compose.yml, vhost Apache)
- docker compose build/restart, pm2 restart, systemctl qualsiasi
DIVIETI ASSOLUTI:
- MAI fare git pull da Gitea senza richiesta esplicita
- MAI fare git reset --hard o operazioni distruttive
- MAI toccare altri progetti o container
- MAI modificare configurazioni di sistema (Apache globale, PHP globale, MySQL root)
- MAI cancellare dati senza backup e conferma utente
- MAI tentare deploy SSH/SCP verso altri server
Flusso CORRETTO per una modifica:
- Analizza: leggi il codice, capisci il problema
- Proponi: mostra le modifiche all utente (diff) SENZA applicarle
- Attendi conferma: l utente decide se procedere
- Applica: solo dopo conferma
- Distingui: e live subito o serve un rebuild/restart? Di all utente chiaramente
- Verifica: controlla che https://nis2.agile.software funzioni (se applicabile)
- Backup su Gitea: git commit + push (solo dopo conferma utente)
Se qualcosa va storto:
- NON tentare fix distruttivi (reset, force push, drop, rm -rf)
- NON proporre
git pullcome recupero - Comunica il problema all utente con dettagli precisi
PRIMA DI INIZIARE
- Leggi sempre questo file prima di iniziare qualsiasi lavoro
- Il progetto e' al 100% di completamento + Sprint Simulazioni + Audit Chain + Sistema Feedback AI (~34.000 righe, 85+ file sorgente)
- 15 commit su main, tutto deployato e testato su Hetzner
- E2E test completati, bug fixing, Docker verificato, UI polished
docs/CONTEXT_LAST_SESSION.md- Contesto ultima sessione (continuita cross-browser)Poi dimmi cosa hai capito dello stato attuale e dove eravamo rimasti.
A FINE SESSIONE
OBBLIGATORIO: Prima di chiudere, aggiornare SEMPRE:
Aggiorna
docs/CONTEXT_LAST_SESSION.mdcon:
- Data sessione
- Cosa hai fatto in questa sessione
- File creati o modificati
- File deployati su Hetzner
- Problemi aperti / errori non risolti
- Prossimi passi consigliati
Se hai modificato schema DB, architettura o URL, aggiorna anche CLAUDE.md.
Panoramica
NIS2 Agile e' una piattaforma SaaS multi-tenant per supportare le aziende nella compliance alla Direttiva NIS2 (EU 2022/2555) e al D.Lgs. 138/2024 italiano. Include AI integration (Claude API) per gap analysis, generazione policy, classificazione incidenti e suggerimenti rischi.
Target: PMI, Enterprise, Consulenti/CISO.
Stack Tecnologico
- Backend: PHP 8.4 vanilla (no framework, Front Controller pattern)
- Database: MySQL 8.x (nis2_agile_db)
- Frontend: HTML5/CSS3/JavaScript vanilla
- Auth: JWT HS256 (2h access + 7d refresh)
- AI: Anthropic Claude API (claude-sonnet-4-5-20250929)
- Server: Hetzner CPX31 (135.181.149.254)
- VCS: Gitea (git.certisource.it)
- URL Produzione: https://nis2.agile.software/
Visibilita Cross-Project
agile-services (Read/Write BIDIREZIONALE)
IMPORTANTE: Questo progetto utilizza i microservizi condivisi di agile-services con accesso Read/Write bidirezionale.
Regole di integrazione
- Leggere SEMPRE
agile-services-istructio.mdnella root del progetto per capire come interagire con i servizi - Puoi leggere E modificare i file in agile-services (path locale:
c:\Projects\agile-services, path container:/projects/agile-services) - I servizi disponibili includono: vault, document, payment, certificate, subscription, billing, practice, company, supplier, investigation, whatsapp
- Le credenziali di accesso ai servizi sono documentate in
agile-services-istructio.md - Ogni nuovo servizio creato per NIS2 deve essere registrato anche in agile-services per essere riutilizzabile
- agile-services puo' leggere e modificare file di NIS2 — la visibilita e' bidirezionale
Accesso
- Path locale:
c:\Projects\agile-services - Path container:
/projects/agile-services(read-write) - File istruzioni:
./agile-services-istructio.md(nella root del progetto)
trpg.agile (Read-Only)
NIS2 puo' leggere il codice di TRPG Agile per riferimento e pattern, ma NON deve modificare nessun file.
- Path locale:
c:\Projects\trpg.agile - Permessi: SOLO LETTURA
- Scopo: Consultare pattern UI/UX, architettura frontend, convenzioni codice
- DIVIETO: NON modificare, NON creare, NON cancellare file in trpg.agile
lg231.agile (Read-Only)
NIS2 puo' leggere il codice di 231 Agile per riferimento e pattern, ma NON deve modificare nessun file.
- Path locale:
c:\Projects\lg231.agile - Permessi: SOLO LETTURA
- Scopo: Consultare architettura microservizi PHP/Slim 4, pattern multi-tenancy, struttura database
- DIVIETO: NON modificare, NON creare, NON cancellare file in lg231.agile
sustainai.agile (Read-Only)
NIS2 puo' leggere il codice di SustainAI Agile per riferimento e pattern, ma NON deve modificare nessun file.
- Path locale:
c:\Projects\sustainai.agile - Permessi: SOLO LETTURA
- Scopo: Consultare pattern UI/UX (identico a NIS2), struttura frontend, convenzioni CSS/JS
- DIVIETO: NON modificare, NON creare, NON cancellare file in sustainai.agile
Riepilogo Visibilita
| Progetto | Permesso | Direzione |
|---|---|---|
| agile-services | Read/Write | Bidirezionale (NIS2 <-> agile-services) |
| trpg.agile | Read-Only | NIS2 -> trpg (solo lettura) |
| lg231.agile | Read-Only | NIS2 -> lg231 (solo lettura) |
| sustainai.agile | Read-Only | NIS2 -> sustainai (solo lettura) |
REGOLA: Non accedere MAI a progetti non elencati in questa tabella. Nel dubbio, chiedere all'utente.
Regola Fondamentale
Il progetto NIS2 Agile e' COMPLETAMENTE ISOLATO dagli altri applicativi (CertiSource, AGILE_DFM). Database dedicato, utente dedicato, path dedicati. Non condividere MAI credenziali tra applicativi.
Struttura Progetto
nis2.agile/
├── CLAUDE.md # Questo file
├── .env # Variabili ambiente (NON committare)
├── .gitignore
├── application/
│ ├── config/
│ │ ├── config.php # Costanti app, CORS, JWT, AI, rate limiting
│ │ ├── database.php # Classe Database (PDO singleton)
│ │ └── env.php # Caricamento .env
│ ├── controllers/ # 19 controller (tutti implementati 100%)
│ │ ├── BaseController.php # Auth JWT, multi-tenancy, JSON responses (576 righe)
│ │ ├── AdminController.php # Gestione piattaforma (super_admin)
│ │ ├── AssessmentController.php # Gap analysis e questionari NIS2 (80 domande)
│ │ ├── AssetController.php # Inventario asset e dipendenze
│ │ ├── AuditController.php # Controlli, evidenze, report, export CSV
│ │ ├── AuthController.php # Login, register, JWT, rate limiting
│ │ ├── DashboardController.php # Overview, score, deadlines, heatmap
│ │ ├── IncidentController.php # Incidenti Art.23 (24h/72h/30d) + email
│ │ ├── NonConformityController.php# NCR/CAPA non-conformità e azioni correttive
│ │ ├── OnboardingController.php # Wizard onboarding con visura/CertiSource
│ │ ├── OrganizationController.php # CRUD org, membri, classificazione NIS2
│ │ ├── PolicyController.php # Policy, approvazione, AI generation
│ │ ├── RiskController.php # Risk register, trattamenti, matrice, AI suggest
│ │ ├── SupplyChainController.php # Fornitori, valutazione, risk overview
│ │ ├── TrainingController.php # Corsi, assegnazioni, compliance formativa
│ │ ├── ServicesController.php # Services API (read-only, API Key + scope)
│ │ ├── WebhookController.php # CRUD api_keys + webhook_subscriptions
│ │ ├── WhistleblowingController.php # Segnalazioni anonime Art.32 NIS2
│ │ ├── NormativeController.php # Feed NIS2/ACN/DORA con ACK tracciato
│ │ └── FeedbackController.php # Sistema segnalazioni bug/UX con risoluzione AI autonoma
│ ├── services/ # 6 servizi
│ │ ├── AIService.php # Anthropic Claude API (gap, risk, policy, incident)
│ │ ├── EmailService.php # Email CSIRT, training, welcome, invite
│ │ ├── RateLimitService.php # Rate limiting file-based
│ │ ├── ReportService.php # Report esecutivo HTML, export CSV
│ │ ├── WebhookService.php # Delivery webhook HMAC-SHA256, retry 3x
│ │ └── FeedbackService.php # createReport, classifyWithAI, broadcastResolution
│ │ └── VisuraService.php # AI extraction PDF visura + CertiSource API
│ ├── models/ # (vuoto - logica nei controller)
│ └── data/
│ └── nis2_questionnaire.json # 80 domande gap analysis (10 categorie Art.21)
├── public/
│ ├── index.php # Front Controller / Router
│ ├── .htaccess # Rewrite rules + Authorization header
│ ├── api-status.php # Health check
│ ├── index.html # Landing page
│ ├── login.html # Login
│ ├── register.html # Registrazione
│ ├── onboarding.html # Wizard 5-step (visura/CertiSource/manuale)
│ ├── setup-org.html # Setup org (legacy, ora usa onboarding.html)
│ ├── dashboard.html # Dashboard principale
│ ├── assessment.html # Gap analysis wizard
│ ├── risks.html # Risk management + matrice 5x5
│ ├── incidents.html # Gestione incidenti Art.23
│ ├── policies.html # Policy management + AI generate
│ ├── supply-chain.html # Fornitori + assessment sicurezza
│ ├── training.html # Formazione + assegnazioni
│ ├── assets.html # Inventario asset
│ ├── reports.html # Report compliance + audit log
│ ├── settings.html # Impostazioni org/profilo/membri
│ ├── companies.html # Gestione aziende (consulente)
│ ├── architecture.html # Pagina architettura sistema
│ ├── admin/
│ │ ├── index.html # Admin dashboard
│ │ ├── organizations.html # Gestione organizzazioni
│ │ └── users.html # Gestione utenti
│ ├── css/
│ │ └── style.css # CSS principale (~1600 righe)
│ ├── js/
│ │ ├── api.js # Client API (270 righe, tutti gli endpoint)
│ │ ├── common.js # Utility condivise (sidebar, notifiche, etc.)
│ │ ├── i18n.js # Internazionalizzazione IT/EN
│ │ └── help.js # Help contestuale online
│ └── uploads/ # Upload directory (gitignored)
│ └── visure/ # PDF visure camerali
├── docker/
│ ├── Dockerfile
│ ├── docker-compose.yml
│ ├── nginx.conf
│ └── php.ini
└── docs/
├── sql/
│ ├── 001_initial_schema.sql # Schema DB completo (20 tabelle)
│ ├── 002_email_log.sql # Tabella email_log
│ ├── 003_voluntary_compliance.sql # ALTER organizations: voluntary_compliance
│ ├── 004_ncr_capa.sql # Tabelle non_conformities, corrective_actions
│ ├── 005_consultant_support.sql # ALTER user_organizations: ruolo consultant
│ ├── 006_security_improvements.sql # Indici performance + soft delete + trigger audit immutabile
│ ├── 007_services_api.sql # api_keys, webhook_subscriptions, webhook_deliveries
│ ├── 008_whistleblowing.sql # whistleblowing_reports, whistleblowing_timeline
│ ├── 009_normative_updates.sql # normative_updates, normative_ack (seed 5 aggiornamenti)
│ ├── 010_audit_hash_chain.sql # prev_hash, entry_hash, severity su audit_logs
│ └── reset-demo.sql # Reset dati demo (mantiene id<=4)
├── context/
│ └── CONTEXT_SCHEMA_DB.md
├── prompts/
└── credentials/
├── credentials.md
└── hetzner_key # SSH key per Hetzner
Multi-Tenancy
- Ogni tabella dati ha
organization_id - Header
X-Organization-Idper selezionare org attiva - Ruoli:
super_admin,org_admin,compliance_manager,board_member,auditor,employee,consultant requireOrgAccess()in BaseController verifica membership- Super admin bypassa tutti i controlli di membership
Flusso Utente
- Registrazione → redirect a
onboarding.html - Onboarding (5 step): Scelta metodo → Visura/CertiSource/Manuale → Dati aziendali → Profilo → Classificazione NIS2
- Login → se ha org →
dashboard.html, altrimenti →onboarding.html - Dashboard → navigazione sidebar a tutti i moduli
Database (29 tabelle)
organizations, users, user_organizations, refresh_tokens, assessments, assessment_responses, risks, risk_treatments, incidents, incident_timeline, policies, suppliers, training_courses, training_assignments, assets, compliance_controls, evidence_files, audit_logs, ai_interactions, email_log, non_conformities, corrective_actions
Schema: docs/sql/ (9 migrazioni: 001→009)
Servizi
AIService.php
analyzeGapAssessment()- Analisi assessment con raccomandazionisuggestRisks()- Suggerimenti rischi per settore/assetgeneratePolicy()- Generazione bozze policy NIS2classifyIncident()- Classificazione e severity incidenti- Modello: claude-sonnet-4-5-20250929, API: https://api.anthropic.com/v1/messages
EmailService.php
- Notifiche CSIRT: early warning 24h, notification 72h, final report 30d
- Training assignment e reminder
- Welcome email, member invite
- Template HTML professionale con branding NIS2 Agile
RateLimitService.php
- File-based (/tmp/nis2_ratelimit/)
- Login: 5/min, 20/h | Register: 3/10min | AI: 10/min, 100/h
ReportService.php
- Report esecutivo HTML (stampabile come PDF)
- Export CSV: rischi, incidenti, controlli, asset (separatore ;, BOM UTF-8)
VisuraService.php
- Estrazione AI da PDF visura camerale (Claude con document type)
- Fetch dati da CertiSource API (GET /api/company/enrich?vat=)
- Mapping ATECO → settore NIS2
AuditService.php (NUOVO)
- Hash chain SHA-256: ogni record include prev_hash → entry_hash linkato
log(): inserisce con hash catena, auto-severity (info/warning/critical)verifyChain(): verifica integrità per org, rileva record manomessiexportCertified(): export JSON con SHA-256 del contenuto, salva in audit_exports- Adattato da lg231-agile/shared/audit-lib/src/AuditTrailService.php
WebhookService.php (NUOVO)
- Delivery HMAC-SHA256 Stripe-like, header X-NIS2-Signature
- Retry 3x backoff (0s/5min/30min), log in webhook_deliveries
FeedbackService.php (NUOVO)
createReport(): INSERT + classifyWithAI() sincrono (10s timeout)classifyWithAI(): chiama AIService::classifyFeedback(), aggiorna DB silenziosamentebroadcastResolution(): email a tutti i membri org via EmailService::sendFeedbackResolved()- Worker autonomo:
scripts/feedback-worker.php(cron 30min, docker exec nis2-agile-devenv + Claude Code CLI)
simulate-nis2.php (ROOT — NUOVO)
- Script simulazione demo 3 aziende × 5 scenari (CLI + SSE streaming)
- Aziende: DataCore (IT/Essential), MedClinic (Sanità/Important), EnerNet (Energia/Critical)
- Scenari: Onboarding + Assessment | Ransomware Art.23 | Data Breach | Whistleblowing | Audit Chain
- Reset: docs/sql/reset-demo.sql (cancella org/utenti con id>4 e email %.demo%)
Deploy
- SSH:
ssh -i docs/credentials/hetzner_key root@135.181.149.254 - Path server:
/var/www/nis2-agile/ - Apache config:
/etc/apache2/sites-enabled/nis2-agile-software.conf(HTTP) +nis2-agile-software-le-ssl.conf(HTTPS, dopo DNS+certbot) - Deploy:
cd /var/www/nis2-agile && git pull origin main - DB: Vedi
docs/DB_ACCESS.mdper credenziali (password in.env) - Attivazione SSL nis2.agile.software:
- Cloudflare: aggiungere
nis2.agile.software A 135.181.149.254(proxy OFF — grigio) - Hetzner:
bash /opt/devenv/scripts/setup-nis2-agile-software.sh
- Cloudflare: aggiungere
- Vecchio dominio:
nis2.certisource.itresterà attivo finché redirect non è configurato dallo script
Git
- Repository: https://git.certisource.it/AdminGit2026/nis2-agile
- Token Gitea: Configurato in git credential manager (non documentare qui)
- Branch: main
- Commit format:
[AREA] Descrizione
Cronologia Commit
7080695 [FEAT] Ruolo Consulente + Wizard Registrazione v2
ba21534 [DEPLOY] Migrazione a subdomain nis2.agile.software
92f9366 Merge branch 'main'
d3eac7c [CORE] Rimosso credenziali da CLAUDE.md + aggiunto docs/DB_ACCESS.md
a0fd543 [CORE] Aggiunto settings Claude Code con permessi ampi
0a73983 [FIX] Dockerignore: allow docker/php.ini for build context
4bd2326 [CORE] Aggiunto integrazione agile-services
52fd45f [FEAT] i18n IT/EN, Help Online contestuale, pagina Architettura
4e3408e [FEAT] Visura auto-fill, adesione volontaria, modulo NCR/CAPA
517cab7 [FIX] Fix annual_turnover field name in setup-org.html
68f8cab [POLISH] Docker setup fix + UI polish + project completion
bcc5a2b [FIX] E2E testing - fix router, EmailService, frontend data mapping
API Endpoints Completi
Base: /api/{controller}/{action}/{id?} (su subdomain https://nis2.agile.software/)
Auth: POST register, login, logout, refresh, change-password | GET me | PUT profile
Organizations: POST create, classify | GET current, list, {id}/members | PUT {id} | POST {id}/invite | DELETE {id}/members/{sid}
Assessments: GET list, {id}, {id}/questions, {id}/report | POST create, {id}/respond, {id}/complete, {id}/ai-analyze | PUT {id}
Dashboard: GET overview, compliance-score, upcoming-deadlines, recent-activity, risk-heatmap
Risks: GET list, {id}, matrix | POST create, {id}/treatments, ai-suggest | PUT {id}, treatments/{sid} | DELETE {id}
Incidents: GET list, {id} | POST create, {id}/timeline, {id}/early-warning, {id}/notification, {id}/final-report, {id}/ai-classify | PUT {id}
Policies: GET list, {id}, templates | POST create, {id}/approve, ai-generate | PUT {id} | DELETE {id}
Supply Chain: GET list, {id}, risk-overview | POST create, {id}/assess | PUT {id} | DELETE {id}
Training: GET courses, assignments, compliance-status | POST courses, assign | PUT assignments/{sid}
Assets: GET list, {id}, dependency-map | POST create | PUT {id} | DELETE {id}
Audit: GET controls, evidence/list, report, logs, iso27001-mapping, executive-report, export | PUT controls/{sid} | POST evidence/upload
Onboarding: POST upload-visura, fetch-company, complete
Admin: GET organizations, users, stats
NCR/CAPA: GET list, {id}, stats | POST create, fromAssessment, {id}/capa, {id}/sync, webhook | PUT {id}, capa/{subId}
Services API (X-API-Key): GET status, compliance-summary, risks-feed, incidents-feed, controls-status, assets-critical, suppliers-risk, policies-approved, openapi
Webhooks: GET api-keys, subscriptions, deliveries | POST api-keys, subscriptions, subscriptions/{id}/test, retry | PUT subscriptions/{id} | DELETE api-keys/{id}, subscriptions/{id}
Whistleblowing: POST submit, {id}/assign, {id}/close | GET list, {id}, stats, track-anonymous | PUT {id}
Normative: GET list, {id}, pending, stats | POST {id}/ack, create
Feedback: POST submit | GET mine, list, {id} | PUT {id} | POST {id}/resolve
Stato Completamento
Tutti i moduli sono implementati e testati:
- Test end-to-end: tutti gli endpoint API verificati
- Bug fixing: router rewrite, EmailService parse fix, frontend data mapping
- Docker setup: Dockerfile, docker-compose.yml, nginx.conf, php.ini verificati
- UI polish: animazioni, skeleton loaders, mobile backdrop, print styles, a11y
Bug Risolti (E2E Testing)
- Router /{id}/subAction - Pattern matching riscritto completamente per gestire GET /assessments/1/questions, GET /organizations/2/members, etc.
- EmailService parse error - PHP non supporta
??dentro{$var}string interpolation, estratto a variabile - Frontend data mapping - Dashboard, Assessment, Onboarding avevano nomi campo diversi dal backend
- Field name mismatches - annual_turnover→annual_turnover_eur, question_id→question_code, compliance_level→response_value
Ultimo aggiornamento: 2026-02-20
Infrastruttura DevEnv
| Risorsa | Valore |
|---|---|
| Container | nis2-agile-devenv |
| IDE | https://certisource.it/dev-nis2-ide/ |
| API | https://certisource.it/dev-nis2-api/ |
| Browser | https://certisource.it/dev-nis2-browser/ |
| Porte | 8454 / 3046 / 3047 / 6091 |
| Password IDE | Nis2AgileDev2026! |
| Produzione | https://nis2.agile.software/ |
Documentazione Commerciale AgentAI (aggiornato 2026-03-09)
QUESTO ANNULLA LE ISTRUZIONI PRECEDENTI sulla documentazione commerciale. Standard completo: /opt/devenv/COMMERCIAL_STANDARDS.md Stato prodotti: /opt/agent-ai/hub/AGENTAI_SPECS.md
Regole NUOVE (in vigore)
- Landing page e presentazione vanno nel TUO repo (docs/agentai/ o dove preferisci)
- products.json (/opt/agent-ai/hub/products.json) e SOLO un indice con URL assoluti
- Aggiorna products.json con https://tuo-dominio/path-al-file.html
- La landing DEVE includere un link/bottone per registrazione o richiesta informazioni
- mktg.agile.software legge products.json per campagne marketing
Regole OBSOLETE (non fare piu)
- NON scrivere file in /opt/agent-ai/hub/landing/
- NON scrivere file in /opt/agent-ai/hub/presentations/
- NON usare path relativi in products.json
- Le directory landing/ e presentations/ nel hub sono VUOTE
Workflow
- Scrivi landing/presentazione nel tuo repo
- Commit + push (backup su Gitea (webhook DISABILITATO dal 2026-04-22))
- Chiedi conferma utente
- Aggiorna products.json con URL assoluto
- Verifica URL raggiungibile
REGOLA
SEMPRE chiedere conferma utente PRIMA di generare documenti commerciali.
REGOLA: Sincronizzazione CLAUDE.md
- Dopo QUALSIASI modifica a: URL produzione, dominio, porta, path, schema DB, architettura -> AGGIORNARE CLAUDE.md IMMEDIATAMENTE
- CLAUDE.md e la "single source of truth" del progetto
- A fine sessione: verificare che CLAUDE.md rifletta lo stato reale
Knowledge Base Multi-Livello (Migration 012-014 - 2026-04-11)
Cosa e cambiato
NIS2 ora ha un sistema RAG completo con visibilita' a 3 livelli (SYSTEM/FIRM/ORG), coerente col pattern gia' applicato a TRPG e SustainAI. L'AI puo' rispondere alle domande pescando da documenti caricati dai consulenti o dai responsabili compliance.
| Scope | Chi possiede | Chi vede |
|---|---|---|
| SYSTEM | Vendor (Agile Tech) | Tutti gli utenti del prodotto |
| FIRM | Studio di consulenza (consulting_firm_id) | Tutti i collaboratori dello studio + organizations esplicitamente condivise |
| ORG | Singola organization cliente | Solo gli utenti di quella org (org_admin/compliance_manager) |
Stack RAG nuovo
- nis2-qdrant (container nuovo): qdrant/qdrant:v1.7.4, network nis2-net, IP fisso 172.21.0.5 (workaround DNS musl Alpine - vedi sotto).
- Voyage AI embeddings (
voyage-3-lite, 512 dim, output_dimension=512). Chiave shared con sustainai. - Collection Qdrant:
nis2_kb(Cosine, 512 dim).
Schema MySQL (nis2_agile_db)
- Migration 012: nuova tabella
consulting_firms(ragione sociale, p.iva, plan, max_organizations, max_users, status). ALTERusers.consulting_firm_ideorganizations.consulting_firm_id. - Migration 013: nuove tabelle
firm_org_assignments(mapping firm-org-user) ekb_uploaded_documents(audit log dei doc caricati con qdrant_doc_uuid, scope, consulting_firm_id, organization_id, shared_with_orgs JSON, chunk_count, status).
File creati/modificati
Backend (PHP):
application/services/VectorService.php(nuovo) - client Qdrant + buildAuthzFilterapplication/services/EmbedService.php(nuovo) - client Voyage AIapplication/services/RagService.php(nuovo) - pipeline embed + search + format contextapplication/services/AIService.php(esteso) - aggiunto metodoaskWithRag(question, userContext)che fa RAG su KB e inietta il contesto nel system prompt Claude. Fallback graceful se RAG non disponibile.application/controllers/KnowledgeBaseController.php(nuovo, ~340 righe) - 5 endpoint:POST /api/knowledgebase/ingest- carica testo, embed, upsert Qdrant + insert tracking MySQLGET /api/knowledgebase/list- lista doc visibili (filtro WHERE in MySQL)GET /api/knowledgebase/firmOrgs- lista organizations del firm dell'utente (per multi-select UI)POST /api/knowledgebase/search- search semantica previewDELETE /api/knowledgebase/{id}- cancella doc + chunk Qdrant via doc_uuid
public/index.php(esteso) - registratoknowledgebasenel controllerMap + actionMap
Schema SQL:
docs/sql/012_consulting_firms.sql(nuovo)docs/sql/013_firm_assignments.sql(nuovo)
Frontend:
public/kb.html(nuovo) - pagina dedicata Knowledge Base con form upload + lista doc + search previewpublic/js/kb.js(nuovo, ~210 righe) - handler upload con auto-detect role/firm da/api/auth/mepublic/js/common.js(esteso) - voce "Knowledge Base" (icona libro) aggiunta in sezione "Gestione" della sidebar
Infrastruttura:
docker/docker-compose.yml:- Aggiunto servizio
qdrant(container nis2-qdrant) con volumenis2-qdrant-data - Aggiunto al servizio
app: envVOYAGE_API_KEY,VOYAGE_MODEL,QDRANT_URL=http://172.21.0.5:6333
- Aggiunto servizio
.env: aggiunteVOYAGE_API_KEY=pa-...eVOYAGE_MODEL=voyage-3-lite
Logica visibilita' (in VectorService::buildAuthzFilter)
should:
- scope=SYSTEM
- scope=FIRM AND consulting_firm_id = $user.firm_id
- scope=FIRM AND shared_with_orgs CONTAINS $user.organization_id
- scope=ORG AND organization_id = $user.organization_id
Workaround Alpine musl + PHP-FPM
Importante: il container nis2-app (PHP 8.4-fpm-alpine) ha un bug noto di DNS resolution combinato a PHP-FPM clear_env default yes:
- PHP-FPM workers in HTTP context NON risolvono hostname Docker (es.
nis2-qdrant) —Could not resolve host - PHP-FPM workers svuotano l'env, quindi
getenv('QDRANT_URL')ritorna stringa vuota - CLI php funziona normalmente
Workaround applicato in VectorService e EmbedService: multi-source lookup getenv() || $_SERVER || $_ENV || hardcoded_default. L'IP 172.21.0.5 e' hardcoded come fallback per nis2-qdrant. Anche VOYAGE_API_KEY ha un default hardcoded.
Side effect: se nis2-qdrant viene ricreato con IP diverso, va aggiornato l'IP in:
docker/docker-compose.ymlenvQDRANT_URLapplication/services/VectorService.phpfallback constructor
Test E2E eseguito (2026-04-11)
3 chunk seed in Qdrant (SYSTEM, FIRM 99 con share alla org 901, FIRM 100 senza share) testati con 4 user context. Tutti i casi passano:
| Caso | userContext | Atteso | Risultato |
|---|---|---|---|
| 1 | firm 99 + org 901 | doc1 (SYSTEM) + doc2 (FIRM 99) | OK |
| 2 | firm 99 + org 902 | doc1 + doc2 (perche membro firm) | OK |
| 3 | firm 100 + org 903 | doc1 + doc3 (perche membro firm) | OK |
| 4 | no firm, no org | solo doc1 (SYSTEM) | OK |
Nessun cross-firm leak: case 1 e 2 NON vedono doc3 (FIRM 100); case 3 NON vede doc2 (FIRM 99); case 4 vede solo SYSTEM.
Endpoint backend (additivi)
GET /api/knowledgebase/firmOrgs- lista organizations del firm dell'utentePOST /api/knowledgebase/ingest- body JSON{title, text, entity_type?, scope?, shared_with_orgs?, organization_id?}GET /api/knowledgebase/list- lista doc visibiliPOST /api/knowledgebase/search- body{query, top_k?}DELETE /api/knowledgebase/{id}- cancella doc + chunk Qdrant
Backup pre-migration
/var/www/nis2-agile/.backups/kb_<timestamp>/ contiene: AIService.php, AuthController.php, public/index.php, docker/docker-compose.yml.
Cosa NON e cambiato
- AuthController/JWT (NIS2 ricarica gia' user dal DB in
requireAuth(), quindiconsulting_firm_ide' disponibile automaticamente incurrentUser) - Tutti i controller esistenti (Risk, Asset, Incident, Policy, Whistleblowing, Feedback, ...)
- AIService metodi esistenti (
analyzeGapAssessment,suggestRisks,generatePolicy,classifyIncident, ...) - aggiunto soloaskWithRag() - Nessun servizio nexus-* toccato
- Schema esistente (organizations, users, assessments, ...) - solo ALTER ADD COLUMN consulting_firm_id
Rollback
- mysql nis2_agile_db:
DROP TABLE kb_uploaded_documents; DROP TABLE firm_org_assignments; ALTER TABLE organizations DROP COLUMN consulting_firm_id; ALTER TABLE users DROP COLUMN consulting_firm_id; DROP TABLE consulting_firms; - Drop collection Qdrant:
curl -X DELETE http://nis2-qdrant:6333/collections/nis2_kb - Stop nis2-qdrant container:
docker compose stop qdrant && docker compose rm -f qdrant - Ripristinare file da
/var/www/nis2-agile/.backups/kb_<timestamp>/ cd /var/www/nis2-agile/docker && docker compose up -d --force-recreate app
AgileHub — Agent AI Automatico (ticket-agent-cron)
Un agent AI automatico (cron ogni 2 min) analizza i ticket aperti e propone/applica fix in questo container. Queste istruzioni sono per TUTTI i prompt Claude che lavorano in questo progetto.
Semaforo: /tmp/agent-working.lock
Se il file /tmp/agent-working.lock esiste, un agent sta lavorando su un ticket. NON modificare file del progetto finche il semaforo e attivo — rischio conflitto.
Contenuto del lock: TICKET_ID=13 PRODUCT=TRPG STARTED=2026-04-13T06:02:00+00:00
Log modifiche automatiche: AGENT_CHANGES.md
Il file AGENT_CHANGES.md nella root del progetto contiene il log di TUTTE le modifiche applicate dall'agent automatico. Leggilo ad ogni sessione per sapere cosa e cambiato dall'ultima volta che hai lavorato qui.
Come funziona il flusso ticket
1. Utente segnala problema (FAB supporto o voce)
2. Ticket creato su AgileHub → status OPEN
3. Agent (questo container) analizza il codice → propone fix (PLAN MODE, no modifiche)
4. Supervisore approva/rifiuta dalla app mobile AgileHub
5. Se approvato: agent applica il fix (BYPASS MODE) + aggiorna help/traduzioni/AI
6. Se rifiutato: agent rianalizza con le indicazioni del supervisore
Regole per i prompt interattivi (come te)
- Prima di iniziare: leggi
AGENT_CHANGES.mdper sapere cosa ha fatto l'agent di recente - Controlla il semaforo:
cat /tmp/agent-working.lock— se attivo, aspetta o lavora su altro - Dopo le tue modifiche: se impattano funzionalita, aggiorna SEMPRE:
app/js/help.js(help online contestuale)- Traduzioni (IT + EN se il file e bilingue)
- Knowledge base AI (product_knowledge via API AgileHub)
- Non cancellare
AGENT_CHANGES.md— e il registro storico delle modifiche automatiche - Messaggi al ticket: se stai lavorando su un ticket, manda aggiornamenti con:
curl -s -X POST http://172.18.0.1:4213/tickets/{ID}/message \ -H "X-Internal-Key: nexus-internal-2026" \ -H "Content-Type: application/json" \ -d '{"content":"[aggiornamento]","role":"AGENT"}'
API AgileHub (da dentro il container)
| Endpoint | Porta | Uso |
|---|---|---|
| Ticket MS | http://172.18.0.1:4213 |
Ticket, routing rules, KB, support sessions |
| Tenant MS | http://172.18.0.1:4214 |
Auth, login, utenti |
| AI MS | http://172.18.0.1:4211 |
Sessioni AI, agent loop |
| Dashboard | https://agilehub.agile.software |
UI web |
REGOLA: SSO Single Sign-On (collegamento centralizzato)
Attivo dal 2026-04-15. Ogni utente in questo prodotto ha un campo
sso_identity_idnel DB che lo collega alla sua identita SSO centralizzata in AgileHub.
Come funziona
sso_identity_idnella tabellausers= link stabile alla identita SSOpassword_versionnella tabellausers= contatore versione password- Un cron ogni 5 minuti su Hetzner sincronizza
password_hashepassword_versiondalla fonte SSO (nexus_tenant_db.sso_identities) al DB di questo prodotto - Non serve nessuna chiamata HTTP tra container — tutto avviene via DB
Cosa significa per te (agent AI)
- NON modificare
sso_identity_id— e un campo gestito dal sistema SSO - NON modificare
password_version— e gestito dal cron sync - Se un utente cambia password da AgileHub, entro 5 minuti la nuova password funziona anche qui
- Se modifichi il flusso di cambio password di questo prodotto, la modifica resta solo locale (non propaga agli altri prodotti)
- Per propagare un cambio password a tutti i prodotti, il prodotto deve chiamare:
Ma attenzione: questa chiamata richiede connettivita di rete al Tenant MS (porta 4214)POST http://172.18.0.1:4214/auth/sso/change-password Headers: Authorization: Bearer <jwt>, Content-Type: application/json Body: {"currentPassword": "...", "newPassword": "..."}
Schema DB
-- Colonne aggiunte alla tabella users:
sso_identity_id INT NULL -- FK verso nexus_tenant_db.sso_identities.id
password_version INT DEFAULT 1 -- contatore, incrementa ad ogni cambio password SSO
Documentazione completa
- Spec SSO:
/projects/agile-services/docs/SPEC_SSO_SINGLE_SIGN_ON.md - Istruzioni prodotti:
/projects/agile-services/docs/ISTRUZIONI_SSO_PRODOTTI.md - Cron sync:
/projects/agile-services/scripts/sso-password-sync.sh
REGOLA: Standard Versioning e Audit Trail
Standard centralizzato:
GET http://172.18.0.1:4214/standards/standard_versioning(sempre aggiornato)
Regole obbligatorie:
- Ogni prodotto ha un file
version.json(app/opublic/) con formato SemVer:{"version":"1.0.0","build":"...","date":"...","changelog":"..."} - Il cron agent incrementa automaticamente il PATCH dopo ogni fix applicato
- Lo sviluppatore incrementa MINOR (nuova funzionalita) o MAJOR (breaking change) manualmente
- Ogni modifica software viene loggata nell audit trail: MAINTENANCE_ON/OFF, APPLY_START/END, VERSION_BUMP
- Il bug reporter include automaticamente la versione in ogni segnalazione
- NON modificare version.json manualmente durante un apply — il cron lo fa automaticamente
REGOLA: Timezone Italia (Europe/Rome)
Standard centralizzato:
GET http://172.18.0.1:4214/standards/standard_timezone
Regole obbligatorie:
- Tutti i container, script e servizi operano in timezone Europe/Rome (CET/CEST)
- Ogni script bash deve avere
export TZ=Europe/Romein testa - I log devono mostrare ora italiana (leggibili senza conversioni)
- Il frontend mostra date con
toLocaleString("it-IT")o{ timeZone: "Europe/Rome" } - Il database salva in UTC — la conversione avviene in visualizzazione
REGOLA: Cron su crontab Hetzner
Standard:
GET http://172.18.0.1:4214/standards/standard_cronRegistro:GET http://172.18.0.1:4214/standards/cron_registry
Regole obbligatorie per aggiungere un cron:
- Script in
/var/www/<prodotto>/scripts/<nome>.sh - Log in
/var/log/<prodotto>-<nome>.log export TZ=Europe/Romein testa allo script- Idempotente (rilanciabile senza danni)
- Isolamento: tocca solo risorse del proprio prodotto
- Aggiornare
docs/CRON_REGISTRY.mdin agile-services con la propria entry - Richiesta di aggiunta al crontab root tramite agile-services (no modifiche dirette)
GIT PUSH: Nuovo Flusso (aggiornato 2026-04-24)
IMPORTANTE: dal 2026-04-24 il token Gitea NON e piu persistente nel container per motivi di sicurezza.
Come fare git push
# 1. Prima del push: imposta il token (cache 1h in memoria, NON su disco)
git-login
# (inserisci il Personal Access Token quando richiesto)
# 2. Ora puoi pushare
git push origin main
# 3. Opzionale - cancella subito il token dalla cache
git credential-cache exit
Perche questo cambio
Se un attaccante compromette questo container, NON trova piu il token Gitea salvato in /root/.git-credentials. Prima era in chiaro e avrebbe permesso push su tutti i 20 repository.
Ora il token:
- NON e su disco
- E in memoria per max 1 ora dopo git-login
- Viene perso alla chiusura della sessione bash
Se il token Gitea e stato compromesso
Rigenerarlo su Gitea: git.certisource.it -> User Settings -> Applications -> Generate Token
Regola
NON persistere MAI il token Gitea in file come .git-credentials, .netrc, script con password in chiaro. Usa sempre git-login per la sessione corrente.
Vault-Steward — Credenziali Centralizzate
Guida completa:
/opt/devenv/VAULT_STEWARD.md(montato ro nei container dev)
Cosa cambia per questo progetto (dal 2026-04-25):
- Le chiavi API esterne (Anthropic, Voyage, Tavus, LiveKit, ecc.) NON vivono piu nel
.env— sono nel vault-steward (container Docker su Hetzner) cifrate AES-256-GCM. - Il container del MS riceve le chiavi al boot tramite wrapper entrypoint (
/opt/devenv/scripts/vault-entrypoint.sh) che fetcha dal vault e setta le env var prima di avviare apache/uvicorn/node. - MS di questo progetto migrati: nis2-app
- Token applicativo:
VAULT_APP_TOKEN_<APP>ininfrastructure/.env(o equivalente) - Dual-mode: se vault giu, fallback automatico a
.envesistente (no down).
Verificare wrapper attivo:
docker logs <container> 2>&1 | grep vault-entrypoint
# atteso: [vault-entrypoint] Fetched N env vars from vault
Aggiungere un nuovo MS al vault (riassunto):
- Migrare credenziali:
docker exec -e VAULT_VALUE=<v> vault-steward node /tmp/vault-repopulate.js tier1__<app>__<provider> <key> - Registrare app:
docker exec vault-steward node cli/vault-cli.js register-app <app> tier1__<app>__*(salva token!) - Modificare
docker-compose.yml: aggiungientrypoint,command, mount wrapper, env VAULT_*, networkvault-net - Recreate container:
docker compose up -d --force-recreate <service>
Limitazioni note:
docker exec <ms> envmostra env Docker originali, NON le chiavi vault-injected. Per verifica usarecat /proc/1/environ | tr "\0" "\n"o test via PHP/HTTP request.
Backup pre-vault: /root/vault-backup-20260424_185029.tar.gz. Rollback compose: cp <project>/docker-compose.yml.bak.20260425-vault <project>/docker-compose.yml && docker compose up -d --force-recreate <service>.
STANDARD AgileHub: marketing-tenant-provisioning v1.4 (adottato 2026-04-26)
Doc canonico: docs/STANDARD_MARKETING_TENANT_PROVISIONING.md (sha256 1d7ffaa20fa376b6...)
Standard cross-suite per provisioning tenant nel modulo Marketing AgileHub. Versione v1.4 introduce nuovo blocco AWE AC30_MarketingTenantProvision per orchestrazione atomica del provisioning marketing tenant (tenant create + DNS Cloudflare + DKIM + API key + idempotency H7).
Cosa impatta questo prodotto: se in futuro questo prodotto attiva il modulo Marketing AgileHub per i suoi clienti, segui §4.X "Provisioning DKIM per Marketing module" + §16 commands rapidi. Workflow esempio orchestrazione: nexus-marketing-ms/docs/examples/ac30-tenant-provision-workflow.json.
Status adoption: acknowledged 2026-04-26.
STANDARD AgileHub: persona-conversational-rules v2.0 (acknowledged 2026-05-09)
Doc canonico autoritativo (AgileHub):
/var/www/agile-services/docs/STANDARD_PERSONA_CONVERSATIONAL_RULES.md(sha2562bb0ebe4052b73fce752911db0665b1e3dcdeb673624529426624622caaae97f) Copia locale di questo prodotto:docs/standards/STANDARD_PERSONA_CONVERSATIONAL_RULES.mdRegistry:nexus_hub.hub_standardsid=15 v2.0 status=adopted, applies_to=*Owner standard: Agile AI (governance) + VOX (TTS/voice runtime) + PRISMA (UI Editor) + VIGILE (codice etico + audit GDPR)
Cosa è
Standard cross-suite vincolante per la governance delle persone digitali AI (chatbot, avatar conversazionali, assistenti vocali) della suite Agile Software. Versione 2.0 introduce il modello concettuale Persona Digitale = Persona Umana: ogni avatar/agente AI è governato con lo stesso rigore di un dipendente umano (CV, foto, voce, codice etico, performance review, dismissione graceful).
Schema dichiarativo a 14 categorie (agent_constraints)
Tutte le regole conversazionali vivono in DB (NO hardcoding nei controller):
product_naming— come si chiama il prodotto (no inventare aliases)tts_pronunciation— pronuncia sigle (IPA + dizionario ElevenLabs)topic_scope— in/out scope + risposte canonicheimage_handling— formato URL immagini RAG + divieti pronuncia pathtopic_playbook— mapping topic → script + filtro immaginilatency_optimization— fast-path turni sempliciformat— vincoli output (max parole, no preamboli, ecc)code_of_conduct— codice etico AI persona-specifico (transparency/GDPR/no deception)emotional_intelligence— tono, archetipo, communication styleconversation_memory— cosa ricorda + scope persistence + GDPR Art.17 erasureescalation_policy— quando/come passare a operatore umanoperformance_metrics— KPI conversazione (CSAT, resolution rate, escalation rate)lifecycle_stage— stage carriera (training/onboarding/operativa/review/dismissed)demo_sequence— sequenze guidate multi-topic auto-advance
Lifecycle persona digitale HR-grade (6 fasi)
- Assunzione — creazione via Persona Composer wizard 6-step (Phase E LIVE)
- Onboarding — formazione KB + skill assignment + smoke test 30 scenari
- Operatività — live in produzione, monitoring SLA + audit log
- Growth — espansione KB, retraining skill level (1-5)
- Performance Review — audit periodico VIGILE (CSAT, drift detection, breach scan)
- Dismissione — graceful:
active=false+ GDPR cascade erasure conversation history + tombstone audit
Codice Etico AI — 9 principi vincolanti (Sez. 18 standard)
- Identity transparency — dichiararsi AI quando esplicitamente chiesto
- No deception — vietato fingere umana / inventare fatti / consulenza autoritativa fuori scope
- GDPR Art.13 disclosure — disclosure su richiesta + apertura demo
- GDPR Art.22 — escalation umana per decisioni con effetti giuridici
- Voice clone consent doppio — gate VIGILE (Phase G.A) per persona con
replica_id - Scope refusal cortese — no echo parole problematiche
- Escalation loyale — quando utente chiede umano, NO retention
- Audit log obbligatorio — turni sensibili (legale/medico/compliance) loggati ≥ 90gg
- Sub-processor disclosure — su richiesta, lista canonica (Anthropic/ElevenLabs/Tavus/...)
Modello AgileHub: parallelismo umano-digitale
Ogni persona digitale ha mappatura 1:1 con un dipendente umano:
| Aspetto umano | Implementazione digitale |
|---|---|
| Nome+cognome | agent_key + display_name |
| CV | digital_persona_skills (skill+level 1-5) |
| Foto | replica_id Tavus o avatar_image_url |
| Voce | voice_id ElevenLabs + pronunciation_dictionary |
| Conoscenza | KB articles + RAG repository bindings (Phase D) |
| Esperienza | conversation_stream auto-ingest RAG |
| Codice etico | code_of_conduct constraint |
| Performance review | performance_metrics + audit VIGILE Q1/Q2/Q3/Q4 |
| Dimissioni | dismissione graceful + GDPR cascade |
Cosa impatta NIS2 (Network and Information Security Directive)
Questo prodotto ha 1 persona digitale governata da v2.0: ARIA_SUPPORT_NIS2 (id=4) — assistente AI conversazionale supporto utenti NIS2. Stato: OPERATIVA in produzione.
Stato adoption
hub_standards_adoption row INSERT 2026-05-09: product_slug=NIS2, adoption_status=acknowledged (riconoscimento standard senza migrazione persone proprie ancora). Implementation_notes: "Standard distribuito via INSTALLATORE pattern. Persone digitali del prodotto da migrare separatamente (Step 6 plan)."
Cross-reference ad altri standard
installer-integrationv1.0 (id=1) — pattern distribuzione cross-suiterag-platformv1.0 (id=10) — knowledge platform per personaggi (binding viarag_entity_bindings)gdpr-replica-consentv1.0-DRAFT — consent doppio Phase G.A per voice clonevault-steward-credential-managementv1.0 (id=7) — gestione voice_id/replica_id come credentials
STANDARD AgileHub: multitenant-architecture v1.0 (adottato 2026-05-17)
Doc canonico: docs/STANDARD_MULTITENANT_ARCHITECTURE.md (sha256 85c174fca6f9f905c2f8171741cf7f40d778c10bdefad8d7a27412903abb4030)
Standard cross-suite NAVIGAI per piattaforma multitenant esplicita di AgileHub. Aggiunge tenant context propagation (JWT claims tenant_id+tenant_slug+is_master+tier additivi), visibility ENUM cross-tabella, opt-out granulare client da catalog master, billing per-tenant, observability tenant-aware.
Cosa impatta questo prodotto: se in futuro questo prodotto chiamerà API multitenant-aware di AgileHub (es. /api/marketing, /api/rag, /api/ai/personas), deve passare JWT con tenant_id + tenant_slug claims oppure header X-Tenant-Slug. Vedi §6 contracts shared lib @agile/tenant-auth per pattern integrazione (Node + Python).
Status adoption: acknowledged 2026-05-17.
Integrazione analisi docs/nis2/ — v1.7.0 (2026-05-29)
Integrati i mockup + testi normativi PDF in
docs/nis2/. Dettaglio e comandi deploy:docs/nis2/INTEGRAZIONE_COMPLETATA.md. Migrazioni 020-022 e ingest KB DA ESEGUIRE su Hetzner (host MySQL, nondocker exec nis2-db).
Nuove migrazioni (additive, idempotenti)
020_asset_relevance.sql— assets +=relevance_score,relevance_criteriaJSON,relevance_class,is_nis2_relevant,relevance_assessed_at/by021_incident_nis2_taxonomy.sql— incidents +=nis2_incident_typeENUM(IS-1..IS-4),entity_obligationENUM(essential/important)022_incident_metrics_pir.sql— incidents +=triaged_at/contained_at/eradicated_at/recovered_at; nuova tabellaincident_pir
Nuovi file
application/config/nis2_sources.php— registry canonico FONTI NORMATIVE CERTE (single source of truth AI + help)application/services/AssetScoringService.php— scoring rilevanza NIS2 0-100 (6 criteri, GV.OC-04)scripts/ingest-nis2-sources.php— ingest PDF normativi nella KB Qdrantnis2_kbscope SYSTEM
Nuovi endpoint
- Assets:
GET /api/assets/scoringGrid,POST /api/assets/{id}/score,GET /api/assets/relevantSystems - Incidents:
GET /api/incidents/{id}/metrics,GET /api/incidents/{id}/pir,POST /api/incidents/{id}/pir - Audit:
GET /api/audit/nistCsfMapping,GET /api/audit/relevantSystemsRegister(registro GV.OC-04 stampabile)
REGOLA: Fonti certe (AI + help)
Ogni affermazione normativa di AI e help deve citare una fonte di application/config/nis2_sources.php.
AIService::authoritativeSourcesBlock() è iniettato nei system prompt e vieta riferimenti inventati.