Files
nis2-agile/docs/mappa-logica/14_kb.md
T
DevEnv nis2-agileandClaude Opus 4.8 4dfab2a391 [FORMAZIONE] Avatar di prodotto — mappa-logica COMPLETA (22 viste) + SELETTORI_DEMO + tassonomia corso + fix kb.js
Deliverable formazione-first (DESIGN_AVATAR_FORMAZIONE / product-demo-complete):
- docs/mappa-logica/01..22_*.md: tutte le viste app V2 mappate (formato canonico standard §2),
  selettori VERIFICATI sul DOM reale, endpoint verificati su api.js/script, gate ruolo dai controller
- docs/mappa-logica/SELETTORI_DEMO.md: registry canonico (22 viste, 131 visualizzazione + 89 azioni)
  + worklist consolidata 132 id stabili da aggiungere (modifiche chirurgiche future)
- docs/formazione/TASSONOMIA_CORSO_NIS2.{md,json}: 10 moduli / 28 lezioni / ~7h45, prerequisiti+durate,
  esame con soglia 80%, sandbox 'prova tu' org 996002
- fix kb.js: ingest scope=ORG ora invia organization_id (prima 422 KB_ORG_REQUIRED) — bug trovato da A2

Prodotto con 4 trittici di agenti (A1 esecutore -> A2 revisore -> A3 controllore avversariale):
A2: ~14 correzioni (cross-ref, gate ruolo, comportamenti); A3 PASS: 38 selettori campionati 0 rotti,
18 endpoint reali, 0 violazioni normative (Allegati 3/4, IS-4, '1 mese', PII.* interna), 9 claim verificati.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-06-12 18:50:19 +02:00

4.9 KiB
Raw Blame History

MAPPA-LOGICA · Knowledge Base

⟦ INIZIO · U-KB · Videata "Knowledge Base" ⟧ File: public/kb.html · URL: /kb.html · Scopo: caricamento e gestione dei documenti (procedure, policy, normative, training material) che l'AI usa per rispondere con citazioni precise (pipeline RAG su Qdrant), con visibilità a 3 livelli: SYSTEM (vendor), FIRM (studio + condivisioni esplicite), ORG (singola organizzazione cliente) · Profili: lettura/ricerca per tutti gli utenti autenticati (la visibilità applica il filtro authz a 3 livelli); l'upload (ingest) è riservato ai ruoli super_admin, org_admin, compliance_manager e consultant (employee/auditor read-only, 403 KB_FORBIDDEN). Per scope: SYSTEM solo super_admin; FIRM solo utenti con consulting_firm_id (consulenti di studio); ORG richiede ruolo org_admin/compliance_manager sull'organizzazione destinataria (super_admin bypassa) e organization_id valorizzato lato backend. La UI mostra/nasconde le radio di scope client-side (setupScopeForUser), ma l'enforcement è nel backend (KnowledgeBaseController::ingest).

• U-KB.1 — Header pagina + "Carica documento" Mostra: titolo "Knowledge Base"; paragrafo introduttivo sul modello di visibilità a 3 livelli (SYSTEM/FIRM/ORG). Azioni: bottone "Carica documento" → toggle del form di upload (U-KB.2); all'apertura chiama setupScopeForUser() che mostra/nasconde le opzioni di scope in base a ruolo e firm. Dati da: GET /api/auth/me (per role e consulting_firm_id, determina gli scope disponibili). Confine: #btn-kb-upload (riga 34).

• U-KB.2 — Form di upload/indicizzazione documento (nascosto di default) Mostra: campo "Titolo"; select "Tipo" (Procedura interna / Linea guida / Normativa / Training); textarea "Contenuto (testo libero, 50–50.000 caratteri)"; radio "Visibilità": "Sistema (super_admin)" (visibile solo a super_admin), "Studio + condivisioni" (visibile solo a utenti firm), "Solo organizzazione corrente" (default, sempre visibile); status di indicizzazione ("Indicizzazione in corso..." / "Documento indicizzato (SCOPE, N chunk)" / messaggi di errore con validazione: titolo obbligatorio, testo minimo 50 caratteri). Azioni: "Indicizza documento" → POST ingest (embed Voyage + upsert Qdrant + tracking MySQL), poi svuota i campi e ricarica la lista; "Annulla" → nasconde il form; selezione radio "FIRM" → mostra il blocco condivisione (U-KB.3). Dati da: POST /api/knowledgebase/ingest (body: title, text, entity_type, scope, shared_with_orgs[]). Confine: #kb-form-card (riga 50); #kb-title (55), #kb-entity-type (59), #kb-text (70), radio input[name="kb-scope"] con label [data-scope-opt="SYSTEM|FIRM|ORG"] (righe 77-84), #btn-kb-submit (102), #btn-kb-cancel (103), #kb-status (104).

• U-KB.3 — Blocco condivisione FIRM (visibile solo con scope=FIRM) Mostra: multi-select "Organizzazioni clienti destinatarie (Ctrl/Cmd per selezione multipla, opzionale)" popolata con le organizzazioni dello studio (nome + P.IVA); nota: "Lascia vuoto per condividere solo con i collaboratori dello studio". Azioni: selezione multipla delle org destinatarie → inviate come shared_with_orgs nell'ingest. Dati da: GET /api/knowledgebase/firmOrgs (risposta: data.organizations[]). Confine: #kb-share-block (riga 89), #kb-shared-with (riga 93).

• U-KB.4 — Lista "Documenti caricati visibili" Mostra: per ogni documento visibile all'utente: titolo, badge scope colorato (SYSTEM blu / FIRM ambra / ORG verde), tipo entità, numero chunk, data di creazione; "Nessun documento visibile" se vuota. La visibilità applica il filtro authz a 3 livelli lato backend. Azioni: bottone "Elimina" per documento → conferma → DELETE (rimuove documento + chunk da Qdrant) e ricarica la lista. Dati da: GET /api/knowledgebase/list (risposta: data.documents[]); DELETE /api/knowledgebase/{id}. Confine: card .kb-doc-list (riga 110); contenitore lista #kb-doc-list (riga 115); bottoni elimina dinamici con attributo [data-del-id="<id>"] (kb.js riga 110).

• U-KB.5 — "Test search semantica" Mostra: campo query (placeholder "Es: come gestire un incidente NIS2?"); risultati: per ogni hit [N] titolo, badge scope, score di similarità, estratto del contenuto (primi 300 caratteri); "Nessun risultato" se vuoto. Azioni: bottone "Cerca" → POST search semantica (top 5 risultati) nel perimetro di visibilità dell'utente. Dati da: POST /api/knowledgebase/search (body: {query, top_k: 5}; risposta: data.results[]). Confine: #kb-search-query (riga 127), #btn-kb-search (riga 128), #kb-search-results (riga 133).

⟦ FINE · U-KB ⟧

ID STABILI MANCANTI (da aggiungere)

Elemento Riga Id proposto
Card lista documenti (wrapper) 110 nis2-kb-doc-list-card
Card test search (wrapper) 122 nis2-kb-search-card
Paragrafo intro visibilità 42 nis2-kb-intro
Bottone "Elimina" documento (dinamico) kb.js 110 già presente data-del-id (selettore stabile, ok)