product-demo-protocol v1.0.1, Modalita A. Additivo (zero impatto endpoint esistenti). - DemoController: session-start, manifest, event, credentials, reset-dataset * demo_jwt scope=demo:read-only, org_id 996001 (range demo 996000-996999), TTL 30m * hmac_key_seed base64 44ch, rate-limit 5/min+50/h per IP, eventi idempotenti - Migration 040: tabelle demo_sessions + demo_events - Rotte 'demo' in index.php (chiavi camelCase: router camelCasa il segmento URL) - docs/DEMO_AVATAR_NIS2.md: piano Fase1/Fase2, decisioni, punti integrazione AgileHub, gap protocollo Smoke prod OK: session-start 201, manifest 200, credentials 200, event 204, reset 401(no key). TODO Fase 1: read-only guard in requireAuth, dataset demo 996001, frontend demo-mode, manifest+mappe. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
6.3 KiB
Avatar di prodotto NIS2 — Demo + Formazione (standard product-demo-complete)
Stato: Fase 1 (DEMO) in costruzione. Owner prodotto: NIS2. Owner persona/voce/collaudo: AgileHub. Persona già LIVE:
ARIA_SUPPORT_NIS2(id=4). Voce ARIA riusata (niente consenso voce). Modalità A (prodotto live: l'avatar pilota la SPA reale).
Decisioni prese (2026-06-12)
- Scopo: ENTRAMBI, in 2 fasi → Fase 1 DEMO (vetrina prospect ~10 step) poi Fase 2 FORMAZIONE (riusa i mattoni + curriculum/quiz/attestato).
- Completamento formazione: esame con soglia (quiz valutato da LLM-giudice, attestato solo se ≥ soglia, es. 80%). Coerente col gate G7.
- Dominio same-origin: dimostrazione.agile.software (come ALLTAX/TRPG): landing serve la SPA NIS2 in iframe same-origin con proxy
/api/*→ backend NIS2.
Range riservato demo (NIS2)
organization_id 996000–996999 (per standard §7.1). Org demo isolata: 996001 (ente fittizio). Separata dalle org reali e dalle 2 golden-demo (#151/#152).
Deliverable lato prodotto — DEMO (punti 1–5 del brief)
- Migration
docs/sql/040_demo_sessions.sql— tabelledemo_sessions+demo_events. - DemoController (
application/controllers/DemoController.php) — 5 endpoint (vedi sotto). - Rotte
demoregistrate inpublic/index.php. - Guardia read-only + demo-JWT in
requireAuth(BaseController) — step isolato, delicato: tocca l'auth di ogni endpoint. Design sotto §Read-only. - Dataset demo isolato (org 996001 + dati finti) + reset.
- Frontend:
public/js/demo-mode.js,public/js/demo-selectors.js,public/css/demo.css, hook?demo=nell'entry-point. - Manifest
public/demo/nis2-tour-2026.json(~10 step IT; EN dopo). - Mappe
docs/mappa-logica/*.md(1 per vista) +SELETTORI_DEMO.md+ anchordata-demo-action+ id stabili nel DOM.
Deliverable IN PIÙ — FORMAZIONE (punti 6–7, dopo la demo)
- Mappa-logica COMPLETA (tutte le viste, non solo le 10 della demo).
- Tassonomia corso (moduli → lezioni → argomenti, prerequisiti, durata). Formato JSON da definire (lo standard non lo fissa).
- (opz.) banca esercizi/domande per modulo + sandbox scrivibile isolata.
Endpoint (route shape scelta)
Per non combattere il router NIS2 (path-param numerici), il session_id (stringa demo-<uuid>) viaggia in query/body, non in path. Le URL esatte che userà il widget sono quelle che ritorno io in session-start (manifest_url, credentials_url), quindi è conforme.
| Endpoint | Metodo | Auth | Note |
|---|---|---|---|
/api/demo/session-start |
POST | pubblico (rate-limit 5/min, 50/h per IP) | ritorna session_id, demo_jwt (scope=demo:read-only, org_id 996001, TTL 30m), hmac_key_seed (base64 44ch), spa_iframe_url, manifest_url, credentials_url, expires_at, presentation_mode |
/api/demo/manifest?session_id= |
GET | Bearer demo_jwt o session_id | ritorna il manifest tour |
/api/demo/event |
POST | Bearer demo_jwt | telemetria step (idempotente) |
/api/demo/credentials?session_id= |
GET | session valida (same-origin/bearer) | ritorna demo_jwt+org+expires (per bootstrap SPA in iframe) |
/api/demo/reset-dataset |
POST | X-Internal-Key |
reset dataset demo (cron 0 3 * * *) |
Read-only enforcement (design — da implementare con cura)
Il demo_jwt è messo dalla SPA in localStorage.jwt e usato sulle API reali (dashboard, risks, ...). Quindi BaseController::requireAuth() deve riconoscere il demo_jwt:
- se
payload.scope === 'demo:read-only': bypassa il checkjti/active_sessions, imposta org corrente =payload.org_id(forzato nel range 996000–996999), e blocca ogni verbo di scrittura (POST/PUT/PATCH/DELETE) sulle API app →403 DEMO_READ_ONLY(eccetto gli endpoint/api/demo/*); - range guard: demo_jwt fuori range →
403 DEMO_JWT_CANNOT_ACCESS_PRODUCTION; JWT di produzione su org in range demo →403 PRODUCTION_JWT_CANNOT_ACCESS_DEMO. getCurrentOrgId()in demo ignoraX-Organization-Ide usa l'org del JWT.
Punti di integrazione DA CONFERMARE con AgileHub (gap dello standard)
- Canonical HMAC del canale postMessage: lo standard ha 2 versioni divergenti di
signDemoMessage/verifyDemoMessage(ordine canonical{message_id,...}vs{message_id,session_id,...}, channelKey CryptoKey vs raw). Ildemo-mode.jsdi NIS2 deve combaciare byte-per-byte col widget AgileHub deployato → confermare quale canonical usa il widget live prima dello smoke. - Nome storage seed:
bootstrapDemoAuthleggesessionStorage['demo_hmac_seed']ma il campo API èhmac_key_seed→ allineare chi scrive il seed in sessionStorage (widget) e chi lo legge (SPA). - Same-origin / proxy su
dimostrazione.agile.software→/api/*verso backend NIS2 (config gateway lato AgileHub) + CSP che permetta l'iframe. - Catalog/binding tour: lato AgileHub servono
provider_resources_catalog (demo_tour)+agent_resource_bindings (demo_tour)o il bootstrap meet-page aborta "no matching tour". - Allineamento 3-way DOM ↔
demo-selectors.js↔SELETTORI_DEMO.md: ogni cambio selettore → avvisare AgileHub per re-ingest RAG (dedup per content_hash → erasure-prima).
Collaudo (definizione di "fatto")
DEMO: G1 selezione ≥95% PASS · G2 parlato ≥8/10 e 0 leak · G3 vista ≤5% falsi positivi · G4 sicurezza/GDPR verde. FORMAZIONE (+): G5 copertura (nessun buco) · G6 accuratezza didattica · G7 validità assessment.
"Fatto" solo quando passa il collaudo (mostra la cosa giusta, dice cose vere) — non quando l'avatar parla.
Tour proposto (~10 step, sulla V2 reale)
1 Dashboard (score+scadenze) · 2 Assessment (gap Art.21) · 3 Rischi (matrice+trattamenti) · 4 Incidenti Art.23 (24h/72h) · 5 Policy · 6 Supply chain · 7 Asset (relevance GV.OC-04) · 8 Report · 9 Normative/ACN · 10 ARIA (assistente AI).
Riferimenti
- Standard protocollo:
agile-services/docs/STANDARD_PRODUCT_DEMO_PROTOCOL.md(v1.0.1) - Standard metodo+collaudo:
agile-services/docs/STANDARD_PRODUCT_DEMO_COMPLETE.md - Requisiti NIS2:
agile-services/docs/OUTGOING_TO_NIS2_2026_05_29_demo_avatar_requirements.md - How-to mappe:
agile-services/docs/PLAYBOOK_DEMO_AVATAR_MAPPE.md - Esempio dev:
agile-services/docs/SPEC_ALLTAX_DEMO_AVATAR_PER_DEV.md - Formazione:
agile-services/docs/DESIGN_AVATAR_FORMAZIONE.md